@happyvertical/smrt-scanner 0.47.2 → 0.49.0
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner-DKLhd-mh.js","names":["description"],"sources":["../../src/source-location.ts","../../src/agent-surface.ts","../../src/discovery.ts","../../src/inheritance-resolver.ts","../../src/oxc-parser.ts","../../src/manifest-adapter.ts","../../src/scanner.ts"],"sourcesContent":["/**\n * Source-offset helpers shared by the OXC class parser and the agent-surface\n * matcher.\n *\n * Lives in its own module so `agent-surface.ts` can resolve a diagnostic's\n * line/column without importing `oxc-parser.ts`, which imports it back.\n */\n\n/**\n * Extract line/column from offset in source text.\n *\n * Note: oxc-parser v0.108+ removed magicString, so this is computed manually.\n *\n * @param sourceText - Full source text the offset indexes into.\n * @param offset - 0-based character offset.\n * @returns 1-based line and column, or `undefined` when the offset is out of\n * range.\n */\nexport function getLineColumn(\n sourceText: string,\n offset: number,\n): { line: number; column: number } | undefined {\n if (offset < 0 || offset > sourceText.length) {\n return undefined;\n }\n\n let line = 1;\n let lastNewlinePos = -1;\n\n for (let i = 0; i < offset; i++) {\n if (sourceText[i] === '\\n') {\n line++;\n lastNewlinePos = i;\n }\n }\n\n return {\n line,\n column: offset - lastNewlinePos, // 1-based column\n };\n}\n","/**\n * Agent-surface matcher (#2591).\n *\n * The class scanner discovers `@smrt()`-decorated classes by matching\n * DECORATORS. Neither a view intent (#2588) nor a playbook (#2589) is a class,\n * so this module adds the second recognizable shape the framework emits from:\n * a **module-scope call with a single object-literal argument**.\n *\n * ```ts\n * import { defineIntent } from '@happyvertical/smrt-web/intents';\n * export const nextPage = defineIntent({ id: 'orders.next_page', ... });\n * ```\n *\n * It keeps exactly the discipline the decorator matcher keeps:\n *\n * - **structural only** — nothing is evaluated, no import is followed, no\n * module is loaded. A value that is not spelled literally in the argument is\n * not a value this matcher can read;\n * - **never a silent drop** — every declaration this matcher recognizes but\n * cannot read produces a diagnostic naming `useWebMcpTool`, the documented\n * escape hatch for a tool set that genuinely cannot be static. A declaration\n * that vanishes from the emitted surface without a word is the failure mode\n * this module exists to prevent;\n * - **binding-aware** — a call is matched only when its callee resolves to an\n * import binding from the ONE accepted specifier per helper. A local helper\n * that happens to be named `defineIntent` is not a view intent.\n *\n * Accepted import specifiers, exactly:\n *\n * | Helper | Specifier |\n * | --- | --- |\n * | `defineIntent` | `@happyvertical/smrt-web/intents` |\n * | `definePlaybook` | `@happyvertical/smrt-playbooks` |\n *\n * `defineIntent` deliberately ships ONLY from the `/intents` subpath entry, so\n * an `OrderTable.intents.ts` sidecar never drags the client-data engine into a\n * page (see `packages/smrt-web/AGENTS.md`). Recognizing the subpath and not the\n * package root is therefore part of the contract, not an omission.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { getLineColumn } from './source-location.js';\nimport type {\n AgentSurface,\n AgentSurfaceCapability,\n AgentSurfaceDiagnostic,\n AgentSurfaceHelper,\n AgentSurfaceIntent,\n AgentSurfacePlaybook,\n AgentSurfacePlaybookStep,\n} from './types.js';\n\n/** Import specifier that makes a callee name mean the framework helper. */\nconst HELPER_SPECIFIERS: Readonly<Record<AgentSurfaceHelper, string>> = {\n defineIntent: '@happyvertical/smrt-web/intents',\n definePlaybook: '@happyvertical/smrt-playbooks',\n};\n\nconst HELPER_NAMES = Object.keys(HELPER_SPECIFIERS) as AgentSurfaceHelper[];\n\n/**\n * The sentence every \"this is not static\" diagnostic ends with. Named\n * explicitly because the escape hatch is the actionable half of the message: a\n * computed tool set is not a bug, it is simply the other path.\n */\nconst ESCAPE_HATCH =\n 'A declaration the scanner cannot read without evaluating it is not emittable — ' +\n 'use `useWebMcpTool` for a tool set derived from computed or fetched data.';\n\nconst MAX_LITERAL_DEPTH = 32;\n\n/**\n * Intent identity rules, mirrored from `defineIntent` in\n * `@happyvertical/smrt-web/intents`.\n *\n * Mirrored for the same reason the capability rule is: this package cannot\n * depend on `@happyvertical/smrt-web`. Keeping them in step matters more than\n * it looks — an emitted entry the runtime would REJECT is worse than no entry\n * at all, because `smrt doctor` and the knowledge graph would then advertise an\n * operation that can never register. If `defineIntent` tightens these, tighten\n * them here too.\n *\n * Playbook keys get no equivalent check because `definePlaybook` imposes no key\n * pattern — only uniqueness, which `mergeAgentSurfaces` already enforces.\n */\nconst INTENT_ID_PATTERN = /^[a-z][a-z0-9]*(?:\\.[a-z0-9][a-z0-9_]*)+$/;\nconst INTENT_ID_MAX_LENGTH = 128;\nconst DESCRIPTION_MAX_LENGTH = 1024;\n\n/**\n * The prefix `defineIntent` itself refuses, mirrored here as a HARD rejection.\n *\n * It stays a literal on purpose, and the reason is the direction of the\n * mirror. The fixed UI tools do register under a configurable\n * `webmcp.ui.prefix`, but this constant does not mirror the UI registrar — it\n * mirrors `RESERVED_TOOL_NAME_PREFIX` in `defineIntent`\n * (`@happyvertical/smrt-web/intents`), which is itself the literal `smrt_ui_`\n * and rejects such an id no matter where an app moved its UI tools. Making\n * this configurable would let the scanner emit an intent the runtime refuses\n * to construct, which is strictly worse than refusing it here: the artifact\n * would advertise an operation that can never register.\n *\n * The configurable half of the same hazard — an intent that collides with the\n * fixed UI tools under a CUSTOM prefix, which `defineIntent` accepts — is not\n * an identity failure at all and is reported by\n * {@link checkAgentSurfaceToolNames} as an advisory collision instead.\n */\nconst RESERVED_TOOL_NAME_PREFIX = 'smrt_ui_';\n\n/**\n * Suffixes of the six fixed UI tools, from `registerWebMcpUiTools`\n * (`packages/smrt-svelte/src/web/webmcp-ui.ts`). Each registers as\n * `${prefix}${suffix}`.\n *\n * The suffixes are framework-owned and fixed; the prefix is the app's, so a\n * fixed UI tool's name is only knowable once the prefix is. Hence\n * {@link AgentSurfaceToolNameOptions.uiToolPrefixes} rather than a guess: a\n * name is compared against the six tools an app WILL register, never against\n * every name some prefix could have produced.\n */\nconst FIXED_UI_TOOL_SUFFIXES = [\n 'execute_data_surface_control',\n 'execute_form_control',\n 'inspect_data_surface',\n 'inspect_form_control',\n 'list_data_surfaces',\n 'list_form_controls',\n] as const;\n\n/**\n * Prefixes `registerWebMcpUiTools` accepts, mirrored from its own\n * `PREFIX_PATTERN`. A prefix it would reject registers no UI tools at all, so\n * nothing can collide with it.\n */\nconst UI_TOOL_PREFIX_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;\n\n/**\n * The prefix `registerWebMcpUiTools` uses when an app configures none. Named\n * separately from {@link RESERVED_TOOL_NAME_PREFIX} even though the two\n * strings match today: one is the UI registrar's default, the other is\n * `defineIntent`'s hard rejection, and they answer to different owners.\n */\nconst DEFAULT_UI_TOOL_PREFIX = 'smrt_ui_';\n\n/** Keys `defineIntent` accepts; anything else is a hard failure there. */\nconst INTENT_DECLARATION_KEYS = new Set([\n 'id',\n 'description',\n 'inputSchema',\n 'capability',\n 'target',\n]);\nconst CONTROL_TARGET_KEYS = new Set([\n 'registry',\n 'action',\n 'formId',\n 'controlId',\n]);\nconst DATA_SURFACE_TARGET_KEYS = new Set([\n 'registry',\n 'controlId',\n 'surfaceId',\n 'kind',\n]);\nconst CONTROL_ACTIONS = new Set([\n 'focus',\n 'reveal',\n 'highlight',\n 'explain',\n 'validate',\n 'stage',\n 'apply',\n 'discard',\n 'clear',\n 'undo',\n]);\nconst DATA_SURFACE_KINDS = new Set(['table', 'list', 'report', 'custom']);\n\n/**\n * Playbook rules, mirrored from `definePlaybook`'s normalizers in\n * `@happyvertical/smrt-playbooks`, for the same reason and with the same\n * obligation to stay in step.\n *\n * These are validated rather than repaired. Coercing an invalid `planes` to the\n * default would be worse than dropping the declaration: the artifact would\n * positively assert server validity the author never declared, which is exactly\n * the fail-open the plane rule exists to prevent.\n */\nconst PLAYBOOK_PLANES = new Set(['browser', 'server']);\nconst FAILURE_POLICIES = new Set(['abort', 'continue']);\nconst QUALIFIED_MODEL_PATTERN = /^\\S+:\\S+$/;\n\n/** Derive the WebMCP tool name for an intent id, as `viewIntentToolName` does. */\nfunction intentToolName(id: string): string {\n return id.replace(/[.-]/g, '_');\n}\n\n/**\n * Directories a declaration may never be read from.\n *\n * `dist`/`build`/`coverage` matter more than they look. A build that transpiles\n * rather than bundles keeps both the import specifier and the module-scope call\n * in its output, so `dist/foo.intents.js` matches this matcher exactly — and\n * because `dist` sorts before `src`, it would WIN the duplicate-identity tie and\n * become the recorded source of a declaration nobody authored there.\n */\nconst EXCLUDED_DIRECTORIES = new Set([\n 'node_modules',\n 'dist',\n 'build',\n 'coverage',\n '__tests__',\n '__typechecks__',\n]);\n\n/**\n * Whether the agent-surface emitter reads this file. **This is the one\n * authority on that question.**\n *\n * Both the scanner's declaration pass and `dev:knowledge-check`'s freshness\n * re-scan call it, because the two answering differently is not a cosmetic\n * inconsistency: a file the emitter reads but the checker skips is reported as\n * \"no longer present in source\" on every run, and a file the checker reads but\n * the emitter skips is reported as \"missing from smrt-knowledge.json\" — both\n * unclearable by any rebuild. It is a path predicate rather than a glob so the\n * two sides cannot drift through differing glob semantics either.\n *\n * Callers still pass globs to prune the WALK for speed; this decides what\n * counts.\n */\nexport function isAgentSurfaceSourcePath(\n filePath: string,\n rootDir?: string,\n): boolean {\n if (!/\\.(?:ts|tsx|js|jsx)$/.test(filePath)) return false;\n if (filePath.endsWith('.d.ts')) return false;\n if (/\\.(?:test|spec)\\.(?:ts|tsx|js|jsx)$/.test(filePath)) return false;\n return !isPrunedAgentSurfacePath(filePath, rootDir);\n}\n\n/**\n * Whether a path lies in a directory declarations are never read from,\n * measured **relative to the project root**.\n *\n * `rootDir` is not optional in spirit. Matching these segments against an\n * absolute path would disable the entire feature for a checkout that merely\n * LIVES under one — a container with `WORKDIR /build`, or a clone in\n * `~/build/…` — and it would do so with no diagnostic at all, because the\n * freshness check applies the same predicate and would agree that nothing is\n * declared. That is the silent drop this module exists to prevent, so the same\n * care `discovery.ts` takes to rewrite globs relative to `cwd` applies here.\n *\n * Exported so the `.svelte` pass and `dev:knowledge-check`'s walk prune\n * identically; a `.svelte` file cannot go through\n * {@link isAgentSurfaceSourcePath}, which rejects it on extension.\n */\nexport function isPrunedAgentSurfacePath(\n filePath: string,\n rootDir?: string,\n): boolean {\n let scoped = filePath;\n if (rootDir) {\n const relativePath = relative(rootDir, filePath);\n // A path outside the root cannot be measured against it; fall back rather\n // than reading `..` segments as if they were project directories.\n if (relativePath && !relativePath.startsWith('..')) scoped = relativePath;\n }\n return scoped.split(/[\\\\/]/).some(\n (segment) =>\n EXCLUDED_DIRECTORIES.has(segment) ||\n // `discoverSourceFiles` ignores `**/.*` and `**/.*/**` unconditionally,\n // so the emitter never reads a hidden path. Saying so here as well is\n // what makes this predicate the COMPLETE answer: leaving it to the glob\n // meant the freshness walk, which enumerates files directly, counted a\n // `src/.generated/foo.intents.ts` the emitter had skipped — unclearable\n // drift, in the opposite direction to the pruned-directory case.\n (segment.startsWith('.') && segment !== '.' && segment !== '..'),\n );\n}\n\n// ---------------------------------------------------------------------------\n// Minimal structural AST view\n// ---------------------------------------------------------------------------\n\ninterface AstNode {\n type: string;\n start?: number;\n end?: number;\n [key: string]: unknown;\n}\n\nfunction isNode(value: unknown): value is AstNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { type?: unknown }).type === 'string'\n );\n}\n\n/**\n * Resolve the local names bound to each helper by an accepted import.\n *\n * Handles the two forms an author actually writes: a named import (with or\n * without an alias) and a namespace import. A default import is deliberately\n * NOT accepted — neither package has a default export, so treating one as the\n * helper would be inventing a contract.\n */\nfunction collectHelperBindings(\n body: readonly AstNode[],\n): Map<string, AgentSurfaceHelper> {\n const bindings = new Map<string, AgentSurfaceHelper>();\n const namespaces = new Map<string, string>();\n\n for (const node of body) {\n if (node.type !== 'ImportDeclaration') continue;\n const source = node.source as { value?: unknown } | undefined;\n if (!source || typeof source.value !== 'string') continue;\n const specifier = source.value;\n const specifiers = (node.specifiers as AstNode[] | undefined) ?? [];\n\n for (const spec of specifiers) {\n const local = (spec.local as { name?: string } | undefined)?.name;\n if (!local) continue;\n\n if (spec.type === 'ImportSpecifier') {\n const imported = (spec.imported as { name?: string } | undefined)?.name;\n const helper = HELPER_NAMES.find(\n (name) => name === imported && HELPER_SPECIFIERS[name] === specifier,\n );\n if (helper) bindings.set(local, helper);\n continue;\n }\n\n if (spec.type === 'ImportNamespaceSpecifier') {\n namespaces.set(local, specifier);\n }\n }\n }\n\n // Namespace imports are recorded as `local.helperName` keys so a\n // `MemberExpression` callee resolves through the same map as a plain\n // identifier.\n for (const [local, specifier] of namespaces) {\n for (const helper of HELPER_NAMES) {\n if (HELPER_SPECIFIERS[helper] === specifier) {\n bindings.set(`${local}.${helper}`, helper);\n }\n }\n }\n\n return bindings;\n}\n\n/** Resolve a callee expression to the helper it names, if any. */\nfunction resolveCallee(\n callee: unknown,\n bindings: ReadonlyMap<string, AgentSurfaceHelper>,\n): AgentSurfaceHelper | undefined {\n if (!isNode(callee)) return undefined;\n if (callee.type === 'Identifier') {\n return bindings.get(String(callee.name));\n }\n if (callee.type === 'MemberExpression' && callee.computed !== true) {\n const object = callee.object;\n const property = callee.property;\n if (\n isNode(object) &&\n object.type === 'Identifier' &&\n isNode(property) &&\n property.type === 'Identifier'\n ) {\n return bindings.get(`${String(object.name)}.${String(property.name)}`);\n }\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Literal extraction\n// ---------------------------------------------------------------------------\n\ninterface LiteralFailure {\n reason: string;\n start?: number;\n}\n\n/**\n * Read an expression as pure JSON data, or record why it cannot be read.\n *\n * Deliberately narrower than the decorator-config extractor: that one resolves\n * spreads against module-scope constants because a dropped `@smrt({ ...CFG })`\n * key would silently reopen an exposure surface. Here the requirement runs the\n * other way — the emitted entry must be exactly what an author can see in one\n * object literal — so a spread, an identifier reference, a call, a template\n * literal, and a conditional are all refused rather than partially resolved.\n */\nfunction readLiteral(\n node: unknown,\n failures: LiteralFailure[],\n path: string,\n depth = 0,\n): unknown {\n if (!isNode(node)) {\n failures.push({ reason: `${path} is not a readable expression` });\n return undefined;\n }\n if (depth > MAX_LITERAL_DEPTH) {\n failures.push({\n reason: `${path} nests deeper than ${MAX_LITERAL_DEPTH} levels`,\n start: node.start,\n });\n return undefined;\n }\n\n switch (node.type) {\n case 'Literal': {\n const value = node.value;\n if (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n typeof value === 'number'\n ) {\n return value;\n }\n failures.push({\n reason: `${path} is not a JSON literal`,\n start: node.start,\n });\n return undefined;\n }\n\n case 'UnaryExpression': {\n const argument = node.argument;\n if (\n node.operator === '-' &&\n isNode(argument) &&\n argument.type === 'Literal' &&\n typeof argument.value === 'number'\n ) {\n return -argument.value;\n }\n failures.push({\n reason: `${path} is a computed unary expression`,\n start: node.start,\n });\n return undefined;\n }\n\n case 'ArrayExpression': {\n const elements = (node.elements as unknown[] | undefined) ?? [];\n const result: unknown[] = [];\n elements.forEach((element, index) => {\n if (isNode(element) && element.type === 'SpreadElement') {\n failures.push({\n reason: `${path}[${index}] is a spread`,\n start: element.start,\n });\n return;\n }\n if (element === null) {\n failures.push({ reason: `${path}[${index}] is an array hole` });\n return;\n }\n result.push(\n readLiteral(element, failures, `${path}[${index}]`, depth + 1),\n );\n });\n return result;\n }\n\n case 'ObjectExpression': {\n const properties = (node.properties as AstNode[] | undefined) ?? [];\n const result: Record<string, unknown> = {};\n for (const property of properties) {\n if (property.type === 'SpreadElement') {\n failures.push({\n reason: `${path} contains a spread`,\n start: property.start,\n });\n continue;\n }\n if (property.type !== 'Property') {\n failures.push({\n reason: `${path} contains an unsupported member`,\n start: property.start,\n });\n continue;\n }\n if (property.computed === true || property.shorthand === true) {\n failures.push({\n reason: `${path} contains a ${\n property.computed === true ? 'computed' : 'shorthand'\n } key`,\n start: property.start,\n });\n continue;\n }\n const key = readPropertyKey(property.key);\n if (key === undefined) {\n failures.push({\n reason: `${path} contains a non-literal key`,\n start: property.start,\n });\n continue;\n }\n if (!isSafeKey(key)) {\n failures.push({\n reason: `${path}.${key} uses a reserved prototype key`,\n start: property.start,\n });\n continue;\n }\n result[key] = readLiteral(\n property.value,\n failures,\n `${path}.${key}`,\n depth + 1,\n );\n }\n return result;\n }\n\n case 'TSAsExpression':\n case 'TSSatisfiesExpression':\n case 'TSNonNullExpression':\n case 'TSTypeAssertion':\n return readLiteral(node.expression, failures, path, depth);\n\n case 'Identifier': {\n const name = String(node.name);\n if (name === 'undefined') return undefined;\n failures.push({\n reason: `${path} references the identifier \\`${name}\\``,\n start: node.start,\n });\n return undefined;\n }\n\n case 'TemplateLiteral':\n failures.push({\n reason: `${path} is a template literal`,\n start: node.start,\n });\n return undefined;\n\n case 'ConditionalExpression':\n failures.push({\n reason: `${path} is a conditional expression`,\n start: node.start,\n });\n return undefined;\n\n default:\n failures.push({\n reason: `${path} is a computed \\`${node.type}\\``,\n start: node.start,\n });\n return undefined;\n }\n}\n\nfunction readPropertyKey(key: unknown): string | undefined {\n if (!isNode(key)) return undefined;\n if (key.type === 'Identifier') return String(key.name);\n if (key.type === 'Literal' && typeof key.value === 'string') return key.value;\n return undefined;\n}\n\n/** Prototype-pollution guard, mirroring the class parser's `isSafeObjectKey`. */\nfunction isSafeKey(key: string): boolean {\n return key !== '__proto__' && key !== 'constructor' && key !== 'prototype';\n}\n\n// ---------------------------------------------------------------------------\n// Call discovery\n// ---------------------------------------------------------------------------\n\ninterface MatchedCall {\n helper: AgentSurfaceHelper;\n node: AstNode;\n moduleScope: boolean;\n}\n\nfunction unwrapTypeWrappers(node: unknown): AstNode | undefined {\n let current = node;\n while (\n isNode(current) &&\n (current.type === 'TSAsExpression' ||\n current.type === 'TSSatisfiesExpression' ||\n current.type === 'TSNonNullExpression' ||\n current.type === 'TSTypeAssertion')\n ) {\n current = current.expression;\n }\n return isNode(current) ? current : undefined;\n}\n\n/**\n * Collect the CallExpression nodes that sit directly at module scope, in the\n * three positions a declaration is actually written:\n * `definePlaybook({...});`, `const x = defineIntent({...})`, and\n * `export default defineIntent({...})`.\n */\nfunction collectModuleScopeCalls(body: readonly AstNode[]): Set<AstNode> {\n const calls = new Set<AstNode>();\n\n // `export const intents = [defineIntent({…}), defineIntent({…})]` is a\n // plausible authoring form and is genuinely at module scope — not inside a\n // function, class, conditional, or loop, which is what the contract actually\n // forbids. Reporting it as \"not at module scope\" would be false and would\n // leave the author with no usable next step.\n const addInitializer = (value: unknown): void => {\n const init = unwrapTypeWrappers(value);\n if (!init) return;\n if (init.type === 'CallExpression') {\n calls.add(init);\n return;\n }\n if (init.type === 'ArrayExpression') {\n for (const element of (init.elements as unknown[]) ?? []) {\n const entry = unwrapTypeWrappers(element);\n if (entry && entry.type === 'CallExpression') calls.add(entry);\n }\n }\n };\n\n const addDeclaration = (declaration: unknown): void => {\n if (!isNode(declaration)) return;\n if (declaration.type !== 'VariableDeclaration') return;\n for (const declarator of (declaration.declarations as AstNode[]) ?? []) {\n addInitializer(declarator.init);\n }\n };\n\n for (const statement of body) {\n if (statement.type === 'ExpressionStatement') {\n const expression = unwrapTypeWrappers(statement.expression);\n if (expression && expression.type === 'CallExpression') {\n calls.add(expression);\n }\n continue;\n }\n if (statement.type === 'VariableDeclaration') {\n addDeclaration(statement);\n continue;\n }\n if (statement.type === 'ExportNamedDeclaration') {\n addDeclaration(statement.declaration);\n continue;\n }\n if (statement.type === 'ExportDefaultDeclaration') {\n const declaration = unwrapTypeWrappers(statement.declaration);\n if (declaration && declaration.type === 'CallExpression') {\n calls.add(declaration);\n }\n }\n }\n\n return calls;\n}\n\n/**\n * Walk the whole program for helper calls.\n *\n * The walk is deliberately exhaustive rather than module-scope-only: a\n * declaration written inside a function is not emittable, and finding it is the\n * only way to say so instead of dropping it in silence.\n */\nfunction collectMatchedCalls(\n body: readonly AstNode[],\n bindings: ReadonlyMap<string, AgentSurfaceHelper>,\n): MatchedCall[] {\n const moduleScope = collectModuleScopeCalls(body);\n const matches: MatchedCall[] = [];\n const seen = new Set<AstNode>();\n\n const visit = (value: unknown): void => {\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry);\n return;\n }\n if (!isNode(value) || seen.has(value)) return;\n seen.add(value);\n if (value.type === 'CallExpression') {\n const helper = resolveCallee(value.callee, bindings);\n if (helper) {\n matches.push({\n helper,\n node: value,\n moduleScope: moduleScope.has(value),\n });\n }\n }\n for (const key of Object.keys(value)) {\n if (key === 'type' || key === 'loc' || key === 'range') continue;\n visit(value[key]);\n }\n };\n\n visit(body as unknown);\n // Source order keeps diagnostics readable; emitted identity is sorted in\n // `mergeAgentSurfaces` and never depends on this order.\n matches.sort((a, b) => (a.node.start ?? 0) - (b.node.start ?? 0));\n return matches;\n}\n\n// ---------------------------------------------------------------------------\n// Declaration normalization\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a partial capability declaration through the ONE fail-closed rule\n * (#2587, `@happyvertical/smrt-types` `CapabilityClassification`): an\n * undeclared capability is `destructive`, non-idempotent, open-world.\n *\n * Mirrored structurally rather than imported: this package carries no\n * `@happyvertical/*` dependency, because core depends on it and the cycle would\n * close. `smrt-web` mirrors the same contract for the same reason.\n */\nfunction resolveCapability(declared: unknown): AgentSurfaceCapability {\n const value =\n typeof declared === 'object' && declared !== null\n ? (declared as Record<string, unknown>)\n : {};\n const effect = value.effect;\n return {\n effect:\n effect === 'read' || effect === 'write' || effect === 'destructive'\n ? effect\n : 'destructive',\n idempotent: value.idempotent === true,\n openWorld: value.openWorld !== false,\n };\n}\n\n/**\n * A present, non-blank string.\n *\n * `trim()` matters: the runtime normalizers reject `' '` with\n * `trim() === ''`, so treating whitespace as present would emit a playbook that\n * throws at registration.\n */\nfunction readString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value : undefined;\n}\n\n/**\n * `assertIdentifier` in `defineIntent`: bounded length, no control characters.\n * A `formId` past the bound or carrying a control character is rejected at\n * runtime, so emitting it would advertise an intent that never registers.\n */\nconst IDENTIFIER_MAX_LENGTH = 256;\n\nfunction identifierProblem(value: unknown, path: string): string | undefined {\n if (typeof value !== 'string' || value.length === 0) {\n return `${path} must be a non-empty string`;\n }\n if (value.length > IDENTIFIER_MAX_LENGTH) {\n return `${path} is longer than ${IDENTIFIER_MAX_LENGTH} characters, which \\`defineIntent\\` rejects`;\n }\n for (const character of value) {\n const code = character.charCodeAt(0);\n if (code < 32 || code === 127) {\n return `${path} contains a control character, which \\`defineIntent\\` rejects`;\n }\n }\n return undefined;\n}\n\n/**\n * Why this intent id could never register, or `undefined` when it can.\n *\n * The declaration types this against `string`, so an id that violates the\n * runtime pattern type-checks cleanly and fails only when the page loads.\n * Catching it here turns that into a build-time diagnostic.\n */\n/**\n * Why this whole intent declaration could never register, or `undefined`.\n *\n * Mirrors `defineIntent`'s key allowlist, description bound, and\n * `normalizeTarget` — the closed `registry` union, the control-action union,\n * the required data-surface `controlId`, and the surface-kind union. Validating\n * only the id would still let `target: { registry: 'rest', url: … }` reach the\n * artifact verbatim, where an agent reads it as an addressable operation that\n * cannot exist.\n */\nfunction intentDeclarationProblem(\n declaration: Record<string, unknown>,\n id: string,\n description: string,\n): string | undefined {\n const identity = intentIdentityProblem(id);\n if (identity) return identity;\n\n for (const key of Object.keys(declaration)) {\n if (!INTENT_DECLARATION_KEYS.has(key)) {\n return `view intent '${id}' declares unknown key '${key}'. A declaration is data only — there is no field for an execute function, a URL, a route, or a fetch, and \\`defineIntent\\` rejects one.`;\n }\n }\n if (description.length > DESCRIPTION_MAX_LENGTH) {\n return `view intent '${id}' has a description longer than ${DESCRIPTION_MAX_LENGTH} characters, which \\`defineIntent\\` rejects.`;\n }\n if (\n declaration.inputSchema !== undefined &&\n !isPlainRecord(declaration.inputSchema)\n ) {\n return `view intent '${id}' has an inputSchema that is not an object literal, which \\`defineIntent\\` rejects.`;\n }\n\n // The fail-closed default is for an OMITTED capability, not a malformed one.\n // Quietly defaulting `{ effect: 'reed' }` would emit an entry the runtime\n // refuses, and hide the typo behind a plausible-looking classification.\n const capability = declaration.capability;\n if (capability !== undefined) {\n if (!isPlainRecord(capability)) {\n return `view intent '${id}' has a capability that is not an object literal, which \\`defineIntent\\` rejects.`;\n }\n for (const key of Object.keys(capability)) {\n if (key !== 'effect' && key !== 'idempotent' && key !== 'openWorld') {\n return `view intent '${id}' declares unknown capability key '${key}', which \\`defineIntent\\` rejects.`;\n }\n }\n if (\n capability.effect !== undefined &&\n capability.effect !== 'read' &&\n capability.effect !== 'write' &&\n capability.effect !== 'destructive'\n ) {\n return `view intent '${id}' declares capability.effect '${String(capability.effect)}'; \\`defineIntent\\` accepts only read, write, or destructive.`;\n }\n for (const flag of ['idempotent', 'openWorld'] as const) {\n if (\n capability[flag] !== undefined &&\n typeof capability[flag] !== 'boolean'\n ) {\n return `view intent '${id}' declares a non-boolean capability.${flag}, which \\`defineIntent\\` rejects.`;\n }\n }\n }\n\n const target = declaration.target as Record<string, unknown>;\n const registry = target.registry;\n if (registry !== 'control' && registry !== 'dataSurface') {\n return `view intent '${id}' targets registry '${String(registry)}'; \\`defineIntent\\` accepts only 'control' or 'dataSurface'. An intent moves mounted browser state and has no path to REST.`;\n }\n\n const allowed =\n registry === 'control' ? CONTROL_TARGET_KEYS : DATA_SURFACE_TARGET_KEYS;\n for (const key of Object.keys(target)) {\n if (!allowed.has(key)) {\n return `view intent '${id}' declares unknown target key '${key}' for the '${registry}' registry, which \\`defineIntent\\` rejects.`;\n }\n }\n\n if (registry === 'control') {\n if (!CONTROL_ACTIONS.has(String(target.action))) {\n return `view intent '${id}' declares control action '${String(target.action)}', which is not a \\`ControlInteractionRegistry\\` command.`;\n }\n for (const key of ['formId', 'controlId'] as const) {\n if (target[key] === undefined) continue;\n const problem = identifierProblem(target[key], `target.${key}`);\n if (problem) return `view intent '${id}': ${problem}.`;\n }\n return undefined;\n }\n\n if (!isNonEmptyString(target.controlId)) {\n return `view intent '${id}' targets the dataSurface registry without a \\`controlId\\`, which \\`defineIntent\\` requires.`;\n }\n for (const key of ['controlId', 'surfaceId'] as const) {\n if (target[key] === undefined) continue;\n const problem = identifierProblem(target[key], `target.${key}`);\n if (problem) return `view intent '${id}': ${problem}.`;\n }\n if (\n target.kind !== undefined &&\n !DATA_SURFACE_KINDS.has(String(target.kind))\n ) {\n return `view intent '${id}' declares data-surface kind '${String(target.kind)}', which \\`defineIntent\\` rejects.`;\n }\n return undefined;\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Why this playbook declaration could never register, or `undefined`.\n *\n * Mirrors `definePlaybook`'s normalizers, which THROW on each of these rather\n * than defaulting. Repairing them here would be actively harmful for `planes`:\n * an author who wrote `planes: []` or a typo'd plane would get an emitted entry\n * claiming both planes, so the artifact would assert server validity nobody\n * declared.\n */\nfunction playbookDeclarationProblem(\n declaration: Record<string, unknown>,\n key: string,\n steps: readonly AgentSurfacePlaybookStep[],\n): string | undefined {\n if (steps.length === 0) {\n // `normalizeSteps` requires at least one step and throws. Emitting the\n // empty declaration would advertise a playbook that resolves to no plan.\n return `playbook '${key}' declares no steps; \\`definePlaybook\\` requires at least one.`;\n }\n\n const planes = declaration.planes;\n if (planes !== undefined && planes !== null) {\n if (!Array.isArray(planes)) {\n return `playbook '${key}' declares planes that are not an array, which \\`definePlaybook\\` rejects.`;\n }\n for (const plane of planes) {\n if (!PLAYBOOK_PLANES.has(String(plane))) {\n return `playbook '${key}' declares unknown plane '${String(plane)}'; expected 'browser' or 'server'.`;\n }\n }\n if (planes.length === 0) {\n return `playbook '${key}' declares an empty planes list; \\`definePlaybook\\` requires at least one, and defaulting it here would assert a validity the author never declared.`;\n }\n }\n\n const onStepFailure = declaration.onStepFailure;\n if (\n onStepFailure !== undefined &&\n !FAILURE_POLICIES.has(String(onStepFailure))\n ) {\n return `playbook '${key}' declares onStepFailure '${String(onStepFailure)}'; \\`definePlaybook\\` accepts only 'abort' or 'continue'.`;\n }\n\n const enabled = declaration.enabled;\n if (enabled !== undefined && typeof enabled !== 'boolean') {\n return `playbook '${key}' declares a non-boolean \\`enabled\\`, which \\`definePlaybook\\` rejects rather than coercing — a truthy '\"false\"' would otherwise read as enabled.`;\n }\n\n for (const step of (declaration.steps as unknown[]) ?? []) {\n const record = step as Record<string, unknown>;\n if (\n record.kind === 'operation' &&\n !QUALIFIED_MODEL_PATTERN.test(String(record.model))\n ) {\n return `playbook '${key}' has a step whose model '${String(record.model)}' is not a qualified pair such as '@happyvertical/smrt-commerce:Order'.`;\n }\n }\n return undefined;\n}\n\nfunction intentIdentityProblem(id: string): string | undefined {\n if (id.length > INTENT_ID_MAX_LENGTH) {\n return `intent id '${id}' is longer than ${INTENT_ID_MAX_LENGTH} characters, which \\`defineIntent\\` rejects.`;\n }\n if (!INTENT_ID_PATTERN.test(id)) {\n return `intent id '${id}' must be lowercase and namespaced with at least one dot, e.g. 'orders.filter_by_status' — \\`defineIntent\\` rejects it as written, so emitting it would advertise an operation that can never register.`;\n }\n if (intentToolName(id).startsWith(RESERVED_TOOL_NAME_PREFIX)) {\n return `intent id '${id}' resolves into the reserved '${RESERVED_TOOL_NAME_PREFIX}' namespace of the six fixed UI tools, which \\`defineIntent\\` rejects.`;\n }\n return undefined;\n}\n\nfunction normalizeSteps(\n value: unknown,\n): AgentSurfacePlaybookStep[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const steps: AgentSurfacePlaybookStep[] = [];\n for (const entry of value) {\n if (typeof entry !== 'object' || entry === null) return undefined;\n const step = entry as Record<string, unknown>;\n if (step.kind === 'operation') {\n const model = readString(step.model);\n const action = readString(step.action);\n if (!model || !action) return undefined;\n steps.push({ kind: 'operation', model, action });\n continue;\n }\n if (step.kind === 'intent') {\n const id = readString(step.id);\n if (!id) return undefined;\n steps.push({ kind: 'intent', id });\n continue;\n }\n return undefined;\n }\n return steps;\n}\n\nfunction normalizePlanes(value: unknown): Array<'browser' | 'server'> {\n if (!Array.isArray(value)) return [];\n return value\n .filter(\n (entry): entry is 'browser' | 'server' =>\n entry === 'browser' || entry === 'server',\n )\n .sort();\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport interface ExtractAgentSurfaceOptions {\n /** Program body from an OXC parse. */\n body: readonly unknown[];\n /** Full source text, used for diagnostic line/column. */\n sourceText: string;\n /** Path recorded on every emitted entry and diagnostic. */\n filePath: string;\n}\n\n/**\n * Fast pre-check: a file that names neither helper cannot declare either, so\n * the AST walk is skipped entirely. Callers use it to keep the matcher off the\n * hot path of a large scan.\n */\nexport function sourceMayDeclareAgentSurface(sourceText: string): boolean {\n return HELPER_NAMES.some((helper) => sourceText.includes(helper));\n}\n\n/**\n * Match `defineIntent(...)` / `definePlaybook(...)` declarations in one parsed\n * module.\n *\n * @returns Emittable entries plus a diagnostic for every recognized call that\n * is not emittable. A recognized call always produces exactly one of the two.\n */\nexport function extractAgentSurface(\n options: ExtractAgentSurfaceOptions,\n): AgentSurface {\n const { sourceText, filePath } = options;\n const body = (options.body as AstNode[]).filter(isNode);\n const intents: AgentSurfaceIntent[] = [];\n const playbooks: AgentSurfacePlaybook[] = [];\n const diagnostics: AgentSurfaceDiagnostic[] = [];\n\n const bindings = collectHelperBindings(body);\n if (bindings.size === 0) return { intents, playbooks, diagnostics };\n\n const report = (\n code: AgentSurfaceDiagnostic['code'],\n helper: AgentSurfaceHelper,\n message: string,\n start?: number,\n ): void => {\n const loc =\n start === undefined ? undefined : getLineColumn(sourceText, start);\n diagnostics.push({\n code,\n helper,\n message,\n filePath,\n line: loc?.line,\n column: loc?.column,\n });\n };\n\n for (const match of collectMatchedCalls(body, bindings)) {\n const { helper, node } = match;\n\n if (!match.moduleScope) {\n report(\n 'not-module-scope',\n helper,\n `\\`${helper}()\\` must be called at module scope to be emitted into the manifest and knowledge graph. ${ESCAPE_HATCH}`,\n node.start,\n );\n continue;\n }\n\n const args = (node.arguments as unknown[] | undefined) ?? [];\n if (args.length !== 1) {\n report(\n 'argument-count',\n helper,\n `\\`${helper}()\\` takes exactly one object-literal argument; found ${args.length}. ${ESCAPE_HATCH}`,\n node.start,\n );\n continue;\n }\n\n const argument = unwrapTypeWrappers(args[0]);\n if (argument?.type !== 'ObjectExpression') {\n report(\n 'non-literal-argument',\n helper,\n `\\`${helper}()\\` must be called with an object literal, not a ${\n argument?.type ?? 'unknown expression'\n }. ${ESCAPE_HATCH}`,\n (argument ?? node).start,\n );\n continue;\n }\n\n const failures: LiteralFailure[] = [];\n const declaration = readLiteral(argument, failures, helper) as\n | Record<string, unknown>\n | undefined;\n\n if (failures.length > 0) {\n for (const failure of failures) {\n report(\n 'non-literal-argument',\n helper,\n `${failure.reason}. ${ESCAPE_HATCH}`,\n failure.start ?? node.start,\n );\n }\n continue;\n }\n if (!declaration) continue;\n\n if (helper === 'defineIntent') {\n const id = readString(declaration.id);\n const description = readString(declaration.description);\n const target = declaration.target;\n if (\n !id ||\n !description ||\n typeof target !== 'object' ||\n target === null ||\n Array.isArray(target)\n ) {\n report(\n 'incomplete-declaration',\n helper,\n 'a view intent needs a literal `id`, `description`, and `target` to be emitted. ' +\n ESCAPE_HATCH,\n node.start,\n );\n continue;\n }\n const problem = intentDeclarationProblem(declaration, id, description);\n if (problem) {\n // Emitting this would advertise, in the artifact and in `smrt doctor`,\n // an operation `defineIntent` refuses to register at runtime.\n report('invalid-identity', helper, problem, node.start);\n continue;\n }\n intents.push({\n kind: 'intent',\n id,\n description,\n capability: resolveCapability(declaration.capability),\n target: target as Record<string, unknown>,\n hasInputSchema:\n typeof declaration.inputSchema === 'object' &&\n declaration.inputSchema !== null,\n // An intent moves mounted browser state, so it is browser-valid only.\n // A server-side agent reaches one through the #2446 command/ack bridge,\n // which the referencing playbook must declare explicitly.\n planes: ['browser'],\n filePath,\n });\n continue;\n }\n\n const key = readString(declaration.key);\n const title = readString(declaration.title);\n const description = readString(declaration.description);\n const steps = normalizeSteps(declaration.steps);\n if (!key || !title || !description || !steps) {\n report(\n 'incomplete-declaration',\n helper,\n 'a playbook needs a literal `key`, `title`, `description`, and a `steps` array of ' +\n '`{ kind: \"operation\", model, action }` / `{ kind: \"intent\", id }` members to be ' +\n `emitted. ${ESCAPE_HATCH}`,\n node.start,\n );\n continue;\n }\n const playbookProblem = playbookDeclarationProblem(declaration, key, steps);\n if (playbookProblem) {\n report('invalid-identity', helper, playbookProblem, node.start);\n continue;\n }\n const declaredPlanes = normalizePlanes(declaration.planes);\n playbooks.push({\n kind: 'playbook',\n key,\n title,\n description,\n steps,\n // Mirrors `smrt-playbooks`: silence means browser-only as soon as any\n // step is a view intent, because server validity for one rides the #2446\n // command/ack bridge and must be declared explicitly.\n planes:\n declaredPlanes.length > 0\n ? declaredPlanes\n : steps.some((step) => step.kind === 'intent')\n ? ['browser']\n : ['browser', 'server'],\n planesDeclared: declaredPlanes.length > 0,\n onStepFailure:\n declaration.onStepFailure === 'continue' ? 'continue' : 'abort',\n enabled: declaration.enabled !== false,\n filePath,\n });\n }\n\n return { intents, playbooks, diagnostics };\n}\n\n/**\n * Report `defineIntent` / `definePlaybook` written inside a `.svelte` file.\n *\n * The scanner walks `.ts` and `.tsx` only, so such a declaration is invisible\n * to every emitter — which is exactly why it must not be invisible to the\n * author. The check is textual on purpose: a Svelte template is not a\n * TypeScript program, and reaching for a Svelte compiler here would buy\n * nothing, since the answer is \"move it to a `.ts` sidecar\" regardless of what\n * the declaration says.\n *\n * Both the accepted import specifier and the call token must appear, so an\n * unrelated component that merely mentions the word is not flagged.\n */\n/**\n * Offset of a call to `helper` — or to a local name the file aliased it to — in\n * a Svelte component, or `undefined` when there is none.\n *\n * Textual, but not naively so. Requiring the literal token `defineIntent(`\n * would miss `defineIntent ({...})` and, worse, miss\n * `import { defineIntent as declare }` followed by `declare({...})` — which is\n * the exact silent omission this whole pass exists to prevent. So the local\n * names bound by the file's own import statement are resolved first, and\n * whitespace before the parenthesis is allowed.\n */\nfunction svelteCallOffset(\n text: string,\n helper: AgentSurfaceHelper,\n): number | undefined {\n const names = new Set<string>([helper]);\n\n // `import { defineIntent as declare, x } from '<specifier>'` — capture the\n // brace group for this helper's specifier and read the local name out of it.\n const importPattern = new RegExp(\n `import\\\\s*\\\\{([^}]*)\\\\}\\\\s*from\\\\s*['\"\\`]${escapeRegExp(\n HELPER_SPECIFIERS[helper],\n )}['\"\\`]`,\n 'g',\n );\n for (const match of text.matchAll(importPattern)) {\n for (const clause of match[1].split(',')) {\n const alias = clause.trim().match(/^(\\w+)\\s+as\\s+(\\w+)$/);\n if (alias && alias[1] === helper) {\n names.add(alias[2]);\n }\n }\n }\n\n let earliest: number | undefined;\n for (const name of names) {\n // A word boundary before the name keeps `myDefineIntent(` from matching.\n const call = new RegExp(`\\\\b${escapeRegExp(name)}\\\\s*\\\\(`, 'g');\n for (const match of text.matchAll(call)) {\n if (\n match.index !== undefined &&\n (earliest === undefined || match.index < earliest)\n ) {\n earliest = match.index;\n }\n }\n }\n return earliest;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function scanSvelteAgentSurface(\n filePath: string,\n sourceText?: string,\n): AgentSurfaceDiagnostic[] {\n let text: string;\n try {\n text = sourceText ?? readFileSync(filePath, 'utf-8');\n } catch {\n return [];\n }\n\n const diagnostics: AgentSurfaceDiagnostic[] = [];\n for (const helper of HELPER_NAMES) {\n if (!text.includes(HELPER_SPECIFIERS[helper])) continue;\n const callIndex = svelteCallOffset(text, helper);\n if (callIndex === undefined) continue;\n const loc = getLineColumn(text, callIndex);\n const sidecar = helper === 'defineIntent' ? 'intents' : 'playbooks';\n diagnostics.push({\n code: 'svelte-declaration',\n helper,\n message:\n `\\`${helper}()\\` is called in a .svelte file, which the scanner never reads, so this ` +\n 'declaration can never reach the manifest or knowledge graph. Move it to a `.ts` ' +\n `sidecar (\\`Foo.${sidecar}.ts\\`) and import it from the component. ${ESCAPE_HATCH}`,\n filePath,\n line: loc?.line,\n column: loc?.column,\n });\n }\n return diagnostics;\n}\n\n// ---------------------------------------------------------------------------\n// Deterministic identity\n// ---------------------------------------------------------------------------\n\nfunction compareStrings(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Merge per-file results into ONE deterministic surface.\n *\n * Emission must not depend on the order the file system happened to hand files\n * to the scanner — a cross-profile parity snapshot that churns on directory\n * order proves nothing. So identity is total and content-derived:\n *\n * - an intent is identified by its `id`, a playbook by its `key`;\n * - entries sort by that identity, then by the recorded source path;\n * - when two files declare the same identity, the entry from the\n * lexicographically smaller path wins and the other is reported as a\n * `duplicate-identity` diagnostic — a rule that gives the same answer for\n * every input order, which \"first one scanned wins\" does not;\n * - diagnostics sort by path, then line, column, code, and message.\n *\n * `relativize` maps an absolute scan path to the stable path recorded in the\n * artifact; callers pass the package root's relativizer so a checked-in\n * artifact never carries a machine-specific absolute path.\n */\nexport function mergeAgentSurfaces(\n surfaces: readonly AgentSurface[],\n relativize: (filePath: string) => string = (filePath) => filePath,\n): AgentSurface {\n const diagnostics: AgentSurfaceDiagnostic[] = [];\n const intents = new Map<string, AgentSurfaceIntent>();\n const playbooks = new Map<string, AgentSurfacePlaybook>();\n\n const claim = <T extends { filePath: string }>(\n bucket: Map<string, T>,\n identity: string,\n entry: T,\n helper: AgentSurfaceHelper,\n label: string,\n ): void => {\n const existing = bucket.get(identity);\n if (!existing) {\n bucket.set(identity, entry);\n return;\n }\n const [winner, loser] =\n entry.filePath < existing.filePath\n ? [entry, existing]\n : [existing, entry];\n bucket.set(identity, winner);\n diagnostics.push({\n code: 'duplicate-identity',\n helper,\n message:\n `${label} \\`${identity}\\` is declared in both \\`${winner.filePath}\\` and ` +\n `\\`${loser.filePath}\\`. Identity must be unique across the project; the declaration in ` +\n 'the first path is emitted and this one is dropped.',\n filePath: loser.filePath,\n });\n };\n\n for (const surface of surfaces) {\n for (const intent of surface.intents) {\n claim(\n intents,\n intent.id,\n { ...intent, filePath: relativize(intent.filePath) },\n 'defineIntent',\n 'view intent',\n );\n }\n for (const playbook of surface.playbooks) {\n claim(\n playbooks,\n playbook.key,\n { ...playbook, filePath: relativize(playbook.filePath) },\n 'definePlaybook',\n 'playbook',\n );\n }\n for (const diagnostic of surface.diagnostics) {\n diagnostics.push({\n ...diagnostic,\n filePath: relativize(diagnostic.filePath),\n });\n }\n }\n\n // `intentToolName` is not injective — `orders.foo_bar` and `orders.foo.bar`\n // both flatten to `orders_foo_bar` — and `defineIntent` rejects the second\n // registration of a colliding pair. Emitting both would overstate the usable\n // surface with two entries only one of which can ever exist, so the collision\n // is resolved by the same path-ordered rule as a duplicate identity.\n const sortedIntents = [...intents.values()].sort(\n (a, b) =>\n compareStrings(a.id, b.id) || compareStrings(a.filePath, b.filePath),\n );\n const byToolName = new Map<string, AgentSurfaceIntent>();\n const survivingIntents: AgentSurfaceIntent[] = [];\n for (const intent of sortedIntents) {\n const toolName = intentToolName(intent.id);\n const claimed = byToolName.get(toolName);\n if (!claimed) {\n byToolName.set(toolName, intent);\n survivingIntents.push(intent);\n continue;\n }\n const [winner, loser] =\n intent.filePath < claimed.filePath\n ? [intent, claimed]\n : [claimed, intent];\n byToolName.set(toolName, winner);\n if (winner !== claimed) {\n survivingIntents[survivingIntents.indexOf(claimed)] = winner;\n }\n diagnostics.push({\n code: 'duplicate-identity',\n helper: 'defineIntent',\n message:\n `view intents \\`${winner.id}\\` and \\`${loser.id}\\` both derive the WebMCP tool name ` +\n `\\`${toolName}\\`, which \\`defineIntent\\` rejects at registration. The declaration in ` +\n `\\`${winner.filePath}\\` is emitted and the one in \\`${loser.filePath}\\` is dropped.`,\n filePath: loser.filePath,\n });\n }\n\n return {\n intents: survivingIntents.sort(\n (a, b) =>\n compareStrings(a.id, b.id) || compareStrings(a.filePath, b.filePath),\n ),\n playbooks: [...playbooks.values()].sort(\n (a, b) =>\n compareStrings(a.key, b.key) || compareStrings(a.filePath, b.filePath),\n ),\n diagnostics: diagnostics.sort(\n (a, b) =>\n compareStrings(a.filePath, b.filePath) ||\n (a.line ?? 0) - (b.line ?? 0) ||\n (a.column ?? 0) - (b.column ?? 0) ||\n compareStrings(a.code, b.code) ||\n compareStrings(a.message, b.message),\n ),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Collisions with names this pass does not own (#2725)\n// ---------------------------------------------------------------------------\n\n/**\n * One WebMCP tool name the build will register for a generated model action,\n * supplied by the caller that knows the exposure policy.\n */\nexport interface GeneratedModelToolName {\n /**\n * The tool name EXACTLY as it will be registered.\n *\n * This pass never derives a generated name and never applies a namespace of\n * its own: it compares the strings it is handed. That is deliberate. The\n * WebMCP `namespace` is a runtime `<Provider webmcp={{ namespace }}>` value\n * that no build artifact records, so inventing a build-time declaration of\n * it here would create a second place to say what the provider already says,\n * free to disagree with it silently. Taking names instead means a caller\n * that ever does know the namespace qualifies them itself and nothing in\n * this module changes.\n */\n name: string;\n /** What owns that name, for the message — e.g. `Product.list`. */\n declaredBy?: string;\n}\n\nexport interface AgentSurfaceToolNameOptions {\n /**\n * Generated model tool names for the SAME manifest, already filtered by the\n * exposure policy.\n *\n * Filtered, not enumerated: comparing against every verb a class COULD\n * expose would report collisions with tools that are never registered.\n * `buildWebMcpToolDefinitions` in `@happyvertical/smrt-core/vite-plugin` is\n * the function that emits the runtime definitions, so its output is the only\n * honest input here.\n */\n generatedToolNames?: readonly GeneratedModelToolName[];\n /**\n * Prefixes the fixed UI tools are mounted under, defaulting to the\n * registrar's own `smrt_ui_`.\n *\n * Supplied for the same reason `generatedToolNames` is: a name is compared\n * against tools that will really register. Quantifying over every prefix an\n * app COULD have configured — deriving the would-be prefix from the name —\n * looks like more coverage and is the opposite. Under the default it has no\n * true positive at all, because an id flattening to `smrt_ui_*` is rejected\n * by {@link intentIdentityProblem} before it can become an entry, so every\n * diagnostic such a rule emits for a default-configured app is false. A\n * warning that is always wrong where it fires is worse than silence: it is\n * persisted into the knowledge artifact, counted by `smrt doctor`, and\n * clearable only by renaming an intent that was correct.\n *\n * There is no build-time source for this today — `ui.prefix` is a runtime\n * `<Provider webmcp={{ ui: { prefix } }}>` prop — so the default leaves this\n * half dormant. That is the honest state of it, and the seam is ready for\n * the caller that can fill it.\n */\n uiToolPrefixes?: readonly string[];\n}\n\n/**\n * Report an emitted intent whose derived WebMCP tool name is already spoken\n * for by something OUTSIDE the declared surface (#2725).\n *\n * `mergeAgentSurfaces` resolves the collisions it can see on its own —\n * intent vs intent, where `intentToolName` is not injective. It cannot see the\n * two sources that live outside the declaration set:\n *\n * - **generated model tools**, `${className.toLowerCase()}_${action}`, so\n * `defineIntent({ id: 'product.list' })` lands exactly on `Product.list`;\n * - **the six fixed UI tools** under a CUSTOM `webmcp.ui.prefix`. The default\n * `smrt_ui_` is already a hard rejection in {@link intentIdentityProblem},\n * mirroring `defineIntent`; a custom prefix is not, because `defineIntent`\n * accepts such an id and the intent really does register.\n *\n * ### These are warnings, not drops — unlike intent vs intent\n *\n * The asymmetry is real and it is the whole reason this is a separate pass.\n * Two colliding intents are a closed question: `defineIntent` REJECTS the\n * second declaration, so only one can exist and emitting both would overstate\n * the surface by an entry that cannot be. Neither collision here is closed:\n *\n * - `defineIntent` accepts the intent, so the declaration is real and the\n * entry belongs in the artifact. Dropping it would make the emitted surface\n * disagree with the source, which is the failure this module exists to\n * prevent;\n * - which registration survives is decided at mount by the document-global\n * tool-name lock (#2613), which rejects the second with a\n * `WebMcpToolNameCollisionError` naming the owner. That is a runtime answer\n * to a question the build can already see coming, and it costs whoever loses\n * its tool; the build-time notice is the earlier, cheaper one;\n * - and whether it happens at all depends on runtime values no artifact\n * records: a WebMCP `namespace` moves every generated tool out of the way,\n * an `effects` policy can exclude the action, and a page need not mount\n * both. A build-time drop would be a guess about all three.\n *\n * So the entry stays and the report is advisory. The message names both sides,\n * the consequence, and — because those runtime values are unknowable here and\n * a `namespace` genuinely dissolves the collision — the precondition under\n * which it holds. Without that last part a namespaced app gets a notice that\n * is always wrong where it fires, recommending the very remedy it already\n * applied, with renaming a correct intent as the only clearing action. That is\n * the standard `uiToolPrefixes` exists to meet; the generated half has to meet\n * it too, and it does so in the message because the caller CAN supply\n * namespaced names when it knows them.\n *\n * @param surface - A MERGED surface; intent-vs-intent losers are already gone.\n * @returns Diagnostics only. The caller appends them; nothing is removed.\n */\nexport function checkAgentSurfaceToolNames(\n surface: AgentSurface,\n options: AgentSurfaceToolNameOptions = {},\n): AgentSurfaceDiagnostic[] {\n const diagnostics: AgentSurfaceDiagnostic[] = [];\n const generated = new Map<string, GeneratedModelToolName>();\n for (const tool of options.generatedToolNames ?? []) {\n if (!generated.has(tool.name)) generated.set(tool.name, tool);\n }\n // A prefix `registerWebMcpUiTools` would refuse mounts no UI tools, so it\n // owns no names. Skipped rather than thrown: an advisory pass must not be\n // the thing that fails a build over a malformed diagnostic input.\n const uiTools = new Map<string, string>();\n for (const prefix of options.uiToolPrefixes ?? [DEFAULT_UI_TOOL_PREFIX]) {\n if (!UI_TOOL_PREFIX_PATTERN.test(prefix)) continue;\n for (const suffix of FIXED_UI_TOOL_SUFFIXES) {\n if (!uiTools.has(`${prefix}${suffix}`)) {\n uiTools.set(`${prefix}${suffix}`, prefix);\n }\n }\n }\n\n for (const intent of surface.intents) {\n const toolName = intentToolName(intent.id);\n\n const collidingTool = generated.get(toolName);\n if (collidingTool) {\n const owner = collidingTool.declaredBy\n ? `\\`${collidingTool.declaredBy}\\``\n : 'a generated model action';\n diagnostics.push({\n code: 'tool-name-collision',\n helper: 'defineIntent',\n message:\n `view intent \\`${intent.id}\\` derives the WebMCP tool name \\`${toolName}\\`, which is ` +\n `also the generated model tool for ${owner}. Both are emitted — \\`defineIntent\\` ` +\n 'accepts the id, so the declaration is real. On a page that mounts both with no ' +\n 'WebMCP `namespace`, the document-global tool-name lock rejects whichever registers ' +\n \"second with a `WebMcpToolNameCollisionError`. A build cannot see the provider's \" +\n '`namespace` or `effects` policy, so if either already separates this pair, disregard ' +\n 'this. Otherwise set a `namespace`, which prefixes the generated tools and leaves ' +\n 'intents alone, or rename the intent.',\n filePath: intent.filePath,\n });\n }\n\n const uiPrefix = uiTools.get(toolName);\n if (uiPrefix !== undefined) {\n diagnostics.push({\n code: 'tool-name-collision',\n helper: 'defineIntent',\n message:\n `view intent \\`${intent.id}\\` derives the WebMCP tool name \\`${toolName}\\`, which is ` +\n `also one of the six fixed UI tools mounted under \\`ui.prefix\\` \\`${uiPrefix}\\`. ` +\n '`defineIntent` accepts the id because it reserves only the default `smrt_ui_` ' +\n 'prefix, so the two reach the document-global tool-name lock and whichever registers ' +\n 'second is rejected with a `WebMcpToolNameCollisionError`. Rename the intent, or give ' +\n 'the fixed UI tools a different `ui.prefix`.',\n filePath: intent.filePath,\n });\n }\n }\n\n // Path, code, message — deliberately WITHOUT the `line`/`column` keys\n // `mergeAgentSurfaces` sorts on. A collision is a property of an emitted\n // ENTRY, and `AgentSurfaceIntent` records only `filePath`; nothing here has a\n // source offset to resolve, so those keys would be provably constant and the\n // reader would be left wondering which caller sets them. What remains is\n // still a total order: the message embeds the intent id, which is unique\n // across the merged surface, so two diagnostics can never tie.\n return diagnostics.sort(\n (a, b) =>\n compareStrings(a.filePath, b.filePath) ||\n compareStrings(a.code, b.code) ||\n compareStrings(a.message, b.message),\n );\n}\n\n/** An empty surface, for callers that skipped the scan. */\nexport function emptyAgentSurface(): AgentSurface {\n return { intents: [], playbooks: [], diagnostics: [] };\n}\n","import { isAbsolute, resolve, sep, win32 } from 'node:path';\nimport fg from 'fast-glob';\n\nconst MANDATORY_DISCOVERY_EXCLUDES: readonly string[] = Object.freeze([\n '**/node_modules/**',\n '**/.*/**',\n '**/.*',\n]);\n\nexport interface SourceDiscoveryOptions {\n cwd: string;\n include: string[];\n exclude: string[];\n followSymbolicLinks?: boolean;\n}\n\n/**\n * Discover authored source files with the bounded policy shared by every\n * scanner entry point, including ManifestBuilder's preflight (#2275).\n */\nexport async function discoverSourceFiles(\n options: SourceDiscoveryOptions,\n): Promise<string[]> {\n const cwd = resolve(options.cwd);\n return fg(\n options.include.map((pattern) => relativeGlobToCwd(pattern, cwd)),\n {\n cwd,\n ignore: [\n ...options.exclude.map((pattern) => relativeGlobToCwd(pattern, cwd)),\n ...MANDATORY_DISCOVERY_EXCLUDES,\n ],\n absolute: true,\n onlyFiles: true,\n dot: true,\n followSymbolicLinks: options.followSymbolicLinks ?? false,\n },\n );\n}\n\n/** Preserve relative glob escapes; normalize separators only after rewriting. */\nexport function relativeGlobToCwd(pattern: string, cwd: string): string {\n const windowsAbsolute = win32.isAbsolute(pattern);\n if (!isAbsolute(pattern) && !windowsAbsolute) return pattern;\n\n const cwdVariants = [\n cwd,\n cwd.replaceAll('\\\\', '/'),\n cwd.replaceAll('/', '\\\\'),\n ];\n for (const prefix of new Set(cwdVariants)) {\n const comparablePattern = windowsAbsolute ? pattern.toLowerCase() : pattern;\n const comparablePrefix = windowsAbsolute ? prefix.toLowerCase() : prefix;\n if (comparablePattern === comparablePrefix) return '.';\n\n const boundary = pattern.charAt(prefix.length);\n if (\n comparablePattern.startsWith(comparablePrefix) &&\n (boundary === '/' || boundary === '\\\\')\n ) {\n const rewritten = pattern.slice(prefix.length + 1);\n // A slash-authored glob can contain meaningful backslash escapes such as\n // `\\\\[id\\\\]`; only native Windows path syntax needs separator rewriting.\n return boundary === '\\\\'\n ? normalizeGlobSeparators(rewritten, '\\\\')\n : rewritten;\n }\n }\n\n // fast-glob requires slash separators even when an absolute pattern points\n // outside cwd and therefore cannot be made relative.\n const slashAuthoredWindows = /^[A-Za-z]:\\//.test(pattern);\n return windowsAbsolute && !slashAuthoredWindows\n ? normalizeGlobSeparators(pattern, '\\\\')\n : pattern;\n}\n\nexport function normalizeGlobSeparators(\n pattern: string,\n pathSeparator = sep,\n): string {\n return pathSeparator === '/'\n ? pattern\n : pattern.replaceAll(pathSeparator, '/');\n}\n","/**\n * Inheritance Resolver\n *\n * Resolves class inheritance chains using in-memory class map.\n * Handles STI (Single Table Inheritance) detection and field merging.\n */\n\nimport type {\n ExternalManifest,\n RawClassDefinition,\n RawFieldDefinition,\n ResolvedClassDefinition,\n} from './types.js';\n\n/**\n * Framework base classes that are always recognized.\n *\n * Hardcoded list — every framework abstract base class that consuming\n * packages can subclass without needing `@smrt()` must appear here, or\n * the scanner will silently drop undecorated subclasses from the manifest.\n *\n * `SmrtJunction`, `SmrtHierarchical`, and `SmrtPolymorphicAssociation` are\n * stopgap entries pending a manifest-driven base-class detection scheme —\n * core would export its abstract bases in its manifest and dependents would\n * resolve through them via the existing cross-package chain walker (see\n * `findClassDefinition`). After tracing the wiring at R3 kickoff\n * (2026-05-18), generalization was deferred: new `SmartObjectManifest →\n * ExternalManifest` adapter, new vite-plugin scan-path failure modes,\n * new sync-I/O surface — large cost for ~two saved lines per future\n * abstract base. R4 added the third base and re-confirmed the call: a new\n * abstract base is still two lines here + two in\n * `FRAMEWORK_ABSTRACT_BASE_NAMES`, far cheaper than the generalization's\n * new failure surface. Extend this list instead.\n */\nconst FRAMEWORK_BASE_CLASSES = new Set([\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n 'SmrtJunction',\n 'SmrtHierarchical',\n 'SmrtPolymorphicAssociation',\n 'SmrtReport',\n 'SmrtReportCollection',\n]);\n\n/**\n * Resolves class inheritance chains and STI hierarchies from raw OXC scan output.\n *\n * After {@link OxcScanner} parses files, `InheritanceResolver` builds a\n * class map from the raw definitions and walks each class's `extends` chain\n * to produce fully-resolved {@link ResolvedClassDefinition} objects.\n *\n * Key responsibilities:\n * - Walking extends chains across local classes and external package manifests.\n * - Detecting which classes participate in STI (Single Table Inheritance).\n * - Merging fields from ancestor classes for STI subclasses (base fields first).\n * - Caching resolved chains to avoid repeated traversals.\n *\n * Framework base classes (`SmrtObject`, `SmrtClass`, `SmrtCollection`) are\n * recognized without needing to appear in source files.\n *\n * @example\n * ```typescript\n * import { InheritanceResolver } from '@happyvertical/smrt-scanner';\n *\n * const resolver = new InheritanceResolver({ baseClasses: ['MyBaseClass'] });\n * resolver.addClasses(rawClasses);\n * const resolved = resolver.resolveAll();\n * ```\n *\n * @see {@link OxcScanner} which owns and drives this resolver internally.\n */\nexport class InheritanceResolver {\n /** Map of className -> RawClassDefinition */\n private classMap: Map<string, RawClassDefinition> = new Map();\n\n /** External package manifests for cross-package resolution */\n private externalManifests: Map<string, ExternalManifest> = new Map();\n\n /** Known base classes (user-provided) */\n private knownBaseClasses: Set<string>;\n\n /** Cache of resolved inheritance chains */\n private chainCache: Map<string, string[]> = new Map();\n\n /**\n * Create a new `InheritanceResolver`.\n *\n * @param options.baseClasses - Additional class names to treat as known\n * framework base classes (beyond the built-in `SmrtObject`, `SmrtClass`,\n * and `SmrtCollection`).\n * @param options.externalManifests - Pre-loaded external package manifests\n * keyed by package name, used for cross-package parent class resolution.\n */\n constructor(\n options: {\n baseClasses?: string[];\n externalManifests?: Map<string, ExternalManifest>;\n } = {},\n ) {\n this.knownBaseClasses = new Set([\n ...FRAMEWORK_BASE_CLASSES,\n ...(options.baseClasses || []),\n ]);\n this.externalManifests = options.externalManifests || new Map();\n }\n\n /**\n * Register raw class definitions from a scan pass.\n *\n * Adds each class to the internal class map by `className`. Calling this\n * clears the inheritance chain cache so subsequent calls to\n * {@link resolveAll} or {@link resolveInheritanceChain} reflect the new\n * classes.\n *\n * @param classes - Array of {@link RawClassDefinition} objects from\n * {@link ScanResults.classes}.\n */\n addClasses(classes: RawClassDefinition[]): void {\n for (const classDef of classes) {\n this.classMap.set(classDef.className, classDef);\n }\n // Clear cache when classes are added\n this.chainCache.clear();\n }\n\n /**\n * Register an external package manifest for cross-package base class resolution.\n *\n * Clears the chain cache after registration so re-resolution picks up the\n * new definitions.\n *\n * @param manifest - External package manifest providing class definitions\n * that may appear as base classes in the local project.\n *\n * @see {@link ExternalManifest}\n */\n addExternalManifest(manifest: ExternalManifest): void {\n this.externalManifests.set(manifest.packageName, manifest);\n this.chainCache.clear();\n }\n\n /**\n * Resolve all registered classes and return fully-resolved definitions.\n *\n * A class is included in the output if it either:\n * 1. Has an `@smrt()` decorator, or\n * 2. Directly or transitively extends a framework base class\n * (`SmrtObject`, `SmrtClass`, `SmrtCollection`) — this captures\n * collection classes such as `class MeetingCollection extends\n * SmrtCollection<Meeting>` that do not carry `@smrt()` themselves.\n *\n * @returns An array of {@link ResolvedClassDefinition} — one entry per\n * eligible class, with inheritance chain, STI metadata, and merged fields\n * populated.\n *\n * @see {@link resolve} to resolve a single class definition.\n */\n resolveAll(): ResolvedClassDefinition[] {\n const resolved: ResolvedClassDefinition[] = [];\n\n for (const classDef of this.classMap.values()) {\n // Include classes with @smrt() decorator\n // OR classes that extend framework base classes\n const extendsFrameworkBase = this.extendsFrameworkBase(classDef);\n if (!classDef.hasSmartDecorator && !extendsFrameworkBase) continue;\n\n const resolvedClass = this.resolve(classDef);\n resolved.push(resolvedClass);\n }\n\n return resolved;\n }\n\n /**\n * Check if a class extends a framework base class\n * (SmrtObject, SmrtClass, or SmrtCollection)\n */\n private extendsFrameworkBase(classDef: RawClassDefinition): boolean {\n // Direct extension of framework base\n if (\n classDef.extendsClause &&\n this.knownBaseClasses.has(classDef.extendsClause)\n ) {\n return true;\n }\n\n // Walk inheritance chain to check indirect extension\n const chain = this.resolveInheritanceChain(classDef.className);\n return chain.some((className) => this.knownBaseClasses.has(className));\n }\n\n /**\n * Resolve a single raw class definition into a fully-resolved definition.\n *\n * Computes the inheritance chain, determines the effective table strategy,\n * detects STI membership, and merges ancestor fields for STI classes.\n *\n * @param classDef - The raw class definition to resolve.\n * @returns A {@link ResolvedClassDefinition} with all inherited metadata\n * applied. The `packageName` field is left as `null` and must be set by\n * the caller (e.g. {@link ManifestAdapter}).\n *\n * @see {@link resolveAll} to resolve every registered class at once.\n */\n resolve(classDef: RawClassDefinition): ResolvedClassDefinition {\n const inheritanceChain = this.resolveInheritanceChain(classDef.className);\n const stiBase = this.findSTIBase(inheritanceChain);\n const effectiveTableStrategy = this.determineTableStrategy(\n classDef,\n inheritanceChain,\n );\n const isFrameworkBase = this.knownBaseClasses.has(classDef.className);\n const isSTI = effectiveTableStrategy === 'sti';\n\n // Merge fields for STI classes. For non-STI classes, the\n // ManifestGenerator in core selectively merges fields from framework\n // abstract bases (e.g. `SmrtHierarchical.parentId`) — see\n // `FRAMEWORK_ABSTRACT_BASE_NAMES` in\n // `packages/core/src/scanner/manifest-generator.ts`. Doing that merge\n // here too would compound with subtly different field shapes and\n // regress universal-baseline expectations in `fieldsFromClass`.\n const allFields = isSTI\n ? this.mergeFieldsForSTI(inheritanceChain)\n : classDef.fields;\n\n return {\n ...classDef,\n inheritanceChain,\n stiBase,\n effectiveTableStrategy,\n isSTI,\n isFrameworkBase,\n allFields,\n packageName: null, // Will be set by manifest adapter\n };\n }\n\n /**\n * Resolve the full inheritance chain for a named class, from the root base\n * class down to the named class itself.\n *\n * Results are memoised in an internal cache that is cleared whenever\n * {@link addClasses} or {@link addExternalManifest} is called.\n *\n * @param className - Name of the class to resolve.\n * @returns An ordered array of class names starting from the furthest\n * ancestor and ending with `className`.\n *\n * @example\n * ```typescript\n * // Given: class Article extends Content, class Content extends SmrtObject\n * resolver.resolveInheritanceChain('Article');\n * // => ['SmrtObject', 'Content', 'Article']\n * ```\n */\n resolveInheritanceChain(className: string): string[] {\n // Check cache\n const cached = this.chainCache.get(className);\n if (cached) return cached;\n\n const chain: string[] = [];\n const visited = new Set<string>();\n let current: string | null = className;\n\n while (current && !visited.has(current)) {\n visited.add(current);\n chain.unshift(current);\n\n // Check if this is a framework base class\n if (this.knownBaseClasses.has(current)) {\n break;\n }\n\n // Find parent class\n const classDef = this.findClassDefinition(current);\n current = classDef?.extendsClause || null;\n }\n\n // Cache result\n this.chainCache.set(className, chain);\n\n return chain;\n }\n\n /**\n * Look up a class definition by name, searching in priority order:\n * 1. Local classes added via {@link addClasses}.\n * 2. External package manifests added via {@link addExternalManifest}.\n * 3. Built-in framework base classes (`SmrtObject`, `SmrtClass`,\n * `SmrtCollection`) — returns a minimal stub definition so chain walking\n * can terminate cleanly.\n *\n * @param className - Class name to look up.\n * @returns The {@link RawClassDefinition} if found, or `null` if the class\n * is unknown to the resolver.\n */\n findClassDefinition(className: string): RawClassDefinition | null {\n // 1. Check local classes\n const local = this.classMap.get(className);\n if (local) return local;\n\n // 2. Check external manifests\n for (const manifest of this.externalManifests.values()) {\n const external = manifest.classes.get(className);\n if (external) return external;\n }\n\n // 3. Check if it's a known base class\n if (this.knownBaseClasses.has(className)) {\n // Return a minimal definition for framework bases\n return {\n className,\n filePath: '',\n extendsClause: null,\n extendsTypeArg: null,\n decoratorConfig: null,\n hasSmartDecorator: false,\n fields: [],\n methods: [],\n startLine: 0,\n endLine: 0,\n };\n }\n\n return null;\n }\n\n /**\n * Find the STI root class in a resolved inheritance chain.\n *\n * Walks the chain from base to leaf and returns the name of the first class\n * whose `@smrt()` decorator explicitly declares `tableStrategy: 'sti'`.\n *\n * @param chain - Ordered inheritance chain (base → leaf) as returned by\n * {@link resolveInheritanceChain}.\n * @returns The class name of the STI root, or `null` if no class in the\n * chain uses `tableStrategy: 'sti'`.\n */\n findSTIBase(chain: string[]): string | null {\n for (const className of chain) {\n const classDef = this.findClassDefinition(className);\n if (classDef?.decoratorConfig?.tableStrategy === 'sti') {\n return className;\n }\n }\n return null;\n }\n\n /**\n * Determine the effective table strategy (`'sti'` or `'cti'`) for a class.\n *\n * Resolution order:\n * 1. The class's own `@smrt({ tableStrategy })` declaration, if present.\n * 2. The nearest ancestor that declares `tableStrategy: 'sti'` — STI is\n * inherited automatically by all subclasses.\n * 3. Defaults to `'cti'` if no STI ancestor is found.\n *\n * @param classDef - Raw class definition whose strategy is being determined.\n * @param chain - Pre-resolved inheritance chain for `classDef` (base → leaf).\n * @returns `'sti'` or `'cti'`.\n */\n determineTableStrategy(\n classDef: RawClassDefinition,\n chain: string[],\n ): 'sti' | 'cti' {\n // Check if this class explicitly declares a strategy\n if (classDef.decoratorConfig?.tableStrategy) {\n return classDef.decoratorConfig.tableStrategy;\n }\n\n // Check ancestors for STI\n for (const className of chain) {\n if (className === classDef.className) continue;\n\n const ancestorDef = this.findClassDefinition(className);\n if (ancestorDef?.decoratorConfig?.tableStrategy === 'sti') {\n return 'sti';\n }\n }\n\n return 'cti';\n }\n\n /**\n * Merge fields from all classes in an STI inheritance chain.\n *\n * Iterates from the root base class to the leaf class so that base class\n * fields appear first in the returned array. If a field name is declared in\n * both an ancestor and a descendant, the ancestor's definition takes\n * precedence (first-seen wins), preserving the base-class column layout.\n *\n * @param chain - Ordered inheritance chain (base → leaf) as returned by\n * {@link resolveInheritanceChain}.\n * @returns A deduplicated, ordered array of {@link RawFieldDefinition}\n * covering every field in the STI hierarchy.\n */\n mergeFieldsForSTI(chain: string[]): RawFieldDefinition[] {\n const allFields: RawFieldDefinition[] = [];\n const seenNames = new Set<string>();\n\n for (const className of chain) {\n const classDef = this.findClassDefinition(className);\n if (!classDef) continue;\n\n for (const field of classDef.fields) {\n // Skip if already seen (child overrides parent)\n if (seenNames.has(field.name)) continue;\n\n seenNames.add(field.name);\n allFields.push(field);\n }\n }\n\n return allFields;\n }\n\n /**\n * Return all known descendants of a class.\n *\n * Useful for STI schema generation where the base table must accommodate\n * columns from every subclass.\n *\n * @param className - The ancestor class name to search from.\n * @returns An array of class names (local classes only) whose resolved\n * inheritance chain includes `className`. Does not include `className`\n * itself.\n */\n getDescendants(className: string): string[] {\n const descendants: string[] = [];\n\n for (const [name] of this.classMap) {\n if (name === className) continue;\n\n const chain = this.resolveInheritanceChain(name);\n if (chain.includes(className)) {\n descendants.push(name);\n }\n }\n\n return descendants;\n }\n\n /**\n * Check whether a class participates in an STI hierarchy.\n *\n * @param className - Name of the class to check.\n * @returns `true` if any class in the resolved inheritance chain declares\n * `tableStrategy: 'sti'`, `false` otherwise.\n */\n isSTIClass(className: string): boolean {\n const chain = this.resolveInheritanceChain(className);\n return this.findSTIBase(chain) !== null;\n }\n\n /**\n * Return aggregate statistics about the classes registered with this resolver.\n *\n * @returns An object with:\n * - `totalClasses` — total number of classes in the class map.\n * - `smrtClasses` — classes that carry `@smrt()`.\n * - `stiClasses` — `@smrt()` classes in an STI hierarchy.\n * - `maxInheritanceDepth` — length of the deepest inheritance chain among\n * `@smrt()` classes.\n */\n getStats(): {\n totalClasses: number;\n smrtClasses: number;\n stiClasses: number;\n maxInheritanceDepth: number;\n } {\n let smrtClasses = 0;\n let stiClasses = 0;\n let maxInheritanceDepth = 0;\n\n for (const classDef of this.classMap.values()) {\n if (classDef.hasSmartDecorator) {\n smrtClasses++;\n\n const chain = this.resolveInheritanceChain(classDef.className);\n maxInheritanceDepth = Math.max(maxInheritanceDepth, chain.length);\n\n if (this.findSTIBase(chain)) {\n stiClasses++;\n }\n }\n }\n\n return {\n totalClasses: this.classMap.size,\n smrtClasses,\n stiClasses,\n maxInheritanceDepth,\n };\n }\n}\n","/**\n * OXC-based TypeScript parser for SMRT class extraction\n *\n * Uses oxc-parser for high-performance syntactic parsing of TypeScript files.\n * Extracts @smrt() decorated classes with their fields, methods, and inheritance.\n *\n * @see https://oxc.rs/docs/guide/usage/parser.html\n */\n\nimport { readFileSync } from 'node:fs';\nimport { parseSync } from 'oxc-parser';\nimport {\n extractAgentSurface,\n sourceMayDeclareAgentSurface,\n} from './agent-surface.js';\nimport { getLineColumn } from './source-location.js';\nimport type {\n AgentSurface,\n FileScanResult,\n RawClassDefinition,\n RawDecorator,\n RawDecoratorConfig,\n RawFieldDefinition,\n RawMethodDefinition,\n RawParameterDefinition,\n ScanError,\n} from './types.js';\n\n/**\n * Get file extension for oxc-parser lang option\n */\nfunction getLangFromFilename(filename: string): 'ts' | 'tsx' | 'js' | 'jsx' {\n if (filename.endsWith('.tsx')) return 'tsx';\n if (filename.endsWith('.ts')) return 'ts';\n if (filename.endsWith('.jsx')) return 'jsx';\n return 'js';\n}\n\nexport { getLineColumn };\n\n// ============================================================================\n// AST Node Types (TS-ESTree format from oxc-parser)\n// ============================================================================\n\ninterface Position {\n line: number;\n column: number;\n}\n\ninterface SourceLocation {\n start: Position;\n end: Position;\n}\n\ninterface BaseNode {\n type: string;\n loc?: SourceLocation;\n range?: [number, number];\n start?: number;\n end?: number;\n}\n\n/**\n * Get source range from an AST node.\n * oxc-parser v0.108+ uses start/end instead of range.\n */\nfunction getRange(node: BaseNode): [number, number] | null {\n if (node.range) return node.range;\n if (node.start !== undefined && node.end !== undefined)\n return [node.start, node.end];\n return null;\n}\n\n/**\n * Slice source text from an AST node's range.\n */\nfunction sliceSource(node: BaseNode, sourceText: string): string | null {\n const range = getRange(node);\n return range ? sourceText.slice(range[0], range[1]) : null;\n}\n\ninterface Program extends BaseNode {\n type: 'Program';\n body: Statement[];\n comments?: Comment[];\n}\n\ninterface Comment extends BaseNode {\n type: 'Line' | 'Block';\n value: string;\n}\n\ninterface ImportDeclaration extends BaseNode {\n type: 'ImportDeclaration';\n specifiers?: ImportSpecifierLike[];\n source: Literal;\n}\n\ntype ImportSpecifierLike =\n | ImportSpecifier\n | ImportNamespaceSpecifier\n | ImportDefaultSpecifier;\n\ninterface ImportSpecifier extends BaseNode {\n type: 'ImportSpecifier';\n imported: Identifier;\n local: Identifier;\n}\n\ninterface ImportNamespaceSpecifier extends BaseNode {\n type: 'ImportNamespaceSpecifier';\n local: Identifier;\n}\n\ninterface ImportDefaultSpecifier extends BaseNode {\n type: 'ImportDefaultSpecifier';\n local: Identifier;\n}\n\ntype Statement =\n | ClassDeclaration\n | ExportNamedDeclaration\n | ExportDefaultDeclaration\n | ImportDeclaration\n | TSTypeAliasDeclaration\n | TSEnumDeclaration\n | VariableDeclaration;\n\ninterface VariableDeclaration extends BaseNode {\n type: 'VariableDeclaration';\n kind: 'const' | 'let' | 'var';\n declarations: VariableDeclarator[];\n}\n\ninterface VariableDeclarator extends BaseNode {\n type: 'VariableDeclarator';\n id: Identifier | Pattern;\n init: Expression | null;\n}\n\n/**\n * `expr as const` / `expr satisfies T`. OXC emits these wrappers around the\n * initializer, so a `const CFG = {...} as const` would otherwise never be seen\n * as an `ObjectExpression`. Not part of the {@link Expression} union — the\n * union is a hand-maintained subset — so it is unwrapped via {@link unwrapTypeAssertion}.\n */\ninterface TSTypeAssertionExpression extends BaseNode {\n type:\n | 'TSAsExpression'\n | 'TSSatisfiesExpression'\n | 'TSNonNullExpression'\n | 'TSTypeAssertion'\n | 'ParenthesizedExpression';\n expression: Expression;\n}\n\ninterface ClassDeclaration extends BaseNode {\n type: 'ClassDeclaration';\n id: Identifier | null;\n superClass: Expression | null;\n superTypeParameters?: TSTypeParameterInstantiation;\n // oxc-parser v0.108+ renamed superTypeParameters to superTypeArguments\n superTypeArguments?: TSTypeParameterInstantiation;\n body: ClassBody;\n decorators?: Decorator[];\n}\n\ninterface TSTypeAliasDeclaration extends BaseNode {\n type: 'TSTypeAliasDeclaration';\n id: Identifier;\n typeAnnotation: TSType;\n}\n\ninterface TSEnumDeclaration extends BaseNode {\n type: 'TSEnumDeclaration';\n id: Identifier;\n // oxc-parser wraps members in a TSEnumBody node; older shapes expose\n // `members` directly on the declaration.\n body?: TSEnumBody;\n members?: TSEnumMember[];\n}\n\ninterface TSEnumBody extends BaseNode {\n type: 'TSEnumBody';\n members: TSEnumMember[];\n}\n\ninterface TSEnumMember extends BaseNode {\n type: 'TSEnumMember';\n initializer?: Expression;\n}\n\ninterface ClassBody extends BaseNode {\n type: 'ClassBody';\n body: ClassElement[];\n}\n\ntype ClassElement = PropertyDefinition | MethodDefinition;\n\ninterface PropertyDefinition extends BaseNode {\n type: 'PropertyDefinition';\n key: Expression;\n value: Expression | null;\n computed: boolean;\n static: boolean;\n readonly?: boolean;\n optional?: boolean;\n accessibility?: 'public' | 'private' | 'protected';\n typeAnnotation?: TSTypeAnnotation;\n decorators?: Decorator[];\n}\n\ninterface MethodDefinition extends BaseNode {\n type: 'MethodDefinition';\n key: Expression;\n value: FunctionExpression;\n kind: 'constructor' | 'method' | 'get' | 'set';\n computed: boolean;\n static: boolean;\n accessibility?: 'public' | 'private' | 'protected';\n decorators?: Decorator[];\n}\n\ninterface FunctionExpression extends BaseNode {\n type: 'FunctionExpression';\n async: boolean;\n params: Pattern[];\n returnType?: TSTypeAnnotation;\n body: BlockStatement;\n}\n\ninterface BlockStatement extends BaseNode {\n type: 'BlockStatement';\n body: Statement[];\n}\n\ntype Pattern =\n | Identifier\n | AssignmentPattern\n | RestElement\n | ObjectPattern\n | ArrayPattern;\n\ninterface Identifier extends BaseNode {\n type: 'Identifier';\n name: string;\n typeAnnotation?: TSTypeAnnotation;\n optional?: boolean;\n}\n\ninterface AssignmentPattern extends BaseNode {\n type: 'AssignmentPattern';\n left: Pattern;\n right: Expression;\n}\n\ninterface RestElement extends BaseNode {\n type: 'RestElement';\n argument: Pattern;\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface ObjectPattern extends BaseNode {\n type: 'ObjectPattern';\n properties: (Property | RestElement)[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface ArrayPattern extends BaseNode {\n type: 'ArrayPattern';\n elements: (Pattern | null)[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface Property extends BaseNode {\n type: 'Property';\n key: Expression;\n value: Expression | Pattern;\n kind: 'init' | 'get' | 'set';\n method: boolean;\n shorthand: boolean;\n computed: boolean;\n}\n\ntype Expression =\n | Identifier\n | Literal\n | CallExpression\n | MemberExpression\n | ObjectExpression\n | ArrayExpression\n | NewExpression\n | UnaryExpression;\n\ninterface Literal extends BaseNode {\n type: 'Literal';\n value: string | number | boolean | null | RegExp | bigint;\n raw?: string;\n}\n\ninterface UnaryExpression extends BaseNode {\n type: 'UnaryExpression';\n operator: string;\n argument: Expression;\n}\n\ninterface CallExpression extends BaseNode {\n type: 'CallExpression';\n callee: Expression;\n arguments: Expression[];\n typeParameters?: TSTypeParameterInstantiation;\n}\n\ninterface MemberExpression extends BaseNode {\n type: 'MemberExpression';\n object: Expression;\n property: Expression;\n computed: boolean;\n}\n\ninterface ObjectExpression extends BaseNode {\n type: 'ObjectExpression';\n properties: (Property | SpreadElement)[];\n}\n\ninterface SpreadElement extends BaseNode {\n type: 'SpreadElement';\n argument: Expression;\n}\n\ninterface ArrayExpression extends BaseNode {\n type: 'ArrayExpression';\n elements: (Expression | SpreadElement | null)[];\n}\n\ninterface NewExpression extends BaseNode {\n type: 'NewExpression';\n callee: Expression;\n arguments: Expression[];\n}\n\ninterface Decorator extends BaseNode {\n type: 'Decorator';\n expression: Expression;\n}\n\ninterface ExportNamedDeclaration extends BaseNode {\n type: 'ExportNamedDeclaration';\n declaration: Statement | null;\n specifiers: ExportSpecifier[];\n}\n\ninterface ExportDefaultDeclaration extends BaseNode {\n type: 'ExportDefaultDeclaration';\n declaration: Statement | Expression;\n}\n\ninterface ExportSpecifier extends BaseNode {\n type: 'ExportSpecifier';\n local: Identifier;\n exported: Identifier;\n}\n\ninterface TSTypeAnnotation extends BaseNode {\n type: 'TSTypeAnnotation';\n typeAnnotation: TSType;\n}\n\ntype TSType =\n | TSStringKeyword\n | TSNumberKeyword\n | TSBooleanKeyword\n | TSAnyKeyword\n | TSUnknownKeyword\n | TSNeverKeyword\n | TSObjectKeyword\n | TSBigIntKeyword\n | TSSymbolKeyword\n | TSVoidKeyword\n | TSNullKeyword\n | TSUndefinedKeyword\n | TSThisType\n | TSTypeReference\n | TSArrayType\n | TSUnionType\n | TSTypeLiteral\n | TSLiteralType\n | TSFunctionType;\n\ninterface TSLiteralType extends BaseNode {\n type: 'TSLiteralType';\n // oxc-parser models the literal as a generic `Literal` node.\n literal?: Literal;\n}\n\ninterface TSFunctionType extends BaseNode {\n type: 'TSFunctionType';\n}\n\ninterface TSStringKeyword extends BaseNode {\n type: 'TSStringKeyword';\n}\n\ninterface TSNumberKeyword extends BaseNode {\n type: 'TSNumberKeyword';\n}\n\ninterface TSBooleanKeyword extends BaseNode {\n type: 'TSBooleanKeyword';\n}\n\ninterface TSAnyKeyword extends BaseNode {\n type: 'TSAnyKeyword';\n}\n\ninterface TSUnknownKeyword extends BaseNode {\n type: 'TSUnknownKeyword';\n}\n\ninterface TSNeverKeyword extends BaseNode {\n type: 'TSNeverKeyword';\n}\n\ninterface TSObjectKeyword extends BaseNode {\n type: 'TSObjectKeyword';\n}\n\ninterface TSBigIntKeyword extends BaseNode {\n type: 'TSBigIntKeyword';\n}\n\ninterface TSSymbolKeyword extends BaseNode {\n type: 'TSSymbolKeyword';\n}\n\ninterface TSVoidKeyword extends BaseNode {\n type: 'TSVoidKeyword';\n}\n\ninterface TSNullKeyword extends BaseNode {\n type: 'TSNullKeyword';\n}\n\ninterface TSUndefinedKeyword extends BaseNode {\n type: 'TSUndefinedKeyword';\n}\n\ninterface TSThisType extends BaseNode {\n type: 'TSThisType';\n}\n\ninterface TSTypeReference extends BaseNode {\n type: 'TSTypeReference';\n typeName: Identifier | TSQualifiedName;\n typeParameters?: TSTypeParameterInstantiation;\n // oxc-parser v0.108+ renamed typeParameters to typeArguments\n typeArguments?: TSTypeParameterInstantiation;\n}\n\ninterface TSQualifiedName extends BaseNode {\n type: 'TSQualifiedName';\n left: Identifier | TSQualifiedName;\n right: Identifier;\n}\n\ninterface TSArrayType extends BaseNode {\n type: 'TSArrayType';\n elementType: TSType;\n}\n\ninterface TSUnionType extends BaseNode {\n type: 'TSUnionType';\n types: TSType[];\n}\n\ninterface TSTypeLiteral extends BaseNode {\n type: 'TSTypeLiteral';\n members: TSTypeElement[];\n}\n\ntype TSTypeElement = TSPropertySignature | TSMethodSignature | TSIndexSignature;\n\ninterface TSPropertySignature extends BaseNode {\n type: 'TSPropertySignature';\n key: Expression;\n typeAnnotation?: TSTypeAnnotation;\n optional?: boolean;\n readonly?: boolean;\n}\n\ninterface TSMethodSignature extends BaseNode {\n type: 'TSMethodSignature';\n key: Expression;\n params: Pattern[];\n returnType?: TSTypeAnnotation;\n}\n\ninterface TSIndexSignature extends BaseNode {\n type: 'TSIndexSignature';\n parameters: Identifier[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface TSTypeParameterInstantiation extends BaseNode {\n type: 'TSTypeParameterInstantiation';\n params: TSType[];\n}\n\n// ============================================================================\n// Parser Implementation\n// ============================================================================\n\n/**\n * Parse a single TypeScript file and extract SMRT class definitions.\n *\n * Reads the file from disk, runs oxc-parser on it, and returns all class\n * definitions found, any parse errors, accumulated type aliases, and\n * `@happyvertical/smrt-*` import metadata.\n *\n * @param filePath - Absolute path to the `.ts` or `.tsx` file to parse.\n * @returns A {@link FileScanResult} containing classes, errors, type aliases,\n * SMRT imports, and timing information for the file.\n *\n * @example\n * ```typescript\n * import { parseFile } from '@happyvertical/smrt-scanner';\n *\n * const result = parseFile('/project/src/models/Product.ts');\n * console.log(result.classes.map((c) => c.className));\n * // ['Product', 'ProductCollection']\n * ```\n *\n * @see {@link parseSource} to parse a source string directly (e.g. in tests).\n */\nexport function parseFile(filePath: string): FileScanResult {\n const startTime = performance.now();\n const errors: ScanError[] = [];\n const classes: RawClassDefinition[] = [];\n let typeAliases: Record<string, string> = {};\n let smrtImports: Map<string, Set<string>> | undefined;\n let agentSurface: AgentSurface | undefined;\n\n try {\n const sourceText = readFileSync(filePath, 'utf-8');\n const result = parseSync(filePath, sourceText, {\n lang: getLangFromFilename(filePath),\n preserveParens: false,\n });\n\n // Collect parse errors\n if (result.errors && result.errors.length > 0) {\n for (const error of result.errors) {\n const loc = error.labels?.[0]\n ? getLineColumn(sourceText, error.labels[0].start)\n : undefined;\n errors.push({\n message: error.message || 'Parse error',\n filePath,\n line: loc?.line,\n column: loc?.column,\n severity: error.severity === 'Error' ? 'error' : 'warning',\n });\n }\n }\n\n // Extract classes from AST\n const program = result.program as Program;\n if (program?.body) {\n const importAliases = extractImportAliases(program.body);\n typeAliases = extractTypeAliases(program.body);\n smrtImports = extractSmrtImports(program.body);\n const ctx: DecoratorConfigContext = {\n constants: extractModuleObjectConstants(program.body, sourceText),\n unresolved: [],\n importAliases,\n };\n for (const node of program.body) {\n const extracted = extractClassFromNode(\n node,\n filePath,\n sourceText,\n importAliases,\n ctx,\n );\n if (extracted) {\n classes.push(extracted);\n }\n }\n reportUnresolvedSpreads(ctx.unresolved, filePath, sourceText, errors);\n agentSurface = maybeExtractAgentSurface(program, sourceText, filePath);\n }\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n filePath,\n severity: 'error',\n });\n }\n\n const result2: FileScanResult = {\n filePath,\n classes,\n errors,\n parseTimeMs: performance.now() - startTime,\n typeAliases,\n };\n if (smrtImports && smrtImports.size > 0) {\n result2.smrtImports = smrtImports;\n }\n if (agentSurface) {\n result2.agentSurface = agentSurface;\n }\n return result2;\n}\n\n/**\n * Run the agent-surface matcher when — and only when — the source names one of\n * its helpers, and return the surface only when it found something.\n *\n * The token pre-check keeps a full AST walk off the hot path of a large scan;\n * dropping an empty result keeps `FileScanResult.agentSurface` absent for the\n * overwhelming majority of files that declare nothing.\n */\nfunction maybeExtractAgentSurface(\n program: Program,\n sourceText: string,\n filePath: string,\n): AgentSurface | undefined {\n if (!sourceMayDeclareAgentSurface(sourceText)) return undefined;\n const surface = extractAgentSurface({\n body: program.body,\n sourceText,\n filePath,\n });\n return surface.intents.length > 0 ||\n surface.playbooks.length > 0 ||\n surface.diagnostics.length > 0\n ? surface\n : undefined;\n}\n\n/**\n * Read one file for agent-surface declarations ONLY (#2591).\n *\n * Exists because the agent surface must not be confined to the class scan's\n * `include` glob: an application that scans `src/lib/objects/**` for its models\n * — the shipped template does exactly that — would otherwise never see a\n * `src/lib/agent/Foo.intents.ts` sidecar, and the declaration would vanish from\n * every artifact with no diagnostic. Silent omission is the one failure this\n * matcher exists to prevent, so declarations are discovered on their own terms.\n *\n * The token pre-filter runs before the parse, so a file that declares nothing\n * costs one read and one `String.includes`.\n *\n * @returns The file's surface, or `undefined` when it declares nothing or\n * cannot be read.\n */\nexport function parseAgentSurfaceFile(\n filePath: string,\n): AgentSurface | undefined {\n let sourceText: string;\n try {\n sourceText = readFileSync(filePath, 'utf-8');\n } catch {\n return undefined;\n }\n if (!sourceMayDeclareAgentSurface(sourceText)) return undefined;\n\n try {\n const result = parseSync(filePath, sourceText, {\n lang: getLangFromFilename(filePath),\n preserveParens: false,\n });\n const program = result.program as Program;\n if (!program?.body) return undefined;\n return maybeExtractAgentSurface(program, sourceText, filePath);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Parse TypeScript source text directly and extract SMRT class definitions.\n *\n * Identical to {@link parseFile} but accepts a source string instead of a\n * file path. Primarily used in tests and tooling that constructs source\n * programmatically.\n *\n * @param sourceText - Raw TypeScript source code to parse.\n * @param filename - Virtual filename used to determine the parser language\n * mode (`.ts`, `.tsx`, `.js`, `.jsx`) and to populate `filePath` fields in\n * the result. Defaults to `'test.ts'`.\n * @returns A {@link FileScanResult} containing classes, errors, type aliases,\n * and SMRT import metadata extracted from the source text.\n *\n * @example\n * ```typescript\n * import { parseSource } from '@happyvertical/smrt-scanner';\n *\n * const src = `\n * import { smrt } from '@happyvertical/smrt-core';\n * @smrt()\n * export class Widget extends SmrtObject {\n * label: string = '';\n * }\n * `;\n * const result = parseSource(src, 'Widget.ts');\n * console.log(result.classes[0].className); // 'Widget'\n * ```\n *\n * @see {@link parseFile} to parse a file from disk.\n */\nexport function parseSource(\n sourceText: string,\n filename = 'test.ts',\n): FileScanResult {\n const startTime = performance.now();\n const errors: ScanError[] = [];\n const classes: RawClassDefinition[] = [];\n let typeAliases: Record<string, string> = {};\n let smrtImports: Map<string, Set<string>> | undefined;\n let agentSurface: AgentSurface | undefined;\n\n try {\n const result = parseSync(filename, sourceText, {\n lang: getLangFromFilename(filename),\n preserveParens: false,\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const error of result.errors) {\n const loc = error.labels?.[0]\n ? getLineColumn(sourceText, error.labels[0].start)\n : undefined;\n errors.push({\n message: error.message || 'Parse error',\n filePath: filename,\n line: loc?.line,\n column: loc?.column,\n severity: error.severity === 'Error' ? 'error' : 'warning',\n });\n }\n }\n\n const program = result.program as Program;\n if (program?.body) {\n const importAliases = extractImportAliases(program.body);\n typeAliases = extractTypeAliases(program.body);\n smrtImports = extractSmrtImports(program.body);\n const ctx: DecoratorConfigContext = {\n constants: extractModuleObjectConstants(program.body, sourceText),\n unresolved: [],\n importAliases,\n };\n for (const node of program.body) {\n const extracted = extractClassFromNode(\n node,\n filename,\n sourceText,\n importAliases,\n ctx,\n );\n if (extracted) {\n classes.push(extracted);\n }\n }\n reportUnresolvedSpreads(ctx.unresolved, filename, sourceText, errors);\n agentSurface = maybeExtractAgentSurface(program, sourceText, filename);\n }\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n filePath: filename,\n severity: 'error',\n });\n }\n\n const result2: FileScanResult = {\n filePath: filename,\n classes,\n errors,\n parseTimeMs: performance.now() - startTime,\n typeAliases,\n };\n if (smrtImports && smrtImports.size > 0) {\n result2.smrtImports = smrtImports;\n }\n if (agentSurface) {\n result2.agentSurface = agentSurface;\n }\n return result2;\n}\n\n// ============================================================================\n// AST Extraction Helpers\n// ============================================================================\n\n/**\n * Property keys that must never be assigned onto a plain object built from\n * parsed source. Assigning `obj['__proto__'] = value` mutates the object's\n * prototype rather than adding an own property, which is a prototype-pollution\n * vector. `constructor` / `prototype` are blocked for defense-in-depth.\n *\n * Scanner input is developer-authored source consumed at build time (trusted),\n * so this is a hardening guard, not a fix for a remotely reachable bug: a class\n * field, decorator-config property, or type alias literally named `__proto__`\n * would otherwise silently corrupt the metadata object it is collected into.\n */\nconst FORBIDDEN_OBJECT_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n]);\n\n/**\n * Whether a key is safe to assign as an own property on a plain object built\n * from parsed AST. See {@link FORBIDDEN_OBJECT_KEYS}.\n *\n * @internal Exported for testing.\n */\nexport function isSafeObjectKey(key: string): boolean {\n return !FORBIDDEN_OBJECT_KEYS.has(key);\n}\n\n/**\n * Extract import aliases from program body.\n * Maps local alias names to their original imported names.\n * e.g., `import { Performer as PerformerBase }` → Map { \"PerformerBase\" → \"Performer\" }\n */\nfunction extractImportAliases(body: Statement[]): Map<string, string> {\n const aliases = new Map<string, string>();\n for (const node of body) {\n if (node.type === 'ImportDeclaration' && node.specifiers) {\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportSpecifier' && spec.imported && spec.local) {\n const original = spec.imported.name;\n const local = spec.local.name;\n if (original !== local) {\n aliases.set(local, original);\n }\n }\n }\n }\n }\n return aliases;\n}\n\n/**\n * Extract `@happyvertical/smrt-*` import declarations from an OXC program body.\n *\n * Scans the top-level AST statements for `ImportDeclaration` nodes whose\n * module specifier begins with `@happyvertical/smrt-` and collects the\n * PascalCase identifiers being imported. The result is used for tree-shaking:\n * only externally imported SMRT classes that appear in project source are\n * included in the generated manifest.\n *\n * Handles all import forms:\n * - Side-effect imports — `import '@happyvertical/smrt-messages'` (recorded as `'*'`)\n * - Named imports — `import { Person, Organization } from '@happyvertical/smrt-profiles'`\n * - Renamed named imports — `import { Person as PersonBase } from '...'` (records original name `Person`)\n * - Namespace imports — `import * as Profiles from '@happyvertical/smrt-profiles'` (recorded as `'*'`)\n * - Default imports — `import SomeClass from '@happyvertical/smrt-profiles'`\n *\n * Only PascalCase identifiers are recorded; utility function names (lowercase)\n * are ignored.\n *\n * @param body - The top-level statement array from the OXC-parsed `Program` node.\n * @returns A `Map` keyed by package name (e.g. `'@happyvertical/smrt-profiles'`)\n * whose values are `Set`s of the imported PascalCase class names (or `'*'`\n * for namespace imports).\n *\n * @example\n * ```typescript\n * import { parseSource, extractSmrtImports } from '@happyvertical/smrt-scanner';\n * import { parseSync } from 'oxc-parser';\n *\n * const src = `import { Person, Organization } from '@happyvertical/smrt-profiles';`;\n * const { program } = parseSync('file.ts', src, { lang: 'ts' });\n * const imports = extractSmrtImports(program.body);\n * // Map { '@happyvertical/smrt-profiles' => Set { 'Person', 'Organization' } }\n * ```\n *\n * @internal Exported for testing; use {@link OxcScanner.scanSmrtImports} for\n * production use cases.\n */\nexport function extractSmrtImports(\n body: Statement[],\n): Map<string, Set<string>> {\n const imports = new Map<string, Set<string>>();\n\n for (const node of body) {\n if (node.type !== 'ImportDeclaration') continue;\n\n // Get module specifier string\n const source = node.source;\n if (!source || typeof source.value !== 'string') continue;\n\n const moduleName = source.value;\n\n // Only process @happyvertical/smrt-* packages\n if (!moduleName.startsWith('@happyvertical/smrt-')) continue;\n\n // Get or create the set for this package\n let classSet = imports.get(moduleName);\n if (!classSet) {\n classSet = new Set();\n imports.set(moduleName, classSet);\n }\n\n if (!node.specifiers || node.specifiers.length === 0) {\n classSet.add('*');\n continue;\n }\n\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportSpecifier' && spec.imported && spec.local) {\n // Named import: use original (imported) name, not local alias\n const importedName = spec.imported.name;\n // Only include PascalCase names (likely classes)\n if (/^[A-Z][A-Za-z0-9]*$/.test(importedName)) {\n classSet.add(importedName);\n }\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n // Namespace import: import * as X from '...'\n classSet.add('*');\n } else if (spec.type === 'ImportDefaultSpecifier' && spec.local) {\n // Default import: import SomeClass from '...'\n const defaultName = spec.local.name;\n if (/^[A-Z][A-Za-z0-9]*$/.test(defaultName)) {\n classSet.add(defaultName);\n }\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Extract type alias declarations from program body.\n * Maps alias names to their resolved type strings.\n * e.g., `type Status = 'active' | 'inactive'` → { Status: \"'active' | 'inactive'\" }\n * @internal Exported for testing\n */\nexport function extractTypeAliases(body: Statement[]): Record<string, string> {\n const aliases: Record<string, string> = {};\n for (const node of body) {\n if (node.type === 'TSTypeAliasDeclaration') {\n const name = node.id?.name;\n const resolved = node.typeAnnotation\n ? extractTypeName(node.typeAnnotation)\n : null;\n if (name && resolved && isSafeObjectKey(name)) aliases[name] = resolved;\n }\n // Also check `export type X = ...` (ExportNamedDeclaration wrapping)\n if (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'TSTypeAliasDeclaration'\n ) {\n const decl = node.declaration;\n const name = decl.id?.name;\n const resolved = decl.typeAnnotation\n ? extractTypeName(decl.typeAnnotation)\n : null;\n if (name && resolved && isSafeObjectKey(name)) aliases[name] = resolved;\n }\n\n // Extract enum declarations as string union types\n // e.g., enum Status { PENDING = 'pending', ACTIVE = 'active' }\n // → Status: \"'pending' | 'active'\"\n const enumDecl =\n node.type === 'TSEnumDeclaration'\n ? node\n : node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'TSEnumDeclaration'\n ? node.declaration\n : null;\n if (enumDecl) {\n const name = enumDecl.id?.name;\n // OXC wraps members in a TSEnumBody node: enumDecl.body.members\n const members = enumDecl.body?.members ?? enumDecl.members;\n if (name && isSafeObjectKey(name) && members && members.length > 0) {\n const values = members\n .map((m: TSEnumMember): string | null => {\n if (m.initializer?.type === 'Literal') {\n const val = m.initializer.value;\n if (typeof val === 'string') return `'${val}'`;\n if (typeof val === 'number') return String(val);\n }\n return null;\n })\n .filter((v): v is string => v !== null);\n\n if (values.length > 0) {\n // All string values → string union, all numeric → number union\n const allStrings = values.every((v) => v.startsWith(\"'\"));\n if (allStrings) {\n aliases[name] = values.join(' | ');\n }\n }\n }\n }\n }\n return aliases;\n}\n\n/**\n * Unwrap `as const` / `satisfies T` / `!` wrappers to reach the underlying\n * expression. `const CFG = { api: false } as const` is the idiomatic way to\n * declare a shared surface policy, so the wrapper must be transparent here or\n * the object literal is never found.\n */\nfunction unwrapTypeAssertion(node: Expression | null): Expression | null {\n let current = node;\n // Bounded: assertions can legally nest (`x as unknown as T`), but not deeply.\n for (let depth = 0; current && depth < 8; depth++) {\n const type = (current as unknown as TSTypeAssertionExpression).type;\n if (\n type === 'TSAsExpression' ||\n type === 'TSSatisfiesExpression' ||\n type === 'TSNonNullExpression' ||\n type === 'TSTypeAssertion' ||\n type === 'ParenthesizedExpression'\n ) {\n current = (current as unknown as TSTypeAssertionExpression).expression;\n continue;\n }\n return current;\n }\n return current;\n}\n\n/**\n * A spread inside an `@smrt()` or `@method()` config that could not be\n * resolved statically.\n *\n * Recorded rather than silently dropped: an unresolvable spread may carry\n * `api`/`mcp`/`cli` keys, and because an absent surface key means *default\n * open* (full CRUD), dropping it silently turns a deliberate lockdown into a\n * public surface. The same reasoning covers `@method({ expose: false })`,\n * where a dropped key restores the default-routed behavior the author was\n * withholding. See issues #2100 and #2686.\n */\ninterface UnresolvedSpread {\n /** Source text of the spread, e.g. `...IMPORTED_SURFACE`. */\n expression: string;\n /** Byte offset of the spread node, for line/column resolution. */\n start?: number;\n /**\n * Decorator whose config the expression appeared in, for the diagnostic.\n * Defaults to `@smrt()` when omitted.\n */\n decorator?: string;\n}\n\n/**\n * A module-scope `const` object literal available for spread resolution.\n *\n * `unresolved` carries any spread inside the constant's OWN initializer that\n * could not be resolved (e.g. `const CFG = { ...IMPORTED }`). Such a constant\n * is \"tainted\": `value` is only a partial view of what it holds at runtime.\n * Resolving a decorator spread against it silently would reintroduce the\n * silent-drop failure mode one level removed, so the taint is replayed into the\n * use site's diagnostics instead.\n */\ninterface ModuleConstant {\n value: Record<string, unknown>;\n unresolved: UnresolvedSpread[];\n unsafeReferences: UnresolvedSpread[];\n dependencies: Array<{\n name: string;\n start?: number;\n }>;\n}\n\n/**\n * Context threaded through decorator-config extraction so object spreads can be\n * resolved against module-scope constants, and unresolvable ones reported.\n */\ninterface DecoratorConfigContext {\n /** Module-scope `const NAME = {...}` object literals, by identifier name. */\n constants: Map<string, ModuleConstant>;\n /** Collector for spreads that could not be statically resolved. */\n unresolved: UnresolvedSpread[];\n /** Constant spreads recorded while another module constant is extracted. */\n dependencies?: ModuleConstant['dependencies'];\n /** Require values to be statically literal for security-sensitive @smrt config. */\n requireLiteralValues?: boolean;\n /**\n * Local-name -> imported-name for this file's renamed named imports, so a\n * decorator reached through an alias is still recognized. Without it\n * `import { method as action }` made `@action({ expose: false })` invisible\n * to the scanner while the runtime decorator still ran — a withheld method\n * would silently keep its generated route (#2686).\n */\n importAliases?: Map<string, string>;\n}\n\n/**\n * Collect module-scope `const NAME = { ... }` object literals so that\n * `@smrt({ ...NAME })` can be resolved at scan time.\n *\n * Declaration order is honoured: a constant may spread an earlier constant, and\n * each is extracted against the map built so far. Only `const` is considered —\n * `let`/`var` could be reassigned between declaration and decorator evaluation,\n * so treating them as static would be unsound.\n *\n * Imported constants are intentionally NOT resolved (that would require\n * cross-file resolution); they surface as unresolved spreads and are reported\n * as scan errors instead of being silently dropped.\n *\n * A constant whose own initializer contains an unresolvable spread is recorded\n * as TAINTED rather than dropped: its extracted value is only partial, so any\n * decorator that spreads it replays the taint into its own diagnostics. Without\n * that, `const CFG = { ...IMPORTED }` followed by `@smrt({ ...CFG })` would\n * resolve cleanly against a partial object and report nothing — the exact\n * silent-drop failure mode this guard exists to prevent, one level removed.\n *\n * @param body - Top-level statement array from the OXC-parsed `Program` node.\n * @param sourceText - Full source text, used for nested value reconstruction.\n * @returns Map of constant name to its extracted value plus any taint.\n */\nexport function extractModuleObjectConstants(\n body: Statement[],\n sourceText: string,\n): Map<string, ModuleConstant> {\n const constants = new Map<string, ModuleConstant>();\n\n for (const node of body) {\n // Both `const X = {}` and `export const X = {}`.\n const decl =\n node.type === 'VariableDeclaration'\n ? node\n : node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'VariableDeclaration'\n ? (node.declaration as VariableDeclaration)\n : null;\n\n if (decl?.kind !== 'const') continue;\n\n for (const declarator of decl.declarations) {\n if (declarator.id?.type !== 'Identifier') continue;\n const name = declarator.id.name;\n if (!name || !isSafeObjectKey(name)) continue;\n\n const init = unwrapTypeAssertion(declarator.init);\n if (init?.type !== 'ObjectExpression') continue;\n\n // Extract against the constants seen so far, so `const B = { ...A }`\n // resolves — and capture this constant's OWN unresolvable spreads as\n // taint rather than discarding them. Nothing is reported here: an unused\n // constant is not a manifest problem. The taint only becomes an error\n // when a decorator actually spreads it, and it propagates transitively\n // because spreading a tainted constant re-collects its taint below.\n const unresolved: UnresolvedSpread[] = [];\n const dependencies: ModuleConstant['dependencies'] = [];\n const value = extractObjectLiteral(init, sourceText, {\n constants,\n unresolved,\n dependencies,\n requireLiteralValues: true,\n });\n constants.set(name, {\n value,\n unresolved,\n unsafeReferences: [],\n dependencies,\n });\n }\n }\n\n taintUnsafeModuleConstantReferences(body, constants, sourceText);\n propagateModuleConstantTaint(constants);\n return constants;\n}\n\n/**\n * Conservatively taint shared config objects that escape their declaration or\n * a spread expression.\n *\n * `const` prevents rebinding, not mutation: `const CFG = { api: true };\n * CFG.api = false` is legal JavaScript. Snapshotting only the initializer would\n * therefore make the manifest say open while the runtime decorator sees\n * closed. A reference used as the direct argument of a spread is safe; any\n * other reference (property access, aliasing, function argument, assignment)\n * may mutate or escape the object, so decorators that later spread it fail\n * loudly instead of trusting a stale snapshot.\n */\nfunction taintUnsafeModuleConstantReferences(\n body: Statement[],\n constants: Map<string, ModuleConstant>,\n sourceText: string,\n): void {\n if (constants.size === 0) return;\n\n const tainted = new Set<string>();\n\n const visit = (\n value: unknown,\n ancestors: Array<Record<string, unknown>>,\n shadowed: ReadonlySet<string>,\n ): void => {\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry, ancestors, shadowed);\n return;\n }\n if (!value || typeof value !== 'object') return;\n\n const node = value as Record<string, unknown>;\n if (typeof node.type !== 'string') {\n for (const child of Object.values(node))\n visit(child, ancestors, shadowed);\n return;\n }\n\n if (\n node.type === 'Identifier' &&\n typeof node.name === 'string' &&\n constants.has(node.name) &&\n !shadowed.has(node.name) &&\n !isTypeOnlyReference(node, ancestors) &&\n !isSafeModuleConstantReference(node, ancestors, constants)\n ) {\n const name = node.name;\n if (!tainted.has(name)) {\n tainted.add(name);\n const unresolved = {\n expression:\n sliceSource(node as unknown as BaseNode, sourceText) ?? name,\n start:\n typeof node.start === 'number' ? (node.start as number) : undefined,\n };\n const constant = constants.get(name);\n constant?.unsafeReferences.push(unresolved);\n constant?.unresolved.push(unresolved);\n }\n }\n\n const nextShadowed = createsLexicalScope(node)\n ? new Set([...shadowed, ...collectScopeBindings(node)])\n : shadowed;\n const nextAncestors = [...ancestors, node];\n for (const [key, child] of Object.entries(node)) {\n if (key === 'loc' || key === 'range' || key === 'start' || key === 'end')\n continue;\n visit(child, nextAncestors, nextShadowed);\n }\n };\n\n visit(body, [], new Set());\n}\n\nfunction createsLexicalScope(node: Record<string, unknown>): boolean {\n return (\n node.type === 'BlockStatement' ||\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression' ||\n node.type === 'CatchClause' ||\n node.type === 'ForStatement' ||\n node.type === 'ForInStatement' ||\n node.type === 'ForOfStatement' ||\n node.type === 'ClassDeclaration' ||\n node.type === 'ClassExpression'\n );\n}\n\nfunction collectScopeBindings(node: Record<string, unknown>): Set<string> {\n const bindings = new Set<string>();\n const addPattern = (value: unknown): void => {\n if (!value || typeof value !== 'object') return;\n const pattern = value as Record<string, unknown>;\n if (pattern.type === 'Identifier' && typeof pattern.name === 'string') {\n bindings.add(pattern.name);\n return;\n }\n if (pattern.type === 'RestElement') {\n addPattern(pattern.argument);\n return;\n }\n if (pattern.type === 'AssignmentPattern') {\n addPattern(pattern.left);\n return;\n }\n if (pattern.type === 'ArrayPattern' && Array.isArray(pattern.elements)) {\n for (const element of pattern.elements) addPattern(element);\n return;\n }\n if (pattern.type === 'ObjectPattern' && Array.isArray(pattern.properties)) {\n for (const property of pattern.properties) {\n if (!property || typeof property !== 'object') continue;\n const propertyNode = property as Record<string, unknown>;\n addPattern(\n propertyNode.type === 'RestElement'\n ? propertyNode.argument\n : propertyNode.value,\n );\n }\n }\n };\n\n if (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n ) {\n if (node.type !== 'ArrowFunctionExpression') addPattern(node.id);\n if (Array.isArray(node.params)) {\n for (const parameter of node.params) addPattern(parameter);\n }\n collectFunctionVarBindings(node.body, bindings);\n } else if (node.type === 'CatchClause') {\n addPattern(node.param);\n } else if (\n node.type === 'ForStatement' ||\n node.type === 'ForInStatement' ||\n node.type === 'ForOfStatement'\n ) {\n const declaration = node.type === 'ForStatement' ? node.init : node.left;\n if (\n declaration &&\n typeof declaration === 'object' &&\n (declaration as Record<string, unknown>).type === 'VariableDeclaration'\n ) {\n for (const declarator of (declaration as Record<string, unknown>)\n .declarations as Array<Record<string, unknown>>) {\n addPattern(declarator.id);\n }\n }\n } else if (\n (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') &&\n node.id\n ) {\n addPattern(node.id);\n }\n\n if (node.type === 'BlockStatement' && Array.isArray(node.body)) {\n for (const statement of node.body as Array<Record<string, unknown>>) {\n const declaration =\n statement.type === 'ExportNamedDeclaration'\n ? (statement.declaration as Record<string, unknown> | undefined)\n : statement;\n if (declaration?.type === 'VariableDeclaration') {\n for (const declarator of declaration.declarations as Array<\n Record<string, unknown>\n >) {\n addPattern(declarator.id);\n }\n } else if (\n declaration?.type === 'FunctionDeclaration' ||\n declaration?.type === 'ClassDeclaration'\n ) {\n addPattern(declaration.id);\n }\n }\n }\n\n return bindings;\n}\n\nfunction collectFunctionVarBindings(\n value: unknown,\n bindings: Set<string>,\n): void {\n if (Array.isArray(value)) {\n for (const entry of value) collectFunctionVarBindings(entry, bindings);\n return;\n }\n if (!value || typeof value !== 'object') return;\n const node = value as Record<string, unknown>;\n if (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n ) {\n return;\n }\n if (node.type === 'VariableDeclaration' && node.kind === 'var') {\n for (const declarator of node.declarations as Array<\n Record<string, unknown>\n >) {\n const id = declarator.id as Record<string, unknown> | undefined;\n if (id?.type === 'Identifier' && typeof id.name === 'string') {\n bindings.add(id.name);\n }\n }\n }\n for (const [key, child] of Object.entries(node)) {\n if (key === 'loc' || key === 'range' || key === 'start' || key === 'end')\n continue;\n collectFunctionVarBindings(child, bindings);\n }\n}\n\nfunction isTypeOnlyReference(\n identifier: Record<string, unknown>,\n ancestors: Array<Record<string, unknown>>,\n): boolean {\n let child = identifier;\n for (let index = ancestors.length - 1; index >= 0; index--) {\n const parent = ancestors[index];\n if (\n (parent.type === 'TSAsExpression' ||\n parent.type === 'TSSatisfiesExpression' ||\n parent.type === 'TSNonNullExpression' ||\n parent.type === 'TSTypeAssertion') &&\n parent.expression === child\n ) {\n child = parent;\n continue;\n }\n if (typeof parent.type === 'string' && parent.type.startsWith('TS')) {\n return true;\n }\n break;\n }\n return false;\n}\n\nfunction propagateModuleConstantTaint(\n constants: Map<string, ModuleConstant>,\n): void {\n let changed = true;\n while (changed) {\n changed = false;\n for (const constant of constants.values()) {\n for (const dependency of constant.dependencies) {\n const source = constants.get(dependency.name);\n if (!source) continue;\n for (const unresolved of source.unresolved) {\n if (\n dependency.start !== undefined &&\n unresolved.start !== undefined &&\n unresolved.start > dependency.start &&\n !hasNestedReferenceValue(source.value)\n ) {\n continue;\n }\n if (\n !constant.unresolved.some(\n (existing) =>\n existing.expression === unresolved.expression &&\n existing.start === unresolved.start,\n )\n ) {\n constant.unresolved.push(unresolved);\n changed = true;\n }\n }\n if (hasNestedReferenceValue(source.value)) {\n for (const unsafeReference of constant.unsafeReferences) {\n const matchesUnsafeReference = (existing: UnresolvedSpread) =>\n existing.expression === unsafeReference.expression &&\n existing.start === unsafeReference.start;\n if (!source.unresolved.some(matchesUnsafeReference)) {\n source.unresolved.push(unsafeReference);\n changed = true;\n }\n if (!source.unsafeReferences.some(matchesUnsafeReference)) {\n source.unsafeReferences.push(unsafeReference);\n changed = true;\n }\n }\n }\n }\n }\n }\n}\n\nfunction hasNestedReferenceValue(value: Record<string, unknown>): boolean {\n return Object.values(value).some(\n (entry) => entry !== null && typeof entry === 'object',\n );\n}\n\nfunction isSafeModuleConstantReference(\n identifier: Record<string, unknown>,\n ancestors: Array<Record<string, unknown>>,\n constants: Map<string, ModuleConstant>,\n): boolean {\n let child = identifier;\n\n for (let index = ancestors.length - 1; index >= 0; index--) {\n const parent = ancestors[index];\n\n if (parent.type === 'VariableDeclarator' && parent.id === child) {\n return true;\n }\n\n if (\n parent.type === 'Property' &&\n parent.key === child &&\n parent.computed === false &&\n parent.shorthand === false\n ) {\n return true;\n }\n\n if (\n parent.type === 'MemberExpression' &&\n parent.property === child &&\n parent.computed === false\n ) {\n return true;\n }\n\n if (\n (parent.type === 'TSAsExpression' ||\n parent.type === 'TSSatisfiesExpression' ||\n parent.type === 'TSNonNullExpression' ||\n parent.type === 'TSTypeAssertion' ||\n parent.type === 'ParenthesizedExpression') &&\n parent.expression === child\n ) {\n child = parent;\n continue;\n }\n\n if (parent.type === 'SpreadElement' && parent.argument === child) {\n const name =\n typeof identifier.name === 'string' ? identifier.name : undefined;\n const constant = name ? constants.get(name) : undefined;\n if (!constant || !hasNestedReferenceValue(constant.value)) return true;\n\n const moduleConstantInitializer = [...constants.values()].some(\n (candidate) =>\n candidate.dependencies.some(\n (dependency) =>\n dependency.name === name && dependency.start === parent.start,\n ),\n );\n if (moduleConstantInitializer) return true;\n\n const smrtDecorator = ancestors.some((ancestor) => {\n if (\n ancestor.type !== 'Decorator' ||\n !ancestor.expression ||\n typeof ancestor.expression !== 'object'\n ) {\n return false;\n }\n const expression = ancestor.expression as Record<string, unknown>;\n if (\n expression.type !== 'CallExpression' ||\n !expression.callee ||\n typeof expression.callee !== 'object'\n ) {\n return false;\n }\n const callee = expression.callee as Record<string, unknown>;\n return callee.type === 'Identifier' && callee.name === 'smrt';\n });\n return smrtDecorator;\n }\n\n return false;\n }\n\n return false;\n}\n\n/**\n * Turn unresolvable `@smrt()` config spreads into `severity: 'error'` scan\n * diagnostics.\n *\n * Deliberately fail-loud rather than fail-quiet. A dropped spread may have\n * carried `api`/`mcp`/`cli`, and an absent surface key means *default open* —\n * so silently discarding one converts a deliberate lockdown into a published\n * CRUD surface with no signal anywhere. Erroring matches the precedent in\n * `verify-completeness.ts`, where scan errors short-circuit so a broken source\n * can never masquerade as a complete manifest.\n *\n * @see https://github.com/happyvertical/smrt/issues/2100\n */\nfunction reportUnresolvedSpreads(\n unresolved: UnresolvedSpread[],\n filePath: string,\n sourceText: string,\n errors: ScanError[],\n): void {\n for (const spread of unresolved) {\n const loc =\n spread.start === undefined\n ? undefined\n : getLineColumn(sourceText, spread.start);\n errors.push({\n message:\n `Cannot statically resolve \\`${spread.expression}\\` while expanding a ${spread.decorator ?? '@smrt()'} config. ` +\n `Only literal keys/values and unescaped module-scope \\`const\\` object literals ` +\n `in the same file are supported. Inline the keys or remove the mutation/alias — ` +\n `an unresolved expression would drop keys from the manifest, and every ` +\n `absent exposure key defaults to open.`,\n filePath,\n line: loc?.line,\n column: loc?.column,\n severity: 'error',\n });\n }\n}\n\n/**\n * Extract class definition from an AST node\n */\nfunction extractClassFromNode(\n node: Statement,\n filePath: string,\n sourceText: string,\n importAliases: Map<string, string>,\n ctx?: DecoratorConfigContext,\n): RawClassDefinition | null {\n // Handle export declarations\n if (node.type === 'ExportNamedDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration,\n filePath,\n sourceText,\n importAliases,\n ctx,\n );\n }\n if (node.type === 'ExportDefaultDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration as Statement,\n filePath,\n sourceText,\n importAliases,\n ctx,\n );\n }\n\n // Handle class declaration\n if (node.type === 'ClassDeclaration') {\n return extractClassDeclaration(\n node,\n filePath,\n sourceText,\n importAliases,\n ctx,\n );\n }\n\n return null;\n}\n\n/**\n * Extract class declaration details\n */\nfunction extractClassDeclaration(\n node: ClassDeclaration,\n filePath: string,\n sourceText: string,\n importAliases: Map<string, string>,\n ctx?: DecoratorConfigContext,\n): RawClassDefinition {\n const className = node.id?.name || 'AnonymousClass';\n\n // Extract decorators\n const decorators = node.decorators || [];\n const smrtDecorator = decorators.find((d) =>\n isSmrtDecorator(d, importAliases),\n );\n const reportDecorator = decorators.find((d) =>\n isNamedDecorator(d, 'report', importAliases),\n );\n const tenantScopedDecorator = decorators.find((d) =>\n isNamedDecorator(d, 'TenantScoped', importAliases),\n );\n const hasSmartDecorator = !!smrtDecorator;\n const smrtConfig = smrtDecorator\n ? extractDecoratorConfig(\n smrtDecorator,\n sourceText,\n ctx ? { ...ctx, requireLiteralValues: true } : ctx,\n )\n : null;\n const decoratorConfig =\n tenantScopedDecorator || reportDecorator\n ? {\n ...(smrtConfig ?? {}),\n ...(reportDecorator\n ? {\n report: extractDecoratorConfig(\n reportDecorator,\n sourceText,\n ctx,\n ),\n }\n : {}),\n ...(tenantScopedDecorator\n ? {\n tenantScoped: extractDecoratorConfig(\n tenantScopedDecorator,\n sourceText,\n ctx,\n ),\n }\n : {}),\n }\n : smrtConfig;\n\n // Extract extends clause\n const { extendsClause, extendsTypeArg } = extractExtendsClause(\n node,\n importAliases,\n );\n\n // Extract fields and methods\n const fields: RawFieldDefinition[] = [];\n const methods: RawMethodDefinition[] = [];\n\n for (const member of node.body.body) {\n if (member.type === 'PropertyDefinition') {\n const field = extractPropertyDefinition(member, sourceText);\n if (field) {\n fields.push(field);\n }\n } else if (member.type === 'MethodDefinition') {\n const method = extractMethodDefinition(member, sourceText, ctx);\n if (method) {\n methods.push(method);\n }\n }\n }\n\n return {\n className,\n filePath,\n extendsClause,\n extendsTypeArg,\n decoratorConfig,\n hasSmartDecorator,\n fields,\n methods,\n startLine: node.loc?.start.line || 1,\n endLine: node.loc?.end.line || 1,\n };\n}\n\n/**\n * Check if a decorator is @smrt()\n */\nfunction isSmrtDecorator(\n decorator: Decorator,\n importAliases?: Map<string, string>,\n): boolean {\n return isNamedDecorator(decorator, 'smrt', importAliases);\n}\n\nfunction isNamedDecorator(\n decorator: Decorator,\n name: string,\n importAliases?: Map<string, string>,\n): boolean {\n const expr = decorator.expression;\n // A renamed import binds the decorator to a different local identifier;\n // compare against the name it was imported UNDER, not the local one.\n const resolve = (local: string): string => importAliases?.get(local) ?? local;\n\n // @decoratorName() - CallExpression\n if (expr.type === 'CallExpression') {\n const callee = expr.callee;\n if (callee.type === 'Identifier' && resolve(callee.name) === name) {\n return true;\n }\n }\n\n // @decoratorName - Identifier (no parentheses)\n if (expr.type === 'Identifier' && resolve(expr.name) === name) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Extract @smrt() decorator configuration\n */\nfunction extractDecoratorConfig(\n decorator: Decorator,\n sourceText: string,\n ctx?: DecoratorConfigContext,\n): RawDecoratorConfig | null {\n const expr = decorator.expression;\n\n if (expr.type === 'CallExpression' && expr.arguments.length > 0) {\n const arg = unwrapTypeAssertion(expr.arguments[0]);\n if (arg?.type === 'ObjectExpression') {\n return extractObjectLiteral(arg, sourceText, ctx) as RawDecoratorConfig;\n }\n }\n\n // @smrt() with no config or @smrt\n return {};\n}\n\n/**\n * Extract object literal to plain object\n */\nfunction extractObjectLiteral(\n node: ObjectExpression,\n sourceText: string,\n ctx?: DecoratorConfigContext,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n // Iterate in source order so spread/property precedence matches runtime\n // semantics: `{ api: true, ...CFG }` takes `api` from CFG, while\n // `{ ...CFG, api: true }` overrides it.\n for (const prop of node.properties) {\n if (prop.type === 'SpreadElement') {\n // A spread that reaches the manifest as \"absent\" is indistinguishable\n // from a surface the author never declared — and absent means default\n // *open*. Resolve it, or record it for a scan error. Never drop it\n // silently. See issue #2100.\n const argument = unwrapTypeAssertion(prop.argument);\n const constant =\n argument?.type === 'Identifier'\n ? ctx?.constants.get(argument.name)\n : undefined;\n const resolved =\n constant?.value ??\n (argument?.type === 'ObjectExpression'\n ? extractObjectLiteral(argument, sourceText, ctx)\n : undefined);\n\n if (resolved) {\n if (constant && ctx?.dependencies && argument?.type === 'Identifier') {\n ctx.dependencies.push({\n name: argument.name,\n start: prop.start,\n });\n }\n for (const [key, value] of Object.entries(resolved)) {\n if (isSafeObjectKey(key)) {\n result[key] = value;\n }\n }\n // A tainted constant resolved to a PARTIAL object — replay the spreads\n // its own initializer could not resolve, or the drop would go unnoticed\n // here even though this site depends on the missing keys.\n if (constant?.unresolved.length && ctx && !ctx.dependencies) {\n ctx.unresolved.push(\n ...constant.unresolved.filter(\n (unresolved) =>\n hasNestedReferenceValue(constant.value) ||\n prop.start === undefined ||\n unresolved.start === undefined ||\n unresolved.start <= prop.start,\n ),\n );\n }\n } else if (ctx) {\n ctx.unresolved.push({\n expression: sliceSource(prop, sourceText) ?? '...<unknown>',\n start: prop.start,\n });\n }\n continue;\n }\n\n if (prop.type === 'Property') {\n const key = getPropertyKey(prop.key);\n if (\n prop.shorthand ||\n (prop.computed &&\n !(prop.key.type === 'Literal' && typeof prop.key.value === 'string'))\n ) {\n ctx?.unresolved.push({\n expression: sliceSource(prop, sourceText) ?? '<unknown property>',\n start: prop.start,\n });\n continue;\n }\n // Skip prototype-pollution keys (__proto__/constructor/prototype) so a\n // decorator-config property of that name cannot mutate the metadata\n // object's prototype.\n if (key && isSafeObjectKey(key)) {\n result[key] = extractValue(prop.value, sourceText, ctx);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get property key as string\n */\nfunction getPropertyKey(node: Expression): string | null {\n if (node.type === 'Identifier') {\n return node.name;\n }\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value;\n }\n return null;\n}\n\n/**\n * Extract value from expression\n */\nfunction extractValue(\n node: Expression | Pattern,\n sourceText: string,\n ctx?: DecoratorConfigContext,\n): unknown {\n const unwrapped = unwrapTypeAssertion(node as Expression);\n if (unwrapped && unwrapped !== node) {\n return extractValue(unwrapped, sourceText, ctx);\n }\n\n switch (node.type) {\n case 'Literal':\n return node.value;\n\n case 'Identifier':\n // Handle special identifiers\n if (node.name === 'undefined') return undefined;\n if (node.name === 'null') return null;\n if (node.name === 'true') return true;\n if (node.name === 'false') return false;\n if (ctx?.requireLiteralValues) {\n ctx.unresolved.push({\n expression: sliceSource(node, sourceText) ?? node.name,\n start: node.start,\n });\n }\n return node.name; // Return as string for class references\n\n case 'ArrayExpression': {\n // Array spreads (e.g. `include: [...BASE_ACTIONS, 'archive']`) are not\n // resolved, but must not vanish silently: a dropped element changes an\n // include/exclude allowlist. Record for a scan error instead.\n for (const el of node.elements) {\n if (\n el &&\n typeof el === 'object' &&\n el.type === 'SpreadElement' &&\n ctx\n ) {\n ctx.unresolved.push({\n expression: sliceSource(el, sourceText) ?? '...<unknown>',\n start: el.start,\n });\n }\n }\n return node.elements\n .filter(\n (el: Expression | SpreadElement | null): el is Expression =>\n el !== null &&\n typeof el === 'object' &&\n 'type' in el &&\n el.type !== 'SpreadElement',\n )\n .map((el: Expression) => extractValue(el, sourceText, ctx));\n }\n\n case 'ObjectExpression':\n return extractObjectLiteral(node, sourceText, ctx);\n\n case 'UnaryExpression':\n if (node.operator === '-' && node.argument?.type === 'Literal') {\n const value = node.argument.value;\n if (typeof value === 'number') {\n return -value;\n }\n }\n break;\n\n case 'CallExpression':\n case 'NewExpression': {\n // Return the raw source for complex expressions\n const src = sliceSource(node, sourceText);\n if (src) {\n if (ctx?.requireLiteralValues) {\n ctx.unresolved.push({ expression: src, start: node.start });\n }\n return src;\n }\n break;\n }\n }\n\n // For complex expressions, return raw source if available\n const rawSrc = sliceSource(node, sourceText);\n if (rawSrc) {\n if (ctx?.requireLiteralValues) {\n ctx.unresolved.push({ expression: rawSrc, start: node.start });\n }\n return rawSrc;\n }\n\n return undefined;\n}\n\n/**\n * Extract extends clause information\n */\nfunction extractExtendsClause(\n node: ClassDeclaration,\n importAliases: Map<string, string>,\n): {\n extendsClause: string | null;\n extendsTypeArg: string | null;\n} {\n if (!node.superClass) {\n return { extendsClause: null, extendsTypeArg: null };\n }\n\n let extendsClause: string | null = null;\n let extendsTypeArg: string | null = null;\n\n // Get class name\n if (node.superClass.type === 'Identifier') {\n extendsClause = node.superClass.name;\n } else if (node.superClass.type === 'MemberExpression') {\n // Handle Namespace.Class\n extendsClause = getMemberExpressionString(node.superClass);\n }\n\n // Resolve import aliases (e.g., import { Performer as PerformerBase })\n if (extendsClause && importAliases.has(extendsClause)) {\n const aliasedExtends = importAliases.get(extendsClause);\n if (aliasedExtends) {\n extendsClause = aliasedExtends;\n }\n }\n\n // Get type argument (e.g., Meeting from SmrtCollection<Meeting>)\n // Note: oxc-parser v0.108+ renamed superTypeParameters to superTypeArguments\n const params =\n node.superTypeArguments?.params || node.superTypeParameters?.params;\n if (params && params.length > 0) {\n const typeParam = params[0];\n extendsTypeArg = extractTypeName(typeParam);\n }\n\n return { extendsClause, extendsTypeArg };\n}\n\n/**\n * Get member expression as dotted string\n */\nfunction getMemberExpressionString(node: MemberExpression): string {\n const parts: string[] = [];\n\n let current: Expression = node;\n while (current.type === 'MemberExpression') {\n if (current.property.type === 'Identifier') {\n parts.unshift(current.property.name);\n }\n current = current.object;\n }\n\n if (current.type === 'Identifier') {\n parts.unshift(current.name);\n }\n\n return parts.join('.');\n}\n\n/**\n * Reconstruct call expression string from AST\n * e.g., foreignKey(Customer) or decimal({ required: true })\n */\nfunction reconstructCallExpression(\n node: CallExpression,\n sourceText: string,\n): string | null {\n // Try range first\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n // Reconstruct from AST\n let callee = '';\n if (node.callee.type === 'Identifier') {\n callee = node.callee.name;\n } else if (node.callee.type === 'MemberExpression') {\n callee = getMemberExpressionString(node.callee);\n } else {\n return null;\n }\n\n // Reconstruct arguments\n const args: string[] = [];\n for (const arg of node.arguments) {\n const argSrc = sliceSource(arg, sourceText);\n if (argSrc) {\n args.push(argSrc);\n } else if (arg.type === 'Identifier') {\n args.push(arg.name);\n } else if (arg.type === 'Literal') {\n args.push(arg.raw || String(arg.value));\n } else if (arg.type === 'ObjectExpression') {\n // Simplified object reconstruction\n const objStr = reconstructObjectExpression(arg, sourceText);\n if (objStr) args.push(objStr);\n } else {\n // Skip complex arguments\n args.push('...');\n }\n }\n\n return `${callee}(${args.join(', ')})`;\n}\n\n/**\n * Reconstruct object expression string from AST\n */\nfunction reconstructObjectExpression(\n node: ObjectExpression,\n sourceText: string,\n): string | null {\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n const props: string[] = [];\n for (const prop of node.properties) {\n if (prop.type === 'SpreadElement') continue;\n if (prop.type === 'Property') {\n let key = '';\n if (prop.key.type === 'Identifier') {\n key = prop.key.name;\n } else if (prop.key.type === 'Literal') {\n key = String(prop.key.value);\n }\n if (!key) continue;\n\n let value = '';\n const valSrc = sliceSource(prop.value, sourceText);\n if (valSrc) {\n value = valSrc;\n } else if (prop.value.type === 'ObjectExpression') {\n // Recursively reconstruct nested objects (e.g., uiSlots.sources)\n value =\n reconstructObjectExpression(\n prop.value as ObjectExpression,\n sourceText,\n ) || '';\n } else if (prop.value.type === 'ArrayExpression') {\n value =\n reconstructArrayExpression(\n prop.value as ArrayExpression,\n sourceText,\n ) || '';\n } else if (prop.value.type === 'Identifier') {\n value = prop.value.name;\n } else if (prop.value.type === 'Literal') {\n value = prop.value.raw || String(prop.value.value);\n }\n\n if (value) {\n props.push(`${key}: ${value}`);\n }\n }\n }\n\n return `{ ${props.join(', ')} }`;\n}\n\n/**\n * Reconstruct array expression string from AST\n */\nfunction reconstructArrayExpression(\n node: ArrayExpression,\n sourceText: string,\n): string | null {\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n const elements: string[] = [];\n for (const el of node.elements) {\n if (!el) continue;\n if (el.type === 'SpreadElement') {\n elements.push('...');\n } else {\n const elSrc = sliceSource(el, sourceText);\n if (elSrc) {\n elements.push(elSrc);\n } else if (el.type === 'Identifier') {\n elements.push(el.name);\n } else if (el.type === 'Literal') {\n elements.push(el.raw || String(el.value));\n } else if (el.type === 'ObjectExpression') {\n const objStr = reconstructObjectExpression(\n el as ObjectExpression,\n sourceText,\n );\n if (objStr) elements.push(objStr);\n }\n }\n }\n\n return `[${elements.join(', ')}]`;\n}\n\n/**\n * Extract type name from TSType\n */\nfunction extractTypeName(type: TSType): string | null {\n switch (type.type) {\n case 'TSTypeReference': {\n let baseName: string | null = null;\n if (type.typeName.type === 'Identifier') {\n baseName = type.typeName.name;\n } else if (type.typeName.type === 'TSQualifiedName') {\n baseName = getQualifiedName(type.typeName);\n }\n\n // Include type parameters (e.g., Promise<any>, Map<string, number>)\n // Note: oxc-parser v0.108+ renamed typeParameters to typeArguments\n const typeParams =\n type.typeArguments?.params || type.typeParameters?.params;\n if (baseName && typeParams?.length) {\n const typeArgs = typeParams.map((p: TSType) => extractTypeName(p));\n // An unresolvable ARGUMENT makes the whole reference unresolvable.\n // Dropping it left `Array<[string, Asset]>` as the bare string\n // `'Array'`, which carries no `typeUnresolved` provenance and is then\n // default-accepted by core's wire-ability gate -- a silent widening\n // through the exact channel that provenance exists to close (#2686).\n if (typeArgs.some((arg) => arg === null)) return null;\n if (typeArgs.length > 0) {\n return `${baseName}<${typeArgs.join(', ')}>`;\n }\n }\n return baseName;\n }\n\n case 'TSStringKeyword':\n return 'string';\n case 'TSNumberKeyword':\n return 'number';\n case 'TSBooleanKeyword':\n return 'boolean';\n case 'TSAnyKeyword':\n return 'any';\n // `unknown` used to fall through to `null`, which every consumer then read\n // as the string `'any'` -- indistinguishable from syntax the scanner\n // genuinely could not express. It is an ordinary, resolvable annotation, so\n // it is named here and `null` is left to mean \"not resolved\" (#2686).\n case 'TSUnknownKeyword':\n return 'unknown';\n // NOTE: `TSObjectKeyword` is deliberately NOT resolved here, only in\n // `describeParameterType`. `ManifestAdapter.inferFromAnnotation` gives an\n // `object`-typed FIELD a `{}` column default, so naming the bare keyword\n // here would add a DDL default to an existing nullable column\n // (`VideoWorkflow.workflowJson: object | null = null`) that contradicts its\n // own `= null` initializer -- a schema change, and a wrong one. Parameters\n // run through no such inference, so the keyword is safe to name there.\n case 'TSNeverKeyword':\n return 'never';\n case 'TSBigIntKeyword':\n return 'bigint';\n case 'TSSymbolKeyword':\n return 'symbol';\n case 'TSVoidKeyword':\n return 'void';\n // `this` in a parameter position (`moveTo(p: this | string | null)`) is an\n // instance of the declaring class. Naming it keeps the surrounding union\n // resolvable -- leaving it unresolved would withhold a method whose\n // `string` branch a caller can genuinely satisfy. Consumers judge the name\n // itself; core's wire-ability gate treats it as a model instance (#2686).\n case 'TSThisType':\n return 'this';\n case 'TSNullKeyword':\n return 'null';\n case 'TSUndefinedKeyword':\n return 'undefined';\n\n case 'TSLiteralType': {\n const literal = type.literal;\n if (!literal) return null;\n // oxc-parser uses generic 'Literal' node type — distinguish by value type\n if (typeof literal.value === 'string') return `'${literal.value}'`;\n if (typeof literal.value === 'number') return String(literal.value);\n if (typeof literal.value === 'boolean') return String(literal.value);\n return null;\n }\n\n case 'TSArrayType': {\n const elementType = extractTypeName(type.elementType);\n return elementType ? `${elementType}[]` : null;\n }\n\n case 'TSUnionType': {\n const types = type.types.map((t: TSType) => extractTypeName(t));\n // Same reason as the type-argument case above: silently dropping an\n // unresolvable branch produced a partial union (or, when every branch\n // failed, the empty string, which the adapter maps to `'any'`) with no\n // provenance attached (#2686).\n if (types.some((branch) => branch === null)) return null;\n return types.join(' | ');\n }\n\n // Inline object type literal: { subject?: string; from?: string; body?: string }\n // Maps to 'object' which the ManifestAdapter resolves as json\n case 'TSTypeLiteral':\n return 'object';\n case 'TSFunctionType':\n return 'Function';\n // oxc-parser emits many TSType kinds the scanner does not resolve\n // (e.g. intersections, tuples, conditional types); fall through to null.\n default:\n return null;\n }\n}\n\n/**\n * Get qualified name as string\n */\nfunction getQualifiedName(node: TSQualifiedName): string {\n const parts: string[] = [];\n\n let current: TSQualifiedName | Identifier = node;\n while (current.type === 'TSQualifiedName') {\n parts.unshift(current.right.name);\n current = current.left;\n }\n\n if (current.type === 'Identifier') {\n parts.unshift(current.name);\n }\n\n return parts.join('.');\n}\n\n/**\n * Extract property definition\n */\nfunction extractPropertyDefinition(\n node: PropertyDefinition,\n sourceText: string,\n): RawFieldDefinition | null {\n // Skip computed properties\n if (node.computed) return null;\n\n const name = getPropertyKey(node.key);\n if (!name) return null;\n // Reject prototype-polluting field names before they become manifest map keys\n // (a field literally named `__proto__`/`constructor`/`prototype`). The\n // type-alias/enum/object-literal extractors already gate on this; field\n // definitions must too (review #1559).\n if (!isSafeObjectKey(name)) return null;\n\n // Get type annotation\n const typeAnnotation = node.typeAnnotation\n ? extractTypeName(node.typeAnnotation.typeAnnotation)\n : null;\n\n // Get initializer\n let initializer: string | null = null;\n let hasDecimalPoint = false;\n let numericValue: number | null = null;\n\n if (node.value) {\n // Check for numeric literal with decimal point. Unwrap a leading unary\n // minus first: a negative initializer (`= -5`, `= -1.5`) parses as a\n // `UnaryExpression{ operator: '-', argument: Literal }`, not a bare\n // `Literal`, so without this the 0-vs-0.0 heuristic mis-infers negatives as\n // `integer` and drops the default. Mirrors the `extractValue` pattern above.\n if (\n node.value.type === 'UnaryExpression' &&\n node.value.operator === '-' &&\n node.value.argument?.type === 'Literal' &&\n typeof node.value.argument.value === 'number'\n ) {\n numericValue = -node.value.argument.value;\n // Check the inner literal's raw string for a decimal point (0.0 vs 0).\n if (node.value.argument.raw) {\n hasDecimalPoint = node.value.argument.raw.includes('.');\n }\n } else if (\n node.value.type === 'Literal' &&\n typeof node.value.value === 'number'\n ) {\n numericValue = node.value.value;\n // Check raw string for decimal point (0.0 vs 0)\n if (node.value.raw) {\n hasDecimalPoint = node.value.raw.includes('.');\n }\n }\n\n // Get raw initializer string - try range first for accurate source text\n const valueSrc = sliceSource(node.value, sourceText);\n if (valueSrc) {\n initializer = valueSrc;\n } else if (node.value.type === 'Literal' && node.value.raw) {\n // Fall back to raw property for literals\n initializer = node.value.raw;\n } else if (node.value.type === 'Literal') {\n // Convert literal value to string\n const val = node.value.value;\n if (typeof val === 'string') {\n initializer = `'${val}'`;\n } else if (val !== null && val !== undefined) {\n initializer = String(val);\n }\n } else if (\n node.value.type === 'CallExpression' ||\n node.value.type === 'NewExpression'\n ) {\n // Reconstruct call expression string from AST\n initializer = reconstructCallExpression(\n node.value as CallExpression,\n sourceText,\n );\n } else if (node.value.type === 'ArrayExpression') {\n // Reconstruct array expression\n initializer = reconstructArrayExpression(node.value, sourceText);\n } else if (node.value.type === 'ObjectExpression') {\n // Reconstruct object expression (e.g., static uiSlots = { ... })\n initializer = reconstructObjectExpression(\n node.value as ObjectExpression,\n sourceText,\n );\n }\n }\n\n // Extract decorators\n const decorators: RawDecorator[] = [];\n if (node.decorators) {\n for (const dec of node.decorators) {\n const extracted = extractFieldDecorator(dec, sourceText);\n if (extracted) {\n decorators.push(extracted);\n }\n }\n }\n\n return {\n name,\n typeAnnotation,\n initializer,\n hasDecimalPoint,\n numericValue,\n decorators,\n optional: node.optional || false,\n isStatic: node.static || false,\n readonly: node.readonly || false,\n accessibility: node.accessibility || 'public',\n line: node.loc?.start.line || 0,\n };\n}\n\n/**\n * Extract field decorator\n */\nfunction extractFieldDecorator(\n decorator: Decorator,\n sourceText: string,\n): RawDecorator | null {\n const expr = decorator.expression;\n\n let name: string | null = null;\n const args: string[] = [];\n\n if (expr.type === 'CallExpression') {\n if (expr.callee.type === 'Identifier') {\n name = expr.callee.name;\n }\n // Extract arguments as strings\n for (const arg of expr.arguments) {\n const argSrc = sliceSource(arg, sourceText);\n if (argSrc) args.push(argSrc);\n }\n } else if (expr.type === 'Identifier') {\n name = expr.name;\n }\n\n if (!name) return null;\n\n return { name, arguments: args };\n}\n\n/**\n * Extract method definition\n */\nfunction extractMethodDefinition(\n node: MethodDefinition,\n sourceText: string,\n ctx?: DecoratorConfigContext,\n): RawMethodDefinition | null {\n // Skip constructors, getters, setters\n if (node.kind !== 'method') return null;\n\n const name = getPropertyKey(node.key);\n if (!name) return null;\n\n const func = node.value;\n\n // Extract parameters\n const parameters: RawParameterDefinition[] = [];\n for (const param of func.params) {\n const extracted = extractParameter(param, sourceText);\n if (extracted) {\n parameters.push(extracted);\n }\n }\n\n // Extract return type\n const returnType = func.returnType\n ? extractTypeName(func.returnType.typeAnnotation)\n : null;\n\n const decoratorConfig = extractMethodDecoratorConfig(node, sourceText, ctx);\n\n return {\n name,\n async: func.async,\n isStatic: node.static,\n accessibility: node.accessibility || 'public',\n parameters,\n returnType,\n description: null, // TODO: Extract JSDoc\n ...(decoratorConfig ? { decoratorConfig } : {}),\n line: node.loc?.start.line || 0,\n };\n}\n\n/**\n * Extract the config object of an `@method()` decorator on a class method.\n *\n * Read with `requireLiteralValues`, exactly like the class-level `@smrt()`\n * config: an `@method({ expose: EXPOSE_CONST })` the scanner cannot resolve\n * becomes a scan error rather than a dropped key. Dropping `expose: false`\n * silently would restore the default-routed behavior the author was\n * deliberately withholding — the same silent-widening failure mode #2100\n * closed for class configs (#2686).\n *\n * Returns `undefined` for an undecorated method, and `{}` for a bare\n * `@method()`; the two differ, so a bare decorator can still mark a method as\n * deliberately reviewed.\n */\nfunction extractMethodDecoratorConfig(\n node: MethodDefinition,\n sourceText: string,\n ctx?: DecoratorConfigContext,\n): Record<string, unknown> | undefined {\n const decorator = node.decorators?.find((d) =>\n isNamedDecorator(d, 'method', ctx?.importAliases),\n );\n if (!decorator) return undefined;\n\n const unresolvedBefore = ctx?.unresolved.length ?? 0;\n const config = extractDecoratorConfig(\n decorator,\n sourceText,\n ctx ? { ...ctx, requireLiteralValues: true } : ctx,\n );\n // `extractDecoratorConfig` pushes into the SHARED collector, which carries no\n // decorator identity of its own; label only what this call added so the\n // diagnostic names `@method()` instead of `@smrt()`.\n if (ctx) {\n for (const entry of ctx.unresolved.slice(unresolvedBefore)) {\n entry.decorator = '@method()';\n }\n }\n return config ?? {};\n}\n\n/**\n * Everything the manifest records about one parameter's declared type.\n *\n * `extractTypeName` answers a single question — \"what string names this\n * type?\" — and answers `null` both for \"there is no annotation\" and for\n * \"there is one but I cannot express it\". Consumers that must fail closed on\n * an uncertain type (the #2686 API wire-ability gate) need those two apart,\n * and they need the members of an inline object literal that the string\n * `'object'` throws away. This wraps `extractTypeName` to supply both without\n * changing what it returns anywhere else (return types, fields).\n */\ninterface ParameterTypeDescription {\n type: string | null;\n typeUnresolved: boolean;\n memberTypes?: string[];\n unionBranches?: ParameterTypeBranch[];\n}\n\n/** One branch of a top-level union, with the members IT declared (#2686). */\ninterface ParameterTypeBranch {\n type: string;\n memberTypes?: string[];\n}\n\n/** Depth bound for {@link collectInlineMemberTypes}'s literal recursion. */\nconst INLINE_MEMBER_TYPE_MAX_DEPTH = 4;\n\nfunction describeParameterType(\n annotation: TSTypeAnnotation | undefined,\n): ParameterTypeDescription {\n // No annotation at all is an implicit `any` the author genuinely wrote by\n // omission — not a scanner failure. Only an annotation that resolves to\n // nothing is unresolved.\n if (!annotation) return { type: null, typeUnresolved: false };\n\n const node = annotation.typeAnnotation;\n // The bare `object` keyword is resolvable for a parameter even though\n // `extractTypeName` leaves it unnamed for fields -- see the note on its\n // `TSNeverKeyword` case. An inline literal already reaches the manifest as\n // `'object'`, so this simply makes the keyword agree with it.\n if (node.type === 'TSObjectKeyword') {\n return { type: 'object', typeUnresolved: false };\n }\n const type = extractTypeName(node);\n if (type === null) return { type: null, typeUnresolved: true };\n\n const members: string[] = [];\n const memberUnresolved = collectInlineMemberTypes(node, members, 0);\n\n // A union's member restrictions belong to the BRANCH that declared them.\n // `collectInlineMemberTypes` flattens across branches, which lets a callback\n // in one branch veto another branch that is perfectly JSON-shaped:\n // `{ callback: () => void } | string` lost its route even though every\n // caller can pass the string. Describe each branch separately so the\n // resolver can apply \"any branch is wire-able\" as documented (#2686).\n //\n // Only emitted when every branch resolves; an unresolvable branch already\n // makes `extractTypeName` return null above, so this loop never sees one.\n let unionBranches: ParameterTypeBranch[] | undefined;\n if (node.type === 'TSUnionType') {\n const branches: ParameterTypeBranch[] = [];\n for (const branch of node.types) {\n const branchType =\n branch.type === 'TSObjectKeyword' ? 'object' : extractTypeName(branch);\n if (branchType === null) {\n // Fail closed rather than describe a union we cannot fully express.\n return { type, typeUnresolved: true };\n }\n const branchMembers: string[] = [];\n collectInlineMemberTypes(branch, branchMembers, 0);\n branches.push({\n type: branchType,\n ...(branchMembers.length > 0\n ? { memberTypes: [...new Set(branchMembers)] }\n : {}),\n });\n }\n if (branches.length > 0) unionBranches = branches;\n }\n\n return {\n type,\n typeUnresolved: memberUnresolved,\n ...(members.length > 0 ? { memberTypes: [...new Set(members)] } : {}),\n ...(unionBranches ? { unionBranches } : {}),\n };\n}\n\n/**\n * Flatten the member types of every INLINE object literal reachable from\n * `node` into `out`, returning whether any member's own type was unresolvable.\n *\n * Only inline literals are expanded. A named interface, type alias, or\n * `Partial<>`/`Pick<>` wrapper is left alone: resolving those needs cross-file\n * type resolution this AST layer deliberately does not do.\n */\nfunction collectInlineMemberTypes(\n node: TSType,\n out: string[],\n depth: number,\n): boolean {\n if (depth > INLINE_MEMBER_TYPE_MAX_DEPTH) return false;\n\n switch (node.type) {\n case 'TSTypeLiteral': {\n let unresolved = false;\n for (const member of node.members) {\n // A method signature IS a callable member, the same hazard an\n // explicit `() => void` property is.\n if (member.type === 'TSMethodSignature') {\n out.push('Function');\n continue;\n }\n const memberAnnotation = member.typeAnnotation;\n if (!memberAnnotation) continue;\n const memberType = extractTypeName(memberAnnotation.typeAnnotation);\n if (memberType === null) {\n unresolved = true;\n continue;\n }\n out.push(memberType);\n if (\n collectInlineMemberTypes(\n memberAnnotation.typeAnnotation,\n out,\n depth + 1,\n )\n ) {\n unresolved = true;\n }\n }\n return unresolved;\n }\n case 'TSArrayType':\n return collectInlineMemberTypes(node.elementType, out, depth + 1);\n case 'TSUnionType': {\n let unresolved = false;\n for (const branch of node.types) {\n if (collectInlineMemberTypes(branch, out, depth + 1)) unresolved = true;\n }\n return unresolved;\n }\n case 'TSTypeReference': {\n let unresolved = false;\n const typeParams =\n node.typeArguments?.params || node.typeParameters?.params;\n for (const param of typeParams ?? []) {\n if (collectInlineMemberTypes(param, out, depth + 1)) unresolved = true;\n }\n return unresolved;\n }\n default:\n return false;\n }\n}\n\n/**\n * Extract parameter definition\n */\nfunction extractParameter(\n param: Pattern,\n sourceText: string,\n): RawParameterDefinition | null {\n // Handle assignment pattern (default value)\n if (param.type === 'AssignmentPattern') {\n const left = param.left;\n if (left.type === 'Identifier') {\n return {\n name: left.name,\n ...describeParameterTypeFields(left.typeAnnotation),\n optional: true,\n defaultValue: sliceSource(param.right, sourceText),\n };\n }\n // Handle destructured parameter with default\n if (left.type === 'ObjectPattern' || left.type === 'ArrayPattern') {\n return {\n name: 'options',\n ...describeParameterTypeFields(left.typeAnnotation, 'any'),\n optional: true,\n defaultValue: sliceSource(param.right, sourceText),\n };\n }\n return null;\n }\n\n // Handle rest parameter\n if (param.type === 'RestElement') {\n const arg = param.argument;\n if (arg.type === 'Identifier') {\n return {\n name: `...${arg.name}`,\n ...describeParameterTypeFields(param.typeAnnotation),\n optional: true,\n defaultValue: null,\n };\n }\n return null;\n }\n\n // Handle simple identifier\n if (param.type === 'Identifier') {\n return {\n name: param.name,\n ...describeParameterTypeFields(param.typeAnnotation),\n optional: param.optional || false,\n defaultValue: null,\n };\n }\n\n // Handle object pattern (destructured)\n if (param.type === 'ObjectPattern') {\n return {\n name: 'options',\n ...describeParameterTypeFields(param.typeAnnotation, 'any'),\n optional: false,\n defaultValue: null,\n };\n }\n\n return null;\n}\n\n/**\n * The `type`/`typeUnresolved`/`memberTypes` triple for one parameter, with the\n * optional keys omitted entirely when they carry no information -- keeping the\n * emitted manifest byte-identical for the overwhelming majority of parameters\n * that have a plain resolvable type.\n *\n * `missingAnnotationType` is the historical fallback the destructured-parameter\n * branches use (`'any'` rather than `null`); an absent annotation is never\n * \"unresolved\" in either branch.\n */\nfunction describeParameterTypeFields(\n annotation: TSTypeAnnotation | undefined,\n missingAnnotationType: string | null = null,\n): Pick<\n RawParameterDefinition,\n 'type' | 'typeUnresolved' | 'memberTypes' | 'unionBranches'\n> {\n if (!annotation) return { type: missingAnnotationType };\n const described = describeParameterType(annotation);\n return {\n type: described.type,\n ...(described.typeUnresolved ? { typeUnresolved: true } : {}),\n ...(described.memberTypes ? { memberTypes: described.memberTypes } : {}),\n ...(described.unionBranches\n ? { unionBranches: described.unionBranches }\n : {}),\n };\n}\n","/**\n * Manifest Adapter\n *\n * Converts OXC scanner output to smrt-core manifest format.\n * Ensures compatibility with existing manifest consumers.\n */\n\nimport { isSafeObjectKey } from './oxc-parser.js';\nimport type {\n FieldTypeInference,\n InferredFieldType,\n ParameterTypeBranch,\n RawFieldDefinition,\n RawMethodDefinition,\n ResolvedClassDefinition,\n} from './types.js';\n\n// ============================================================================\n// smrt-core compatible types (copied to avoid circular dependency)\n// ============================================================================\n\n/**\n * Qualified class name format: \"@package/name:ClassName\"\n * Uniquely identifies classes across packages.\n */\ntype QualifiedClassName = `${string}:${string}`;\n\ninterface FieldDefinition {\n type:\n | 'text'\n | 'decimal'\n | 'boolean'\n | 'integer'\n | 'datetime'\n | 'json'\n | 'foreignKey'\n | 'crossPackageRef'\n | 'oneToMany'\n | 'manyToMany'\n | 'meta';\n required?: boolean;\n default?: unknown;\n min?: number;\n max?: number;\n maxLength?: number;\n minLength?: number;\n related?: string;\n description?: string;\n _meta?: Record<string, unknown>;\n transient?: boolean;\n /** Sensitive value — excluded from public serialization + where filtering. */\n sensitive?: boolean;\n /** Read-only over generated write surfaces — stripped from create/update bodies. */\n readonly?: boolean;\n /** Permission slug required before the field is included in public reads. */\n readPermission?: string;\n}\n\ntype FieldDecoratorOptions = {\n type?: FieldDefinition['type'];\n required?: boolean;\n nullable?: boolean;\n default?: unknown;\n min?: number;\n max?: number;\n maxLength?: number;\n minLength?: number;\n related?: string;\n /** oneToMany explicit inverse foreign-key field on the target class */\n foreignKey?: string;\n description?: string;\n transient?: boolean;\n unique?: boolean;\n /** crossPackageRef opt-in save-time validation */\n validate?: boolean;\n /** Physical foreign-key constraint engine allowlist. */\n constraint?:\n | boolean\n | { engines: Array<'postgres' | 'sqlite' | 'duckdb' | 'json'> };\n /** manyToMany junction table name */\n through?: string;\n /** manyToMany override of the source-side join column */\n sourceKey?: string;\n /** manyToMany override of the target-side join column */\n targetKey?: string;\n /** meta opt-in JSON-path index */\n indexed?: boolean;\n /** sensitive value — excluded from public serialization + where filtering */\n sensitive?: boolean;\n /** read-only over generated write surfaces */\n readonly?: boolean;\n /** permission slug required before the field is included in public reads */\n readPermission?: string;\n /** report grouping/bucket/aggregate metadata */\n __report?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\ninterface MethodDefinition {\n name: string;\n async: boolean;\n parameters: Array<{\n name: string;\n type: string;\n optional: boolean;\n default?: unknown;\n /** See `RawParameterDefinition.typeUnresolved` (#2686). */\n typeUnresolved?: boolean;\n /** See `RawParameterDefinition.memberTypes` (#2686). */\n memberTypes?: string[];\n /** See `RawParameterDefinition.unionBranches` (#2686). */\n unionBranches?: ParameterTypeBranch[];\n }>;\n returnType: string;\n description?: string;\n isStatic: boolean;\n isPublic: boolean;\n /** Config of an `@method()` decorator on this method (#2686). */\n decoratorConfig?: Record<string, unknown>;\n}\n\ninterface SmartObjectConfig {\n tableStrategy?: 'sti' | 'cti';\n idType?: 'uuid' | 'text';\n features?: Record<\n string,\n {\n defaultEnabled: boolean;\n label?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n }\n >;\n api?: {\n include?: string[];\n exclude?: string[];\n };\n cli?:\n | boolean\n | {\n include?: string[];\n exclude?: string[];\n skipApiCheck?: boolean;\n http?: boolean;\n };\n mcp?: {\n include?: string[];\n exclude?: string[];\n };\n [key: string]: unknown;\n}\n\ninterface SmartObjectDefinition {\n name: string;\n className: string;\n qualifiedName?: QualifiedClassName; // NEW: @package/name:ClassName for namespace isolation (Issue #713)\n collection: string;\n filePath: string;\n packageName?: string;\n packageVersion?: string;\n importPath?: string;\n modulePath?: string;\n exportName?: string;\n collectionExportName?: string;\n fields: Record<string, FieldDefinition>;\n methods: Record<string, MethodDefinition>;\n decoratorConfig: SmartObjectConfig;\n extends?: string;\n extendsTypeArg?: string;\n staticProperties?: Record<string, unknown>;\n}\n\n/**\n * Fixed `timestamp` for generated manifests.\n *\n * The manifest this adapter returns is inlined verbatim into every package\n * bundle by smrt-core's Vite plugin, so a wall-clock value changes the emitted\n * bytes on every build. That changes Vite's content hash, which changes\n * `dist/`, which invalidates every downstream package through Turbo's\n * `dependsOn: ['^build']` — one rebuilt package churned 202 of 245 task\n * hashes, and `typecheck` never reused a cache entry across runs (#2223).\n *\n * Nothing reads the field: manifest invalidation uses filesystem mtimes, and\n * smrt-core's knowledge hashing deletes it before comparing.\n *\n * smrt-core declares the same constant as `MANIFEST_TIMESTAMP`; it is\n * duplicated here rather than imported because this package deliberately does\n * not depend on smrt-core.\n */\nconst MANIFEST_TIMESTAMP = 0;\n\ninterface SmartObjectManifest {\n version: string;\n /** Always {@link MANIFEST_TIMESTAMP}: build output must be reproducible. */\n timestamp: number;\n packageName?: string;\n packageVersion?: string;\n objects: Record<string, SmartObjectDefinition>;\n moduleType?: string;\n smrtDependencies?: string[];\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Property keys that must never appear as own properties on a manifest object.\n * Object literals authored as `{ constructor: ... }` or `{ prototype: ... }`\n * produce real own keys; spreading such a parsed object into a manifest\n * `_meta` / `staticProperties` entry (or assigning it under a class field name)\n * would carry a prototype-pollution gadget into the emitted JSON.\n */\n/**\n * Recursively strip prototype-pollution keys (via the shared\n * {@link isSafeObjectKey} guard — single source of truth with oxc-parser) from a\n * value parsed out of source. Returns a new plain object/array; primitives and\n * built-in objects pass through unchanged.\n */\nfunction sanitizeParsed(value: unknown, seen = new WeakSet<object>()): unknown {\n if (value === null || typeof value !== 'object') return value;\n\n const isArray = Array.isArray(value);\n // Preserve built-ins (Date, RegExp, Map, …) intact. They carry no\n // attacker-controlled own keys, and iterating their enumerable keys would\n // silently turn e.g. `@field({ default: new Date() })` into `{}` (review #1559).\n const proto = Object.getPrototypeOf(value);\n if (!isArray && proto !== Object.prototype && proto !== null) return value;\n\n // Cycle guard: a cyclic literal (e.g. an IIFE returning a self-referential\n // object) would otherwise recurse forever and hang the build (review #1559).\n if (seen.has(value as object)) return undefined;\n seen.add(value as object);\n\n if (isArray) {\n return (value as unknown[]).map((item) => sanitizeParsed(item, seen));\n }\n const clean: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n if (!isSafeObjectKey(key)) continue;\n clean[key] = sanitizeParsed((value as Record<string, unknown>)[key], seen);\n }\n return clean;\n}\n\n/**\n * Parse a JavaScript literal (object or array) from source text.\n *\n * Uses the Function constructor to evaluate literal syntax at build time.\n * This is intentional — AST-based extraction can't handle computed keys,\n * template literals, or spread syntax that may appear in static initializers.\n *\n * The parsed result is run through {@link sanitizeParsed} to strip\n * prototype-pollution keys (`__proto__` / `constructor` / `prototype`) before\n * it is merged into a manifest object.\n *\n * WARNING: This executes the source text. It is only safe when scanning\n * your own trusted codebase at build time. Never run the scanner against\n * untrusted third-party code.\n */\nfunction parseLiteralInitializer(\n source: string,\n): Record<string, unknown> | unknown[] | null {\n const trimmed = source?.trim();\n if (!trimmed || (!trimmed.startsWith('{') && !trimmed.startsWith('[')))\n return null;\n try {\n // Use indirect eval via Function to parse the object/array literal\n // This runs at build time only, on trusted source code from our own codebase\n // The existing pattern (unchanged) uses Function constructor for object literal parsing\n // eslint-disable-next-line no-new-func\n const parsed = new Function(`return (${source})`)() as\n | Record<string, unknown>\n | unknown[];\n return sanitizeParsed(parsed) as Record<string, unknown> | unknown[];\n } catch {\n return null;\n }\n}\n\n/**\n * Strip surrounding quotes from a raw source string.\n * sliceSource() returns raw source text which includes quotes for string\n * literals (e.g., \"'TestProfile'\" or '\"TestProfile\"').\n */\nfunction stripQuotes(value: string | undefined): string | undefined {\n if (!value) return value;\n const match = value.match(/^(['\"`])(.+)\\1$/);\n return match ? match[2] : value;\n}\n\n/** A quoted string literal in raw decorator source: `'Target'` / `\"Target\"`. */\nconst QUOTED_LITERAL_PATTERN = /^(['\"`])(.*)\\1$/s;\n\n/**\n * A bare class reference: `Target`, or the dotted `Target.column` form the\n * schema generator splits on.\n */\nconst RELATED_TARGET_PATTERN = /^[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*$/;\n\n/**\n * A forward-reference thunk argument: `() => Target`, `() => Target.column`, or\n * the block-bodied `() => { return Target; }`. The scanner only ever sees raw\n * source text, so the thunk has to be unwrapped textually — parameterised\n * arrows are not relationship targets and fall through to the reject path\n * below.\n */\nconst RELATED_THUNK_PATTERN =\n /^\\(\\s*\\)\\s*=>\\s*(?:([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)|\\{\\s*return\\s+([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)\\s*;?\\s*\\})$/;\n\n/**\n * Resolve a relationship decorator's first argument (raw source text) to the\n * target class name stored as `related`.\n *\n * Handles the three supported call forms — `@foreignKey('Target')`,\n * `@foreignKey(Target)` and the forward-reference thunk `@foreignKey(() =>\n * Target)` — so the manifest path agrees with the runtime decorator, which\n * resolves the same thunk by invoking it (issue #2379). Without this, thunk\n * call sites stored the literal `\"() => Target\"` source in `related`, which\n * resolves to no class and yields a garbage FK table name (and, once FK\n * columns are indexed, a garbage index).\n *\n * String literals pass through verbatim, matching the runtime decorator, which\n * accepts any non-empty name. A bare expression that is neither an identifier\n * nor a thunk (a call, a computed reference) is rejected as `undefined` rather\n * than written through: an unresolvable `related` produces invalid schema, and\n * the runtime decorator throws on the same source.\n */\nfunction resolveRelatedArgument(raw: string | undefined): string | undefined {\n const value = raw?.trim();\n if (!value) return undefined;\n\n const quoted = value.match(QUOTED_LITERAL_PATTERN);\n if (quoted) return quoted[2].trim() || undefined;\n\n if (RELATED_TARGET_PATTERN.test(value)) return value;\n\n const thunk = value.match(RELATED_THUNK_PATTERN);\n return thunk ? (thunk[1] ?? thunk[2]) : undefined;\n}\n\n// ============================================================================\n// Manifest Adapter\n// ============================================================================\n\n/**\n * Create a qualified name for a class (namespace isolation - Issue #713)\n * Format: @package/name:ClassName\n */\nfunction createQualifiedName(\n packageName: string,\n className: string,\n): QualifiedClassName {\n return `${packageName}:${className}` as QualifiedClassName;\n}\n\n/**\n * Converts OXC scanner output into the smrt-core `SmartObjectManifest` format\n * consumed by code generators, the Vitest plugin, and the SMRT CLI.\n *\n * The adapter handles field type inference (applying the `0` vs `0.0` integer /\n * decimal heuristic), decorator interpretation (`@foreignKey`, `@oneToMany`,\n * `@manyToMany`, `@field`), type alias resolution, STI `Meta<T>` unwrapping,\n * static property capture (`uiSlots`, `adminRoutes`), and qualified name\n * generation for namespace isolation across packages.\n *\n * @example\n * ```typescript\n * import { OxcScanner, ManifestAdapter } from '@happyvertical/smrt-scanner';\n *\n * const scanner = new OxcScanner({ cwd: process.cwd() });\n * const { results, resolved } = await scanner.scanAndResolve();\n *\n * const adapter = new ManifestAdapter();\n * const manifest = adapter.toManifest(resolved, {\n * packageName: '@my-org/my-package',\n * packageVersion: '1.0.0',\n * typeAliases: results.typeAliases,\n * });\n * ```\n *\n * @see {@link OxcScanner} for producing the `ResolvedClassDefinition[]` input.\n * @see {@link ResolvedClassDefinition} for the shape of each input element.\n */\nexport class ManifestAdapter {\n private typeAliases: Record<string, string> = {};\n private _aliasDepth?: number;\n\n /**\n * Convert an array of resolved class definitions into a `SmartObjectManifest`.\n *\n * Each class is converted to a `SmartObjectDefinition` via\n * {@link toSmartObjectDefinition} and stored under its qualified name key\n * (e.g. `@my-org/my-package:MyClass`) when `packageName` is provided, or\n * under its lowercased class name otherwise.\n *\n * @param resolved - Resolved class definitions from {@link OxcScanner.resolve}\n * or {@link OxcScanner.scanAndResolve}.\n * @param options.packageName - npm package name used to generate qualified\n * class names for namespace isolation across multi-package projects.\n * @param options.packageVersion - Package version recorded in the manifest\n * metadata.\n * @param options.typeAliases - Map of type alias names to their resolved type\n * strings (from {@link ScanResults.typeAliases}). Used to resolve custom\n * types like `type Status = 'active' | 'inactive'` during field inference.\n * @returns A complete `SmartObjectManifest` ready for serialisation.\n *\n * @example\n * ```typescript\n * const manifest = adapter.toManifest(resolved, {\n * packageName: '@my-org/my-package',\n * packageVersion: '1.0.0',\n * typeAliases: results.typeAliases,\n * });\n * fs.writeFileSync('manifest.json', JSON.stringify(manifest, null, 2));\n * ```\n */\n toManifest(\n resolved: ResolvedClassDefinition[],\n options: {\n packageName?: string;\n packageVersion?: string;\n typeAliases?: Record<string, string>;\n } = {},\n ): SmartObjectManifest {\n this.typeAliases = options.typeAliases || {};\n const objects: Record<string, SmartObjectDefinition> = {};\n\n for (const classDef of resolved) {\n const definition = this.toSmartObjectDefinition(classDef, options);\n\n // Use qualified name as key if packageName is available (Issue #713)\n // This enables namespace isolation for multi-package scenarios\n const manifestKey =\n definition.qualifiedName || definition.name.toLowerCase();\n objects[manifestKey] = definition;\n }\n\n return {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n packageName: options.packageName,\n packageVersion: options.packageVersion,\n objects,\n moduleType: 'smrt',\n };\n }\n\n /**\n * Convert a single resolved class definition to a `SmartObjectDefinition`.\n *\n * Handles:\n * - Static property capture (`uiSlots`, `adminRoutes`) with child-wins\n * semantics for overridden statics.\n * - Field conversion (non-static public fields only) via {@link convertField}.\n * - Method conversion (public instance/static methods) via {@link convertMethod}.\n * - Collection name pluralisation.\n * - Qualified name generation when `packageName` is supplied.\n *\n * @param classDef - A fully-resolved class definition.\n * @param options.packageName - Package name used to build the qualified class\n * name (`@pkg:ClassName`).\n * @param options.packageVersion - Package version (informational, stored in\n * the definition).\n * @returns A `SmartObjectDefinition` ready to be stored in a manifest.\n *\n * @see {@link toManifest} for the bulk conversion entry point.\n */\n toSmartObjectDefinition(\n classDef: ResolvedClassDefinition,\n options: { packageName?: string; packageVersion?: string } = {},\n ): SmartObjectDefinition {\n // Extract static properties (e.g., uiSlots, adminRoutes on Agent subclasses)\n // Use own fields (classDef.fields) not allFields — static properties use\n // child-wins semantics (static override), not parent-wins like STI columns.\n // Fall back to allFields for inherited static props not redeclared by child.\n let staticProperties: Record<string, unknown> | undefined;\n const knownStaticProps = ['uiSlots', 'adminRoutes', 'signalSubscriptions'];\n const ownStaticNames = new Set<string>();\n // First pass: own fields (child overrides win)\n for (const field of classDef.fields) {\n if (\n field.isStatic &&\n knownStaticProps.includes(field.name) &&\n field.initializer\n ) {\n try {\n const parsed = parseLiteralInitializer(field.initializer);\n if (parsed) {\n if (!staticProperties) staticProperties = {};\n staticProperties[field.name] = parsed;\n ownStaticNames.add(field.name);\n }\n } catch {\n // Failed to parse static property initializer — skip\n }\n }\n }\n // Second pass: inherited fields for any static props not overridden\n for (const field of classDef.allFields) {\n if (\n field.isStatic &&\n knownStaticProps.includes(field.name) &&\n field.initializer\n ) {\n if (ownStaticNames.has(field.name)) continue;\n try {\n const parsed = parseLiteralInitializer(field.initializer);\n if (parsed) {\n if (!staticProperties) staticProperties = {};\n staticProperties[field.name] = parsed;\n }\n } catch {\n // Failed to parse static property initializer — skip\n }\n }\n }\n\n // Convert fields (skip static fields — they're not database columns)\n const fields: Record<string, FieldDefinition> = {};\n for (const field of classDef.allFields) {\n if (field.isStatic) continue;\n const converted = this.convertField(field);\n if (converted) {\n fields[field.name] = converted;\n }\n }\n\n // Convert methods\n const methods: Record<string, MethodDefinition> = {};\n for (const method of classDef.methods) {\n const converted = this.convertMethod(method);\n if (converted) {\n methods[method.name] = converted;\n }\n }\n\n // Generate collection name (pluralize)\n const collection = this.pluralize(classDef.className);\n\n // Determine package name (prefer option, then classDef value)\n const packageName = options.packageName || classDef.packageName;\n\n // Generate qualified name if packageName is available (Issue #713)\n // Format: @package/name:ClassName for namespace isolation\n const qualifiedName = packageName\n ? createQualifiedName(packageName, classDef.className)\n : undefined;\n\n return {\n name: classDef.className.toLowerCase(),\n className: classDef.className,\n qualifiedName,\n collection,\n filePath: classDef.filePath,\n packageName: packageName || undefined,\n fields,\n methods,\n decoratorConfig: (classDef.decoratorConfig || {}) as SmartObjectConfig,\n extends: classDef.extendsClause || undefined,\n extendsTypeArg: classDef.extendsTypeArg || undefined,\n exportName: classDef.className,\n collectionExportName: `${classDef.className}Collection`,\n staticProperties,\n };\n }\n\n /**\n * Framework internal fields that should NOT be included in manifests\n * These are SmrtObject internals used by the framework, not user-defined fields\n */\n private static readonly FRAMEWORK_INTERNAL_FIELDS = new Set([\n '_tableName',\n 'options',\n '_loadedRelationships',\n '_db',\n '_ai',\n '_fs',\n '_isInitialized',\n '_errors',\n '_warnings',\n ]);\n\n /**\n * Convert a single raw field definition to a manifest `FieldDefinition`.\n *\n * Returns `null` for fields that should be omitted from the manifest:\n * - `private` or `protected` fields.\n * - Framework-internal fields (`_tableName`, `_db`, `_ai`, etc.).\n *\n * Delegates type inference to {@link inferFieldType} and applies additional\n * post-processing:\n * - Marks fields with `Function` type annotation as `transient`.\n * - Marks fields with `@field({ transient: true })` decorator as `transient`.\n * - Populates `_meta.underlyingType` for STI `Meta<T>` fields.\n *\n * @param field - Raw field definition from a scanned class.\n * @returns A `FieldDefinition` for the manifest, or `null` if the field\n * should be excluded.\n *\n * @see {@link inferFieldType} for the type inference logic.\n */\n convertField(field: RawFieldDefinition): FieldDefinition | null {\n // Skip private/protected fields\n if (field.accessibility !== 'public') {\n return null;\n }\n\n // Skip framework internal fields (SmrtObject internals)\n if (ManifestAdapter.FRAMEWORK_INTERNAL_FIELDS.has(field.name)) {\n return null;\n }\n\n // Check if field is a function type (automatically transient)\n const isFunctionType = field.typeAnnotation === 'Function';\n const fieldDecoratorOptions = this.extractFieldDecoratorOptions(field);\n\n const inference = this.inferFieldType(field);\n\n const definition: FieldDefinition = {\n type: inference.type as FieldDefinition['type'],\n required: inference.required,\n };\n\n if (inference.related) {\n definition.related = inference.related;\n }\n\n if (inference.defaultValue !== undefined) {\n definition.default = inference.defaultValue;\n }\n\n // Apply generic @field({...}) options to preserve manifest metadata used by\n // schema generation and runtime decorator merging.\n if (fieldDecoratorOptions.type) {\n definition.type = fieldDecoratorOptions.type;\n }\n\n if (fieldDecoratorOptions.nullable === true) {\n definition.required = false;\n } else if (fieldDecoratorOptions.required !== undefined) {\n definition.required = fieldDecoratorOptions.required;\n }\n\n if (fieldDecoratorOptions.default !== undefined) {\n definition.default = fieldDecoratorOptions.default;\n }\n\n if (fieldDecoratorOptions.related !== undefined) {\n definition.related = fieldDecoratorOptions.related;\n }\n\n if (fieldDecoratorOptions.description !== undefined) {\n definition.description = fieldDecoratorOptions.description;\n }\n\n if (fieldDecoratorOptions.min !== undefined) {\n definition.min = fieldDecoratorOptions.min;\n }\n\n if (fieldDecoratorOptions.max !== undefined) {\n definition.max = fieldDecoratorOptions.max;\n }\n\n if (fieldDecoratorOptions.minLength !== undefined) {\n definition.minLength = fieldDecoratorOptions.minLength;\n }\n\n if (fieldDecoratorOptions.maxLength !== undefined) {\n definition.maxLength = fieldDecoratorOptions.maxLength;\n }\n\n if (Object.keys(fieldDecoratorOptions).length > 0) {\n definition._meta = {\n ...definition._meta,\n ...fieldDecoratorOptions,\n };\n\n if (definition._meta?.type) {\n delete definition._meta.type;\n }\n\n if (definition.related !== undefined && definition._meta?.related) {\n delete definition._meta.related;\n }\n }\n\n // Carry through decorator-derived _meta (validate, through, indexed, etc.)\n if (inference._meta && Object.keys(inference._meta).length > 0) {\n definition._meta = {\n ...definition._meta,\n ...inference._meta,\n };\n }\n\n // For meta fields, store the underlying type for hydration coercion\n if (inference.underlyingType) {\n definition._meta = {\n ...definition._meta,\n underlyingType: inference.underlyingType,\n };\n }\n\n // Mark function type fields as transient (not persisted to database)\n if (isFunctionType) {\n definition.transient = true;\n }\n\n if (fieldDecoratorOptions.transient === true) {\n definition.transient = true;\n }\n\n // Promote security markers to first-class manifest metadata (also retained\n // in `_meta` via the spread above). Honored by `toPublicJSON()` and the\n // collection `where` builder at runtime.\n if (fieldDecoratorOptions.sensitive === true) {\n definition.sensitive = true;\n }\n\n if (fieldDecoratorOptions.readonly === true) {\n definition.readonly = true;\n }\n\n if (typeof fieldDecoratorOptions.readPermission === 'string') {\n definition.readPermission = fieldDecoratorOptions.readPermission;\n }\n\n return definition;\n }\n\n /**\n * Infer the SMRT field type and required flag from a raw field definition.\n *\n * Inference is attempted in the following priority order:\n * 1. **Field helper call in initializer** — currently always returns `null`\n * (field helpers removed); reserved for future use.\n * 2. **Decorator** — `@foreignKey`, `@oneToMany`, `@manyToMany`, `@field({ type })`.\n * 3. **Type annotation** — `string` → `text`, `number` with `0` vs `0.0`\n * heuristic → `integer` / `decimal`, `boolean`, `Date` → `datetime`,\n * arrays → `json`, `Record<>` / `object` → `json`, union types with\n * `null`, inline string/number literal unions, `Meta<T>` wrapper,\n * and type alias resolution (up to depth 5).\n * 4. **Numeric literal without annotation** — `version = 1` → `integer`.\n * 5. **Boolean literal without annotation** — `isRead = false` → `boolean`.\n * 6. **Default** — falls back to `text`.\n *\n * @param field - The raw field definition to analyse.\n * @returns A {@link FieldTypeInference} describing the inferred type,\n * required flag, default value, related class name (for relationships),\n * and the inference source for debugging.\n *\n * @see {@link FieldTypeInference} for the result shape.\n * @see {@link InferredFieldType} for valid type values.\n */\n inferFieldType(field: RawFieldDefinition): FieldTypeInference {\n // 1. Check for field helper calls in initializer\n if (field.initializer) {\n const helperResult = this.inferFromHelper(field.initializer);\n if (helperResult) {\n return helperResult;\n }\n }\n\n // 2. Check decorators\n for (const decorator of field.decorators) {\n const decoratorResult = this.inferFromDecorator(decorator, field);\n if (decoratorResult) {\n return decoratorResult;\n }\n }\n\n // 3. Use type annotation with 0 vs 0.0 heuristic\n if (field.typeAnnotation) {\n return this.inferFromAnnotation(field);\n }\n\n // 3.5. Infer from numeric literal without type annotation\n // Handles cases like `version = 1` where there's no `: number` annotation\n if (field.numericValue !== null) {\n const fieldType: InferredFieldType = field.hasDecimalPoint\n ? 'decimal'\n : 'integer';\n return {\n type: fieldType,\n required: !field.optional,\n defaultValue: field.numericValue,\n source: 'heuristic',\n };\n }\n\n // 3.6. Infer from boolean literal without type annotation\n // Handles cases like `isRead = false` where there's no `: boolean` annotation\n if (field.initializer === 'true' || field.initializer === 'false') {\n return {\n type: 'boolean',\n required: !field.optional,\n defaultValue: field.initializer === 'true',\n source: 'heuristic',\n };\n }\n\n // 4. Default to text\n // A field is only required if it has no default value AND is not optional (?)\n // Fields with initializers (default values) should NOT be required\n const hasDefaultValue = field.initializer !== null;\n return {\n type: 'text',\n required: !field.optional && !hasDefaultValue,\n source: 'default',\n };\n }\n\n /**\n * Infer type from field helper call (removed)\n *\n * Field helpers have been removed in favor of decorators and TypeScript types:\n * - Use TypeScript types: name: string = '', price: number = 0.0\n * - Use @field() decorator for constraints: @field({ required: true })\n * - Use @foreignKey(), @oneToMany(), @manyToMany() decorators for relationships\n */\n private inferFromHelper(_initializer: string): FieldTypeInference | null {\n return null;\n }\n\n /**\n * Infer type from field decorator\n */\n private inferFromDecorator(\n decorator: {\n name: string;\n arguments: string[];\n },\n field: RawFieldDefinition,\n ): FieldTypeInference | null {\n // @field decorator with type config\n if (decorator.name === 'field' && decorator.arguments.length > 0) {\n const fieldOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const type = this.normalizeFieldType(fieldOptions?.type);\n\n if (type) {\n const hasDefaultValue =\n field.initializer !== null || fieldOptions?.default !== undefined;\n let required = !field.optional && !hasDefaultValue;\n\n if (fieldOptions?.nullable === true) {\n required = false;\n } else if (fieldOptions?.required !== undefined) {\n required = fieldOptions.required;\n }\n\n return {\n type,\n required,\n defaultValue: fieldOptions?.default,\n related:\n typeof fieldOptions?.related === 'string'\n ? fieldOptions.related\n : undefined,\n source: 'decorator',\n };\n }\n }\n\n // @meta({ indexed?, required?, nullable?, ... }) decorator — flags the\n // field as STI meta storage AND preserves opt-in options like `indexed`\n // so the manifest-only schema path can emit the JSON-path index.\n if (decorator.name === 'meta') {\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const hasDefaultValue = field.initializer !== null;\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.indexed !== undefined)\n meta.indexed = parsedOptions.indexed;\n if (parsedOptions?.nullable !== undefined)\n meta.nullable = parsedOptions.nullable;\n return {\n type: 'meta',\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @foreignKey(RelatedClass) decorator\n if (decorator.name === 'foreignKey') {\n // First argument is the related class — a name string, a class\n // reference, or a `() => Target` forward-reference thunk. sliceSource()\n // returns raw source text, so quotes and thunk syntax are unwrapped here\n // (issue #2379).\n const relatedClass = resolveRelatedArgument(decorator.arguments[0]);\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n const META_KEYS = [\n 'required',\n 'nullable',\n 'unique',\n 'description',\n 'default',\n 'constraint',\n ] as const;\n if (parsedOptions) {\n for (const key of META_KEYS) {\n if (parsedOptions[key] !== undefined) {\n meta[key] = parsedOptions[key];\n }\n }\n }\n // Respect TypeScript optional marker (?) - fixes #846\n const hasDefaultValue = field.initializer !== null;\n return {\n type: 'foreignKey',\n related: relatedClass || undefined,\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @tenantId({ nullable?, required?, autoFilter?, autoPopulate? }) decorator\n if (decorator.name === 'tenantId') {\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const nullable = parsedOptions?.nullable === true;\n const required =\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !nullable;\n\n return {\n type: 'text',\n required,\n _meta: {\n sqlType: 'UUID',\n ...(parsedOptions ?? {}),\n __tenancy: {\n isTenantIdField: true,\n autoFilter: parsedOptions?.autoFilter ?? true,\n required,\n autoPopulate: parsedOptions?.autoPopulate ?? true,\n nullable,\n },\n },\n source: 'decorator',\n };\n }\n\n // @crossPackageRef('@pkg:Class', { validate?, unique?, nullable?, default?, description? }) decorator\n if (decorator.name === 'crossPackageRef') {\n const qualifiedName = stripQuotes(decorator.arguments[0]?.trim());\n const hasDefaultValue = field.initializer !== null;\n // Preserve every standard field option from the second argument so\n // manifest-only consumers generate the same schema/constraints that\n // the runtime decorator would produce.\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n const META_KEYS = [\n 'validate',\n 'nullable',\n 'unique',\n 'description',\n 'default',\n 'indexed',\n 'idType',\n ] as const;\n if (parsedOptions) {\n for (const key of META_KEYS) {\n if (parsedOptions[key] !== undefined) {\n meta[key] = parsedOptions[key];\n }\n }\n }\n return {\n type: 'crossPackageRef',\n related: qualifiedName || undefined,\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @oneToMany(RelatedClass, { foreignKey? }) decorator\n if (decorator.name === 'oneToMany') {\n const relatedClass = resolveRelatedArgument(decorator.arguments[0]);\n // Preserve an explicit inverse `foreignKey` so manifest-only consumers\n // disambiguate the inverse side the same way the runtime decorator does\n // (needed when the target declares multiple FKs back to this class).\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.foreignKey !== undefined) {\n meta.foreignKey = parsedOptions.foreignKey;\n }\n return {\n type: 'oneToMany',\n related: relatedClass || undefined,\n required: false,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @manyToMany(RelatedClass, { through?, sourceKey?, targetKey? }) decorator\n if (decorator.name === 'manyToMany') {\n const relatedClass = resolveRelatedArgument(decorator.arguments[0]);\n // Preserve junction-table coordinates so manifest-only consumers can\n // execute manyToMany loads without the decorator firing in-process.\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.through !== undefined)\n meta.through = parsedOptions.through;\n if (parsedOptions?.sourceKey !== undefined)\n meta.sourceKey = parsedOptions.sourceKey;\n if (parsedOptions?.targetKey !== undefined)\n meta.targetKey = parsedOptions.targetKey;\n return {\n type: 'manyToMany',\n related: relatedClass || undefined,\n required: false,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n return null;\n }\n\n private extractFieldDecoratorOptions(\n field: RawFieldDefinition,\n ): FieldDecoratorOptions {\n const options: FieldDecoratorOptions = {};\n\n for (const decorator of field.decorators) {\n const reportMetadata = this.parseReportFieldDecorator(decorator, field);\n if (reportMetadata) {\n options.__report = reportMetadata;\n continue;\n }\n\n if (decorator.name !== 'field') continue;\n\n const parsed = this.parseFieldDecoratorOptions(decorator.arguments[0]);\n if (parsed) {\n Object.assign(options, parsed);\n }\n }\n\n return options;\n }\n\n private parseReportFieldDecorator(\n decorator: { name: string; arguments: string[] },\n field: RawFieldDefinition,\n ): Record<string, unknown> | null {\n if (decorator.name === 'groupBy') {\n return {\n kind: 'group',\n sourceColumn: stripQuotes(decorator.arguments[0]?.trim()) ?? field.name,\n };\n }\n\n const bucketUnits = new Set([\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n 'quarter',\n 'year',\n ]);\n if (bucketUnits.has(decorator.name)) {\n const sourceColumn = stripQuotes(decorator.arguments[0]?.trim());\n if (!sourceColumn) return null;\n return {\n kind: 'bucket',\n unit: decorator.name,\n sourceColumn,\n };\n }\n\n if (decorator.name === 'aggregate') {\n const parsed = this.parseFieldDecoratorOptions(decorator.arguments[0]);\n if (!parsed?.fn || typeof parsed.fn !== 'string') return null;\n return {\n kind: 'aggregate',\n fn: parsed.fn,\n ...(typeof parsed.column === 'string' ? { column: parsed.column } : {}),\n ...(typeof parsed.distinct === 'boolean'\n ? { distinct: parsed.distinct }\n : {}),\n };\n }\n\n const aggregateNames = new Set(['sum', 'avg', 'min', 'max']);\n if (aggregateNames.has(decorator.name)) {\n const column = stripQuotes(decorator.arguments[0]?.trim());\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n return {\n kind: 'aggregate',\n fn: decorator.name,\n ...(column ? { column } : {}),\n ...(typeof parsedOptions?.distinct === 'boolean'\n ? { distinct: parsedOptions.distinct }\n : {}),\n };\n }\n\n if (decorator.name === 'count') {\n const firstArg = decorator.arguments[0]?.trim();\n const firstOptions = this.parseFieldDecoratorOptions(firstArg);\n const secondOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const column = firstOptions ? undefined : stripQuotes(firstArg);\n const options = firstOptions ?? secondOptions;\n return {\n kind: 'aggregate',\n fn: 'count',\n ...(column ? { column } : {}),\n ...(typeof options?.distinct === 'boolean'\n ? { distinct: options.distinct }\n : {}),\n };\n }\n\n return null;\n }\n\n private parseFieldDecoratorOptions(\n rawArgument: string | undefined,\n ): FieldDecoratorOptions | null {\n if (!rawArgument) return null;\n\n const parsed = parseLiteralInitializer(rawArgument);\n if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') {\n return null;\n }\n\n return parsed as FieldDecoratorOptions;\n }\n\n private normalizeFieldType(\n value: unknown,\n ): FieldDefinition['type'] | undefined {\n switch (value) {\n case 'text':\n case 'decimal':\n case 'boolean':\n case 'integer':\n case 'datetime':\n case 'json':\n case 'foreignKey':\n case 'crossPackageRef':\n case 'oneToMany':\n case 'manyToMany':\n case 'meta':\n return value;\n default:\n return undefined;\n }\n }\n\n /**\n * Infer type from TypeScript type annotation\n */\n private inferFromAnnotation(field: RawFieldDefinition): FieldTypeInference {\n const type = field.typeAnnotation;\n\n // A field is only required if it has no default value AND is not optional (?)\n // Fields with initializers (default values) should NOT be required\n // This matches the behavior of the legacy TypeScript scanner\n const hasDefaultValue = field.initializer !== null;\n const isRequired = !field.optional && !hasDefaultValue;\n\n // Meta<T> wrapper for STI child fields\n // Extract the inner type T and mark as meta field\n if (type?.startsWith('Meta<') && type.endsWith('>')) {\n const innerType = type.slice(5, -1); // Extract type inside Meta<...>\n\n // Recursively infer the underlying type\n const underlyingInference = this.inferFromAnnotation({\n ...field,\n typeAnnotation: innerType,\n });\n\n return {\n type: 'meta',\n required: isRequired,\n defaultValue: underlyingInference.defaultValue,\n source: 'annotation',\n // Store underlying type for hydration coercion\n underlyingType: underlyingInference.type,\n };\n }\n\n // String types\n if (type === 'string') {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n\n // Number with 0 vs 0.0 heuristic\n if (type === 'number') {\n const fieldType: InferredFieldType = field.hasDecimalPoint\n ? 'decimal'\n : 'integer';\n\n return {\n type: fieldType,\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'heuristic',\n };\n }\n\n // Boolean\n if (type === 'boolean') {\n return {\n type: 'boolean',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'boolean'),\n source: 'annotation',\n };\n }\n\n // Date\n if (type === 'Date') {\n return {\n type: 'datetime',\n required: isRequired,\n source: 'annotation',\n };\n }\n\n // Arrays → JSON\n if (type?.endsWith('[]')) {\n return {\n type: 'json',\n required: isRequired,\n defaultValue: [],\n source: 'annotation',\n };\n }\n\n // Record/object → JSON\n if (type?.startsWith('Record<') || type === 'object') {\n return {\n type: 'json',\n required: isRequired,\n defaultValue: {},\n source: 'annotation',\n };\n }\n\n // Union types with null/undefined → nullable or optional\n if (\n type?.includes(' | null') ||\n type?.includes('null | ') ||\n type?.includes(' | undefined') ||\n type?.includes('undefined | ')\n ) {\n const baseType = type\n .replace(/\\s*\\|\\s*null/g, '')\n .replace(/\\s*\\|\\s*undefined/g, '')\n .replace(/\\bnull\\s*\\|\\s*/g, '')\n .replace(/\\bundefined\\s*\\|\\s*/g, '')\n .trim();\n const inference = this.inferFromAnnotation({\n ...field,\n typeAnnotation: baseType,\n optional: true,\n });\n return inference;\n }\n\n // Inline string literal union: 'pending' | 'ready' | 'archived'\n if (type && /^'[^']*'(\\s*\\|\\s*'[^']*')+$/.test(type)) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n\n // Inline number literal union: 1 | 2 | 3 (supports negatives: -1 | 0 | 1)\n if (type && /^-?\\d+(\\s*\\|\\s*-?\\d+)+$/.test(type)) {\n return {\n type: 'integer',\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'annotation',\n };\n }\n\n // Type alias resolution: look up single-identifier types in typeAliases\n // Guard against circular aliases (e.g., type A = B; type B = A) with depth limit\n if (\n type &&\n !type.includes(' ') &&\n !type.includes('<') &&\n this.typeAliases[type] &&\n (this._aliasDepth ?? 0) < 5\n ) {\n const resolved = this.typeAliases[type];\n this._aliasDepth = (this._aliasDepth ?? 0) + 1;\n try {\n return this.inferFromAnnotation({ ...field, typeAnnotation: resolved });\n } finally {\n this._aliasDepth = (this._aliasDepth ?? 0) - 1;\n }\n }\n\n // String initializer heuristic: if initializer is a quoted string, infer text\n if (field.initializer?.match(/^(['\"]).*\\1$/)) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'heuristic',\n };\n }\n\n // Default to json for unknown/complex types\n // Matches the TS scanner behavior: custom interfaces, type aliases,\n // and other non-primitive types are stored as JSON\n return {\n type: 'json',\n required: isRequired,\n source: 'default',\n };\n }\n\n /**\n * Parse default value from initializer string\n */\n private parseDefaultValue(\n initializer: string | null,\n expectedType: 'string' | 'boolean' | 'number',\n ): string | number | boolean | undefined {\n if (!initializer) return undefined;\n\n switch (expectedType) {\n case 'string': {\n // Match quoted strings (backreference ensures same quote type)\n const stringMatch = initializer.match(/^(['\"`])(.*)\\1$/s);\n if (stringMatch) {\n return stringMatch[2];\n }\n break;\n }\n\n case 'boolean':\n if (initializer === 'true') return true;\n if (initializer === 'false') return false;\n break;\n\n case 'number': {\n const num = parseFloat(initializer);\n if (!Number.isNaN(num)) return num;\n break;\n }\n }\n\n return undefined;\n }\n\n /**\n * Convert a raw method definition to a manifest `MethodDefinition`.\n *\n * Returns `null` for `private` or `protected` methods, which are excluded\n * from the manifest. Parameters are mapped to the manifest parameter shape\n * and default values are parsed via `parseDefaultValue`.\n *\n * @param method - Raw method definition from a scanned class.\n * @returns A manifest-compatible `MethodDefinition`, or `null` if the method\n * should be excluded.\n */\n convertMethod(method: RawMethodDefinition): MethodDefinition | null {\n // Skip private/protected methods\n if (method.accessibility !== 'public') {\n return null;\n }\n\n return {\n name: method.name,\n async: method.async,\n parameters: method.parameters.map((p) => ({\n name: p.name,\n // A missing type becomes `any` for every existing consumer, but the\n // provenance of that `any` is preserved alongside it: `typeUnresolved`\n // separates an annotation the scanner could not express from one the\n // author genuinely wrote (or omitted). Both keys are emitted only when\n // set, so manifests for ordinary parameters are unchanged (#2686).\n type: p.type || 'any',\n optional: p.optional,\n default: p.defaultValue\n ? this.parseDefaultValue(p.defaultValue, 'string')\n : undefined,\n ...(p.typeUnresolved ? { typeUnresolved: true } : {}),\n ...(p.memberTypes ? { memberTypes: p.memberTypes } : {}),\n ...(p.unionBranches ? { unionBranches: p.unionBranches } : {}),\n })),\n returnType: method.returnType || 'any',\n description: method.description || undefined,\n isStatic: method.isStatic,\n isPublic: true,\n ...(method.decoratorConfig\n ? { decoratorConfig: method.decoratorConfig }\n : {}),\n };\n }\n\n /**\n * Simple pluralization for collection names.\n *\n * This produces the manifest's `collection` label only; the authoritative DDL\n * table name is derived independently by core (`classnameToTablename` →\n * the `pluralize` library), so this needs to stay self-consistent rather than\n * cover every irregular plural. Note the `y → ies` rule fires only after a\n * consonant, so vowel+y words pluralise correctly (`Day` → `days`, not\n * `daies`).\n */\n private pluralize(name: string): string {\n // Lowercase the name first for consistent collection/table names\n const lower = name.toLowerCase();\n // Consonant + y → ies (City → cities); vowel + y → +s (Day → days).\n if (/[^aeiou]y$/.test(lower)) {\n return `${lower.slice(0, -1)}ies`;\n }\n if (lower.endsWith('s') || lower.endsWith('x') || lower.endsWith('z')) {\n return `${lower}es`;\n }\n if (lower.endsWith('ch') || lower.endsWith('sh')) {\n return `${lower}es`;\n }\n return `${lower}s`;\n }\n}\n","/**\n * OXC Scanner\n *\n * High-level scanner that orchestrates OXC parsing and inheritance resolution.\n * Provides a simple API for scanning TypeScript files for SMRT classes.\n */\n\nimport { relative, resolve, sep } from 'node:path';\nimport {\n emptyAgentSurface,\n isAgentSurfaceSourcePath,\n isPrunedAgentSurfacePath,\n mergeAgentSurfaces,\n scanSvelteAgentSurface,\n} from './agent-surface.js';\nimport { discoverSourceFiles } from './discovery.js';\nimport { InheritanceResolver } from './inheritance-resolver.js';\nimport { parseAgentSurfaceFile, parseFile } from './oxc-parser.js';\nimport type {\n AgentSurface,\n ExternalManifest,\n FileScanResult,\n OxcScannerOptions,\n ResolvedClassDefinition,\n ScanResults,\n} from './types.js';\n\n/**\n * Default glob patterns for scanning\n */\nconst DEFAULT_INCLUDE = ['**/*.ts', '**/*.tsx'];\n\n/**\n * Files searched only to REPORT a declaration the scanner can never read\n * (#2591). Nothing is emitted from a `.svelte` file — the scan exists so an\n * intent written inline in a component fails loudly instead of vanishing.\n */\nconst DEFAULT_SVELTE_INCLUDE = ['**/*.svelte'];\n\n/**\n * Files searched for `defineIntent` / `definePlaybook` declarations,\n * INDEPENDENTLY of the class-scan `include` glob (#2591).\n *\n * A model scan is routinely narrowed to where models live — the shipped\n * SvelteKit template uses `src/lib/objects/**\\/*.ts` — but an intent sidecar\n * lives beside the component that uses it. Binding declaration discovery to the\n * class glob would make those sidecars vanish from every artifact with no\n * diagnostic, which is the exact silent omission this matcher exists to\n * prevent. Extensions match what the Vite plugin's default include accepts.\n */\nconst DEFAULT_AGENT_SURFACE_INCLUDE = [\n '**/*.ts',\n '**/*.tsx',\n '**/*.js',\n '**/*.jsx',\n];\n\n/**\n * Prunes the declaration and `.svelte` passes ADD to whatever `exclude` a caller\n * passed.\n *\n * A caller's `exclude` replaces {@link DEFAULT_EXCLUDE} wholesale, and every\n * real caller passes one narrower than it — the Vite plugin sends test globs\n * plus `node_modules`, nothing more. That was harmless while the class\n * `include` was narrow; these passes glob the whole project, so build output\n * would otherwise be walked and read.\n */\nconst AGENT_SURFACE_PRUNE = [\n '**/dist/**',\n '**/build/**',\n '**/coverage/**',\n '**/__tests__/**',\n '**/__typechecks__/**',\n];\nconst DEFAULT_EXCLUDE = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/*.d.ts',\n '**/*.test.ts',\n '**/*.spec.ts',\n '**/__tests__/**',\n];\n\n/**\n * Prunes that always apply, on top of whatever `exclude` a caller passes.\n *\n * `exclude` replaces {@link DEFAULT_EXCLUDE} wholesale, so every caller that\n * narrowed the excludes also silently reopened `node_modules` — and installed\n * dependencies are never a project's own `@smrt()` sources. Dot directories are\n * generated or tool state (`.git`, `.svelte-kit`, `.turbo`, `.vercel`, agent\n * scratch) and are pruned for the same reason: nothing authored lives there.\n * `**\\/.*` keeps hidden FILES out of the result too, so turning `dot` on to\n * make these prunes work does not quietly widen what gets scanned.\n *\n * These are load-bearing for termination, not just for speed. See\n * {@link OxcScanner.discoverFiles}.\n */\n/**\n * High-performance TypeScript scanner that discovers `@smrt()`-decorated\n * classes in a project's source files.\n *\n * Orchestrates the two-phase scan pipeline:\n * 1. **Phase 1 — Parse** (`scan()`): uses OXC (Rust) to parse TypeScript files\n * in parallel and extract raw class, field, method, and decorator metadata.\n * 2. **Phase 2 — Resolve** (`resolve()`): walks inheritance chains, detects STI\n * hierarchies, and merges fields from ancestor classes.\n *\n * The common path is {@link scanAndResolve} which runs both phases in sequence.\n *\n * @example\n * ```typescript\n * import { OxcScanner } from '@happyvertical/smrt-scanner';\n *\n * const scanner = new OxcScanner({\n * cwd: process.cwd(),\n * include: ['src/**\\/*.ts'],\n * exclude: ['**\\/*.test.ts'],\n * });\n *\n * const { results, resolved } = await scanner.scanAndResolve();\n * console.log(`Found ${resolved.length} SMRT classes in ${results.fileCount} files`);\n * ```\n *\n * @see {@link OxcScannerOptions} for all available configuration options.\n * @see {@link scanDirectory} for a one-liner convenience wrapper.\n */\nexport class OxcScanner {\n private options: Required<OxcScannerOptions>;\n private resolver: InheritanceResolver;\n private scanResults: ScanResults | null = null;\n\n /**\n * Create a new `OxcScanner` with the given options.\n *\n * All options are optional. By default the scanner targets every `.ts` and\n * `.tsx` file under `process.cwd()`, excluding `node_modules`, `dist`,\n * `build`, declaration files, and test files.\n *\n * @param options - Scanner configuration. See {@link OxcScannerOptions}.\n */\n constructor(options: OxcScannerOptions = {}) {\n this.options = {\n include: options.include || DEFAULT_INCLUDE,\n exclude: options.exclude || DEFAULT_EXCLUDE,\n cwd: options.cwd || process.cwd(),\n tsconfig: options.tsconfig || '',\n followImports: options.followImports ?? false,\n baseClasses: options.baseClasses || [],\n includePrivateMethods: options.includePrivateMethods ?? false,\n includeStaticMethods: options.includeStaticMethods ?? true,\n externalManifests: options.externalManifests || new Map(),\n followSymbolicLinks: options.followSymbolicLinks ?? false,\n agentSurface: options.agentSurface ?? true,\n svelteInclude: options.svelteInclude || DEFAULT_SVELTE_INCLUDE,\n agentSurfaceInclude:\n options.agentSurfaceInclude || DEFAULT_AGENT_SURFACE_INCLUDE,\n };\n\n this.resolver = new InheritanceResolver({\n baseClasses: this.options.baseClasses,\n externalManifests: this.options.externalManifests,\n });\n }\n\n /**\n * Phase 1 — Discover and parse TypeScript files using OXC.\n *\n * Uses `fast-glob` to enumerate matching files and then parses them in\n * parallel with OXC (Rust). The raw class definitions are registered with\n * the internal {@link InheritanceResolver} for use in the subsequent\n * {@link resolve} call.\n *\n * @returns A {@link ScanResults} object containing all classes found, any\n * parse errors, accumulated type aliases, SMRT import metadata, and\n * aggregate timing information.\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: '/project' });\n * const results = await scanner.scan();\n * console.log(`Parsed ${results.fileCount} files in ${results.totalParseTimeMs.toFixed(1)}ms`);\n * ```\n */\n async scan(): Promise<ScanResults> {\n const startTime = performance.now();\n\n // Discover files\n const files = await this.discoverFiles();\n\n // Parse files in parallel\n const fileResults = await Promise.all(\n files.map((filePath) => this.parseFileWithTiming(filePath)),\n );\n\n // Collect results\n const results: ScanResults = {\n files: fileResults,\n classes: [],\n errors: [],\n totalParseTimeMs: performance.now() - startTime,\n fileCount: files.length,\n typeAliases: {},\n agentSurface: emptyAgentSurface(),\n };\n\n // Flatten classes, errors, and type aliases\n const surfaces: AgentSurface[] = [];\n for (const file of fileResults) {\n for (const classDef of file.classes) {\n results.classes.push(classDef);\n }\n for (const error of file.errors) {\n results.errors.push(error);\n }\n Object.assign(results.typeAliases, file.typeAliases);\n // The class pass has its own `include`/`exclude`, which may well cover a\n // test fixture or a build artifact. What counts as a DECLARATION source\n // is one question with one answer, asked here and in\n // `dev:knowledge-check` alike — the two disagreeing yields drift errors\n // no rebuild can clear.\n if (\n file.agentSurface &&\n isAgentSurfaceSourcePath(file.filePath, this.options.cwd)\n ) {\n surfaces.push(file.agentSurface);\n }\n }\n\n if (this.options.agentSurface) {\n surfaces.push(\n ...(await this.scanDeclarationsOutsideClassGlob(new Set(files))),\n );\n surfaces.push(await this.scanSvelteDeclarations());\n results.agentSurface = mergeAgentSurfaces(surfaces, (filePath) =>\n this.relativizeSourcePath(filePath),\n );\n }\n\n // Add classes to resolver\n this.resolver.addClasses(results.classes);\n\n this.scanResults = results;\n return results;\n }\n\n /**\n * Phase 2 — Resolve inheritance chains for all scanned classes.\n *\n * Must be called after {@link scan}. Walks each class's extends chain,\n * detects STI hierarchies, merges ancestor fields for STI subclasses, and\n * marks framework base classes.\n *\n * @returns An array of {@link ResolvedClassDefinition} objects — one for\n * every class that either carries `@smrt()` or extends a framework base\n * class (`SmrtObject`, `SmrtClass`, `SmrtCollection`).\n *\n * @throws {Error} If called before {@link scan}.\n *\n * @see {@link scanAndResolve} to run both phases in one call.\n */\n resolve(): ResolvedClassDefinition[] {\n if (!this.scanResults) {\n throw new Error('Must call scan() before resolve()');\n }\n\n return this.resolver.resolveAll();\n }\n\n /**\n * Run both scan phases in a single call.\n *\n * Equivalent to calling `await scanner.scan()` followed by\n * `scanner.resolve()`. This is the most common entry point for callers\n * that want the fully-resolved manifest-ready data in one step.\n *\n * @returns An object with:\n * - `results` — raw {@link ScanResults} from Phase 1.\n * - `resolved` — array of {@link ResolvedClassDefinition} from Phase 2.\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: '/project/src' });\n * const { results, resolved } = await scanner.scanAndResolve();\n * // resolved is ready to pass to ManifestAdapter.toManifest()\n * ```\n *\n * @see {@link ManifestAdapter} to convert `resolved` into a manifest JSON.\n */\n async scanAndResolve(): Promise<{\n results: ScanResults;\n resolved: ResolvedClassDefinition[];\n }> {\n const results = await this.scan();\n const resolved = this.resolve();\n\n return { results, resolved };\n }\n\n /**\n * Register an external package manifest for cross-package base class resolution.\n *\n * When a project class extends a class defined in an installed SMRT package,\n * the resolver needs access to that package's class definitions to walk the\n * full inheritance chain. Call this method with each external package's\n * {@link ExternalManifest} before calling {@link scan} or {@link resolve}.\n *\n * @param manifest - The external manifest to register, including `packageName`,\n * `packageVersion`, and a `classes` map keyed by class name.\n *\n * @see {@link ExternalManifest}\n */\n addExternalManifest(manifest: ExternalManifest): void {\n this.resolver.addExternalManifest(manifest);\n }\n\n /**\n * Scan all discovered files for @happyvertical/smrt-* imports.\n * Returns a map of package name → Set of imported class names.\n *\n * Used for tree-shaking: only external objects that are actually imported\n * in the project's source files will be included in the manifest.\n *\n * Must be called after scan() or as part of scanAndResolve().\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: process.cwd() });\n * await scanner.scan();\n * const imports = scanner.scanSmrtImports();\n * // Map { '@happyvertical/smrt-profiles' => Set { 'Person', 'Organization' } }\n * ```\n */\n scanSmrtImports(): Map<string, Set<string>> {\n if (!this.scanResults) {\n throw new Error('Must call scan() before scanSmrtImports()');\n }\n\n const merged = new Map<string, Set<string>>();\n\n for (const file of this.scanResults.files) {\n if (file.smrtImports) {\n for (const [pkg, classes] of file.smrtImports) {\n if (!merged.has(pkg)) {\n merged.set(pkg, new Set());\n }\n const mergedSet = merged.get(pkg)!;\n for (const cls of classes) {\n mergedSet.add(cls);\n }\n }\n }\n }\n\n return merged;\n }\n\n /**\n * Return aggregate statistics about the last scan.\n *\n * Can be called after {@link scan} has completed. Returns counts useful for\n * diagnostics and the `--stats` CLI flag.\n *\n * @returns An object with:\n * - `totalClasses` — total class declarations seen (including non-SMRT).\n * - `smrtClasses` — classes with `@smrt()` decorator.\n * - `stiClasses` — SMRT classes participating in an STI hierarchy.\n * - `maxInheritanceDepth` — length of the deepest inheritance chain.\n * - `fileCount` — number of files scanned.\n * - `parseTimeMs` — total wall-clock parse time in milliseconds.\n */\n getStats(): {\n totalClasses: number;\n smrtClasses: number;\n stiClasses: number;\n maxInheritanceDepth: number;\n fileCount: number;\n parseTimeMs: number;\n } {\n const resolverStats = this.resolver.getStats();\n\n return {\n ...resolverStats,\n fileCount: this.scanResults?.fileCount || 0,\n parseTimeMs: this.scanResults?.totalParseTimeMs || 0,\n };\n }\n\n /**\n * Discover files to scan using fast-glob.\n *\n * Two settings here decide whether discovery terminates at all when the\n * scanner is pointed at an application root rather than a package `src/`:\n *\n * - `dot: true`. Without it a `**` in an ignore pattern cannot cross a\n * dot segment, so `**\\/node_modules/**` prunes `node_modules` at the root\n * but NOT `.svelte-kit/…/node_modules` or any other `node_modules` under a\n * dot directory. Those subtrees were then walked in full and every entry\n * discarded — unbounded work that could never produce a match.\n * - `followSymbolicLinks: false`. pnpm materializes `node_modules` as a\n * symlink graph with cycles, so a link-following walk revisits the same\n * real directories once per path that reaches them.\n *\n * Together they were enough to exhaust a 4 GB heap on a consumer app that\n * installs the published packages (#2275).\n *\n * Patterns are rewritten relative to `cwd` first. fast-glob matches `ignore`\n * in whatever space the patterns use, so an absolute pattern would hand\n * `**\\/.*\\/**` the project's own ancestors — a checkout under `~/.worktrees`\n * or `~/.cache` would then match nothing at all, silently.\n */\n private async discoverFiles(): Promise<string[]> {\n return discoverSourceFiles({\n cwd: this.options.cwd,\n include: this.options.include,\n exclude: this.options.exclude,\n followSymbolicLinks: this.options.followSymbolicLinks,\n });\n }\n\n /**\n * Find declarations in files the CLASS scan did not cover.\n *\n * The class `include` is routinely narrowed to where models live, but an\n * intent sidecar lives beside its component. Without this pass those\n * declarations would be missing from every artifact with no diagnostic — a\n * silent omission, and in the shipped SvelteKit template's own layout at\n * that. Files already parsed by the class scan are skipped so a declaration\n * is never counted twice and cannot collide with itself.\n *\n * @param alreadyScanned - Absolute paths the class scan already parsed.\n */\n private async scanDeclarationsOutsideClassGlob(\n alreadyScanned: ReadonlySet<string>,\n ): Promise<AgentSurface[]> {\n if (this.options.agentSurfaceInclude.length === 0) return [];\n\n let files: string[];\n try {\n files = await discoverSourceFiles({\n cwd: this.options.cwd,\n include: this.options.agentSurfaceInclude,\n // A caller's `exclude` REPLACES the scanner defaults, and every real\n // caller passes one narrower than `DEFAULT_EXCLUDE` — the Vite plugin\n // sends only test globs plus node_modules. That was harmless while the\n // class `include` was narrow, but this pass globs the whole project, so\n // the prunes have to be restored explicitly or `dist/` becomes an\n // emission source. See `isAgentSurfaceSourcePath`.\n exclude: [...this.options.exclude, ...AGENT_SURFACE_PRUNE],\n followSymbolicLinks: this.options.followSymbolicLinks,\n });\n } catch {\n return [];\n }\n\n const surfaces: AgentSurface[] = [];\n for (const filePath of files) {\n if (alreadyScanned.has(filePath)) continue;\n // The globs prune the walk; this predicate decides what counts, and it is\n // the same one `dev:knowledge-check` uses.\n if (!isAgentSurfaceSourcePath(filePath, this.options.cwd)) continue;\n const surface = parseAgentSurfaceFile(filePath);\n if (surface) surfaces.push(surface);\n }\n return surfaces;\n }\n\n /**\n * Search `.svelte` files for declarations the scanner can never read.\n *\n * A `.svelte` file is not a TypeScript program and is never parsed here, so\n * this pass produces diagnostics only — never an emitted entry. It exists\n * because the alternative is silence: an intent declared inline in a\n * component simply would not appear anywhere, with nothing to explain why.\n */\n private async scanSvelteDeclarations(): Promise<AgentSurface> {\n const surface = emptyAgentSurface();\n if (this.options.svelteInclude.length === 0) return surface;\n\n // Callers routinely exclude `**/*.svelte` from the CLASS scan, because OXC\n // cannot parse a Svelte component. Honouring that here would silence the\n // one thing this pass exists to say, so a `.svelte`-targeting exclude is\n // dropped; every other prune (node_modules, dist, dot directories) stands.\n const exclude = [\n ...this.options.exclude.filter((pattern) => !pattern.endsWith('.svelte')),\n ...AGENT_SURFACE_PRUNE,\n ];\n\n let files: string[];\n try {\n files = await discoverSourceFiles({\n cwd: this.options.cwd,\n include: this.options.svelteInclude,\n exclude,\n followSymbolicLinks: this.options.followSymbolicLinks,\n });\n } catch {\n return surface;\n }\n\n for (const filePath of files) {\n // The globs prune the walk; this is the semantic gate, and it is the same\n // one `dev:knowledge-check` applies to `.svelte` files. A `.svelte` path\n // cannot go through `isAgentSurfaceSourcePath`, which rejects it on\n // extension, so the prune check is shared directly.\n if (isPrunedAgentSurfacePath(filePath, this.options.cwd)) continue;\n surface.diagnostics.push(...scanSvelteAgentSurface(filePath));\n }\n return surface;\n }\n\n /**\n * Record a declaring module as a `cwd`-relative POSIX path.\n *\n * Emitted entries land in checked-in artifacts, so an absolute path would\n * make them machine-specific and a Windows separator would make them\n * platform-specific — either one churns a snapshot that is supposed to prove\n * two builds agree.\n */\n private relativizeSourcePath(filePath: string): string {\n const relativePath = relative(this.options.cwd, filePath);\n if (!relativePath || relativePath.startsWith('..')) return filePath;\n return sep === '/' ? relativePath : relativePath.split(sep).join('/');\n }\n\n /**\n * Parse a single file with timing\n */\n private async parseFileWithTiming(filePath: string): Promise<FileScanResult> {\n // parseFile is synchronous but we wrap it for potential future async\n return parseFile(filePath);\n }\n}\n\n/**\n * Convenience wrapper that creates an {@link OxcScanner} for `dir` and runs\n * both scan phases in a single call.\n *\n * @param dir - Directory to scan (resolved to an absolute path automatically).\n * @param options - Scanner options, excluding `cwd` which is set from `dir`.\n * See {@link OxcScannerOptions}.\n * @returns An object with `results` ({@link ScanResults}) and `resolved`\n * ({@link ResolvedClassDefinition}[]).\n *\n * @example\n * ```typescript\n * import { scanDirectory } from '@happyvertical/smrt-scanner';\n *\n * const { resolved } = await scanDirectory('src/', {\n * include: ['**\\/*.ts'],\n * exclude: ['**\\/*.test.ts'],\n * });\n * console.log(`Found ${resolved.length} SMRT classes`);\n * ```\n *\n * @see {@link OxcScanner} for the full class API with more control.\n */\nexport async function scanDirectory(\n dir: string,\n options: Omit<OxcScannerOptions, 'cwd'> = {},\n): Promise<{\n results: ScanResults;\n resolved: ResolvedClassDefinition[];\n}> {\n const scanner = new OxcScanner({\n ...options,\n cwd: resolve(dir),\n });\n\n return scanner.scanAndResolve();\n}\n"],"mappings":"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"}
|