@happyvertical/smrt-scanner 0.55.7 → 0.55.8

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-BbpPS8Aq.js","names":["description","key","value","name","value"],"sources":["../../src/source-location.ts","../../src/agent-surface.ts","../../src/discovery.ts","../../src/enum-values.ts","../../src/inheritance-resolver.ts","../../src/recipe-widgets.ts","../../src/recipes.ts","../../src/oxc-parser.ts","../../src/manifest-adapter.ts","../../src/ui-selectors.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 * Resolve the closed set of allowed values of a field's declared type (#3598).\n *\n * The scanner records annotations as strings and keeps a project-wide\n * `typeAliases` map (`type X = 'a' | 'b'` and `enum X { A = 'a' }` both land\n * there as the union string `'a' | 'b'`). This module walks such a string:\n * splits the top-level union, follows alias identifiers (so a union that\n * *contains* an alias is flattened rather than treated as opaque), drops\n * `null` / `undefined`, and returns the literal values in declaration order.\n *\n * It answers `undefined` unless EVERY non-nullish member resolves to a string\n * or number literal. A union that also admits `string` / `number` / an object\n * type is not a closed set, so no `enum` is emitted for it.\n */\n\n/** A value an enum-typed field may hold. */\nexport type EnumValue = string | number;\n\n/** Alias recursion bound; matches the adapter's circular-alias guard. */\nconst MAX_ALIAS_DEPTH = 8;\n\n/** Split a union string on `|` outside quotes. */\nfunction splitUnion(type: string): string[] {\n const parts: string[] = [];\n let current = '';\n let quote: string | null = null;\n let escaped = false;\n for (const ch of type) {\n if (quote) {\n current += ch;\n if (escaped) {\n escaped = false;\n } else if (ch === '\\\\') {\n escaped = true;\n } else if (ch === quote) {\n quote = null;\n }\n continue;\n }\n if (ch === \"'\" || ch === '\"') {\n quote = ch;\n current += ch;\n } else if (ch === '|') {\n parts.push(current.trim());\n current = '';\n } else {\n current += ch;\n }\n }\n parts.push(current.trim());\n return parts.filter((part) => part !== '');\n}\n\nfunction resolveMember(\n member: string,\n aliases: Record<string, string>,\n depth: number,\n out: EnumValue[],\n): boolean {\n const quoted = member.match(/^(['\"])(.*)\\1$/s);\n if (quoted) {\n try {\n let encoded = member;\n if (quoted[1] === \"'\") {\n encoded = '\"';\n for (let index = 0; index < quoted[2].length; index += 1) {\n const char = quoted[2][index];\n if (char === '\\\\' && quoted[2][index + 1]) {\n const escapedChar = quoted[2][index + 1];\n encoded += escapedChar === \"'\" ? \"'\" : `\\\\${escapedChar}`;\n index += 1;\n } else {\n encoded += char === '\"' ? '\\\\\"' : char;\n }\n }\n encoded += '\"';\n }\n const value: unknown = JSON.parse(encoded);\n if (typeof value !== 'string') return false;\n out.push(value);\n return true;\n } catch {\n return false;\n }\n }\n if (/^-?\\d+(\\.\\d+)?$/.test(member)) {\n out.push(Number(member));\n return true;\n }\n if (member === 'null' || member === 'undefined') return true;\n if (\n depth < MAX_ALIAS_DEPTH &&\n /^[A-Za-z_$][\\w$]*$/.test(member) &&\n Object.hasOwn(aliases, member)\n ) {\n const nested = collect(aliases[member], aliases, depth + 1);\n if (!nested) return false;\n out.push(...nested);\n return true;\n }\n return false;\n}\n\nfunction collect(\n type: string,\n aliases: Record<string, string>,\n depth: number,\n): EnumValue[] | undefined {\n const out: EnumValue[] = [];\n for (const member of splitUnion(type)) {\n if (!resolveMember(member, aliases, depth, out)) return undefined;\n }\n return out;\n}\n\n/**\n * Allowed values for a declared type string, or `undefined` when the type is\n * not a closed literal set. Order is declaration order; duplicates (from a\n * union that re-lists an aliased member) are dropped, keeping the first.\n */\nexport function resolveEnumValues(\n type: string | null | undefined,\n aliases: Record<string, string> = {},\n): EnumValue[] | undefined {\n if (!type) return undefined;\n const values = collect(type.trim(), aliases, 0);\n if (!values || values.length === 0) return undefined;\n const seen = new Set<EnumValue>();\n const unique: EnumValue[] = [];\n for (const value of values) {\n if (seen.has(value)) continue;\n seen.add(value);\n unique.push(value);\n }\n return unique;\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 'SmrtJunctionBase',\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 * Validation of the recipe `widget` surface kind (#3727, phase 2).\n *\n * Kept apart from `recipes.ts` so the surface reader there only dispatches to\n * it. Everything here is a literal copy of a smrt-svelte overview rule (the\n * scanner cannot import smrt-svelte): the option field types, key / type / page\n * id patterns and the span range. `recipe-widgets.test.ts` in smrt-svelte\n * checks the copies against the source.\n */\nimport type {\n RecipeWidgetData,\n RecipeWidgetOption,\n RecipeWidgetOptionType,\n} from '@happyvertical/smrt-types';\n\n/** smrt-svelte `WidgetOptionType`, in its order. */\nexport const RECIPE_WIDGET_OPTION_TYPES = [\n 'text',\n 'markdown',\n 'identifier',\n 'model',\n 'integer',\n 'number',\n 'boolean',\n 'enum',\n] as const satisfies readonly RecipeWidgetOptionType[];\n\n/** Keys a `widget` surface accepts, in emitted order. */\nexport const RECIPE_WIDGET_KEYS = [\n 'kind',\n 'type',\n 'export',\n 'label',\n 'description',\n 'icon',\n 'version',\n 'migrate',\n 'options',\n 'data',\n 'allowedIn',\n 'defaultSpan',\n 'minSpan',\n 'maxSpan',\n] as const;\n\n/** smrt-svelte `WIDGET_TYPE_PATTERN`. */\nexport const WIDGET_TYPE_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;\n/** smrt-svelte `OVERVIEW_PAGE_ID_PATTERN`. */\nexport const OVERVIEW_PAGE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/;\n/** smrt-svelte schema `KEY_PATTERN`. */\nexport const OPTION_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9]{0,31}$/;\n/** smrt-svelte `IDENTIFIER_PATTERN`. */\nexport const IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_.-]{0,63}$/;\n/** smrt-svelte `MODEL_PATTERN`, with the package part required for data needs. */\nexport const MODEL_PATTERN =\n /^(?:(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*:)?[A-Za-z][A-Za-z0-9_]{0,63}$/;\nconst QUALIFIED_MODEL_PATTERN =\n /^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*:[A-Za-z][A-Za-z0-9_]{0,63}$/;\nexport const MODEL_MAX_LENGTH = 160;\nconst ICON_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;\nexport const SPAN_MIN = 1;\nexport const SPAN_MAX = 4;\nexport const TEXT_MAX = 200;\nexport const MARKDOWN_MAX = 10_000;\n\nconst OPTION_KEYS = new Set([\n 'key',\n 'type',\n 'label',\n 'help',\n 'required',\n 'default',\n 'min',\n 'max',\n 'maxLength',\n 'choices',\n]);\n\ntype Fail = (message: string) => void;\ntype ReadRef = (\n value: unknown,\n at: string,\n field: string,\n) => string | undefined;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction nonEmpty(value: unknown): value is string {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction readOption(\n raw: unknown,\n at: string,\n fail: Fail,\n): RecipeWidgetOption | undefined {\n if (!isRecord(raw)) {\n fail(`${at} must be an object literal`);\n return undefined;\n }\n let ok = true;\n const bad = (message: string) => {\n fail(`${at}${message}`);\n ok = false;\n };\n for (const key of Object.keys(raw)) {\n if (!OPTION_KEYS.has(key)) bad(` does not accept \\`${key}\\``);\n }\n const { key, type } = raw;\n if (typeof key !== 'string' || !OPTION_KEY_PATTERN.test(key)) {\n bad('.key must be a camelCase name of at most 32 letters and digits');\n }\n if (\n typeof type !== 'string' ||\n !(RECIPE_WIDGET_OPTION_TYPES as readonly string[]).includes(type)\n ) {\n bad(\n `.type must be one of ${RECIPE_WIDGET_OPTION_TYPES.join(', ')} (got \\`${String(type)}\\`)`,\n );\n return undefined;\n }\n if (!nonEmpty(raw.label)) bad('.label must be a non-empty string');\n if (raw.help !== undefined && !nonEmpty(raw.help)) {\n bad('.help must be a non-empty string');\n }\n if (raw.required !== undefined && typeof raw.required !== 'boolean') {\n bad('.required must be a boolean');\n }\n const numeric = type === 'integer' || type === 'number';\n for (const bound of ['min', 'max'] as const) {\n const value = raw[bound];\n if (value === undefined) continue;\n if (!numeric) {\n bad(`.${bound} applies only to integer and number options`);\n } else if (typeof value !== 'number' || !Number.isFinite(value)) {\n bad(`.${bound} must be a finite number`);\n }\n }\n if (\n typeof raw.min === 'number' &&\n typeof raw.max === 'number' &&\n raw.min > raw.max\n ) {\n bad('.min cannot exceed .max');\n }\n const textual = type === 'text' || type === 'markdown';\n if (raw.maxLength !== undefined) {\n if (!textual) {\n bad('.maxLength applies only to text and markdown options');\n } else if (\n typeof raw.maxLength !== 'number' ||\n !Number.isSafeInteger(raw.maxLength) ||\n raw.maxLength < 1\n ) {\n bad('.maxLength must be a positive integer');\n }\n }\n\n let choiceValues: string[] | undefined;\n if (type === 'enum') {\n const choices = raw.choices;\n if (!Array.isArray(choices) || choices.length === 0) {\n bad('.choices must be a non-empty list of { value, label }');\n } else {\n choiceValues = [];\n choices.forEach((choice, index) => {\n const where = `.choices[${index}]`;\n if (\n !isRecord(choice) ||\n Object.keys(choice).some((k) => k !== 'value' && k !== 'label')\n ) {\n bad(`${where} must be { value, label } and nothing else`);\n } else if (!nonEmpty(choice.value) || !nonEmpty(choice.label)) {\n bad(`${where} needs a non-empty value and label`);\n } else if (choiceValues?.includes(choice.value)) {\n bad(`${where} repeats the value \\`${choice.value}\\``);\n } else {\n choiceValues?.push(choice.value);\n }\n });\n }\n } else if (raw.choices !== undefined) {\n bad('.choices applies only to enum options');\n }\n\n const value = raw.default;\n if (value !== undefined) {\n const mismatch = (what: string) => bad(`.default must be ${what}`);\n switch (type) {\n case 'text':\n case 'markdown': {\n const max =\n typeof raw.maxLength === 'number'\n ? raw.maxLength\n : type === 'markdown'\n ? MARKDOWN_MAX\n : TEXT_MAX;\n if (typeof value !== 'string') mismatch('a string');\n else if (value.length > max) mismatch(`at most ${max} characters`);\n break;\n }\n case 'identifier':\n if (typeof value !== 'string' || !IDENTIFIER_PATTERN.test(value)) {\n mismatch('an identifier (letters, digits, `_`, `.`, `-`)');\n }\n break;\n case 'model':\n if (\n typeof value !== 'string' ||\n value.length > MODEL_MAX_LENGTH ||\n !MODEL_PATTERN.test(value)\n ) {\n mismatch('a model name (`Class`, `pkg:Class` or `@scope/pkg:Class`)');\n }\n break;\n case 'enum':\n if (\n typeof value !== 'string' ||\n (choiceValues && !choiceValues.includes(value))\n ) {\n mismatch('one of the choices');\n }\n break;\n case 'boolean':\n if (typeof value !== 'boolean') mismatch('a boolean');\n break;\n default:\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n mismatch('a finite number');\n } else if (type === 'integer' && !Number.isSafeInteger(value)) {\n mismatch('a safe integer');\n } else if (\n (typeof raw.min === 'number' && value < raw.min) ||\n (typeof raw.max === 'number' && value > raw.max)\n ) {\n mismatch('within min and max');\n }\n }\n }\n if (!ok) return undefined;\n\n const out: Record<string, unknown> = {};\n for (const name of [\n 'key',\n 'type',\n 'label',\n 'help',\n 'required',\n 'default',\n 'min',\n 'max',\n 'maxLength',\n 'choices',\n ]) {\n if (raw[name] !== undefined) out[name] = raw[name];\n }\n if (type === 'enum') {\n out.choices = (raw.choices as Array<Record<string, string>>).map(\n (choice) => ({ value: choice.value, label: choice.label }),\n );\n }\n return out as unknown as RecipeWidgetOption;\n}\n\nfunction readOptions(\n raw: unknown,\n at: string,\n fail: Fail,\n): RecipeWidgetOption[] | undefined {\n if (!Array.isArray(raw) || raw.length === 0) {\n fail(`${at}.options must be a non-empty list of option objects`);\n return undefined;\n }\n const out: RecipeWidgetOption[] = [];\n const keys = new Set<string>();\n let ok = true;\n raw.forEach((entry, index) => {\n const option = readOption(entry, `${at}.options[${index}]`, fail);\n if (!option) {\n ok = false;\n return;\n }\n if (keys.has(option.key)) {\n fail(`${at}.options[${index}].key \\`${option.key}\\` is already declared`);\n ok = false;\n return;\n }\n keys.add(option.key);\n out.push(option);\n });\n return ok ? out : undefined;\n}\n\nfunction readData(\n raw: unknown,\n at: string,\n fail: Fail,\n readRef: ReadRef,\n): RecipeWidgetData | undefined {\n if (!isRecord(raw)) {\n fail(`${at}.data must be an object literal`);\n return undefined;\n }\n let ok = true;\n for (const key of Object.keys(raw)) {\n if (key !== 'load' && key !== 'models') {\n fail(`${at}.data does not accept \\`${key}\\``);\n ok = false;\n }\n }\n const out: RecipeWidgetData = {};\n if (raw.load !== undefined) {\n const ref = readRef(raw.load, `${at}.data`, 'load');\n if (ref === undefined) ok = false;\n else out.load = ref as RecipeWidgetData['load'];\n }\n if (raw.models !== undefined) {\n const models = raw.models;\n if (!Array.isArray(models) || models.length === 0) {\n fail(`${at}.data.models must be a non-empty list of qualified models`);\n ok = false;\n } else {\n const seen = new Set<string>();\n for (const [index, model] of models.entries()) {\n if (\n typeof model !== 'string' ||\n model.length > MODEL_MAX_LENGTH ||\n !QUALIFIED_MODEL_PATTERN.test(model)\n ) {\n fail(\n `${at}.data.models[${index}] must be a qualified class name like \\`@scope/pkg:Class\\``,\n );\n ok = false;\n } else if (seen.has(model)) {\n fail(`${at}.data.models[${index}] repeats \\`${model}\\``);\n ok = false;\n } else {\n seen.add(model);\n }\n }\n out.models = [...seen];\n }\n }\n if (ok && !out.load && !out.models) {\n fail(`${at}.data needs \\`load\\` or \\`models\\``);\n ok = false;\n }\n return ok ? out : undefined;\n}\n\n/**\n * Validate the widget-specific part of a `widget` surface (everything but\n * `kind`, `export` and `label`, which the generic surface reader owns). Returns\n * the validated fields (without the generic ones), or `undefined` after\n * reporting every problem through `fail`.\n */\nexport function readWidgetSurface(\n entry: Record<string, unknown>,\n at: string,\n fail: Fail,\n readRef: ReadRef,\n): Record<string, unknown> | undefined {\n let ok = true;\n const bad = (message: string) => {\n fail(`${at}${message}`);\n ok = false;\n };\n const out: Record<string, unknown> = {};\n\n const { type } = entry;\n if (typeof type !== 'string' || !WIDGET_TYPE_PATTERN.test(type)) {\n bad('.type must be a lowercase kebab id of at most 32 characters');\n } else {\n out.type = type;\n }\n if (entry.description !== undefined) {\n if (nonEmpty(entry.description)) out.description = entry.description;\n else bad('.description must be a non-empty string');\n }\n if (entry.icon !== undefined) {\n if (typeof entry.icon === 'string' && ICON_PATTERN.test(entry.icon)) {\n out.icon = entry.icon;\n } else {\n bad('.icon must be an icon name');\n }\n }\n\n let version = 1;\n if (entry.version !== undefined) {\n if (\n typeof entry.version === 'number' &&\n Number.isSafeInteger(entry.version) &&\n entry.version >= 1\n ) {\n version = entry.version;\n out.version = entry.version;\n } else {\n bad('.version must be a positive integer');\n }\n }\n if (entry.migrate !== undefined) {\n const ref = readRef(entry.migrate, at, 'migrate');\n if (ref === undefined) ok = false;\n else if (version < 2) {\n bad('.migrate needs a `version` above 1');\n } else out.migrate = ref;\n }\n\n if (entry.options !== undefined) {\n const options = readOptions(entry.options, at, fail);\n if (options) out.options = options;\n else ok = false;\n }\n if (entry.data !== undefined) {\n const data = readData(entry.data, at, fail, readRef);\n if (data) out.data = data;\n else ok = false;\n }\n\n if (entry.allowedIn !== undefined) {\n const placements = entry.allowedIn;\n if (!Array.isArray(placements) || placements.length === 0) {\n bad('.allowedIn must be a non-empty list of overview ids');\n } else {\n const seen = new Set<string>();\n placements.forEach((id, index) => {\n if (typeof id !== 'string' || !OVERVIEW_PAGE_ID_PATTERN.test(id)) {\n bad(\n `.allowedIn[${index}] must be an overview id like \\`events.home\\``,\n );\n } else if (seen.has(id)) {\n bad(`.allowedIn[${index}] repeats \\`${id}\\``);\n } else {\n seen.add(id);\n }\n });\n out.allowedIn = [...seen];\n }\n }\n\n const spans: Record<'minSpan' | 'defaultSpan' | 'maxSpan', number> = {\n minSpan: SPAN_MIN,\n defaultSpan: SPAN_MIN,\n maxSpan: SPAN_MAX,\n };\n for (const name of ['defaultSpan', 'minSpan', 'maxSpan'] as const) {\n const value = entry[name];\n if (value === undefined) continue;\n if (\n typeof value !== 'number' ||\n !Number.isInteger(value) ||\n value < SPAN_MIN ||\n value > SPAN_MAX\n ) {\n bad(`.${name} must be an integer from ${SPAN_MIN} to ${SPAN_MAX}`);\n } else {\n out[name] = value;\n spans[name] = value;\n }\n }\n if (\n ok &&\n (spans.minSpan > spans.maxSpan ||\n (entry.defaultSpan !== undefined &&\n (spans.defaultSpan < spans.minSpan ||\n spans.defaultSpan > spans.maxSpan)))\n ) {\n bad('.minSpan <= .defaultSpan <= .maxSpan must hold');\n }\n return ok ? out : undefined;\n}\n","/**\n * Recipe matcher (#3590).\n *\n * A recipe is a class that extends `SmrtRecipe` and declares static\n * properties. It is not `@smrt()`-decorated and not persisted, so the class\n * scanner (which discovers classes by decorator) never sees it. This module is\n * the second recognizable shape: a **class whose `extends` clause resolves to\n * the `SmrtRecipe` import binding** from smrt-core.\n *\n * It keeps the discipline the agent-surface matcher keeps:\n *\n * - **structural only** — nothing is evaluated and no module is loaded. A\n * value that is not spelled literally cannot be read;\n * - **never a silent drop** — a recipe that is recognized but unreadable\n * produces a scan error, and scan errors fail the build;\n * - **binding-aware** — `extends X` matches only when `X` is the local name of\n * an import of `SmrtRecipe` from `@happyvertical/smrt-core`, so aliased\n * imports (`import { SmrtRecipe as Recipe }`) and namespace imports\n * (`Core.SmrtRecipe`) are recognized and a local class that merely shares the\n * name is not.\n *\n * Model class references (`static models = [Order]`) are resolved to the class\n * they import, through the import binding, never by evaluating anything:\n * a relative specifier selects the scanned class by file, then by name (a\n * barrel re-export keeps the same class name); a bare package specifier is\n * another package's class and is rejected, because a recipe's models belong to\n * its own package.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, isAbsolute, resolve as resolvePath } from 'node:path';\nimport type {\n RecipeDefinition,\n RecipeDemoSeed,\n RecipeExportRef,\n RecipeExposureNarrowing,\n RecipeFieldOptions,\n RecipeGroup,\n RecipeHelp,\n RecipeModelOptions,\n RecipeProvider,\n RecipeRuntime,\n RecipeSection,\n RecipeShellSlot,\n RecipeSurface,\n} from '@happyvertical/smrt-types';\nimport { RECIPE_WIDGET_KEYS, readWidgetSurface } from './recipe-widgets.js';\nimport { getLineColumn } from './source-location.js';\nimport type { ResolvedClassDefinition, ScanError } from './types.js';\n\ntype AstNode = { type: string } & Record<string, unknown>;\n\nconst RECIPE_BASE = 'SmrtRecipe';\n\n/**\n * Runtime lists behind the `@happyvertical/smrt-types` unions (types carries no\n * runtime code). `RECIPE_SHELL_SLOTS` copies smrt-svelte's `SHELL_SLOTS`; tests\n * check it against that source and smrt-svelte checks the type union.\n */\nexport const RECIPE_SHELL_SLOTS = [\n 'header.start',\n 'header.center',\n 'header.end',\n 'footer.start',\n 'footer.center',\n 'footer.end',\n 'leftSidebar.header',\n 'leftSidebar.footer',\n 'rightSidebar.header',\n 'rightSidebar.footer',\n] as const satisfies readonly RecipeShellSlot[];\nconst RECIPE_SURFACE_KINDS = [\n 'shell-widget',\n 'route',\n 'settings-panel',\n 'playground',\n 'widget',\n] as const satisfies readonly RecipeSurface['kind'][];\nconst RECIPE_RUNTIMES = [\n 'browser',\n 'server',\n 'both',\n] as const satisfies readonly RecipeRuntime[];\nconst CORE_SPECIFIER = '@happyvertical/smrt-core';\n\n/** The core package itself or one of its subpaths (`/browser`), nothing else. */\nfunction isCoreSpecifier(source: string): boolean {\n return source === CORE_SPECIFIER || source.startsWith(`${CORE_SPECIFIER}/`);\n}\n\n/** `commerce.sales`: dotted, lowercase, at least two segments. */\nconst RECIPE_ID_PATTERN = /^[a-z][a-z0-9]*(?:\\.[a-z0-9][a-z0-9_-]*)+$/;\nconst RECIPE_ID_MAX_LENGTH = 128;\n\nconst FIELD_OPTION_KEYS = new Set([\n 'default',\n 'label',\n 'help',\n 'order',\n 'visibility',\n 'locked',\n 'required',\n]);\nconst NAV_EXTRA_KEYS = ['icon', 'description', 'key', 'noun'] as const;\nconst GROUP_KEYS = new Set(['id', 'label', 'summary']);\nconst SECTION_KEYS = new Set(['id', 'label', 'icon', 'description']);\n/** Ids of groups, sections and nav keys: lowercase, digits, `-`, `_`. */\nconst SLUG_PATTERN = /^[a-z][a-z0-9_-]*$/;\nconst ICON_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;\nconst VISIBILITIES = new Set(['basic', 'advanced', 'hidden']);\nconst EXPOSURE_TRANSPORTS = ['api', 'mcp', 'cli'] as const;\n\n/**\n * A model reference as authored: the local binding, the name it was exported\n * under, and the module it came from (`null` when declared in the same file).\n */\nexport interface RawRecipeModelRef {\n /** Identifier as written (`Order`, or `Models.Order` for a namespace). */\n local: string;\n /** Exported name the binding refers to. */\n imported: string;\n /** Import specifier, or `null` for a same-file declaration. */\n source: string | null;\n line?: number;\n}\n\n/** One recipe as read from source, before models are resolved. */\nexport interface RawRecipe {\n className: string;\n filePath: string;\n line?: number;\n id: string | null;\n label: string | null;\n summary: string | null;\n synonyms: string[];\n models: RawRecipeModelRef[];\n nav: Array<{\n label: string;\n model: RawRecipeModelRef;\n line?: number;\n icon?: string;\n description?: string;\n key?: string;\n noun?: string;\n filter?: unknown;\n }>;\n requires: string[];\n /** `static requiresAny`, as authored (shape checked at resolve). */\n requiresAny: { value: unknown; line?: number } | null;\n /** `static group`, as authored (shape checked at resolve). */\n group: { value: unknown; line?: number } | null;\n /** `static section`, as authored (shape checked at resolve). */\n section: { value: unknown; line?: number } | null;\n /** Options entries in authored order; the key is a model name. */\n options: Array<{ key: string; value: unknown; line?: number }>;\n /** `static help`: a path to a Markdown file, relative to the recipe's file. */\n help: { path: string; line?: number } | null;\n /** `static surfaces` / `providers` / `runtime` / `demoSeed`, as authored (#3708). */\n surfaces: { value: unknown; line?: number } | null;\n providers: { value: unknown; line?: number } | null;\n runtime: { value: unknown; line?: number } | null;\n demoSeed: { value: unknown; line?: number } | null;\n}\n\n/** Cheap pre-filter: a file that never names the base cannot declare one. */\nexport function sourceMayDeclareRecipe(sourceText: string): boolean {\n return sourceText.includes(RECIPE_BASE);\n}\n\nclass RecipeReadError extends Error {\n constructor(\n message: string,\n readonly node?: AstNode,\n ) {\n super(message);\n }\n}\n\ninterface ImportBinding {\n imported: string;\n source: string;\n namespace: boolean;\n}\n\nfunction collectImports(body: AstNode[]): Map<string, ImportBinding> {\n const bindings = new Map<string, ImportBinding>();\n for (const node of body) {\n if (node.type !== 'ImportDeclaration') continue;\n const source = (node.source as AstNode | undefined)?.value;\n if (typeof source !== 'string') continue;\n for (const spec of (node.specifiers as AstNode[] | undefined) ?? []) {\n const local = (spec.local as AstNode | undefined)?.name;\n if (typeof local !== 'string') continue;\n if (spec.type === 'ImportSpecifier') {\n const imported = spec.imported as AstNode | undefined;\n const name = (imported?.name ?? imported?.value) as string | undefined;\n if (typeof name === 'string') {\n bindings.set(local, { imported: name, source, namespace: false });\n }\n } else if (spec.type === 'ImportDefaultSpecifier') {\n bindings.set(local, { imported: local, source, namespace: false });\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n bindings.set(local, { imported: '*', source, namespace: true });\n }\n }\n }\n return bindings;\n}\n\nfunction unwrap(node: AstNode): AstNode {\n let current = node;\n for (let depth = 0; depth < 8; depth++) {\n if (\n current.type === 'TSAsExpression' ||\n current.type === 'TSSatisfiesExpression' ||\n current.type === 'TSNonNullExpression' ||\n current.type === 'TSTypeAssertion' ||\n current.type === 'ParenthesizedExpression'\n ) {\n current = current.expression as AstNode;\n continue;\n }\n break;\n }\n return current;\n}\n\nfunction isRecipeBase(\n superClass: AstNode | null | undefined,\n imports: Map<string, ImportBinding>,\n): boolean {\n if (!superClass) return false;\n const node = unwrap(superClass);\n if (node.type === 'Identifier') {\n const binding = imports.get(node.name as string);\n return (\n !!binding &&\n binding.imported === RECIPE_BASE &&\n isCoreSpecifier(binding.source)\n );\n }\n if (node.type === 'MemberExpression' && node.computed !== true) {\n const object = node.object as AstNode;\n const property = node.property as AstNode;\n const binding =\n object.type === 'Identifier'\n ? imports.get(object.name as string)\n : undefined;\n return (\n !!binding &&\n binding.namespace &&\n isCoreSpecifier(binding.source) &&\n property.name === RECIPE_BASE\n );\n }\n return false;\n}\n\nfunction keyName(node: AstNode): string | null {\n if (node.computed === true) return null;\n const key = node.key as AstNode | undefined;\n if (!key) return null;\n if (key.type === 'Identifier') return key.name as string;\n if (key.type === 'Literal' && typeof key.value === 'string') return key.value;\n return null;\n}\n\nfunction stringValue(node: AstNode, what: string): string {\n const value = unwrap(node);\n if (value.type === 'Literal' && typeof value.value === 'string') {\n return value.value;\n }\n if (\n value.type === 'TemplateLiteral' &&\n (value.expressions as unknown[]).length === 0\n ) {\n const quasi = (value.quasis as AstNode[])[0];\n const cooked = (quasi?.value as { cooked?: string } | undefined)?.cooked;\n if (typeof cooked === 'string') return cooked;\n }\n throw new RecipeReadError(`${what} must be a string literal`, node);\n}\n\nfunction arrayElements(node: AstNode, what: string): AstNode[] {\n const value = unwrap(node);\n if (value.type !== 'ArrayExpression') {\n throw new RecipeReadError(`${what} must be an array literal`, node);\n }\n return (value.elements as Array<AstNode | null>).map((element) => {\n if (!element || element.type === 'SpreadElement') {\n throw new RecipeReadError(\n `${what} must list its entries literally (no spread or holes)`,\n element ?? node,\n );\n }\n return element;\n });\n}\n\nfunction objectEntries(\n node: AstNode,\n what: string,\n): Array<{ key: string; value: AstNode; node: AstNode }> {\n const value = unwrap(node);\n if (value.type !== 'ObjectExpression') {\n throw new RecipeReadError(`${what} must be an object literal`, node);\n }\n return (value.properties as AstNode[]).map((property) => {\n if (property.type !== 'Property' || property.kind !== 'init') {\n throw new RecipeReadError(\n `${what} must use plain \\`key: value\\` properties (no spread, getters, or methods)`,\n property,\n );\n }\n if (property.method === true) {\n throw new RecipeReadError(`${what} cannot contain methods`, property);\n }\n const key = keyName(property);\n if (key === null) {\n throw new RecipeReadError(\n `${what} cannot use computed property keys`,\n property,\n );\n }\n return { key, value: property.value as AstNode, node: property };\n });\n}\n\n/** JSON-shaped literal reader for option values. */\nfunction literalValue(node: AstNode, what: string, depth = 0): unknown {\n if (depth > 16) {\n throw new RecipeReadError(`${what} is nested too deeply`, node);\n }\n const value = unwrap(node);\n switch (value.type) {\n case 'Literal':\n if (value.regex || typeof value.value === 'bigint') break;\n return value.value;\n case 'TemplateLiteral':\n return stringValue(value, what);\n case 'UnaryExpression': {\n const argument = unwrap(value.argument as AstNode);\n if (\n (value.operator === '-' || value.operator === '+') &&\n argument.type === 'Literal' &&\n typeof argument.value === 'number'\n ) {\n return value.operator === '-' ? -argument.value : argument.value;\n }\n break;\n }\n case 'ArrayExpression':\n return arrayElements(value, what).map((element) =>\n literalValue(element, what, depth + 1),\n );\n case 'ObjectExpression': {\n const out: Record<string, unknown> = {};\n for (const entry of objectEntries(value, what)) {\n if (isUnsafeKey(entry.key)) {\n throw new RecipeReadError(\n `${what} cannot use the key \\`${entry.key}\\``,\n entry.node,\n );\n }\n out[entry.key] = literalValue(entry.value, what, depth + 1);\n }\n return out;\n }\n default:\n break;\n }\n throw new RecipeReadError(\n `${what} must be a literal value; the scanner cannot evaluate expressions`,\n node,\n );\n}\n\nfunction isUnsafeKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype';\n}\n\nfunction modelRef(\n node: AstNode,\n imports: Map<string, ImportBinding>,\n declaredHere: Set<string>,\n what: string,\n sourceText: string,\n): RawRecipeModelRef {\n const value = unwrap(node);\n const line = lineOf(sourceText, value);\n if (value.type === 'Identifier') {\n const local = value.name as string;\n const binding = imports.get(local);\n if (binding && !binding.namespace) {\n return {\n local,\n imported: binding.imported,\n source: binding.source,\n line,\n };\n }\n if (declaredHere.has(local)) {\n return { local, imported: local, source: null, line };\n }\n throw new RecipeReadError(\n `${what} \\`${local}\\` is neither imported nor declared in this file`,\n node,\n );\n }\n if (\n value.type === 'MemberExpression' &&\n value.computed !== true &&\n (value.object as AstNode).type === 'Identifier'\n ) {\n const object = (value.object as AstNode).name as string;\n const binding = imports.get(object);\n const property = (value.property as AstNode).name as string;\n if (binding?.namespace && typeof property === 'string') {\n return {\n local: `${object}.${property}`,\n imported: property,\n source: binding.source,\n line,\n };\n }\n }\n throw new RecipeReadError(\n `${what} must be a class reference (an imported or same-file class identifier), not an expression or a string`,\n node,\n );\n}\n\nfunction lineOf(sourceText: string, node: AstNode): number | undefined {\n const start = node.start;\n return typeof start === 'number'\n ? getLineColumn(sourceText, start)?.line\n : undefined;\n}\n\n/**\n * Find every `SmrtRecipe` subclass in a parsed module and read its statics.\n * Read errors are returned, never swallowed.\n */\nexport function extractRecipes(input: {\n body: unknown[];\n sourceText: string;\n filePath: string;\n}): { recipes: RawRecipe[]; errors: ScanError[] } {\n const body = input.body as AstNode[];\n const imports = collectImports(body);\n const recipes: RawRecipe[] = [];\n const errors: ScanError[] = [];\n const classes: AstNode[] = [];\n const declaredHere = new Set<string>();\n\n for (const statement of body) {\n let node = statement;\n if (\n (node.type === 'ExportNamedDeclaration' ||\n node.type === 'ExportDefaultDeclaration') &&\n node.declaration\n ) {\n node = node.declaration as AstNode;\n }\n if (node.type === 'ClassDeclaration') {\n classes.push(node);\n const name = (node.id as AstNode | undefined)?.name;\n if (typeof name === 'string') declaredHere.add(name);\n }\n }\n\n // A recipe must extend `SmrtRecipe` directly. Anything that extends another\n // recipe, or declares the base through a class expression, would otherwise\n // vanish from the artifacts with the build still green.\n const recipeNames = new Set<string>();\n for (const node of classes) {\n if (isRecipeBase(node.superClass as AstNode | null, imports)) {\n recipeNames.add(((node.id as AstNode | undefined)?.name ?? '') as string);\n }\n }\n const reportAt = (message: string, at: AstNode) => {\n const loc =\n typeof at.start === 'number'\n ? getLineColumn(input.sourceText, at.start)\n : undefined;\n errors.push({\n message,\n filePath: input.filePath,\n line: loc?.line,\n column: loc?.column,\n severity: 'error',\n });\n };\n for (const node of classes) {\n const base = node.superClass\n ? unwrap(node.superClass as AstNode)\n : undefined;\n if (\n base?.type === 'Identifier' &&\n recipeNames.has(base.name as string) &&\n !isRecipeBase(base, imports)\n ) {\n reportAt(\n `Recipe ${(node.id as AstNode | undefined)?.name ?? 'AnonymousRecipe'}: extends the recipe ${base.name as string}; a recipe must extend SmrtRecipe directly`,\n node,\n );\n }\n }\n for (const found of findClassExpressions(body)) {\n if (isRecipeBase(found.superClass as AstNode | null, imports)) {\n reportAt(\n 'Recipe declared as a class expression or inside a block; declare it as a top-level `class X extends SmrtRecipe`',\n found,\n );\n }\n }\n\n for (const node of classes) {\n if (!isRecipeBase(node.superClass as AstNode | null, imports)) continue;\n const className = ((node.id as AstNode | undefined)?.name ??\n 'AnonymousRecipe') as string;\n const report = (message: string, at?: AstNode) => {\n const loc =\n typeof at?.start === 'number'\n ? getLineColumn(input.sourceText, at.start)\n : undefined;\n errors.push({\n message: `Recipe ${className}: ${message}`,\n filePath: input.filePath,\n line: loc?.line,\n column: loc?.column,\n severity: 'error',\n });\n };\n\n const recipe: RawRecipe = {\n className,\n filePath: input.filePath,\n line: lineOf(input.sourceText, node),\n id: null,\n label: null,\n summary: null,\n synonyms: [],\n models: [],\n nav: [],\n requires: [],\n requiresAny: null,\n group: null,\n section: null,\n options: [],\n help: null,\n surfaces: null,\n providers: null,\n runtime: null,\n demoSeed: null,\n };\n const seen = new Set<string>();\n\n for (const member of (node.body as { body: AstNode[] }).body) {\n if (member.type !== 'PropertyDefinition' || member.static !== true) {\n continue;\n }\n const name = keyName(member);\n if (!name || !member.value) continue;\n const value = member.value as AstNode;\n try {\n switch (name) {\n case 'id':\n recipe.id = stringValue(value, 'static id');\n break;\n case 'label':\n recipe.label = stringValue(value, 'static label');\n break;\n case 'summary':\n recipe.summary = stringValue(value, 'static summary');\n break;\n case 'synonyms':\n recipe.synonyms = arrayElements(value, 'static synonyms').map(\n (entry) => stringValue(entry, 'static synonyms entries'),\n );\n break;\n case 'requires':\n recipe.requires = arrayElements(value, 'static requires').map(\n (entry) => stringValue(entry, 'static requires entries'),\n );\n break;\n case 'models':\n recipe.models = arrayElements(value, 'static models').map((entry) =>\n modelRef(\n entry,\n imports,\n declaredHere,\n 'static models entry',\n input.sourceText,\n ),\n );\n break;\n case 'nav':\n recipe.nav = arrayElements(value, 'static nav').map((entry) => {\n const fields = objectEntries(entry, 'static nav entries');\n const label = fields.find((field) => field.key === 'label');\n const model = fields.find((field) => field.key === 'model');\n const extra = fields.find(\n (field) =>\n field.key !== 'label' &&\n field.key !== 'model' &&\n field.key !== 'filter' &&\n !(NAV_EXTRA_KEYS as readonly string[]).includes(field.key),\n );\n if (extra) {\n throw new RecipeReadError(\n `static nav entries accept only \\`label\\`, \\`model\\`, \\`icon\\`, \\`description\\`, \\`key\\`, \\`noun\\` and \\`filter\\`, not \\`${extra.key}\\``,\n extra.node,\n );\n }\n const extras: Record<string, string> = {};\n for (const name of NAV_EXTRA_KEYS) {\n const found = fields.find((field) => field.key === name);\n if (found) {\n extras[name] = stringValue(found.value, `static nav ${name}`);\n }\n }\n const filter = fields.find((field) => field.key === 'filter');\n if (!label || !model) {\n throw new RecipeReadError(\n 'static nav entries need both `label` and `model`',\n entry,\n );\n }\n return {\n label: stringValue(label.value, 'static nav label'),\n model: modelRef(\n model.value,\n imports,\n declaredHere,\n 'static nav model',\n input.sourceText,\n ),\n line: lineOf(input.sourceText, entry),\n ...extras,\n ...(filter\n ? {\n filter: literalValue(filter.value, 'static nav filter'),\n }\n : {}),\n };\n });\n break;\n case 'requiresAny':\n case 'group':\n case 'section':\n case 'surfaces':\n case 'providers':\n case 'runtime':\n case 'demoSeed':\n recipe[name] = {\n value: literalValue(value, `static ${name}`),\n line: lineOf(input.sourceText, member),\n };\n break;\n case 'options':\n recipe.options = objectEntries(value, 'static options').map(\n (entry) => ({\n key: entry.key,\n value: literalValue(entry.value, 'static options'),\n line: lineOf(input.sourceText, entry.node),\n }),\n );\n break;\n case 'help':\n recipe.help = {\n path: stringValue(value, 'static help'),\n line: lineOf(input.sourceText, member),\n };\n break;\n default:\n continue;\n }\n seen.add(name);\n } catch (error) {\n if (!(error instanceof RecipeReadError)) throw error;\n report(error.message, error.node ?? member);\n }\n }\n\n for (const required of ['id', 'label', 'summary', 'models'] as const) {\n if (!seen.has(required)) {\n report(\n `must declare a readable \\`static ${required}\\``,\n node.id as AstNode,\n );\n }\n }\n recipes.push(recipe);\n }\n\n return { recipes, errors };\n}\n\nconst HELP_EXTENSION = '.md';\nconst FIELD_REF_PATTERN =\n /\\{field:([A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)?)\\}/g;\n\n/**\n * Distinct `{field:...}` references in help Markdown, as written, sorted.\n * Mirrors core's `extractFieldRefs` (`recipe-help.ts`): a reference inside an\n * inline code span is code, not a reference. The scanner cannot import core, so\n * core re-derives the list from the same Markdown at manifest generation and\n * fails the build if the two ever disagree.\n */\nexport function deriveHelpFieldRefs(markdown: string): string[] {\n const refs = new Set<string>();\n for (const block of markdown.replace(/\\r\\n?/g, '\\n').split(/\\n\\s*\\n/)) {\n for (const match of block\n .replace(/`[^`]+`/g, '')\n .matchAll(FIELD_REF_PATTERN)) {\n refs.add(match[1] as string);\n }\n }\n return [...refs].sort();\n}\n\n/**\n * Read a recipe's help file. The path is relative to the recipe's own file and\n * must stay beside it or below it, so a recipe cannot reach outside its package.\n */\nfunction readHelp(\n help: NonNullable<RawRecipe['help']>,\n raw: RawRecipe,\n): RecipeHelp {\n const fail = (message: string): never => {\n throw new RecipeReadError(`static help ${message}`);\n };\n if (\n help.path.trim() === '' ||\n isAbsolute(help.path) ||\n help.path.split(/[\\\\/]/).includes('..') ||\n !help.path.toLowerCase().endsWith(HELP_EXTENSION)\n ) {\n return fail(\n `must be a relative path to a ${HELP_EXTENSION} file beside the recipe (got \\`${help.path}\\`)`,\n );\n }\n const absolute = resolvePath(dirname(raw.filePath), help.path);\n let markdown: string;\n try {\n markdown = readFileSync(absolute, 'utf-8');\n } catch (error) {\n return fail(\n `file \\`${help.path}\\` cannot be read (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n markdown = markdown.replace(/\\r\\n?/g, '\\n');\n if (markdown.trim() === '') return fail(`file \\`${help.path}\\` is empty`);\n return { markdown, fieldRefs: deriveHelpFieldRefs(markdown) };\n}\n\n/**\n * Class expressions and non-top-level class declarations anywhere in the\n * module, so a recipe declared there is reported instead of silently skipped.\n */\nfunction findClassExpressions(body: AstNode[]): AstNode[] {\n const found: AstNode[] = [];\n const topLevel = new Set<unknown>();\n for (const statement of body) {\n const node =\n (statement.type === 'ExportNamedDeclaration' ||\n statement.type === 'ExportDefaultDeclaration') &&\n statement.declaration\n ? (statement.declaration as AstNode)\n : statement;\n if (node.type === 'ClassDeclaration') topLevel.add(node);\n }\n const visit = (value: unknown, depth: number): void => {\n if (depth > 200 || !value || typeof value !== 'object') return;\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry, depth + 1);\n return;\n }\n const node = value as AstNode;\n if (\n (node.type === 'ClassExpression' || node.type === 'ClassDeclaration') &&\n !topLevel.has(node)\n ) {\n found.push(node);\n }\n for (const [key, child] of Object.entries(node)) {\n if (key === 'loc' || key === 'range') continue;\n visit(child, depth + 1);\n }\n };\n visit(body, 0);\n return found;\n}\n\n// ============================================================================\n// Resolution and validation\n// ============================================================================\n\nfunction stripExtension(path: string): string {\n return path.replace(/\\.(?:[cm]?[jt]sx?|svelte)$/, '');\n}\n\nfunction isRelativeSpecifier(source: string): boolean {\n return source.startsWith('./') || source.startsWith('../');\n}\n\n/**\n * A specifier that names another package: bare, and not one of the common\n * in-project alias forms (`$lib/...`, `~/...`, `#internal`, `@/...`).\n */\nfunction isExternalPackageSpecifier(source: string): boolean {\n if (isRelativeSpecifier(source) || source.startsWith('/')) return false;\n if (/^[$~#]/.test(source) || source.startsWith('@/')) return false;\n return true;\n}\n\nfunction resolveModel(\n ref: RawRecipeModelRef,\n recipe: RawRecipe,\n classes: ResolvedClassDefinition[],\n what: string,\n): ResolvedClassDefinition {\n const byName = classes.filter(\n (candidate) => candidate.className === ref.imported,\n );\n let candidates = byName;\n if (ref.source === null) {\n candidates = byName.filter((c) => c.filePath === recipe.filePath);\n } else if (isExternalPackageSpecifier(ref.source)) {\n throw new RecipeReadError(\n `${what} \\`${ref.local}\\` is imported from \\`${ref.source}\\`, another package; a recipe's models must belong to its own package`,\n );\n } else if (isRelativeSpecifier(ref.source)) {\n const target = stripExtension(\n resolvePath(dirname(recipe.filePath), ref.source),\n );\n const byFile = byName.filter((c) => {\n const file = stripExtension(c.filePath);\n return file === target || file === `${target}/index`;\n });\n // A barrel re-export keeps the class name but not the file.\n candidates = byFile.length > 0 ? byFile : byName;\n }\n if (candidates.length === 0) {\n throw new RecipeReadError(\n `${what} \\`${ref.local}\\` does not resolve to a model class scanned in this package`,\n );\n }\n if (candidates.length > 1) {\n throw new RecipeReadError(\n `${what} \\`${ref.local}\\` is ambiguous: ${candidates.length} scanned classes are named \\`${ref.imported}\\``,\n );\n }\n return candidates[0];\n}\n\n/**\n * The generated CRUD verbs, mirrored from `CRUD_OPERATIONS` in smrt-core\n * (`generators/custom-action.ts`); this package cannot import core. An\n * `exclude` entry must be one of these or a method the model declares, so a\n * typo cannot pass as a narrowing that narrows nothing.\n */\nconst CRUD_VERBS = ['list', 'get', 'create', 'update', 'delete'];\n\nfunction isNarrowing(\n value: unknown,\n operations: ReadonlySet<string>,\n): value is RecipeExposureNarrowing {\n if (value === false) return true;\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const keys = Object.keys(value);\n const exclude = (value as { exclude?: unknown }).exclude;\n return (\n keys.length === 1 &&\n keys[0] === 'exclude' &&\n Array.isArray(exclude) &&\n exclude.length > 0 &&\n exclude.every((entry) => typeof entry === 'string' && operations.has(entry))\n );\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Validate one model's options, reporting EVERY problem rather than the first\n * so an author fixes a recipe in one pass.\n */\nfunction readModelOptions(\n raw: unknown,\n model: ResolvedClassDefinition,\n classes: ResolvedClassDefinition[],\n where: string,\n bad: (message: string) => void,\n): RecipeModelOptions | undefined {\n if (!isPlainObject(raw)) {\n bad(`${where} must be an object`);\n return undefined;\n }\n let ok = true;\n const fail = (message: string) => {\n ok = false;\n bad(message);\n };\n const out: RecipeModelOptions = {};\n // Public instance methods of the model and every ancestor it inherits from.\n const operations = new Set<string>(CRUD_VERBS);\n const chain = new Set([model.className, ...model.inheritanceChain]);\n for (const candidate of classes) {\n if (!chain.has(candidate.className)) continue;\n for (const method of candidate.methods) {\n if (\n !method.isStatic &&\n method.accessibility === 'public' &&\n method.name !== 'constructor'\n ) {\n operations.add(method.name);\n }\n }\n }\n for (const [key, value] of Object.entries(raw)) {\n if (key === 'fields') {\n if (!isPlainObject(value)) {\n fail(`${where}.fields must be an object`);\n continue;\n }\n const fields: Record<string, RecipeFieldOptions> = {};\n // Field NAMES are validated against the final manifest in smrt-core\n // (`assertRecipeOptions`): only that merged view knows STI-merged,\n // injected tenant, and framework-base fields such as `parentId`.\n for (const [field, hints] of Object.entries(value)) {\n if (!isPlainObject(hints)) {\n fail(`${where}.fields.${field} must be an object`);\n continue;\n }\n const entry: Record<string, unknown> = {};\n for (const [hint, hintValue] of Object.entries(hints)) {\n const at = `${where}.fields.${field}.${hint}`;\n if (!FIELD_OPTION_KEYS.has(hint)) {\n fail(\n `${at} is not a field option; use default, label, help, order, visibility, locked, or required`,\n );\n } else if (\n (hint === 'label' || hint === 'help') &&\n typeof hintValue !== 'string'\n ) {\n fail(`${at} must be a string`);\n } else if (\n hint === 'order' &&\n (typeof hintValue !== 'number' || !Number.isFinite(hintValue))\n ) {\n fail(`${at} must be a finite number`);\n } else if (\n (hint === 'locked' || hint === 'required') &&\n typeof hintValue !== 'boolean'\n ) {\n fail(`${at} must be a boolean`);\n } else if (\n hint === 'visibility' &&\n !(typeof hintValue === 'string' && VISIBILITIES.has(hintValue))\n ) {\n fail(`${at} must be one of basic, advanced, hidden`);\n } else {\n entry[hint] = hintValue;\n }\n }\n fields[field] = entry as RecipeFieldOptions;\n }\n out.fields = fields;\n } else if (key === 'exposure') {\n if (!isPlainObject(value)) {\n fail(`${where}.exposure must be an object`);\n continue;\n }\n const exposure: NonNullable<RecipeModelOptions['exposure']> = {};\n for (const [transport, narrowing] of Object.entries(value)) {\n if (!(EXPOSURE_TRANSPORTS as readonly string[]).includes(transport)) {\n fail(\n `${where}.exposure.${transport} is not a transport; use api, mcp, or cli`,\n );\n } else if (!isNarrowing(narrowing, operations)) {\n fail(\n `${where}.exposure.${transport} may only be \\`false\\` or a non-empty \\`{ exclude: [...] }\\` naming ${[...CRUD_VERBS].join('/')} or a method of \\`${model.className}\\`: options narrow exposure and never widen it, so \\`true\\` and \\`include\\` are rejected`,\n );\n } else {\n exposure[transport as (typeof EXPOSURE_TRANSPORTS)[number]] =\n narrowing;\n }\n }\n out.exposure = exposure;\n } else {\n fail(\n `${where}.${key} is not a model option; use \\`fields\\` or \\`exposure\\``,\n );\n }\n }\n return ok ? out : undefined;\n}\n\n/**\n * Resolve every raw recipe against the scanned classes and validate the set.\n *\n * Model names in the result are class names; qualification with the package\n * name belongs to the manifest adapter, which knows it. Errors carry the\n * recipe's file and line and fail the build like any other scan error.\n */\n/** Validate a nav `filter`: `{ field, value }` naming a field of the model. */\nfunction readNavFilter(\n value: unknown,\n fail: (message: string) => void,\n): { field: string; value: string } | undefined {\n if (value === undefined) return undefined;\n if (!isPlainObject(value)) {\n fail('filter must be an object `{ field, value }`');\n return undefined;\n }\n const extra = Object.keys(value).find((k) => k !== 'field' && k !== 'value');\n if (extra) {\n fail(`filter accepts only \\`field\\` and \\`value\\`, not \\`${extra}\\``);\n return undefined;\n }\n if (typeof value.field !== 'string' || typeof value.value !== 'string') {\n fail('filter needs a string `field` and a string `value`');\n return undefined;\n }\n // Field names are checked against the merged manifest in core\n // (`assertRecipeOptions`), which also knows inherited and tenant fields.\n return { field: value.field, value: value.value };\n}\n\n/** `requiresAny`: a non-empty list of non-empty lists of recipe ids. */\nfunction readRequiresAny(\n raw: RawRecipe,\n id: string,\n report: (message: string, line?: number) => void,\n): string[][] | undefined {\n if (!raw.requiresAny) return undefined;\n const { value, line } = raw.requiresAny;\n if (\n !Array.isArray(value) ||\n value.length === 0 ||\n !value.every((alt) => Array.isArray(alt) && alt.length > 0)\n ) {\n report(\n \"requiresAny must be a non-empty list of non-empty id lists, e.g. [['a.b', 'c.d']]\",\n line,\n );\n return undefined;\n }\n const out: string[][] = [];\n for (const alt of value as unknown[][]) {\n const ids: string[] = [];\n for (const entry of alt) {\n if (\n typeof entry !== 'string' ||\n entry.length > RECIPE_ID_MAX_LENGTH ||\n !RECIPE_ID_PATTERN.test(entry)\n ) {\n report(\n `requiresAny entry \\`${String(entry)}\\` is not a recipe id`,\n line,\n );\n } else if (entry === id) {\n report('a recipe cannot require itself', line);\n } else if (ids.includes(entry)) {\n report(`requiresAny lists \\`${entry}\\` more than once`, line);\n } else {\n ids.push(entry);\n }\n }\n out.push(ids);\n }\n return out;\n}\n\n/** Validate `group` / `section`: `{ id, label, ... }` strings, known keys only. */\nfunction readLabelled(\n raw: { value: unknown; line?: number } | null,\n name: string,\n allowed: Set<string>,\n report: (message: string, line?: number) => void,\n): Record<string, string> | undefined {\n if (!raw) return undefined;\n const { value, line } = raw;\n if (!isPlainObject(value)) {\n report(`${name} must be an object literal`, line);\n return undefined;\n }\n const out: Record<string, string> = {};\n let ok = true;\n for (const [key, entry] of Object.entries(value)) {\n if (!allowed.has(key)) {\n report(\n `${name} accepts only ${[...allowed].join(', ')}, not \\`${key}\\``,\n line,\n );\n ok = false;\n } else if (typeof entry !== 'string' || entry.trim() === '') {\n report(`${name}.${key} must be a non-empty string`, line);\n ok = false;\n } else {\n out[key] = entry;\n }\n }\n if (!out.id || !out.label) {\n if (ok) report(`${name} needs both \\`id\\` and \\`label\\``, line);\n return undefined;\n }\n if (!SLUG_PATTERN.test(out.id)) {\n report(\n `${name}.id \\`${out.id}\\` must be lowercase letters, digits, \\`-\\` or \\`_\\``,\n line,\n );\n return undefined;\n }\n if (out.icon !== undefined && !ICON_PATTERN.test(out.icon)) {\n report(`${name}.icon \\`${out.icon}\\` must be an icon name`, line);\n return undefined;\n }\n return ok ? out : undefined;\n}\n\n/** `pkg#Name` / `@scope/pkg/sub#Name`: a bare package specifier and an export. */\nconst EXPORT_REF_PATTERN =\n /^((?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*(?:\\/[A-Za-z0-9._-]+)*)#([A-Za-z_$][A-Za-z0-9_$]*)$/;\nconst ROUTE_PATH_PATTERN = /^\\/(?![/\\\\])[^\\s?#\\\\]*$/;\nconst PROVIDER_SLUG_PATTERN = /^[a-z][a-z0-9_-]*$/;\nconst SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;\nconst DEMO_SEED_MAX_BYTES = 8192;\n\ntype Report = (message: string, line?: number) => void;\n\nfunction readExportRef(\n value: unknown,\n at: string,\n report: Report,\n line?: number,\n field = 'export',\n): string | undefined {\n if (typeof value !== 'string') {\n report(\n `${at}.${field} must be a string like \\`pkg/svelte#Component\\``,\n line,\n );\n return undefined;\n }\n const match = EXPORT_REF_PATTERN.exec(value);\n if (\n !match ||\n match[1]\n .split('/')\n .some((part) => part === '.' || part === '..' || part.endsWith('.'))\n ) {\n report(\n `${at}.${field} \\`${value}\\` must be \\`<package specifier>#<ExportName>\\` (a package specifier, not a relative path)`,\n line,\n );\n return undefined;\n }\n return value;\n}\n\nfunction readNonEmpty(\n value: unknown,\n at: string,\n report: Report,\n line?: number,\n): string | undefined {\n if (typeof value !== 'string' || value.trim() === '') {\n report(`${at} must be a non-empty string`, line);\n return undefined;\n }\n return value;\n}\n\n/** Validate `static surfaces` (#3708). */\nfunction readSurfaces(\n raw: RawRecipe['surfaces'],\n report: Report,\n): RecipeSurface[] | undefined {\n if (!raw) return undefined;\n const { value, line } = raw;\n if (!Array.isArray(value) || value.length === 0) {\n report('surfaces must be a non-empty array of surface objects', line);\n return undefined;\n }\n const out: RecipeSurface[] = [];\n const seen = new Set<string>();\n let ok = true;\n value.forEach((entry, index) => {\n const at = `surfaces[${index}]`;\n if (!isPlainObject(entry)) {\n report(`${at} must be an object literal`, line);\n ok = false;\n return;\n }\n const kind = entry.kind;\n if (\n typeof kind !== 'string' ||\n !(RECIPE_SURFACE_KINDS as readonly string[]).includes(kind)\n ) {\n report(\n `${at}.kind must be one of ${RECIPE_SURFACE_KINDS.join(', ')} (got \\`${String(kind)}\\`)`,\n line,\n );\n ok = false;\n return;\n }\n const allowed: Record<string, string[]> = {\n 'shell-widget': ['kind', 'slot', 'export', 'label', 'icon'],\n route: ['kind', 'path', 'export', 'label'],\n 'settings-panel': ['kind', 'export', 'label'],\n playground: ['kind', 'export', 'label'],\n widget: [...RECIPE_WIDGET_KEYS],\n };\n for (const key of Object.keys(entry)) {\n if (!allowed[kind].includes(key)) {\n report(`${at} (${kind}) does not accept \\`${key}\\``, line);\n ok = false;\n }\n }\n const before = ok;\n const ref = readExportRef(\n entry.export,\n at,\n (m, l) => {\n report(m, l);\n ok = false;\n },\n line,\n );\n const fail = (message: string) => {\n report(message, line);\n ok = false;\n };\n let label: string | undefined;\n if (kind === 'playground' && entry.label === undefined) {\n label = undefined;\n } else {\n label = readNonEmpty(entry.label, `${at}.label`, fail, line);\n }\n let identity = `${kind}:${ref}`;\n const surface: Record<string, unknown> = { kind };\n if (kind === 'shell-widget') {\n const slot = entry.slot;\n if (\n typeof slot !== 'string' ||\n !(RECIPE_SHELL_SLOTS as readonly string[]).includes(slot)\n ) {\n fail(\n `${at}.slot \\`${String(slot)}\\` is not a shell slot (${RECIPE_SHELL_SLOTS.join(', ')})`,\n );\n }\n surface.slot = slot;\n if (entry.icon !== undefined) {\n if (typeof entry.icon !== 'string' || !ICON_PATTERN.test(entry.icon)) {\n fail(`${at}.icon must be an icon name`);\n } else {\n surface.icon = entry.icon;\n }\n }\n identity = `${identity}@${String(slot)}`;\n } else if (kind === 'route') {\n const path = entry.path;\n if (typeof path !== 'string' || !ROUTE_PATH_PATTERN.test(path)) {\n fail(\n `${at}.path must start with \\`/\\` and contain no whitespace, \\`?\\` or \\`#\\``,\n );\n } else if (\n /%2e|%2f|%5c/i.test(path) ||\n path\n .slice(1)\n .split('/')\n .some(\n (part, i, parts) =>\n part === '.' ||\n part === '..' ||\n (part === '' && i < parts.length - 1),\n )\n ) {\n fail(\n `${at}.path cannot contain \\`.\\`/\\`..\\` or empty segments, or encoded separators`,\n );\n } else {\n surface.path = path;\n identity = `route-path:${path}`;\n }\n } else if (kind === 'widget') {\n // Widget-specific fields live in recipe-widgets.ts (#3727).\n const extras = readWidgetSurface(entry, at, fail, (value, where, field) =>\n readExportRef(\n value,\n where,\n (m, l) => {\n report(m, l);\n ok = false;\n },\n line,\n field,\n ),\n );\n if (extras) Object.assign(surface, extras);\n if (typeof entry.type === 'string')\n identity = `widget-type:${entry.type}`;\n }\n if (ref !== undefined) {\n if (seen.has(identity)) fail(`${at} repeats an earlier surface`);\n seen.add(identity);\n }\n if (ok === before && ref !== undefined) {\n surface.export = ref;\n if (label !== undefined) surface.label = label;\n // Stable key order for deterministic artifacts.\n const ordered: Record<string, unknown> = { kind };\n const keyOrder: readonly string[] =\n kind === 'widget'\n ? RECIPE_WIDGET_KEYS\n : ['slot', 'path', 'export', 'label', 'icon'];\n for (const key of keyOrder) {\n if (surface[key] !== undefined) ordered[key] = surface[key];\n }\n out.push(ordered as unknown as RecipeSurface);\n }\n });\n return ok ? out : undefined;\n}\n\n/** Validate `static providers` (#3708). */\nfunction readProviders(\n raw: RawRecipe['providers'],\n report: Report,\n): RecipeProvider[] | undefined {\n if (!raw) return undefined;\n const { value, line } = raw;\n if (!Array.isArray(value) || value.length === 0) {\n report('providers must be a non-empty array of provider objects', line);\n return undefined;\n }\n const out: RecipeProvider[] = [];\n const ids = new Set<string>();\n let ok = true;\n const fail = (message: string) => {\n report(message, line);\n ok = false;\n };\n value.forEach((entry, index) => {\n const at = `providers[${index}]`;\n if (!isPlainObject(entry)) {\n fail(`${at} must be an object literal`);\n return;\n }\n for (const key of Object.keys(entry)) {\n if (\n ![\n 'id',\n 'kind',\n 'options',\n 'required',\n 'secrets',\n 'browserOptions',\n ].includes(key)\n ) {\n fail(`${at} does not accept \\`${key}\\``);\n }\n }\n const { id, kind, options, required, secrets, browserOptions } = entry;\n if (typeof id !== 'string' || !PROVIDER_SLUG_PATTERN.test(id)) {\n fail(`${at}.id must be a lowercase slug`);\n } else if (ids.has(id)) {\n fail(`${at}.id \\`${id}\\` is declared more than once`);\n } else {\n ids.add(id);\n }\n if (typeof kind !== 'string' || !PROVIDER_SLUG_PATTERN.test(kind)) {\n fail(`${at}.kind must be a lowercase slug such as email, oauth, storage`);\n }\n if (\n !Array.isArray(options) ||\n options.length === 0 ||\n !options.every(\n (o) => typeof o === 'string' && PROVIDER_SLUG_PATTERN.test(o),\n ) ||\n new Set(options).size !== options.length\n ) {\n fail(\n `${at}.options must be a non-empty list of distinct lowercase slugs`,\n );\n }\n if (typeof required !== 'boolean') {\n fail(`${at}.required must be written as true or false`);\n }\n if (\n secrets !== undefined &&\n (!Array.isArray(secrets) ||\n !secrets.every(\n (n) => typeof n === 'string' && SECRET_NAME_PATTERN.test(n),\n ) ||\n new Set(secrets).size !== secrets.length)\n ) {\n fail(\n `${at}.secrets must be distinct UPPER_SNAKE names (names, not values)`,\n );\n }\n if (\n browserOptions !== undefined &&\n (!Array.isArray(browserOptions) ||\n browserOptions.length === 0 ||\n new Set(browserOptions).size !== browserOptions.length ||\n !browserOptions.every(\n (o) =>\n typeof o === 'string' &&\n Array.isArray(options) &&\n options.includes(o),\n ))\n ) {\n fail(\n `${at}.browserOptions must be a non-empty list of distinct entries of options`,\n );\n }\n if (ok) {\n out.push({\n id: id as string,\n kind: kind as string,\n options: options as string[],\n required: required as boolean,\n ...(secrets ? { secrets: secrets as string[] } : {}),\n ...(browserOptions\n ? { browserOptions: browserOptions as string[] }\n : {}),\n });\n }\n });\n return ok ? out : undefined;\n}\n\n/** Validate `static runtime` (#3708). Returns `undefined` for the default. */\nfunction readRuntime(\n raw: RawRecipe['runtime'],\n report: Report,\n): RecipeRuntime | undefined {\n if (!raw) return undefined;\n const { value, line } = raw;\n if (\n typeof value !== 'string' ||\n !(RECIPE_RUNTIMES as readonly string[]).includes(value)\n ) {\n report(`runtime must be one of ${RECIPE_RUNTIMES.join(', ')}`, line);\n return undefined;\n }\n return value as RecipeRuntime;\n}\n\n/** Validate `static demoSeed` (#3708): a fixture export or small inline JSON. */\nfunction readDemoSeed(\n raw: RawRecipe['demoSeed'],\n report: Report,\n): RecipeDemoSeed | undefined {\n if (!raw) return undefined;\n const { value, line } = raw;\n if (!isPlainObject(value)) {\n report('demoSeed must be { export } or { data }', line);\n return undefined;\n }\n const keys = Object.keys(value);\n if (keys.length !== 1 || (keys[0] !== 'export' && keys[0] !== 'data')) {\n report('demoSeed must have exactly one of `export` or `data`', line);\n return undefined;\n }\n if (keys[0] === 'export') {\n const ref = readExportRef(value.export, 'demoSeed', report, line);\n return ref ? { export: ref as RecipeExportRef } : undefined;\n }\n const finite = (node: unknown): boolean =>\n typeof node === 'number'\n ? Number.isFinite(node)\n : Array.isArray(node)\n ? node.every(finite)\n : isPlainObject(node)\n ? Object.values(node).every(finite)\n : true;\n if (!finite(value.data)) {\n report('demoSeed.data cannot contain non-finite numbers', line);\n return undefined;\n }\n const size = Buffer.byteLength(JSON.stringify(value.data ?? null));\n if (value.data === undefined || value.data === null) {\n report('demoSeed.data must be JSON data', line);\n return undefined;\n }\n if (size > DEMO_SEED_MAX_BYTES) {\n report(\n `demoSeed.data is ${size} bytes; inline seeds are limited to ${DEMO_SEED_MAX_BYTES}, reference a fixture export instead`,\n line,\n );\n return undefined;\n }\n return { data: value.data };\n}\n\nexport function resolveRecipes(\n raws: RawRecipe[],\n classes: ResolvedClassDefinition[],\n): { recipes: RecipeDefinition[]; errors: ScanError[] } {\n const errors: ScanError[] = [];\n const recipes: RecipeDefinition[] = [];\n const ids = new Map<string, RawRecipe>();\n\n for (const raw of raws) {\n const report = (message: string, line?: number) =>\n errors.push({\n message: `Recipe ${raw.className}: ${message}`,\n filePath: raw.filePath,\n line: line ?? raw.line,\n severity: 'error',\n });\n const attempt = <T>(work: () => T, line?: number): T | undefined => {\n try {\n return work();\n } catch (error) {\n if (!(error instanceof RecipeReadError)) throw error;\n report(error.message, line);\n return undefined;\n }\n };\n\n if (raw.id === null || raw.label === null || raw.summary === null) {\n // Missing statics were already reported at extraction.\n continue;\n }\n const id = raw.id;\n if (id.length > RECIPE_ID_MAX_LENGTH || !RECIPE_ID_PATTERN.test(id)) {\n report(\n `id \\`${id}\\` must be dotted lowercase segments such as \\`commerce.sales\\``,\n );\n }\n const first = ids.get(id);\n if (first) {\n report(\n `id \\`${id}\\` is already declared by ${first.className} (${first.filePath})`,\n );\n } else {\n ids.set(id, raw);\n }\n if (raw.label.trim() === '') report('label must not be empty');\n if (raw.models.length === 0) report('models must list at least one model');\n\n // Resolve models; remember the class each local name denotes.\n const byLocal = new Map<string, ResolvedClassDefinition>();\n const models: ResolvedClassDefinition[] = [];\n for (const ref of raw.models) {\n const model = attempt(\n () => resolveModel(ref, raw, classes, 'static models entry'),\n ref.line,\n );\n if (!model) continue;\n if (models.includes(model)) {\n report(`models lists \\`${model.className}\\` more than once`, ref.line);\n continue;\n }\n models.push(model);\n byLocal.set(ref.local, model);\n byLocal.set(model.className, model);\n }\n\n const nav: RecipeDefinition['nav'] = [];\n for (const entry of raw.nav) {\n const model = attempt(\n () => resolveModel(entry.model, raw, classes, 'static nav model'),\n entry.line,\n );\n if (!model) continue;\n if (!models.includes(model)) {\n report(\n `nav entry \\`${entry.label}\\` points at \\`${model.className}\\`, which is not listed in models`,\n entry.line,\n );\n continue;\n }\n const filter = readNavFilter(entry.filter, (message) =>\n report(`nav entry \\`${entry.label}\\`: ${message}`, entry.line),\n );\n if (entry.key !== undefined && !SLUG_PATTERN.test(entry.key)) {\n report(\n `nav entry \\`${entry.label}\\`: key \\`${entry.key}\\` must be lowercase letters, digits, \\`-\\` or \\`_\\``,\n entry.line,\n );\n }\n if (entry.icon !== undefined && !ICON_PATTERN.test(entry.icon)) {\n report(\n `nav entry \\`${entry.label}\\`: icon \\`${entry.icon}\\` must be an icon name`,\n entry.line,\n );\n }\n for (const text of ['description', 'noun'] as const) {\n if (entry[text] !== undefined && entry[text]?.trim() === '') {\n report(\n `nav entry \\`${entry.label}\\`: ${text} must not be empty`,\n entry.line,\n );\n }\n }\n if (filter && entry.key === undefined) {\n report(\n `nav entry \\`${entry.label}\\`: a filter needs a key, which names its view`,\n entry.line,\n );\n }\n nav.push({\n label: entry.label,\n model: model.className,\n ...(entry.icon !== undefined ? { icon: entry.icon } : {}),\n ...(entry.description !== undefined\n ? { description: entry.description }\n : {}),\n ...(entry.key !== undefined ? { key: entry.key } : {}),\n ...(entry.noun !== undefined ? { noun: entry.noun } : {}),\n ...(filter ? { filter } : {}),\n });\n }\n // One view per (model, key): a second entry over a model needs its own key.\n const viewKeys = new Set<string>();\n for (const entry of nav) {\n const view = `${entry.model}:${entry.key ?? ''}`;\n if (viewKeys.has(view)) {\n report(\n `nav entry \\`${entry.label}\\` repeats the view of ${entry.model}${entry.key ? ` key \\`${entry.key}\\`` : ''}; give each extra entry over a model its own key`,\n );\n }\n viewKeys.add(view);\n }\n\n const requires: string[] = [];\n for (const required of raw.requires) {\n if (\n required.length > RECIPE_ID_MAX_LENGTH ||\n !RECIPE_ID_PATTERN.test(required)\n ) {\n report(`requires \\`${required}\\` is not a recipe id`);\n } else if (required === id) {\n report('a recipe cannot require itself');\n } else if (requires.includes(required)) {\n report(`requires lists \\`${required}\\` more than once`);\n } else {\n requires.push(required);\n }\n }\n\n const requiresAny = readRequiresAny(raw, id, report);\n const group = readLabelled(raw.group, 'group', GROUP_KEYS, report);\n const section = readLabelled(raw.section, 'section', SECTION_KEYS, report);\n\n let options: Record<string, RecipeModelOptions> | undefined;\n for (const entry of raw.options) {\n const model = byLocal.get(entry.key);\n if (!model) {\n report(\n `options.${entry.key} does not name one of the recipe's models`,\n entry.line,\n );\n continue;\n }\n const read = readModelOptions(\n entry.value,\n model,\n classes,\n `options.${entry.key}`,\n (message) => report(message, entry.line),\n );\n if (read) {\n options ??= {};\n if (options[model.className]) {\n report(\n `options names \\`${model.className}\\` more than once`,\n entry.line,\n );\n } else {\n options[model.className] = read;\n }\n }\n }\n\n const surfaces = readSurfaces(raw.surfaces, report);\n const providers = readProviders(raw.providers, report);\n const runtime = readRuntime(raw.runtime, report);\n const demoSeed = readDemoSeed(raw.demoSeed, report);\n\n const help = raw.help\n ? attempt(\n () => readHelp(raw.help as NonNullable<RawRecipe['help']>, raw),\n raw.help.line,\n )\n : undefined;\n\n recipes.push({\n id,\n className: raw.className,\n label: raw.label,\n summary: raw.summary,\n synonyms: raw.synonyms,\n models: models.map((model) => model.className),\n nav,\n requires,\n ...(requiresAny ? { requiresAny } : {}),\n ...(group ? { group: group as unknown as RecipeGroup } : {}),\n ...(section ? { section: section as unknown as RecipeSection } : {}),\n ...(options && Object.keys(options).length > 0 ? { options } : {}),\n ...(help ? { help } : {}),\n ...(surfaces ? { surfaces } : {}),\n ...(providers ? { providers } : {}),\n ...(runtime ? { runtime } : {}),\n ...(demoSeed ? { demoSeed } : {}),\n });\n }\n\n recipes.sort((a, b) => a.id.localeCompare(b.id));\n\n // Cross-recipe consistency within the package: a nav key names one layout id\n // (`item:<pkg>:<Model>:<key>`), and a shared group or section id means one\n // card or section, so its labels must agree.\n const navKeys = new Map<string, string>();\n const widgetTypes = new Map<string, string>();\n const labelled = new Map<string, { label: string; recipe: string }>();\n for (const recipe of recipes) {\n const raw = ids.get(recipe.id);\n const note = (message: string) =>\n errors.push({\n message: `Recipe ${recipe.className}: ${message}`,\n filePath: raw?.filePath ?? '',\n line: raw?.line,\n severity: 'error',\n });\n for (const entry of recipe.nav) {\n if (!entry.key) continue;\n const slot = `${entry.model}:${entry.key}`;\n const owner = navKeys.get(slot);\n if (owner && owner !== recipe.id) {\n note(\n `nav key \\`${entry.key}\\` over ${entry.model} is already used by recipe ${owner}; layout ids must be unique`,\n );\n }\n navKeys.set(slot, owner ?? recipe.id);\n }\n // A widget type is one registry key, so two recipes cannot share it (#3727).\n for (const surface of recipe.surfaces ?? []) {\n if (surface.kind !== 'widget') continue;\n const owner = widgetTypes.get(surface.type);\n if (owner && owner !== recipe.id) {\n note(\n `widget type \\`${surface.type}\\` is already used by recipe ${owner}; widget types must be unique`,\n );\n }\n widgetTypes.set(surface.type, owner ?? recipe.id);\n }\n for (const [kind, value] of [\n ['group', recipe.group],\n ['section', recipe.section],\n ] as const) {\n if (!value) continue;\n const slot = `${kind}:${value.id}`;\n const first = labelled.get(slot);\n if (first && first.label !== value.label) {\n note(\n `${kind} \\`${value.id}\\` is labelled \"${value.label}\" here but \"${first.label}\" in recipe ${first.recipe}`,\n );\n } else if (!first) {\n labelled.set(slot, { label: value.label, recipe: recipe.id });\n }\n }\n }\n\n // `requires` cycles among this package's own recipes.\n const byId = new Map(recipes.map((recipe) => [recipe.id, recipe]));\n const reported = new Set<string>();\n const visit = (recipe: RecipeDefinition, trail: string[]) => {\n if (trail.includes(recipe.id)) {\n const cycle = [...trail.slice(trail.indexOf(recipe.id)), recipe.id];\n const key = [...cycle].sort().join('|');\n if (!reported.has(key)) {\n reported.add(key);\n const raw = ids.get(recipe.id);\n errors.push({\n message: `Recipe ${recipe.className}: requires cycle ${cycle.join(' -> ')}`,\n filePath: raw?.filePath ?? '',\n line: raw?.line,\n severity: 'error',\n });\n }\n return;\n }\n for (const required of recipe.requires) {\n const next = byId.get(required);\n if (next) visit(next, [...trail, recipe.id]);\n }\n };\n for (const recipe of recipes) visit(recipe, []);\n\n recipes.sort((a, b) => a.id.localeCompare(b.id));\n return { recipes, errors };\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 {\n extractRecipes,\n type RawRecipe,\n sourceMayDeclareRecipe,\n} from './recipes.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 let recipes: RawRecipe[] | 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 if (sourceMayDeclareRecipe(sourceText)) {\n const found = extractRecipes({\n body: program.body,\n sourceText,\n filePath: filePath,\n });\n errors.push(...found.errors);\n if (found.recipes.length > 0) recipes = found.recipes;\n }\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 if (recipes) {\n result2.recipes = recipes;\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 * Read one file for `SmrtRecipe` declarations ONLY (#3590).\n *\n * The class scan's `include` is routinely narrowed to where models live, while\n * a recipe may sit beside them or elsewhere; binding recipe discovery to that\n * glob would drop the declaration with no diagnostic. A read or parse failure is\n * reported as a scan error for the same reason.\n */\nexport function parseRecipeFile(filePath: string): {\n recipes: RawRecipe[];\n errors: ScanError[];\n} {\n let sourceText: string;\n try {\n sourceText = readFileSync(filePath, 'utf-8');\n } catch (error) {\n return {\n recipes: [],\n errors: [\n {\n message: `Cannot read file for recipe discovery: ${error instanceof Error ? error.message : String(error)}`,\n filePath,\n severity: 'error',\n },\n ],\n };\n }\n if (!sourceMayDeclareRecipe(sourceText)) return { recipes: [], errors: [] };\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 { recipes: [], errors: [] };\n return extractRecipes({ body: program.body, sourceText, filePath });\n } catch (error) {\n return {\n recipes: [],\n errors: [\n {\n message: error instanceof Error ? error.message : String(error),\n filePath,\n severity: 'error',\n },\n ],\n };\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 let recipes: RawRecipe[] | 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 if (sourceMayDeclareRecipe(sourceText)) {\n const found = extractRecipes({\n body: program.body,\n sourceText,\n filePath: filename,\n });\n errors.push(...found.errors);\n if (found.recipes.length > 0) recipes = found.recipes;\n }\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 if (recipes) {\n result2.recipes = recipes;\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 union = enumMembersToUnion(members);\n if (union) aliases[name] = union;\n }\n }\n }\n return aliases;\n}\n\n/**\n * Render an enum's members as the union string the alias map stores\n * (`'a' | 'b'` or `0 | 1`), in declaration order, using the member VALUES\n * rather than their names (#3598).\n *\n * Handles string, numeric, negative and substitution-free template\n * initializers, plus TypeScript's auto-increment for members without one\n * (`enum E { A, B }` is `0 | 1`; `const enum` parses to the same node).\n * Returns `null` when any member is not statically resolvable or when string\n * and numeric members are mixed: a partial value list would be wrong, and a\n * mixed enum has no single column type.\n */\nfunction enumMembersToUnion(members: TSEnumMember[]): string | null {\n const values: Array<string | number> = [];\n let next = 0;\n for (const member of members) {\n const init = member.initializer as\n | {\n type?: string;\n value?: unknown;\n operator?: string;\n argument?: { type?: string; value?: unknown };\n quasis?: Array<{ value?: { cooked?: string | null } }>;\n expressions?: unknown[];\n }\n | undefined;\n if (!init) {\n values.push(next);\n next += 1;\n } else if (init.type === 'Literal' && typeof init.value === 'string') {\n values.push(init.value);\n } else if (init.type === 'Literal' && typeof init.value === 'number') {\n values.push(init.value);\n next = init.value + 1;\n } else if (\n init.type === 'UnaryExpression' &&\n init.operator === '-' &&\n init.argument?.type === 'Literal' &&\n typeof init.argument.value === 'number'\n ) {\n values.push(-init.argument.value);\n next = -init.argument.value + 1;\n } else if (\n init.type === 'TemplateLiteral' &&\n init.expressions?.length === 0 &&\n typeof init.quasis?.[0]?.value?.cooked === 'string'\n ) {\n values.push(init.quasis[0].value.cooked);\n } else {\n return null;\n }\n }\n const allStrings = values.every((v) => typeof v === 'string');\n const allNumbers = values.every((v) => typeof v === 'number');\n if (!allStrings && !allNumbers) return null;\n return values\n .map((v) => {\n if (typeof v !== 'string') return String(v);\n const encoded = JSON.stringify(v);\n return `'${encoded.slice(1, -1).replaceAll(\"'\", \"\\\\'\")}'`;\n })\n .join(' | ');\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 outerStart?: number,\n): RawClassDefinition | null {\n // Handle export declarations. `outerStart` carries the `export` keyword's\n // offset so the class JSDoc is found above it (decorators and `export` can\n // both sit between the comment and the `class` keyword).\n if (node.type === 'ExportNamedDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration,\n filePath,\n sourceText,\n importAliases,\n ctx,\n node.start ?? outerStart,\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 node.start ?? outerStart,\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 outerStart,\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 outerStart?: number,\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 const explicitDescription =\n typeof smrtConfig?.description === 'string'\n ? normalizeModelDescription(smrtConfig.description)\n : undefined;\n const description =\n explicitDescription ??\n extractClassJsDocDescription(\n sourceText,\n className,\n [node.start, outerStart, ...decorators.map((d) => d.start)].filter(\n (n): n is number => typeof n === 'number',\n ),\n );\n\n return {\n className,\n filePath,\n extendsClause,\n extendsTypeArg,\n decoratorConfig,\n hasSmartDecorator,\n ...(description ? { description } : {}),\n fields,\n methods,\n startLine: node.loc?.start.line || 1,\n endLine: node.loc?.end.line || 1,\n ...(typeof node.body?.start === 'number'\n ? { bodyStart: node.body.start }\n : {}),\n };\n}\n\nconst MODEL_DESCRIPTION_MAX = 200;\n\n/** Collapse whitespace and cap at {@link MODEL_DESCRIPTION_MAX}, cutting at a sentence boundary. */\nfunction normalizeModelDescription(raw: string): string | undefined {\n const text = raw.replace(/\\s+/g, ' ').trim();\n if (!text) return undefined;\n if (text.length <= MODEL_DESCRIPTION_MAX) return text;\n const head = text.slice(0, MODEL_DESCRIPTION_MAX);\n const sentenceEnd = Math.max(\n head.lastIndexOf('. '),\n head.lastIndexOf('! '),\n head.lastIndexOf('? '),\n );\n if (sentenceEnd > 0) return head.slice(0, sentenceEnd + 1);\n const wordEnd = head.lastIndexOf(' ');\n return `${(wordEnd > 0 ? head.slice(0, wordEnd) : head).replace(/[,;:\\s]+$/, '')}…`;\n}\n\n/**\n * Summarize the JSDoc block directly above a class (before any `export` or\n * decorators) as a one-line model description: the first paragraph, minus a\n * leading `ClassName - ` / `ClassName: ` prefix, tags and inline markup.\n * `@internal` classes yield nothing. Pure text work on the already-parsed\n * source; nothing is executed.\n */\nexport function extractClassJsDocDescription(\n sourceText: string,\n className: string,\n anchors: number[],\n): string | undefined {\n if (anchors.length === 0) return undefined;\n const before = sourceText.slice(0, Math.min(...anchors)).trimEnd();\n if (!before.endsWith('*/')) return undefined;\n const open = before.lastIndexOf('/**');\n if (open < 0 || before.indexOf('*/', open) !== before.length - 2) {\n return undefined;\n }\n return summarizeJsDoc(before.slice(open, before.length), className);\n}\n\n/** @internal Exported for testing. */\nexport function summarizeJsDoc(\n block: string,\n className: string,\n): string | undefined {\n const lines = block\n .replace(/^\\/\\*\\*/, '')\n .replace(/\\*\\/$/, '')\n .split('\\n')\n .map((line) => line.replace(/^\\s*\\*\\s?/, '').trimEnd());\n const summary: string[] = [];\n let internal = false;\n let inFence = false;\n for (const line of lines) {\n if (/^\\s*@internal\\b/.test(line)) internal = true;\n if (/^\\s*```/.test(line)) {\n inFence = !inFence;\n continue;\n }\n if (inFence) continue;\n if (/^\\s*@\\w+/.test(line)) {\n summary.push('\\u0000');\n continue;\n }\n summary.push(line);\n }\n if (internal) return undefined;\n const paragraph: string[] = [];\n for (const line of summary) {\n if (line === '\\u0000') break;\n if (line.trim() === '') {\n if (paragraph.length > 0) break;\n continue;\n }\n paragraph.push(line.trim());\n }\n let text = paragraph.join(' ');\n const escaped = className.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n text = text\n .replace(new RegExp(`^${escaped}\\\\s*(?:[-\\u2013\\u2014:]+)\\\\s*`), '')\n .replace(\n /\\{@(?:link|linkcode|linkplain)\\s+([^}|\\s]+)(?:[|\\s]+([^}]*))?\\}/g,\n (_m, target, label) => (label?.trim() ? label.trim() : target),\n )\n .replace(/\\{@\\w+\\s*([^}]*)\\}/g, '$1')\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/`([^`]*)`/g, '$1')\n .replace(/<\\/?[a-zA-Z][^>]*>/g, '')\n .replace(/(\\*\\*|__)(.+?)\\1/g, '$2');\n if (text.length > 0) text = text[0].toUpperCase() + text.slice(1);\n return normalizeModelDescription(text);\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 type { RecipeDefinition } from '@happyvertical/smrt-types';\nimport { type EnumValue, resolveEnumValues } from './enum-values.js';\nimport { isSafeObjectKey } from './oxc-parser.js';\nimport type {\n FieldTypeInference,\n InferredFieldType,\n ParameterTypeBranch,\n RawFieldDefinition,\n RawMethodDefinition,\n ResolvedClassDefinition,\n UiSelectorDeclaration,\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 /**\n * Closed set of allowed values for an enum- or literal-union-typed field, in\n * declaration order, values not member names (#3598).\n */\n enum?: EnumValue[];\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 | string[];\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 /** User-facing model description (explicit option, else class JSDoc summary). */\n description?: 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 recipes?: RecipeDefinition[];\n /** Selector slots keyed by slot id (#3599). Mirrors smrt-core's type. */\n uiSelectors?: Record<\n string,\n {\n slotId: string;\n selects: `${string}:${string}`;\n label?: string;\n description?: string;\n }\n >;\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 * Recipes from `ScanResults.recipes` (#3590). Model names are class\n * names; they are qualified here with `packageName`.\n */\n recipes?: RecipeDefinition[];\n /** Selector slots from {@link ScanResults.uiSelectors} (#3599). */\n uiSelectors?: Record<string, UiSelectorDeclaration>;\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 const recipes = this.qualifyRecipes(\n options.recipes ?? [],\n options.packageName,\n );\n // Selector bindings carry no source path: manifests must stay portable.\n const selectorEntries = Object.entries(options.uiSelectors ?? {}).sort(\n ([a], [b]) => (a < b ? -1 : a > b ? 1 : 0),\n );\n const selectors =\n selectorEntries.length > 0\n ? Object.fromEntries(\n selectorEntries.map(([id, decl]) => [\n id,\n {\n slotId: decl.slotId,\n selects: decl.selects,\n ...(decl.label !== undefined ? { label: decl.label } : {}),\n ...(decl.description !== undefined\n ? { description: decl.description }\n : {}),\n },\n ]),\n )\n : undefined;\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 // Additive: a package that declares no recipe emits no key, so its\n // checked-in manifest stays byte-identical.\n ...(recipes.length > 0 ? { recipes } : {}),\n ...(selectors ? { uiSelectors: selectors } : {}),\n };\n }\n\n /** Qualify recipe model names (`@scope/pkg:Class`) once the package is known. */\n private qualifyRecipes(\n recipes: RecipeDefinition[],\n packageName: string | undefined,\n ): RecipeDefinition[] {\n const qualify = (className: string): string =>\n packageName ? createQualifiedName(packageName, className) : className;\n return recipes.map((recipe) => ({\n ...recipe,\n models: recipe.models.map(qualify),\n nav: recipe.nav.map((entry) => ({\n ...entry,\n model: qualify(entry.model),\n })),\n ...(recipe.options\n ? {\n options: Object.fromEntries(\n Object.entries(recipe.options).map(([model, value]) => [\n qualify(model),\n value,\n ]),\n ),\n }\n : {}),\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 = [\n 'uiSlots',\n 'adminRoutes',\n 'signalSubscriptions',\n 'createEntries',\n ];\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 // The declared route/permission namespace is independent of the table name.\n const collection =\n typeof classDef.decoratorConfig?.collection === 'string'\n ? classDef.decoratorConfig.collection\n : 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 ...(classDef.description ? { description: classDef.description } : {}),\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 // Closed literal sets (enum / literal union / aliases of either) carry\n // their allowed values so forms and generated tool schemas can constrain\n // the field (#3598).\n const enumValues = this.resolveFieldEnum(field, definition.type);\n if (enumValues) {\n definition.enum = enumValues;\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 // #3023: the declared delete policy must reach the manifest, or the\n // manifest generator falls back to the natural-key default (CASCADE\n // for a conflictColumns member) and the DDL disagrees with the\n // runtime decorator.\n 'onDelete',\n 'onUpdate',\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 // #3023: keep the declared app-side delete policy for manifest-only\n // consumers, matching the runtime decorator.\n 'onDelete',\n 'onUpdate',\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 // A union that CONTAINS an alias or enum (`Base | 'extra'`) is still a\n // closed literal set once flattened (#3598); without this it fell to json.\n const closedSet = type\n ? resolveEnumValues(type, this.typeAliases)\n : undefined;\n if (closedSet?.every((v) => typeof v === 'string')) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n if (closedSet?.every((v) => typeof v === 'number')) {\n return {\n type: closedSet.every(Number.isInteger) ? 'integer' : 'decimal',\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'annotation',\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 * Allowed values of a field whose declared type is a closed literal set.\n * Only emitted when the final column type agrees with the value kind, so a\n * `@field({ type })` override can never contradict its own `enum`.\n */\n private resolveFieldEnum(\n field: RawFieldDefinition,\n fieldType: FieldDefinition['type'],\n ): EnumValue[] | undefined {\n if (!field.typeAnnotation) return undefined;\n const values = resolveEnumValues(field.typeAnnotation, this.typeAliases);\n if (!values) return undefined;\n if (fieldType === 'text') {\n return values.every((v) => typeof v === 'string') ? values : undefined;\n }\n if (fieldType === 'integer' || fieldType === 'decimal') {\n return values.every((v) => typeof v === 'number') ? values : undefined;\n }\n return undefined;\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 * Selector-slot discovery (#3599).\n *\n * A package declares its UI slots in a module-scope `Record<string,\n * ModuleUISlot>` constant (conventionally `src/ui.ts`). A slot carrying\n * `selects: '@scope/pkg:Model'` marks that component as the selector for the\n * model. This reads those declarations statically, with no package code\n * loaded, so they can ride the manifest for hosts that render generic forms.\n *\n * Only slots that declare `selects` are collected: the manifest records\n * selector bindings, not the package's whole UI inventory.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { parseSync } from 'oxc-parser';\nimport { extractModuleObjectConstants } from './oxc-parser.js';\nimport type { ScanError, UiSelectorDeclaration } from './types.js';\n\nconst QUALIFIED_NAME = /^@[^/\\s:]+\\/[^/\\s:]+:[A-Za-z_$][\\w$]*$/;\n\n/** Locale-independent order: manifests must be byte-stable across machines. */\nfunction ordinal(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/** Result of reading one file for selector slots. */\nexport interface UiSelectorFileResult {\n selectors: UiSelectorDeclaration[];\n errors: ScanError[];\n}\n\nfunction langOf(filePath: string): 'ts' | 'tsx' | 'js' | 'jsx' {\n if (filePath.endsWith('.tsx')) return 'tsx';\n if (filePath.endsWith('.ts')) return 'ts';\n if (filePath.endsWith('.jsx')) return 'jsx';\n return 'js';\n}\n\nfunction collect(\n value: unknown,\n fallbackId: string | undefined,\n filePath: string,\n out: UiSelectorDeclaration[],\n errors: ScanError[],\n seen: Set<unknown>,\n): void {\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n if (Array.isArray(value)) {\n for (const entry of value)\n collect(entry, undefined, filePath, out, errors, seen);\n return;\n }\n const record = value as Record<string, unknown>;\n if (Object.hasOwn(record, 'selects')) {\n const slotId =\n typeof record.id === 'string' && record.id !== ''\n ? record.id\n : fallbackId;\n if (\n typeof record.selects !== 'string' ||\n !QUALIFIED_NAME.test(record.selects)\n ) {\n errors.push({\n message: `UI slot \"${slotId ?? '?'}\" declares selects ${JSON.stringify(record.selects)}; it must be a string literal qualified model name (\"@scope/package:ClassName\").`,\n filePath,\n severity: 'error',\n });\n } else if (!slotId) {\n errors.push({\n message: `A UI slot selecting ${record.selects} has no string \\`id\\`.`,\n filePath,\n severity: 'error',\n });\n } else {\n out.push({\n slotId,\n selects: record.selects as UiSelectorDeclaration['selects'],\n ...(typeof record.label === 'string' ? { label: record.label } : {}),\n ...(typeof record.description === 'string'\n ? { description: record.description }\n : {}),\n filePath,\n });\n }\n }\n for (const [key, child] of Object.entries(record)) {\n if (key === 'selects') continue;\n collect(child, key, filePath, out, errors, seen);\n }\n}\n\n/** Read one file for selector slots. Unreadable or unparsable files yield nothing. */\nexport function parseUiSelectorsFile(filePath: string): UiSelectorFileResult {\n const empty: UiSelectorFileResult = { selectors: [], errors: [] };\n let sourceText: string;\n try {\n sourceText = readFileSync(filePath, 'utf-8');\n } catch {\n return empty;\n }\n if (!sourceText.includes('selects')) return empty;\n try {\n const program = parseSync(filePath, sourceText, {\n lang: langOf(filePath),\n preserveParens: false,\n }).program;\n if (!program?.body) return empty;\n const constants = extractModuleObjectConstants(\n program.body as unknown as Parameters<\n typeof extractModuleObjectConstants\n >[0],\n sourceText,\n );\n const selectors: UiSelectorDeclaration[] = [];\n const errors: ScanError[] = [];\n const seen = new Set<unknown>();\n for (const [name, constant] of constants) {\n collect(constant.value, name, filePath, selectors, errors, seen);\n }\n return { selectors, errors };\n } catch {\n return empty;\n }\n}\n\n/**\n * Merge per-file declarations into one deterministic, id-keyed record.\n * A slot id declared twice, or one model claimed by two slots, is an error:\n * a host must be able to resolve exactly one selector per model.\n */\nexport function mergeUiSelectors(\n files: UiSelectorFileResult[],\n relativize: (filePath: string) => string = (p) => p,\n): {\n selectors: Record<string, UiSelectorDeclaration>;\n errors: ScanError[];\n} {\n const errors: ScanError[] = files.flatMap((file) => file.errors);\n const all = files\n .flatMap((file) => file.selectors)\n .sort(\n (a, b) => ordinal(a.slotId, b.slotId) || ordinal(a.filePath, b.filePath),\n );\n const selectors: Record<string, UiSelectorDeclaration> = {};\n const byModel = new Map<string, string>();\n for (const decl of all) {\n if (selectors[decl.slotId]) {\n errors.push({\n message: `UI slot id \"${decl.slotId}\" is declared more than once.`,\n filePath: decl.filePath,\n severity: 'error',\n });\n continue;\n }\n const other = byModel.get(decl.selects);\n if (other) {\n errors.push({\n message: `UI slots \"${other}\" and \"${decl.slotId}\" both select ${decl.selects}; a model has one selector.`,\n filePath: decl.filePath,\n severity: 'error',\n });\n continue;\n }\n byModel.set(decl.selects, decl.slotId);\n selectors[decl.slotId] = { ...decl, filePath: relativize(decl.filePath) };\n }\n return { selectors, errors };\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 {\n parseAgentSurfaceFile,\n parseFile,\n parseRecipeFile,\n} from './oxc-parser.js';\nimport { type RawRecipe, resolveRecipes } from './recipes.js';\nimport type {\n AgentSurface,\n ExternalManifest,\n FileScanResult,\n OxcScannerOptions,\n ResolvedClassDefinition,\n ScanError,\n ScanResults,\n} from './types.js';\nimport { mergeUiSelectors, parseUiSelectorsFile } from './ui-selectors.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 */\n/** Where package UI slot declarations conventionally live (#3599). */\nconst DEFAULT_UI_SELECTOR_INCLUDE = ['src/**/ui.ts'];\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 private recipeErrors: ScanError[] = [];\n private outsideRecipes: RawRecipe[] = [];\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 uiSelectorInclude:\n options.uiSelectorInclude || DEFAULT_UI_SELECTOR_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 recipes: [],\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 // Recipes outside the class glob are found by their own pass, for the same\n // reason declarations are: a narrowed model glob must not drop them.\n const outside = await this.scanRecipesOutsideClassGlob(new Set(files));\n this.outsideRecipes = outside.recipes;\n results.errors.push(...outside.errors);\n\n const uiSelectors = await this.scanUiSelectors();\n if (uiSelectors) {\n results.uiSelectors = uiSelectors.selectors;\n results.errors.push(...uiSelectors.errors);\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 const resolved = this.resolver.resolveAll();\n\n // Recipes name model classes, so they resolve only once the classes do.\n // Their errors join the scan errors every caller already fails closed on.\n const raw = [\n ...this.scanResults.files.flatMap((file) => file.recipes ?? []),\n ...this.outsideRecipes,\n ];\n const { recipes, errors } = resolveRecipes(raw, resolved);\n this.scanResults.recipes = recipes;\n // resolve() may run more than once; never report the same error twice.\n this.scanResults.errors = this.scanResults.errors.filter(\n (error) => !this.recipeErrors.includes(error),\n );\n this.recipeErrors = errors;\n this.scanResults.errors.push(...errors);\n\n return resolved;\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 * Find `SmrtRecipe` declarations in files the CLASS scan did not cover.\n *\n * Same rule as {@link scanDeclarationsOutsideClassGlob}: the model glob is\n * narrowed to where models live, a recipe need not live there, and a recipe\n * that vanished with no diagnostic is the failure to prevent.\n */\n private async scanRecipesOutsideClassGlob(\n alreadyScanned: ReadonlySet<string>,\n ): Promise<{ recipes: RawRecipe[]; errors: ScanError[] }> {\n const out = { recipes: [] as RawRecipe[], errors: [] as ScanError[] };\n if (this.options.agentSurfaceInclude.length === 0) return out;\n let files: string[];\n try {\n files = await discoverSourceFiles({\n cwd: this.options.cwd,\n include: this.options.agentSurfaceInclude,\n exclude: [...this.options.exclude, ...AGENT_SURFACE_PRUNE],\n followSymbolicLinks: this.options.followSymbolicLinks,\n });\n } catch {\n return out;\n }\n for (const filePath of files) {\n if (alreadyScanned.has(filePath)) continue;\n if (!isAgentSurfaceSourcePath(filePath, this.options.cwd)) continue;\n const found = parseRecipeFile(filePath);\n out.recipes.push(...found.recipes);\n out.errors.push(...found.errors);\n }\n return out;\n }\n\n /**\n * Read selector-slot declarations (`selects`, #3599) from the package's\n * `ui.ts` files, independently of the class-scan glob.\n */\n private async scanUiSelectors(): Promise<\n ReturnType<typeof mergeUiSelectors> | undefined\n > {\n if (this.options.uiSelectorInclude.length === 0) return undefined;\n let files: string[];\n try {\n files = await discoverSourceFiles({\n cwd: this.options.cwd,\n include: this.options.uiSelectorInclude,\n exclude: [...this.options.exclude, ...AGENT_SURFACE_PRUNE],\n followSymbolicLinks: this.options.followSymbolicLinks,\n });\n } catch {\n return undefined;\n }\n const parsed = files.sort().map((file) => parseUiSelectorsFile(file));\n const merged = mergeUiSelectors(parsed, (filePath) =>\n this.relativizeSourcePath(filePath),\n );\n return Object.keys(merged.selectors).length > 0 || merged.errors.length > 0\n ? merged\n : undefined;\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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"}