@llui/vite-plugin 0.0.36 → 0.0.37

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.
@@ -1 +1 @@
1
- {"version":3,"file":"cross-file-resolver.d.ts","sourceRoot":"","sources":["../src/cross-file-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,iBAAiB,CAAA;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC7E;;;;;OAKG;IACH,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAwGpC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAAC,CAKpD;AA6KD;;;;;;;GAOG;AACH,wBAAsB,wCAAwC,CAC5D,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAK3B;AA4ND;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB,CASA"}
1
+ {"version":3,"file":"cross-file-resolver.d.ts","sourceRoot":"","sources":["../src/cross-file-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,iBAAiB,CAAA;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC7E;;;;;OAKG;IACH,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAwGpC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAAC,CAKpD;AAoLD;;;;;;;GAOG;AACH,wBAAsB,wCAAwC,CAC5D,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAK3B;AA4ND;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB,CASA"}
@@ -245,8 +245,13 @@ function parseMessageAnnotations(comment) {
245
245
  examples: readExamplesTag(comment),
246
246
  warning: readWarningTag(comment),
247
247
  emits: readEmitsTag(comment),
248
+ routeGate: readRouteGateTag(comment),
248
249
  };
249
250
  }
251
+ function readRouteGateTag(comment) {
252
+ const match = comment.match(/@routeGated\s*\(\s*["“]([^"”]*)["”]\s*\)/);
253
+ return match?.[1] ?? null;
254
+ }
250
255
  function readEmitsTag(comment) {
251
256
  const outer = comment.match(/@emits\s*\(([^)]*)\)/);
252
257
  if (!outer || outer[1] === undefined)
@@ -288,6 +293,7 @@ function defaultMessageAnnotations() {
288
293
  examples: [],
289
294
  warning: null,
290
295
  emits: [],
296
+ routeGate: null,
291
297
  };
292
298
  }
293
299
  function readIntentTag(comment) {
@@ -1 +1 @@
1
- {"version":3,"file":"cross-file-resolver.js","sourceRoot":"","sources":["../src/cross-file-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript'\nimport {\n type MessageAnnotations,\n type DispatchMode as MessageDispatchMode,\n} from './msg-annotations.js'\nimport {\n type MsgSchema,\n type MsgField,\n type TypeIndex,\n buildFieldDescriptor,\n} from './msg-schema.js'\n\n/**\n * Cross-file type resolver.\n *\n * The schema/annotation extractors (`extractMsgAnnotations`,\n * `extractMsgSchema`, `extractStateSchema`, `extractEffectSchema`) only\n * see the source string for the file currently being transformed. When\n * a developer keeps the `Msg` (or `State` / `Effect`) union in a\n * separate file and imports it where `component()` is called, those\n * extractors silently return `null` — the plugin emits no annotations,\n * runtime LAP validation is disabled, and Claude can dispatch arbitrary\n * `type` strings that fall through to `assertNever`.\n *\n * This module follows imports and re-exports to find the source file\n * that declares the requested type alias, returning that file's source\n * string + the local name of the alias there. Extractors then run\n * against that source and produce the same output they would have for\n * a co-located declaration.\n *\n * Limitations:\n * - Composition (`type Msg = ImportedA | { type: 'b' }`): only the\n * locally-declared variants are extracted; the imported half isn't\n * walked recursively into. The lint rule `agent-msg-resolvable`\n * catches this case at lint time.\n * - Namespace imports (`import * as ns from './msg'`) and `export *`:\n * not followed. Same lint coverage.\n * - Generic types: not parameterized resolution; the type argument\n * must resolve to a concrete type alias.\n */\n\nexport interface ResolveContext {\n /**\n * Resolve a module specifier (e.g. `'./msg'`, `'@scope/pkg'`) against\n * the importing file's path. Returns the absolute filesystem path of\n * the resolved module, or `null` if it cannot be resolved (the type\n * stays unresolved and the extractor falls back to local-only mode).\n */\n resolveModule: (spec: string, importerPath: string) => Promise<string | null>\n /**\n * Read the source contents of an absolute module path. The contents\n * are parsed by TypeScript so they should be valid TS/TSX. The plugin\n *'s vite hook plumbs `fs/promises.readFile` here; tests provide an\n * in-memory map.\n */\n readSource: (absolutePath: string) => Promise<string>\n}\n\nexport interface ResolvedTypeSource {\n /** The full source string of the file declaring the type alias. */\n source: string\n /** The local name of the alias *in that file* (after rename chains). */\n localName: string\n /** Absolute path of the file declaring the alias (debug aid). */\n filePath: string\n}\n\n/**\n * Walk imports + re-exports to find where a type alias is actually\n * declared. Returns the source string and local name of the alias in\n * its declaring file. Returns `null` if the chain leads to an unresolved\n * module, a re-export through `export *`, a namespace import, or a\n * dead-end (alias not declared anywhere we can see).\n */\nexport async function findTypeSource(\n typeName: string,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n visited: Set<string> = new Set(),\n): Promise<ResolvedTypeSource | null> {\n // Cycle prevention — re-export A → A is a tight loop that some\n // pathological re-export chains can produce. Bail rather than\n // infinitely recurse.\n if (visited.has(`${filePath}::${typeName}`)) return null\n visited.add(`${filePath}::${typeName}`)\n\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true)\n\n // 1. Local declaration wins. `type X = ...` or `interface X { ... }`\n // (extractors only support type aliases today, but check both so\n // the resolver itself isn't a footgun for future extractors).\n for (const stmt of sf.statements) {\n if (ts.isTypeAliasDeclaration(stmt) && stmt.name.text === typeName) {\n return { source, localName: typeName, filePath }\n }\n if (ts.isInterfaceDeclaration(stmt) && stmt.name.text === typeName) {\n return { source, localName: typeName, filePath }\n }\n }\n\n // 2. Re-export with name: `export { X } from './y'` or\n // `export { X as Y } from './y'`. Walk to the source module.\n for (const stmt of sf.statements) {\n if (!ts.isExportDeclaration(stmt)) continue\n if (!stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) continue\n if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier)) continue\n\n for (const spec of stmt.exportClause.elements) {\n const exportedName = spec.name.text\n if (exportedName !== typeName) continue\n // The name in the source module is `propertyName` if present\n // (e.g. `export { Msg as M } from './msg'` exports as M but the\n // source module has it as Msg).\n const sourceName = spec.propertyName?.text ?? spec.name.text\n const resolved = await ctx.resolveModule(stmt.moduleSpecifier.text, filePath)\n if (!resolved) return null\n const subSource = await ctx.readSource(resolved)\n return findTypeSource(sourceName, subSource, resolved, ctx, visited)\n }\n }\n\n // 3. Local re-binding: `export { X } from elsewhere` shorthand was\n // handled above. A separate case is `import { X } from ... ; export\n // { X }` — the import already declares X locally, so step 5 picks\n // it up.\n\n // 4. Star re-exports: `export * from './y'`. The barrel re-exports\n // every named member of `./y` under the same name. Walk each\n // barrel target and return the first hit. Order: textual order\n // in the source file (matches TypeScript's behaviour for\n // multi-barrel name collisions, where the first declared wins).\n //\n // Multiple `export *` declarations are common in monorepo barrel\n // files (`export * from './msg'; export * from './effects'`).\n // Without this step, the resolver returns `null` and the plugin\n // silently emits empty annotations for any consumer that points\n // at a barrel.\n for (const stmt of sf.statements) {\n if (!ts.isExportDeclaration(stmt)) continue\n // `export * from './y'` has no exportClause; `export {} from './y'`\n // is a different beast (re-exports nothing). Skip the latter.\n if (stmt.exportClause) continue\n if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier)) continue\n\n const resolved = await ctx.resolveModule(stmt.moduleSpecifier.text, filePath)\n if (!resolved) continue\n let subSource: string\n try {\n subSource = await ctx.readSource(resolved)\n } catch {\n // Module path resolved but the file isn't readable (deleted,\n // dynamic-only, etc.). Continue to the next barrel.\n continue\n }\n const found = await findTypeSource(typeName, subSource, resolved, ctx, visited)\n if (found) return found\n }\n\n // 5. Imports: `import { X } from './y'` or `import { X as Y } from './y'`.\n // Walk to the source module using the original (imported) name.\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt)) continue\n if (!stmt.importClause) continue\n if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier)) continue\n\n const bindings = stmt.importClause.namedBindings\n if (!bindings || !ts.isNamedImports(bindings)) continue\n\n for (const elem of bindings.elements) {\n const localName = elem.name.text\n if (localName !== typeName) continue\n // The remote name is `propertyName` when there's a rename, else\n // the local name itself.\n const remoteName = elem.propertyName?.text ?? elem.name.text\n const resolved = await ctx.resolveModule(stmt.moduleSpecifier.text, filePath)\n if (!resolved) return null\n const subSource = await ctx.readSource(resolved)\n return findTypeSource(remoteName, subSource, resolved, ctx, visited)\n }\n }\n\n // Not found in this file and no import/re-export to follow.\n return null\n}\n\n/**\n * Annotation extractor that walks composed Msg unions across files.\n *\n * Given a Msg type that may be a union of inline `{ type: 'literal' }`\n * objects AND TypeReferences (e.g.\n * `type Msg = ImportedFoo | { type: 'extra' }`), recursively follow\n * each TypeReference via `findTypeSource` and merge its variants into\n * the returned map.\n *\n * Composition + cross-file is the union of two failure modes the\n * file-local sync extractor silently mishandles. This function\n * produces the same map the runtime expects regardless of how the\n * developer organized the type declarations.\n *\n * Conflict policy: if two composed branches contribute the same\n * discriminant string (e.g. both halves declare `{ type: 'inc' }`),\n * the first one walked wins. The lint rule `agent-msg-resolvable`\n * fires before this point on most pathological cases; ESLint's\n * type-checker would flag the duplicate independently.\n */\nexport async function extractMsgAnnotationsCrossFile(\n source: string,\n typeName: string,\n filePath: string,\n ctx: ResolveContext,\n): Promise<Record<string, MessageAnnotations> | null> {\n const out: Record<string, MessageAnnotations> = {}\n const ok = await collectMsgVariants(typeName, source, filePath, ctx, out, new Set())\n if (!ok) return null\n return Object.keys(out).length === 0 ? null : out\n}\n\nasync function collectMsgVariants(\n typeName: string,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n out: Record<string, MessageAnnotations>,\n visitedAliases: Set<string>,\n): Promise<boolean> {\n const located = await findTypeSource(typeName, source, filePath, ctx, new Set())\n if (!located) return false\n\n const aliasKey = `${located.filePath}::${located.localName}`\n if (visitedAliases.has(aliasKey)) return true\n visitedAliases.add(aliasKey)\n\n const sf = ts.createSourceFile(located.filePath, located.source, ts.ScriptTarget.Latest, true)\n const aliases: ts.TypeAliasDeclaration[] = []\n sf.forEachChild((n) => {\n if (ts.isTypeAliasDeclaration(n)) aliases.push(n)\n })\n const alias = aliases.find((a) => a.name.text === located.localName)\n if (!alias) return false\n\n // Single-variant alias: `type Foo = { type: 'a', ... }`. Treat as a\n // one-element union so a Msg variant can be its own type alias.\n const memberNodes: ts.TypeNode[] = ts.isUnionTypeNode(alias.type)\n ? [...alias.type.types]\n : [alias.type]\n\n for (let i = 0; i < memberNodes.length; i++) {\n const member = memberNodes[i]!\n\n if (ts.isTypeLiteralNode(member)) {\n const variant = readDiscriminantLiteral(member)\n if (!variant) continue\n const comment = readLeadingJSDocForMember(located.source, alias, memberNodes, i)\n if (out[variant] === undefined) {\n out[variant] = parseMessageAnnotations(comment)\n }\n continue\n }\n\n if (ts.isTypeReferenceNode(member) && ts.isIdentifier(member.typeName)) {\n // Composed: recurse through the resolver.\n await collectMsgVariants(\n member.typeName.text,\n located.source,\n located.filePath,\n ctx,\n out,\n visitedAliases,\n )\n continue\n }\n\n // Other shapes (intersections, conditional types, namespace-qualified\n // names) aren't followed. Lint catches this.\n }\n\n return true\n}\n\nfunction readDiscriminantLiteral(lit: ts.TypeLiteralNode): string | null {\n for (const m of lit.members) {\n if (!ts.isPropertySignature(m)) continue\n if (!m.name || !ts.isIdentifier(m.name) || m.name.text !== 'type') continue\n if (!m.type || !ts.isLiteralTypeNode(m.type)) continue\n const literal = m.type.literal\n if (ts.isStringLiteral(literal)) return literal.text\n }\n return null\n}\n\n/**\n * Read leading JSDoc for a union member at index `i` of `members`.\n * The JSDoc lives between the previous element's end and the current\n * element's start (or between the type alias start and the first\n * element for `i === 0`). Mirrors the logic in\n * `extractMsgAnnotations` so the cross-file path produces the same\n * output for the same input.\n */\nfunction readLeadingJSDocForMember(\n source: string,\n alias: ts.TypeAliasDeclaration,\n members: ts.TypeNode[],\n i: number,\n): string {\n const prev = members[i - 1]\n const member = members[i]!\n // For non-union (single-variant) aliases the union pos is the alias\n // body's pos.\n const unionPos = ts.isUnionTypeNode(alias.type) ? alias.type.pos : alias.type.pos\n const scanPos = i === 0 || prev === undefined ? unionPos : prev.end\n const ranges = ts.getLeadingCommentRanges(source, scanPos) ?? []\n const docs = ranges\n .filter((r) => r.kind === ts.SyntaxKind.MultiLineCommentTrivia)\n .map((r) => source.slice(r.pos, r.end))\n .filter((txt) => txt.startsWith('/**'))\n // Cut off comments that appear AFTER the member starts (rare but\n // possible with weird formatting).\n const _end = member.pos\n return docs.join('\\n')\n}\n\nfunction parseMessageAnnotations(comment: string): MessageAnnotations {\n if (!comment) return defaultMessageAnnotations()\n const intent = readIntentTag(comment)\n const human = /@humanOnly\\b/.test(comment)\n const agent = /@agentOnly\\b/.test(comment)\n const dispatchMode: MessageDispatchMode =\n human && !agent ? 'human-only' : agent && !human ? 'agent-only' : 'shared'\n return {\n intent,\n alwaysAffordable: /@alwaysAffordable\\b/.test(comment),\n requiresConfirm: /@requiresConfirm\\b/.test(comment),\n dispatchMode,\n examples: readExamplesTag(comment),\n warning: readWarningTag(comment),\n emits: readEmitsTag(comment),\n }\n}\n\nfunction readEmitsTag(comment: string): string[] {\n const outer = comment.match(/@emits\\s*\\(([^)]*)\\)/)\n if (!outer || outer[1] === undefined) return []\n const inner = outer[1]\n const seen = new Set<string>()\n const out: string[] = []\n const re = /[\"“]([^\"”]*)[\"”]/g\n let m: RegExpExecArray | null\n while ((m = re.exec(inner)) !== null) {\n const v = m[1]\n if (v === undefined || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction readExamplesTag(comment: string): string[] {\n const out: string[] = []\n const re = /@example\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/g\n let m: RegExpExecArray | null\n while ((m = re.exec(comment)) !== null) {\n if (m[1] !== undefined) out.push(m[1])\n }\n return out\n}\n\nfunction readWarningTag(comment: string): string | null {\n const match = comment.match(/@warning\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/)\n return match?.[1] ?? null\n}\n\nfunction defaultMessageAnnotations(): MessageAnnotations {\n return {\n intent: null,\n alwaysAffordable: false,\n requiresConfirm: false,\n dispatchMode: 'shared',\n examples: [],\n warning: null,\n emits: [],\n }\n}\n\nfunction readIntentTag(comment: string): string | null {\n const match = comment.match(/@intent\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/)\n return match?.[1] ?? null\n}\n\n/**\n * Cross-file companion to `extractMsgSchema` / `extractEffectSchema`.\n *\n * Discriminated-union schema extractor that follows composed\n * TypeReferences through the resolver. Same recursion shape as\n * `extractMsgAnnotationsCrossFile`, just collecting field shapes\n * instead of JSDoc annotations.\n */\nexport async function extractDiscriminatedUnionSchemaCrossFile(\n source: string,\n typeName: string,\n filePath: string,\n ctx: ResolveContext,\n): Promise<MsgSchema | null> {\n const variants: MsgSchema['variants'] = {}\n const ok = await collectSchemaVariants(typeName, source, filePath, ctx, variants, new Set())\n if (!ok) return null\n return Object.keys(variants).length === 0 ? null : { discriminant: 'type', variants }\n}\n\nasync function collectSchemaVariants(\n typeName: string,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n variants: MsgSchema['variants'],\n visitedAliases: Set<string>,\n): Promise<boolean> {\n const located = await findTypeSource(typeName, source, filePath, ctx, new Set())\n if (!located) return false\n\n const aliasKey = `${located.filePath}::${located.localName}`\n if (visitedAliases.has(aliasKey)) return true\n visitedAliases.add(aliasKey)\n\n const sf = ts.createSourceFile(located.filePath, located.source, ts.ScriptTarget.Latest, true)\n const aliases: ts.TypeAliasDeclaration[] = []\n sf.forEachChild((n) => {\n if (ts.isTypeAliasDeclaration(n)) aliases.push(n)\n })\n const alias = aliases.find((a) => a.name.text === located.localName)\n if (!alias) return false\n\n const memberNodes: ts.TypeNode[] = ts.isUnionTypeNode(alias.type)\n ? [...alias.type.types]\n : [alias.type]\n\n // Build a typeIndex that combines this file's local types with any\n // *imported* type aliases referenced inside the variant payloads.\n // Without this enrichment, a field typed as `GridSorting` (declared\n // in `./state.ts` and imported here) would resolve to `'unknown'`\n // because the local index doesn't know about it. The synthesizer\n // would then emit `null` and the agent would have to guess at the\n // permissible literal-union values.\n const typeIndex = await buildEnrichedTypeIndex(sf, located.source, located.filePath, ctx)\n\n for (const member of memberNodes) {\n if (ts.isTypeLiteralNode(member)) {\n collectOneVariant(member, variants, located.source, typeIndex)\n continue\n }\n if (ts.isTypeReferenceNode(member) && ts.isIdentifier(member.typeName)) {\n await collectSchemaVariants(\n member.typeName.text,\n located.source,\n located.filePath,\n ctx,\n variants,\n visitedAliases,\n )\n continue\n }\n }\n return true\n}\n\nfunction collectOneVariant(\n lit: ts.TypeLiteralNode,\n variants: MsgSchema['variants'],\n source: string,\n typeIndex: TypeIndex,\n): void {\n let discriminantValue: string | null = null\n const fields: Record<string, MsgField> = {}\n for (const member of lit.members) {\n if (!ts.isPropertySignature(member) || !member.name || !ts.isIdentifier(member.name)) continue\n const name = member.name.text\n const memberType = member.type\n if (name === 'type' && memberType) {\n if (ts.isLiteralTypeNode(memberType) && ts.isStringLiteral(memberType.literal)) {\n discriminantValue = memberType.literal.text\n }\n continue\n }\n fields[name] = buildFieldDescriptor(member, source, typeIndex)\n }\n if (discriminantValue && variants[discriminantValue] === undefined) {\n variants[discriminantValue] = fields\n }\n}\n\n/**\n * Build a TypeIndex that includes the locally-declared types in `sf`\n * AND any types imported by name into `sf`. Following the imports\n * picks up sibling-file aliases like `GridSorting`, `ScoreMode`,\n * `ConfirmRequest` that an app commonly extracts to a state module.\n *\n * Limitations:\n * - Only follows direct named imports (`import type { X } from './y'`).\n * Namespace imports and `export *` aren't followed (the lint rule\n * `agent-msg-resolvable` already catches the namespace case).\n * - The resolved external type must itself be a type alias or\n * interface in the target file — chained re-exports beyond the first\n * hop fall back to `'unknown'`.\n * - Best-effort: any failure to resolve an import is silent. The\n * field type just stays `'unknown'` as it would have without\n * enrichment.\n */\nasync function buildEnrichedTypeIndex(\n sf: ts.SourceFile,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n): Promise<TypeIndex> {\n const index: TypeIndex = new Map()\n\n // 1. Locally-declared aliases / interfaces.\n for (const stmt of sf.statements) {\n if (ts.isTypeAliasDeclaration(stmt)) {\n index.set(stmt.name.text, stmt.type)\n } else if (ts.isInterfaceDeclaration(stmt)) {\n index.set(stmt.name.text, stmt)\n }\n }\n\n // 2. Walk imports transitively. Each file's named imports are\n // resolved, the target declarations are added to the index under\n // their local name, and the target's OWN file is then queued so\n // its imports are followed too. This is what makes\n // `Matrix/AddCriteria.criteria[].type.ease` resolve all the way\n // to its discriminated-union descriptor: `Criterion` is imported\n // from `@decisive/domain`, and `EaseFunction` is in turn imported\n // by Criterion's home file. Without transitivity the inner types\n // collapse to `'unknown'` and the agent has to guess the shape.\n //\n // Type-only imports (`import type { X }`) are followed exactly\n // the same as value imports — TypeScript's `isTypeOnly` flag\n // doesn't change the referent.\n //\n // Name collisions are first-write-wins: a local declaration\n // shadows an imported one of the same name, and the first\n // transitively-discovered import wins over later same-name\n // imports. Intentional — root files almost always import the\n // canonical name, and shallower-import names are more likely\n // correct than deep-import collisions.\n const fileQueue: Array<{ source: string; filePath: string; sf: ts.SourceFile }> = [\n { source, filePath, sf },\n ]\n const visitedFiles = new Set<string>([filePath])\n\n while (fileQueue.length > 0) {\n const cur = fileQueue.shift()\n if (!cur) break\n\n // Add this file's *own* local type declarations to the index so\n // sibling references inside the file's exported types resolve.\n // Without this, a Criterion in domain.ts referencing EaseMode\n // (declared right next to it) would collapse to 'unknown' even\n // though we already followed the import chain to domain.ts.\n // First-write-wins: a local declaration in the entry file\n // shadows a same-named declaration in a transitively-walked\n // file (intentional — entry-file names are canonical).\n if (cur.filePath !== filePath) {\n for (const stmt of cur.sf.statements) {\n if (ts.isTypeAliasDeclaration(stmt)) {\n if (!index.has(stmt.name.text)) index.set(stmt.name.text, stmt.type)\n } else if (ts.isInterfaceDeclaration(stmt)) {\n if (!index.has(stmt.name.text)) index.set(stmt.name.text, stmt)\n }\n }\n }\n\n for (const stmt of cur.sf.statements) {\n if (!ts.isImportDeclaration(stmt)) continue\n const named = stmt.importClause?.namedBindings\n if (!named || !ts.isNamedImports(named)) continue\n for (const spec of named.elements) {\n const localName = spec.name.text\n const importedName = spec.propertyName?.text ?? localName\n if (index.has(localName)) continue\n // Best-effort: any failure to resolve / read silently bails.\n // Bare-specifier imports like `'fs'` resolve to vite's\n // `__vite-browser-external` sentinel, which then ENOENTs at\n // readSource — those imports aren't type-relevant for schema\n // extraction anyway, so the failure is benign.\n let located: ResolvedTypeSource | null\n try {\n located = await findTypeSource(importedName, cur.source, cur.filePath, ctx, new Set())\n } catch {\n located = null\n }\n if (!located) continue\n const targetSf = ts.createSourceFile(\n located.filePath,\n located.source,\n ts.ScriptTarget.Latest,\n true,\n )\n let added = false\n for (const targetStmt of targetSf.statements) {\n if (ts.isTypeAliasDeclaration(targetStmt) && targetStmt.name.text === located.localName) {\n index.set(localName, targetStmt.type)\n added = true\n break\n }\n if (ts.isInterfaceDeclaration(targetStmt) && targetStmt.name.text === located.localName) {\n index.set(localName, targetStmt)\n added = true\n break\n }\n }\n // Queue the target file so its own imports — and own local\n // declarations — flow into the index. Only queue once per file.\n if (added && !visitedFiles.has(located.filePath)) {\n visitedFiles.add(located.filePath)\n fileQueue.push({\n source: located.source,\n filePath: located.filePath,\n sf: targetSf,\n })\n }\n }\n }\n }\n\n return index\n}\n\n/**\n * Inspect the type arguments of a `component<...>()` call and return\n * the textual identifier for each known position. Returns `null` for\n * positions whose type argument isn't a plain identifier (e.g.\n * inline literal types, generic instantiations, namespace-qualified\n * names). Identifiers are what the resolver can chase; everything else\n * we leave to the local extractor's existing behavior.\n *\n * Order: `[State, Msg, Effect]` matching `component<State, Msg, Effect>`.\n */\nexport function readComponentTypeArgNames(call: ts.CallExpression): {\n state: string | null\n msg: string | null\n effect: string | null\n} {\n const args = call.typeArguments\n const get = (i: number): string | null => {\n const t = args?.[i]\n if (!t) return null\n if (ts.isTypeReferenceNode(t) && ts.isIdentifier(t.typeName)) return t.typeName.text\n return null\n }\n return { state: get(0), msg: get(1), effect: get(2) }\n}\n"]}
1
+ {"version":3,"file":"cross-file-resolver.js","sourceRoot":"","sources":["../src/cross-file-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript'\nimport {\n type MessageAnnotations,\n type DispatchMode as MessageDispatchMode,\n} from './msg-annotations.js'\nimport {\n type MsgSchema,\n type MsgField,\n type TypeIndex,\n buildFieldDescriptor,\n} from './msg-schema.js'\n\n/**\n * Cross-file type resolver.\n *\n * The schema/annotation extractors (`extractMsgAnnotations`,\n * `extractMsgSchema`, `extractStateSchema`, `extractEffectSchema`) only\n * see the source string for the file currently being transformed. When\n * a developer keeps the `Msg` (or `State` / `Effect`) union in a\n * separate file and imports it where `component()` is called, those\n * extractors silently return `null` — the plugin emits no annotations,\n * runtime LAP validation is disabled, and Claude can dispatch arbitrary\n * `type` strings that fall through to `assertNever`.\n *\n * This module follows imports and re-exports to find the source file\n * that declares the requested type alias, returning that file's source\n * string + the local name of the alias there. Extractors then run\n * against that source and produce the same output they would have for\n * a co-located declaration.\n *\n * Limitations:\n * - Composition (`type Msg = ImportedA | { type: 'b' }`): only the\n * locally-declared variants are extracted; the imported half isn't\n * walked recursively into. The lint rule `agent-msg-resolvable`\n * catches this case at lint time.\n * - Namespace imports (`import * as ns from './msg'`) and `export *`:\n * not followed. Same lint coverage.\n * - Generic types: not parameterized resolution; the type argument\n * must resolve to a concrete type alias.\n */\n\nexport interface ResolveContext {\n /**\n * Resolve a module specifier (e.g. `'./msg'`, `'@scope/pkg'`) against\n * the importing file's path. Returns the absolute filesystem path of\n * the resolved module, or `null` if it cannot be resolved (the type\n * stays unresolved and the extractor falls back to local-only mode).\n */\n resolveModule: (spec: string, importerPath: string) => Promise<string | null>\n /**\n * Read the source contents of an absolute module path. The contents\n * are parsed by TypeScript so they should be valid TS/TSX. The plugin\n *'s vite hook plumbs `fs/promises.readFile` here; tests provide an\n * in-memory map.\n */\n readSource: (absolutePath: string) => Promise<string>\n}\n\nexport interface ResolvedTypeSource {\n /** The full source string of the file declaring the type alias. */\n source: string\n /** The local name of the alias *in that file* (after rename chains). */\n localName: string\n /** Absolute path of the file declaring the alias (debug aid). */\n filePath: string\n}\n\n/**\n * Walk imports + re-exports to find where a type alias is actually\n * declared. Returns the source string and local name of the alias in\n * its declaring file. Returns `null` if the chain leads to an unresolved\n * module, a re-export through `export *`, a namespace import, or a\n * dead-end (alias not declared anywhere we can see).\n */\nexport async function findTypeSource(\n typeName: string,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n visited: Set<string> = new Set(),\n): Promise<ResolvedTypeSource | null> {\n // Cycle prevention — re-export A → A is a tight loop that some\n // pathological re-export chains can produce. Bail rather than\n // infinitely recurse.\n if (visited.has(`${filePath}::${typeName}`)) return null\n visited.add(`${filePath}::${typeName}`)\n\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true)\n\n // 1. Local declaration wins. `type X = ...` or `interface X { ... }`\n // (extractors only support type aliases today, but check both so\n // the resolver itself isn't a footgun for future extractors).\n for (const stmt of sf.statements) {\n if (ts.isTypeAliasDeclaration(stmt) && stmt.name.text === typeName) {\n return { source, localName: typeName, filePath }\n }\n if (ts.isInterfaceDeclaration(stmt) && stmt.name.text === typeName) {\n return { source, localName: typeName, filePath }\n }\n }\n\n // 2. Re-export with name: `export { X } from './y'` or\n // `export { X as Y } from './y'`. Walk to the source module.\n for (const stmt of sf.statements) {\n if (!ts.isExportDeclaration(stmt)) continue\n if (!stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) continue\n if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier)) continue\n\n for (const spec of stmt.exportClause.elements) {\n const exportedName = spec.name.text\n if (exportedName !== typeName) continue\n // The name in the source module is `propertyName` if present\n // (e.g. `export { Msg as M } from './msg'` exports as M but the\n // source module has it as Msg).\n const sourceName = spec.propertyName?.text ?? spec.name.text\n const resolved = await ctx.resolveModule(stmt.moduleSpecifier.text, filePath)\n if (!resolved) return null\n const subSource = await ctx.readSource(resolved)\n return findTypeSource(sourceName, subSource, resolved, ctx, visited)\n }\n }\n\n // 3. Local re-binding: `export { X } from elsewhere` shorthand was\n // handled above. A separate case is `import { X } from ... ; export\n // { X }` — the import already declares X locally, so step 5 picks\n // it up.\n\n // 4. Star re-exports: `export * from './y'`. The barrel re-exports\n // every named member of `./y` under the same name. Walk each\n // barrel target and return the first hit. Order: textual order\n // in the source file (matches TypeScript's behaviour for\n // multi-barrel name collisions, where the first declared wins).\n //\n // Multiple `export *` declarations are common in monorepo barrel\n // files (`export * from './msg'; export * from './effects'`).\n // Without this step, the resolver returns `null` and the plugin\n // silently emits empty annotations for any consumer that points\n // at a barrel.\n for (const stmt of sf.statements) {\n if (!ts.isExportDeclaration(stmt)) continue\n // `export * from './y'` has no exportClause; `export {} from './y'`\n // is a different beast (re-exports nothing). Skip the latter.\n if (stmt.exportClause) continue\n if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier)) continue\n\n const resolved = await ctx.resolveModule(stmt.moduleSpecifier.text, filePath)\n if (!resolved) continue\n let subSource: string\n try {\n subSource = await ctx.readSource(resolved)\n } catch {\n // Module path resolved but the file isn't readable (deleted,\n // dynamic-only, etc.). Continue to the next barrel.\n continue\n }\n const found = await findTypeSource(typeName, subSource, resolved, ctx, visited)\n if (found) return found\n }\n\n // 5. Imports: `import { X } from './y'` or `import { X as Y } from './y'`.\n // Walk to the source module using the original (imported) name.\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt)) continue\n if (!stmt.importClause) continue\n if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier)) continue\n\n const bindings = stmt.importClause.namedBindings\n if (!bindings || !ts.isNamedImports(bindings)) continue\n\n for (const elem of bindings.elements) {\n const localName = elem.name.text\n if (localName !== typeName) continue\n // The remote name is `propertyName` when there's a rename, else\n // the local name itself.\n const remoteName = elem.propertyName?.text ?? elem.name.text\n const resolved = await ctx.resolveModule(stmt.moduleSpecifier.text, filePath)\n if (!resolved) return null\n const subSource = await ctx.readSource(resolved)\n return findTypeSource(remoteName, subSource, resolved, ctx, visited)\n }\n }\n\n // Not found in this file and no import/re-export to follow.\n return null\n}\n\n/**\n * Annotation extractor that walks composed Msg unions across files.\n *\n * Given a Msg type that may be a union of inline `{ type: 'literal' }`\n * objects AND TypeReferences (e.g.\n * `type Msg = ImportedFoo | { type: 'extra' }`), recursively follow\n * each TypeReference via `findTypeSource` and merge its variants into\n * the returned map.\n *\n * Composition + cross-file is the union of two failure modes the\n * file-local sync extractor silently mishandles. This function\n * produces the same map the runtime expects regardless of how the\n * developer organized the type declarations.\n *\n * Conflict policy: if two composed branches contribute the same\n * discriminant string (e.g. both halves declare `{ type: 'inc' }`),\n * the first one walked wins. The lint rule `agent-msg-resolvable`\n * fires before this point on most pathological cases; ESLint's\n * type-checker would flag the duplicate independently.\n */\nexport async function extractMsgAnnotationsCrossFile(\n source: string,\n typeName: string,\n filePath: string,\n ctx: ResolveContext,\n): Promise<Record<string, MessageAnnotations> | null> {\n const out: Record<string, MessageAnnotations> = {}\n const ok = await collectMsgVariants(typeName, source, filePath, ctx, out, new Set())\n if (!ok) return null\n return Object.keys(out).length === 0 ? null : out\n}\n\nasync function collectMsgVariants(\n typeName: string,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n out: Record<string, MessageAnnotations>,\n visitedAliases: Set<string>,\n): Promise<boolean> {\n const located = await findTypeSource(typeName, source, filePath, ctx, new Set())\n if (!located) return false\n\n const aliasKey = `${located.filePath}::${located.localName}`\n if (visitedAliases.has(aliasKey)) return true\n visitedAliases.add(aliasKey)\n\n const sf = ts.createSourceFile(located.filePath, located.source, ts.ScriptTarget.Latest, true)\n const aliases: ts.TypeAliasDeclaration[] = []\n sf.forEachChild((n) => {\n if (ts.isTypeAliasDeclaration(n)) aliases.push(n)\n })\n const alias = aliases.find((a) => a.name.text === located.localName)\n if (!alias) return false\n\n // Single-variant alias: `type Foo = { type: 'a', ... }`. Treat as a\n // one-element union so a Msg variant can be its own type alias.\n const memberNodes: ts.TypeNode[] = ts.isUnionTypeNode(alias.type)\n ? [...alias.type.types]\n : [alias.type]\n\n for (let i = 0; i < memberNodes.length; i++) {\n const member = memberNodes[i]!\n\n if (ts.isTypeLiteralNode(member)) {\n const variant = readDiscriminantLiteral(member)\n if (!variant) continue\n const comment = readLeadingJSDocForMember(located.source, alias, memberNodes, i)\n if (out[variant] === undefined) {\n out[variant] = parseMessageAnnotations(comment)\n }\n continue\n }\n\n if (ts.isTypeReferenceNode(member) && ts.isIdentifier(member.typeName)) {\n // Composed: recurse through the resolver.\n await collectMsgVariants(\n member.typeName.text,\n located.source,\n located.filePath,\n ctx,\n out,\n visitedAliases,\n )\n continue\n }\n\n // Other shapes (intersections, conditional types, namespace-qualified\n // names) aren't followed. Lint catches this.\n }\n\n return true\n}\n\nfunction readDiscriminantLiteral(lit: ts.TypeLiteralNode): string | null {\n for (const m of lit.members) {\n if (!ts.isPropertySignature(m)) continue\n if (!m.name || !ts.isIdentifier(m.name) || m.name.text !== 'type') continue\n if (!m.type || !ts.isLiteralTypeNode(m.type)) continue\n const literal = m.type.literal\n if (ts.isStringLiteral(literal)) return literal.text\n }\n return null\n}\n\n/**\n * Read leading JSDoc for a union member at index `i` of `members`.\n * The JSDoc lives between the previous element's end and the current\n * element's start (or between the type alias start and the first\n * element for `i === 0`). Mirrors the logic in\n * `extractMsgAnnotations` so the cross-file path produces the same\n * output for the same input.\n */\nfunction readLeadingJSDocForMember(\n source: string,\n alias: ts.TypeAliasDeclaration,\n members: ts.TypeNode[],\n i: number,\n): string {\n const prev = members[i - 1]\n const member = members[i]!\n // For non-union (single-variant) aliases the union pos is the alias\n // body's pos.\n const unionPos = ts.isUnionTypeNode(alias.type) ? alias.type.pos : alias.type.pos\n const scanPos = i === 0 || prev === undefined ? unionPos : prev.end\n const ranges = ts.getLeadingCommentRanges(source, scanPos) ?? []\n const docs = ranges\n .filter((r) => r.kind === ts.SyntaxKind.MultiLineCommentTrivia)\n .map((r) => source.slice(r.pos, r.end))\n .filter((txt) => txt.startsWith('/**'))\n // Cut off comments that appear AFTER the member starts (rare but\n // possible with weird formatting).\n const _end = member.pos\n return docs.join('\\n')\n}\n\nfunction parseMessageAnnotations(comment: string): MessageAnnotations {\n if (!comment) return defaultMessageAnnotations()\n const intent = readIntentTag(comment)\n const human = /@humanOnly\\b/.test(comment)\n const agent = /@agentOnly\\b/.test(comment)\n const dispatchMode: MessageDispatchMode =\n human && !agent ? 'human-only' : agent && !human ? 'agent-only' : 'shared'\n return {\n intent,\n alwaysAffordable: /@alwaysAffordable\\b/.test(comment),\n requiresConfirm: /@requiresConfirm\\b/.test(comment),\n dispatchMode,\n examples: readExamplesTag(comment),\n warning: readWarningTag(comment),\n emits: readEmitsTag(comment),\n routeGate: readRouteGateTag(comment),\n }\n}\n\nfunction readRouteGateTag(comment: string): string | null {\n const match = comment.match(/@routeGated\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/)\n return match?.[1] ?? null\n}\n\nfunction readEmitsTag(comment: string): string[] {\n const outer = comment.match(/@emits\\s*\\(([^)]*)\\)/)\n if (!outer || outer[1] === undefined) return []\n const inner = outer[1]\n const seen = new Set<string>()\n const out: string[] = []\n const re = /[\"“]([^\"”]*)[\"”]/g\n let m: RegExpExecArray | null\n while ((m = re.exec(inner)) !== null) {\n const v = m[1]\n if (v === undefined || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction readExamplesTag(comment: string): string[] {\n const out: string[] = []\n const re = /@example\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/g\n let m: RegExpExecArray | null\n while ((m = re.exec(comment)) !== null) {\n if (m[1] !== undefined) out.push(m[1])\n }\n return out\n}\n\nfunction readWarningTag(comment: string): string | null {\n const match = comment.match(/@warning\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/)\n return match?.[1] ?? null\n}\n\nfunction defaultMessageAnnotations(): MessageAnnotations {\n return {\n intent: null,\n alwaysAffordable: false,\n requiresConfirm: false,\n dispatchMode: 'shared',\n examples: [],\n warning: null,\n emits: [],\n routeGate: null,\n }\n}\n\nfunction readIntentTag(comment: string): string | null {\n const match = comment.match(/@intent\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/)\n return match?.[1] ?? null\n}\n\n/**\n * Cross-file companion to `extractMsgSchema` / `extractEffectSchema`.\n *\n * Discriminated-union schema extractor that follows composed\n * TypeReferences through the resolver. Same recursion shape as\n * `extractMsgAnnotationsCrossFile`, just collecting field shapes\n * instead of JSDoc annotations.\n */\nexport async function extractDiscriminatedUnionSchemaCrossFile(\n source: string,\n typeName: string,\n filePath: string,\n ctx: ResolveContext,\n): Promise<MsgSchema | null> {\n const variants: MsgSchema['variants'] = {}\n const ok = await collectSchemaVariants(typeName, source, filePath, ctx, variants, new Set())\n if (!ok) return null\n return Object.keys(variants).length === 0 ? null : { discriminant: 'type', variants }\n}\n\nasync function collectSchemaVariants(\n typeName: string,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n variants: MsgSchema['variants'],\n visitedAliases: Set<string>,\n): Promise<boolean> {\n const located = await findTypeSource(typeName, source, filePath, ctx, new Set())\n if (!located) return false\n\n const aliasKey = `${located.filePath}::${located.localName}`\n if (visitedAliases.has(aliasKey)) return true\n visitedAliases.add(aliasKey)\n\n const sf = ts.createSourceFile(located.filePath, located.source, ts.ScriptTarget.Latest, true)\n const aliases: ts.TypeAliasDeclaration[] = []\n sf.forEachChild((n) => {\n if (ts.isTypeAliasDeclaration(n)) aliases.push(n)\n })\n const alias = aliases.find((a) => a.name.text === located.localName)\n if (!alias) return false\n\n const memberNodes: ts.TypeNode[] = ts.isUnionTypeNode(alias.type)\n ? [...alias.type.types]\n : [alias.type]\n\n // Build a typeIndex that combines this file's local types with any\n // *imported* type aliases referenced inside the variant payloads.\n // Without this enrichment, a field typed as `GridSorting` (declared\n // in `./state.ts` and imported here) would resolve to `'unknown'`\n // because the local index doesn't know about it. The synthesizer\n // would then emit `null` and the agent would have to guess at the\n // permissible literal-union values.\n const typeIndex = await buildEnrichedTypeIndex(sf, located.source, located.filePath, ctx)\n\n for (const member of memberNodes) {\n if (ts.isTypeLiteralNode(member)) {\n collectOneVariant(member, variants, located.source, typeIndex)\n continue\n }\n if (ts.isTypeReferenceNode(member) && ts.isIdentifier(member.typeName)) {\n await collectSchemaVariants(\n member.typeName.text,\n located.source,\n located.filePath,\n ctx,\n variants,\n visitedAliases,\n )\n continue\n }\n }\n return true\n}\n\nfunction collectOneVariant(\n lit: ts.TypeLiteralNode,\n variants: MsgSchema['variants'],\n source: string,\n typeIndex: TypeIndex,\n): void {\n let discriminantValue: string | null = null\n const fields: Record<string, MsgField> = {}\n for (const member of lit.members) {\n if (!ts.isPropertySignature(member) || !member.name || !ts.isIdentifier(member.name)) continue\n const name = member.name.text\n const memberType = member.type\n if (name === 'type' && memberType) {\n if (ts.isLiteralTypeNode(memberType) && ts.isStringLiteral(memberType.literal)) {\n discriminantValue = memberType.literal.text\n }\n continue\n }\n fields[name] = buildFieldDescriptor(member, source, typeIndex)\n }\n if (discriminantValue && variants[discriminantValue] === undefined) {\n variants[discriminantValue] = fields\n }\n}\n\n/**\n * Build a TypeIndex that includes the locally-declared types in `sf`\n * AND any types imported by name into `sf`. Following the imports\n * picks up sibling-file aliases like `GridSorting`, `ScoreMode`,\n * `ConfirmRequest` that an app commonly extracts to a state module.\n *\n * Limitations:\n * - Only follows direct named imports (`import type { X } from './y'`).\n * Namespace imports and `export *` aren't followed (the lint rule\n * `agent-msg-resolvable` already catches the namespace case).\n * - The resolved external type must itself be a type alias or\n * interface in the target file — chained re-exports beyond the first\n * hop fall back to `'unknown'`.\n * - Best-effort: any failure to resolve an import is silent. The\n * field type just stays `'unknown'` as it would have without\n * enrichment.\n */\nasync function buildEnrichedTypeIndex(\n sf: ts.SourceFile,\n source: string,\n filePath: string,\n ctx: ResolveContext,\n): Promise<TypeIndex> {\n const index: TypeIndex = new Map()\n\n // 1. Locally-declared aliases / interfaces.\n for (const stmt of sf.statements) {\n if (ts.isTypeAliasDeclaration(stmt)) {\n index.set(stmt.name.text, stmt.type)\n } else if (ts.isInterfaceDeclaration(stmt)) {\n index.set(stmt.name.text, stmt)\n }\n }\n\n // 2. Walk imports transitively. Each file's named imports are\n // resolved, the target declarations are added to the index under\n // their local name, and the target's OWN file is then queued so\n // its imports are followed too. This is what makes\n // `Matrix/AddCriteria.criteria[].type.ease` resolve all the way\n // to its discriminated-union descriptor: `Criterion` is imported\n // from `@decisive/domain`, and `EaseFunction` is in turn imported\n // by Criterion's home file. Without transitivity the inner types\n // collapse to `'unknown'` and the agent has to guess the shape.\n //\n // Type-only imports (`import type { X }`) are followed exactly\n // the same as value imports — TypeScript's `isTypeOnly` flag\n // doesn't change the referent.\n //\n // Name collisions are first-write-wins: a local declaration\n // shadows an imported one of the same name, and the first\n // transitively-discovered import wins over later same-name\n // imports. Intentional — root files almost always import the\n // canonical name, and shallower-import names are more likely\n // correct than deep-import collisions.\n const fileQueue: Array<{ source: string; filePath: string; sf: ts.SourceFile }> = [\n { source, filePath, sf },\n ]\n const visitedFiles = new Set<string>([filePath])\n\n while (fileQueue.length > 0) {\n const cur = fileQueue.shift()\n if (!cur) break\n\n // Add this file's *own* local type declarations to the index so\n // sibling references inside the file's exported types resolve.\n // Without this, a Criterion in domain.ts referencing EaseMode\n // (declared right next to it) would collapse to 'unknown' even\n // though we already followed the import chain to domain.ts.\n // First-write-wins: a local declaration in the entry file\n // shadows a same-named declaration in a transitively-walked\n // file (intentional — entry-file names are canonical).\n if (cur.filePath !== filePath) {\n for (const stmt of cur.sf.statements) {\n if (ts.isTypeAliasDeclaration(stmt)) {\n if (!index.has(stmt.name.text)) index.set(stmt.name.text, stmt.type)\n } else if (ts.isInterfaceDeclaration(stmt)) {\n if (!index.has(stmt.name.text)) index.set(stmt.name.text, stmt)\n }\n }\n }\n\n for (const stmt of cur.sf.statements) {\n if (!ts.isImportDeclaration(stmt)) continue\n const named = stmt.importClause?.namedBindings\n if (!named || !ts.isNamedImports(named)) continue\n for (const spec of named.elements) {\n const localName = spec.name.text\n const importedName = spec.propertyName?.text ?? localName\n if (index.has(localName)) continue\n // Best-effort: any failure to resolve / read silently bails.\n // Bare-specifier imports like `'fs'` resolve to vite's\n // `__vite-browser-external` sentinel, which then ENOENTs at\n // readSource — those imports aren't type-relevant for schema\n // extraction anyway, so the failure is benign.\n let located: ResolvedTypeSource | null\n try {\n located = await findTypeSource(importedName, cur.source, cur.filePath, ctx, new Set())\n } catch {\n located = null\n }\n if (!located) continue\n const targetSf = ts.createSourceFile(\n located.filePath,\n located.source,\n ts.ScriptTarget.Latest,\n true,\n )\n let added = false\n for (const targetStmt of targetSf.statements) {\n if (ts.isTypeAliasDeclaration(targetStmt) && targetStmt.name.text === located.localName) {\n index.set(localName, targetStmt.type)\n added = true\n break\n }\n if (ts.isInterfaceDeclaration(targetStmt) && targetStmt.name.text === located.localName) {\n index.set(localName, targetStmt)\n added = true\n break\n }\n }\n // Queue the target file so its own imports — and own local\n // declarations — flow into the index. Only queue once per file.\n if (added && !visitedFiles.has(located.filePath)) {\n visitedFiles.add(located.filePath)\n fileQueue.push({\n source: located.source,\n filePath: located.filePath,\n sf: targetSf,\n })\n }\n }\n }\n }\n\n return index\n}\n\n/**\n * Inspect the type arguments of a `component<...>()` call and return\n * the textual identifier for each known position. Returns `null` for\n * positions whose type argument isn't a plain identifier (e.g.\n * inline literal types, generic instantiations, namespace-qualified\n * names). Identifiers are what the resolver can chase; everything else\n * we leave to the local extractor's existing behavior.\n *\n * Order: `[State, Msg, Effect]` matching `component<State, Msg, Effect>`.\n */\nexport function readComponentTypeArgNames(call: ts.CallExpression): {\n state: string | null\n msg: string | null\n effect: string | null\n} {\n const args = call.typeArguments\n const get = (i: number): string | null => {\n const t = args?.[i]\n if (!t) return null\n if (ts.isTypeReferenceNode(t) && ts.isIdentifier(t.typeName)) return t.typeName.text\n return null\n }\n return { state: get(0), msg: get(1), effect: get(2) }\n}\n"]}
@@ -34,6 +34,28 @@ export type MessageAnnotations = {
34
34
  * Empty when no `@emits` tag is present.
35
35
  */
36
36
  emits: string[];
37
+ /**
38
+ * Boolean predicate gating whether the variant surfaces in
39
+ * `list_actions`. Authored as `@routeGated("expr")`; the compiler
40
+ * captures the predicate string verbatim and the runtime evaluates
41
+ * it with `state` bound to the current state. The variant only
42
+ * appears in the agent's affordance list when the predicate
43
+ * returns true.
44
+ *
45
+ * Compile-time alternative to `agentAffordances(state) => Msg[]`
46
+ * for the common case of "this Msg is reachable when state.X
47
+ * looks like Y." Co-located with the Msg definition rather than
48
+ * threaded through a separate hook.
49
+ *
50
+ * Examples:
51
+ * @routeGated("state.matrixState.kind === 'loaded'")
52
+ * @routeGated("state.route.kind === 'page' && state.route.slug === 'ranking'")
53
+ * @routeGated("state.auth.status === 'authenticated'")
54
+ *
55
+ * Null when no `@routeGated` tag is present (variant defaults to
56
+ * its dispatchMode-driven affordance behavior).
57
+ */
58
+ routeGate: string | null;
37
59
  };
38
60
  /**
39
61
  * Walk a Msg-like discriminated-union type alias and extract JSDoc
@@ -1 +1 @@
1
- {"version":3,"file":"msg-annotations.d.ts","sourceRoot":"","sources":["../src/msg-annotations.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAA;AAEjE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,gBAAgB,EAAE,OAAO,CAAA;IACzB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,YAAY,CAAA;IAC1B;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;;;;;;;;;;;OAYG;IACH,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAYD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM;AACd;;;;;GAKG;AACH,QAAQ,GAAE,MAAc,GACvB,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAgC3C"}
1
+ {"version":3,"file":"msg-annotations.d.ts","sourceRoot":"","sources":["../src/msg-annotations.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAA;AAEjE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,gBAAgB,EAAE,OAAO,CAAA;IACzB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,YAAY,CAAA;IAC1B;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;;;;;;;;;;;OAYG;IACH,KAAK,EAAE,MAAM,EAAE,CAAA;IACf;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB,CAAA;AAaD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM;AACd;;;;;GAKG;AACH,QAAQ,GAAE,MAAc,GACvB,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAgC3C"}
@@ -7,6 +7,7 @@ const DEFAULT = {
7
7
  examples: [],
8
8
  warning: null,
9
9
  emits: [],
10
+ routeGate: null,
10
11
  };
11
12
  /**
12
13
  * Walk a Msg-like discriminated-union type alias and extract JSDoc
@@ -109,8 +110,23 @@ function parseAnnotations(comment) {
109
110
  examples: readExamples(comment),
110
111
  warning: readWarning(comment),
111
112
  emits: readEmits(comment),
113
+ routeGate: readRouteGate(comment),
112
114
  };
113
115
  }
116
+ /**
117
+ * Match `@routeGated("predicate-expression")` (and curly-quote
118
+ * variant). Returns the verbatim predicate string — the runtime
119
+ * compiles it with `new Function('state', 'return (' + src + ')')`
120
+ * and evaluates against the current state to gate affordances.
121
+ *
122
+ * Mirrors `@validates`'s grammar but with `state` as the bound
123
+ * variable instead of `v` (since the predicate sees the whole app
124
+ * state, not a single field value).
125
+ */
126
+ function readRouteGate(comment) {
127
+ const match = comment.match(/@routeGated\s*\(\s*["“]([^"”]*)["”]\s*\)/);
128
+ return match?.[1] ?? null;
129
+ }
114
130
  /**
115
131
  * Match `@emits("k1", "k2", ...)` — comma-separated list of effect
116
132
  * kind strings. Each entry can use straight or curly quotes; the
@@ -1 +1 @@
1
- {"version":3,"file":"msg-annotations.js","sourceRoot":"","sources":["../src/msg-annotations.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript'\n\nexport type DispatchMode = 'shared' | 'human-only' | 'agent-only'\n\nexport type MessageAnnotations = {\n intent: string | null\n alwaysAffordable: boolean\n requiresConfirm: boolean\n dispatchMode: DispatchMode\n /**\n * Concrete example dispatches the LLM can copy from. Populated by\n * `@example(\"text\")` JSDoc tags. Each tag becomes one entry, in\n * source order, so authors can mix scenarios (\"typical case\",\n * \"edge case with auth\", etc.) without nesting them in a single\n * string.\n */\n examples: string[]\n /**\n * Non-blocking caution. Surfaced verbatim to the agent at affordance\n * time so the LLM can weigh the consequence (\"this overwrites the\n * cloud version\", \"fires analytics that can't be retracted\") before\n * dispatching. Distinct from `requiresConfirm`, which is a runtime\n * gate the user must acknowledge.\n */\n warning: string | null\n /**\n * Effect kinds this variant emits when dispatched, declared by the\n * author via `@emits(\"kind1\", \"kind2\")`. Lets the agent reason\n * about side effects (\"this dispatch hits the cloud, so I should\n * batch\") without the compiler having to walk update.ts. Authored\n * rather than auto-extracted because real apps emit effects\n * through helpers (`track('foo')`, `saveDelta(d)`) — auto-detecting\n * those would require helper-return-shape analysis with\n * ergonomically-painful failure modes; the declarative form trades\n * automatic discovery for accuracy and simplicity.\n *\n * Empty when no `@emits` tag is present.\n */\n emits: string[]\n}\n\nconst DEFAULT: MessageAnnotations = {\n intent: null,\n alwaysAffordable: false,\n requiresConfirm: false,\n dispatchMode: 'shared',\n examples: [],\n warning: null,\n emits: [],\n}\n\n/**\n * Walk a Msg-like discriminated-union type alias and extract JSDoc\n * annotations attached to each union member. Returns null if no\n * recognizable union is found so callers can skip emission cleanly.\n *\n * Expected JSDoc grammar (order-independent):\n * @intent(\"human readable\")\n * @alwaysAffordable\n * @requiresConfirm\n * @humanOnly — sugar for dispatchMode: 'human-only'\n * @agentOnly — sugar for dispatchMode: 'agent-only'\n *\n * Unknown tags are ignored; malformed @intent (no quoted string) is\n * treated as \"no intent\". `@humanOnly` and `@agentOnly` are mutually\n * exclusive — if both are present (which the ESLint rule\n * `agent-exclusive-annotations` reports as an error), the parser\n * falls back to `'shared'` so a misconfigured Msg variant doesn't\n * silently lock out one audience.\n */\nexport function extractMsgAnnotations(\n source: string,\n /**\n * Name of the type alias to extract from. Defaults to `'Msg'` for\n * convention. Passed by the cross-file resolver when the alias has\n * been renamed through imports/re-exports — its local name in the\n * declaring file may differ from `'Msg'`.\n */\n typeName: string = 'Msg',\n): Record<string, MessageAnnotations> | null {\n const sf = ts.createSourceFile('msg.ts', source, ts.ScriptTarget.Latest, true)\n const aliases: ts.TypeAliasDeclaration[] = []\n sf.forEachChild((n) => {\n if (ts.isTypeAliasDeclaration(n)) aliases.push(n)\n })\n const named = aliases.find((a) => a.name.text === typeName)\n // Fallback: only when looking for the conventional 'Msg' name AND the\n // file has no `type Msg = …`; pick any union type alias. With an\n // explicit `typeName` from the resolver, we don't fall back — that\n // would silently match the wrong alias.\n const alias =\n named ?? (typeName === 'Msg' ? aliases.find((a) => ts.isUnionTypeNode(a.type)) : undefined)\n if (!alias || !ts.isUnionTypeNode(alias.type)) return null\n\n const result: Record<string, MessageAnnotations> = {}\n const types = alias.type.types\n for (let i = 0; i < types.length; i++) {\n const member = types[i]\n if (member === undefined || !ts.isTypeLiteralNode(member)) continue\n const variant = readDiscriminantLiteral(member)\n if (!variant) continue\n // Leading JSDoc for union member i is scanned from the end of the\n // previous element (or union.pos for the first member), because\n // TypeScript's parser places comment ranges relative to the token\n // that follows them — and the | bar is not part of the TypeLiteralNode.\n const prev = types[i - 1]\n const scanPos = i === 0 || prev === undefined ? alias.type.pos : prev.end\n const comment = readLeadingJSDoc(source, scanPos)\n result[variant] = parseAnnotations(comment)\n }\n return Object.keys(result).length === 0 ? null : result\n}\n\nfunction readDiscriminantLiteral(lit: ts.TypeLiteralNode): string | null {\n for (const m of lit.members) {\n if (!ts.isPropertySignature(m)) continue\n if (!m.name || !ts.isIdentifier(m.name) || m.name.text !== 'type') continue\n if (!m.type || !ts.isLiteralTypeNode(m.type)) continue\n const literal = m.type.literal\n if (ts.isStringLiteral(literal)) return literal.text\n }\n return null\n}\n\nfunction readLeadingJSDoc(source: string, scanPos: number): string {\n const ranges = ts.getLeadingCommentRanges(source, scanPos) ?? []\n const docs = ranges\n .filter((r) => r.kind === ts.SyntaxKind.MultiLineCommentTrivia)\n .map((r) => source.slice(r.pos, r.end))\n .filter((txt) => txt.startsWith('/**'))\n return docs.join('\\n')\n}\n\nfunction parseAnnotations(comment: string): MessageAnnotations {\n if (!comment) return { ...DEFAULT, examples: [] }\n const intent = readIntent(comment)\n const human = /@humanOnly\\b/.test(comment)\n const agent = /@agentOnly\\b/.test(comment)\n // Mutual-exclusion fallback: both tags present means a config bug;\n // the ESLint rule reports it. At parse time, default to 'shared' so\n // we don't silently lock out one audience based on tag order.\n const dispatchMode: DispatchMode =\n human && !agent ? 'human-only' : agent && !human ? 'agent-only' : 'shared'\n return {\n intent,\n alwaysAffordable: /@alwaysAffordable\\b/.test(comment),\n requiresConfirm: /@requiresConfirm\\b/.test(comment),\n dispatchMode,\n examples: readExamples(comment),\n warning: readWarning(comment),\n emits: readEmits(comment),\n }\n}\n\n/**\n * Match `@emits(\"k1\", \"k2\", ...)` — comma-separated list of effect\n * kind strings. Each entry can use straight or curly quotes; the\n * separator is `,` with arbitrary whitespace. Returns the kinds in\n * source order (deduped). Empty when the tag is absent or has no\n * quoted strings.\n */\nfunction readEmits(comment: string): string[] {\n // Match the whole `@emits(...)` parenthesized group so we can\n // re-parse the inner content for individual quoted strings. The\n // outer match is non-greedy on the closing paren to avoid eating\n // through later JSDoc.\n const outer = comment.match(/@emits\\s*\\(([^)]*)\\)/)\n if (!outer || outer[1] === undefined) return []\n const inner = outer[1]\n const seen = new Set<string>()\n const out: string[] = []\n const re = /[\"“]([^\"”]*)[\"”]/g\n let m: RegExpExecArray | null\n while ((m = re.exec(inner)) !== null) {\n const v = m[1]\n if (v === undefined || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction readIntent(comment: string): string | null {\n const match = comment.match(/@intent\\s*\\(\\s*[\"\\u201c]([^\"\\u201d]*)[\"\\u201d]\\s*\\)/)\n return match?.[1] ?? null\n}\n\n/**\n * Match every `@example(\"\\u2026\")` (and curly-quote variant) in source\n * order. Multiple tags on one variant are common \\u2014 typical-case,\n * edge-case-with-auth, etc. \\u2014 so the parser collects all of them\n * rather than picking the first.\n */\nfunction readExamples(comment: string): string[] {\n const out: string[] = []\n const re = /@example\\s*\\(\\s*[\"\\u201c]([^\"\\u201d]*)[\"\\u201d]\\s*\\)/g\n let m: RegExpExecArray | null\n while ((m = re.exec(comment)) !== null) {\n if (m[1] !== undefined) out.push(m[1])\n }\n return out\n}\n\nfunction readWarning(comment: string): string | null {\n const match = comment.match(/@warning\\s*\\(\\s*[\"\\u201c]([^\"\\u201d]*)[\"\\u201d]\\s*\\)/)\n return match?.[1] ?? null\n}\n"]}
1
+ {"version":3,"file":"msg-annotations.js","sourceRoot":"","sources":["../src/msg-annotations.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript'\n\nexport type DispatchMode = 'shared' | 'human-only' | 'agent-only'\n\nexport type MessageAnnotations = {\n intent: string | null\n alwaysAffordable: boolean\n requiresConfirm: boolean\n dispatchMode: DispatchMode\n /**\n * Concrete example dispatches the LLM can copy from. Populated by\n * `@example(\"text\")` JSDoc tags. Each tag becomes one entry, in\n * source order, so authors can mix scenarios (\"typical case\",\n * \"edge case with auth\", etc.) without nesting them in a single\n * string.\n */\n examples: string[]\n /**\n * Non-blocking caution. Surfaced verbatim to the agent at affordance\n * time so the LLM can weigh the consequence (\"this overwrites the\n * cloud version\", \"fires analytics that can't be retracted\") before\n * dispatching. Distinct from `requiresConfirm`, which is a runtime\n * gate the user must acknowledge.\n */\n warning: string | null\n /**\n * Effect kinds this variant emits when dispatched, declared by the\n * author via `@emits(\"kind1\", \"kind2\")`. Lets the agent reason\n * about side effects (\"this dispatch hits the cloud, so I should\n * batch\") without the compiler having to walk update.ts. Authored\n * rather than auto-extracted because real apps emit effects\n * through helpers (`track('foo')`, `saveDelta(d)`) — auto-detecting\n * those would require helper-return-shape analysis with\n * ergonomically-painful failure modes; the declarative form trades\n * automatic discovery for accuracy and simplicity.\n *\n * Empty when no `@emits` tag is present.\n */\n emits: string[]\n /**\n * Boolean predicate gating whether the variant surfaces in\n * `list_actions`. Authored as `@routeGated(\"expr\")`; the compiler\n * captures the predicate string verbatim and the runtime evaluates\n * it with `state` bound to the current state. The variant only\n * appears in the agent's affordance list when the predicate\n * returns true.\n *\n * Compile-time alternative to `agentAffordances(state) => Msg[]`\n * for the common case of \"this Msg is reachable when state.X\n * looks like Y.\" Co-located with the Msg definition rather than\n * threaded through a separate hook.\n *\n * Examples:\n * @routeGated(\"state.matrixState.kind === 'loaded'\")\n * @routeGated(\"state.route.kind === 'page' && state.route.slug === 'ranking'\")\n * @routeGated(\"state.auth.status === 'authenticated'\")\n *\n * Null when no `@routeGated` tag is present (variant defaults to\n * its dispatchMode-driven affordance behavior).\n */\n routeGate: string | null\n}\n\nconst DEFAULT: MessageAnnotations = {\n intent: null,\n alwaysAffordable: false,\n requiresConfirm: false,\n dispatchMode: 'shared',\n examples: [],\n warning: null,\n emits: [],\n routeGate: null,\n}\n\n/**\n * Walk a Msg-like discriminated-union type alias and extract JSDoc\n * annotations attached to each union member. Returns null if no\n * recognizable union is found so callers can skip emission cleanly.\n *\n * Expected JSDoc grammar (order-independent):\n * @intent(\"human readable\")\n * @alwaysAffordable\n * @requiresConfirm\n * @humanOnly — sugar for dispatchMode: 'human-only'\n * @agentOnly — sugar for dispatchMode: 'agent-only'\n *\n * Unknown tags are ignored; malformed @intent (no quoted string) is\n * treated as \"no intent\". `@humanOnly` and `@agentOnly` are mutually\n * exclusive — if both are present (which the ESLint rule\n * `agent-exclusive-annotations` reports as an error), the parser\n * falls back to `'shared'` so a misconfigured Msg variant doesn't\n * silently lock out one audience.\n */\nexport function extractMsgAnnotations(\n source: string,\n /**\n * Name of the type alias to extract from. Defaults to `'Msg'` for\n * convention. Passed by the cross-file resolver when the alias has\n * been renamed through imports/re-exports — its local name in the\n * declaring file may differ from `'Msg'`.\n */\n typeName: string = 'Msg',\n): Record<string, MessageAnnotations> | null {\n const sf = ts.createSourceFile('msg.ts', source, ts.ScriptTarget.Latest, true)\n const aliases: ts.TypeAliasDeclaration[] = []\n sf.forEachChild((n) => {\n if (ts.isTypeAliasDeclaration(n)) aliases.push(n)\n })\n const named = aliases.find((a) => a.name.text === typeName)\n // Fallback: only when looking for the conventional 'Msg' name AND the\n // file has no `type Msg = …`; pick any union type alias. With an\n // explicit `typeName` from the resolver, we don't fall back — that\n // would silently match the wrong alias.\n const alias =\n named ?? (typeName === 'Msg' ? aliases.find((a) => ts.isUnionTypeNode(a.type)) : undefined)\n if (!alias || !ts.isUnionTypeNode(alias.type)) return null\n\n const result: Record<string, MessageAnnotations> = {}\n const types = alias.type.types\n for (let i = 0; i < types.length; i++) {\n const member = types[i]\n if (member === undefined || !ts.isTypeLiteralNode(member)) continue\n const variant = readDiscriminantLiteral(member)\n if (!variant) continue\n // Leading JSDoc for union member i is scanned from the end of the\n // previous element (or union.pos for the first member), because\n // TypeScript's parser places comment ranges relative to the token\n // that follows them — and the | bar is not part of the TypeLiteralNode.\n const prev = types[i - 1]\n const scanPos = i === 0 || prev === undefined ? alias.type.pos : prev.end\n const comment = readLeadingJSDoc(source, scanPos)\n result[variant] = parseAnnotations(comment)\n }\n return Object.keys(result).length === 0 ? null : result\n}\n\nfunction readDiscriminantLiteral(lit: ts.TypeLiteralNode): string | null {\n for (const m of lit.members) {\n if (!ts.isPropertySignature(m)) continue\n if (!m.name || !ts.isIdentifier(m.name) || m.name.text !== 'type') continue\n if (!m.type || !ts.isLiteralTypeNode(m.type)) continue\n const literal = m.type.literal\n if (ts.isStringLiteral(literal)) return literal.text\n }\n return null\n}\n\nfunction readLeadingJSDoc(source: string, scanPos: number): string {\n const ranges = ts.getLeadingCommentRanges(source, scanPos) ?? []\n const docs = ranges\n .filter((r) => r.kind === ts.SyntaxKind.MultiLineCommentTrivia)\n .map((r) => source.slice(r.pos, r.end))\n .filter((txt) => txt.startsWith('/**'))\n return docs.join('\\n')\n}\n\nfunction parseAnnotations(comment: string): MessageAnnotations {\n if (!comment) return { ...DEFAULT, examples: [] }\n const intent = readIntent(comment)\n const human = /@humanOnly\\b/.test(comment)\n const agent = /@agentOnly\\b/.test(comment)\n // Mutual-exclusion fallback: both tags present means a config bug;\n // the ESLint rule reports it. At parse time, default to 'shared' so\n // we don't silently lock out one audience based on tag order.\n const dispatchMode: DispatchMode =\n human && !agent ? 'human-only' : agent && !human ? 'agent-only' : 'shared'\n return {\n intent,\n alwaysAffordable: /@alwaysAffordable\\b/.test(comment),\n requiresConfirm: /@requiresConfirm\\b/.test(comment),\n dispatchMode,\n examples: readExamples(comment),\n warning: readWarning(comment),\n emits: readEmits(comment),\n routeGate: readRouteGate(comment),\n }\n}\n\n/**\n * Match `@routeGated(\"predicate-expression\")` (and curly-quote\n * variant). Returns the verbatim predicate string — the runtime\n * compiles it with `new Function('state', 'return (' + src + ')')`\n * and evaluates against the current state to gate affordances.\n *\n * Mirrors `@validates`'s grammar but with `state` as the bound\n * variable instead of `v` (since the predicate sees the whole app\n * state, not a single field value).\n */\nfunction readRouteGate(comment: string): string | null {\n const match = comment.match(/@routeGated\\s*\\(\\s*[\"“]([^\"”]*)[\"”]\\s*\\)/)\n return match?.[1] ?? null\n}\n\n/**\n * Match `@emits(\"k1\", \"k2\", ...)` — comma-separated list of effect\n * kind strings. Each entry can use straight or curly quotes; the\n * separator is `,` with arbitrary whitespace. Returns the kinds in\n * source order (deduped). Empty when the tag is absent or has no\n * quoted strings.\n */\nfunction readEmits(comment: string): string[] {\n // Match the whole `@emits(...)` parenthesized group so we can\n // re-parse the inner content for individual quoted strings. The\n // outer match is non-greedy on the closing paren to avoid eating\n // through later JSDoc.\n const outer = comment.match(/@emits\\s*\\(([^)]*)\\)/)\n if (!outer || outer[1] === undefined) return []\n const inner = outer[1]\n const seen = new Set<string>()\n const out: string[] = []\n const re = /[\"“]([^\"”]*)[\"”]/g\n let m: RegExpExecArray | null\n while ((m = re.exec(inner)) !== null) {\n const v = m[1]\n if (v === undefined || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction readIntent(comment: string): string | null {\n const match = comment.match(/@intent\\s*\\(\\s*[\"\\u201c]([^\"\\u201d]*)[\"\\u201d]\\s*\\)/)\n return match?.[1] ?? null\n}\n\n/**\n * Match every `@example(\"\\u2026\")` (and curly-quote variant) in source\n * order. Multiple tags on one variant are common \\u2014 typical-case,\n * edge-case-with-auth, etc. \\u2014 so the parser collects all of them\n * rather than picking the first.\n */\nfunction readExamples(comment: string): string[] {\n const out: string[] = []\n const re = /@example\\s*\\(\\s*[\"\\u201c]([^\"\\u201d]*)[\"\\u201d]\\s*\\)/g\n let m: RegExpExecArray | null\n while ((m = re.exec(comment)) !== null) {\n if (m[1] !== undefined) out.push(m[1])\n }\n return out\n}\n\nfunction readWarning(comment: string): string | null {\n const match = comment.match(/@warning\\s*\\(\\s*[\"\\u201c]([^\"\\u201d]*)[\"\\u201d]\\s*\\)/)\n return match?.[1] ?? null\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EAIpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,qBAAqB,EAA2B,MAAM,sBAAsB,CAAA;AACrF,OAAO,EAAE,kBAAkB,EAAkB,MAAM,mBAAmB,CAAA;AA6KtE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;IAC/C,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IACzD,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;IACnD,YAAY,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;CACtD;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,EACf,iBAAiB,UAAQ,EACzB,OAAO,GAAE,MAAM,GAAG,IAAW,EAC7B,OAAO,UAAQ,EACf,WAAW,CAAC,EAAE,mBAAmB,EACjC,YAAY,CAAC,EAAE,mBAAmB,GACjC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAqYnD;AA4sID,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,wBAAwB,GAAG,IAAI,CAoGjC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4B7D;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,IAAI,CAcrF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASzF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAChE,MAAM,CAYR"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EAIpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,qBAAqB,EAA2B,MAAM,sBAAsB,CAAA;AACrF,OAAO,EAAE,kBAAkB,EAAkB,MAAM,mBAAmB,CAAA;AA6KtE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;IAC/C,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IACzD,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;IACnD,YAAY,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;CACtD;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,EACf,iBAAiB,UAAQ,EACzB,OAAO,GAAE,MAAM,GAAG,IAAW,EAC7B,OAAO,UAAQ,EACf,WAAW,CAAC,EAAE,mBAAmB,EACjC,YAAY,CAAC,EAAE,mBAAmB,GACjC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAqYnD;AA2tID,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,wBAAwB,GAAG,IAAI,CAoGjC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4B7D;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,IAAI,CAcrF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASzF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAChE,MAAM,CAYR"}
package/dist/transform.js CHANGED
@@ -2336,6 +2336,8 @@ function hasNonDefaultAnnotation(a) {
2336
2336
  return true;
2337
2337
  if (v.dispatchMode !== 'shared')
2338
2338
  return true;
2339
+ if (v.routeGate != null)
2340
+ return true;
2339
2341
  }
2340
2342
  return false;
2341
2343
  }
@@ -2354,6 +2356,17 @@ function annotationsToObjectLiteral(a) {
2354
2356
  ts.factory.createPropertyAssignment('alwaysAffordable', ann.alwaysAffordable ? ts.factory.createTrue() : ts.factory.createFalse()),
2355
2357
  ts.factory.createPropertyAssignment('requiresConfirm', ann.requiresConfirm ? ts.factory.createTrue() : ts.factory.createFalse()),
2356
2358
  ts.factory.createPropertyAssignment('dispatchMode', ts.factory.createStringLiteral(ann.dispatchMode)),
2359
+ // Only emit `routeGate` when non-null. The runtime treats
2360
+ // missing as the no-gate default ("variant follows its
2361
+ // dispatchMode-driven affordance behavior") — keeping the
2362
+ // wire shape minimal for the common case of un-gated Msgs.
2363
+ // Use loose `!= null` so test fixtures that omit the
2364
+ // field entirely also fall through to the no-emit path.
2365
+ ...(ann.routeGate != null
2366
+ ? [
2367
+ ts.factory.createPropertyAssignment('routeGate', ts.factory.createStringLiteral(ann.routeGate)),
2368
+ ]
2369
+ : []),
2357
2370
  ], true)));
2358
2371
  }
2359
2372
  return ts.factory.createObjectLiteralExpression(props, true);