/** * Semantic Validation — cross-reference checks that go beyond structural schema validation. * * Currently validates: * 1. Machine transitions reference valid states * 2. No duplicate sibling names (e.g., two `field name=id` in the same interface) * 3. `derive` cannot be a direct child of `each` when that `each` is inside * a `render` block — `derive` compiles to `useMemo`, which violates React's * Rules of Hooks when called inside a `.map()` callback. * 4. `set name=X` must have a matching `state name=X` declared in an ancestor * screen/component. Otherwise codegen emits `setX(...)` with no bound * setter, which fails at React runtime with no compile-time signal. * 5. `module > export` bindings must reference names visible in that module * when the source is local, and resolver-enriched re-exports must name * symbols that the resolver proved exist. */ import type { IRNode } from './types.js'; export interface SemanticViolation { rule: string; nodeType: string; message: string; line?: number; col?: number; } export type ClassSemanticMemberKind = 'field' | 'method' | 'getter' | 'setter'; export type ClassSemanticOverrideStatus = 'compatible' | 'kind-mismatch' | 'arity-mismatch' | 'return-mismatch' | 'param-mismatch'; export interface ClassSemanticLocation { readonly line: number; readonly col: number; } export interface ClassSemanticMemberFact { readonly className: string; readonly owner: string; readonly name: string; readonly kind: ClassSemanticMemberKind; readonly static: boolean; readonly private?: boolean; readonly async?: boolean; readonly stream?: boolean; readonly generator?: boolean; readonly type?: string; readonly returns?: string; readonly paramTypes?: readonly string[]; readonly arity: number; readonly readable: boolean; readonly writable: boolean; readonly inheritedFrom?: string; readonly loc?: ClassSemanticLocation; } export interface ClassSemanticClassFact { readonly name: string; readonly baseName?: string; readonly hasConstructor: boolean; readonly constructorCount: number; readonly members: readonly ClassSemanticMemberFact[]; readonly effectiveMembers: readonly ClassSemanticMemberFact[]; readonly loc?: ClassSemanticLocation; } export type ClassSemanticConstructorSuperStatus = 'not-required' | 'satisfied' | 'missing' | 'conditional' | 'double' | 'this-before-super'; export interface ClassSemanticConstructorFact { readonly className: string; readonly hasConstructor: boolean; readonly constructorCount: number; readonly hasBase: boolean; readonly requiresSuper: boolean; readonly superStatus: ClassSemanticConstructorSuperStatus; readonly superCallCount: number; readonly thisBeforeSuper: boolean; readonly declaredFields: readonly string[]; readonly initializedFields: readonly string[]; readonly uninitializedRequiredFields: readonly string[]; readonly provenance: 'static-analysis'; readonly loc?: ClassSemanticLocation; } export interface ClassSemanticInheritanceEdge { readonly from: string; readonly to: string; readonly relation: 'extends'; readonly resolved: boolean; readonly builtin: boolean; } export interface ClassSemanticImplementsEdge { readonly from: string; readonly to: string; readonly relation: 'implements'; readonly resolved: boolean; readonly external: boolean; } export interface ClassSemanticOverrideFact { readonly className: string; readonly memberName: string; readonly static: boolean; readonly kind: ClassSemanticMemberKind; readonly arity: number; readonly baseClassName: string; readonly baseKind: ClassSemanticMemberKind; readonly baseArity: number; readonly status: ClassSemanticOverrideStatus; readonly loc?: ClassSemanticLocation; } export type ClassSemanticProtocolStatus = 'satisfied' | 'missing-members' | 'external' | 'unknown-interface' | 'invalid-interface' | 'unsupported-protocol'; export interface ClassSemanticProtocolConformanceFact { readonly className: string; readonly interfaceName: string; readonly status: ClassSemanticProtocolStatus; readonly missingMembers: readonly string[]; readonly satisfiedMembers: readonly string[]; readonly missingStaticMembers: readonly string[]; readonly satisfiedStaticMembers: readonly string[]; readonly diagnostics?: readonly string[]; readonly unsupportedReasons?: readonly string[]; readonly loc?: ClassSemanticLocation; } export interface ClassSemanticFacts { readonly classes: readonly ClassSemanticClassFact[]; readonly constructorFacts: readonly ClassSemanticConstructorFact[]; readonly inheritanceEdges: readonly ClassSemanticInheritanceEdge[]; readonly implementsEdges: readonly ClassSemanticImplementsEdge[]; readonly overrides: readonly ClassSemanticOverrideFact[]; readonly unresolvedBases: readonly string[]; readonly unresolvedImplements: readonly string[]; readonly protocolConformance: readonly ClassSemanticProtocolConformanceFact[]; readonly cycles: readonly (readonly string[])[]; } export interface RagSemanticLocation { readonly line: number; readonly col: number; } export interface RagSemanticSourceFact { readonly name?: string; readonly corpusName?: string; readonly kind?: string; readonly uri: string; readonly resourceName?: string; readonly media?: string; readonly acl?: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticChunkingFact { readonly name?: string; readonly corpusName?: string; readonly sourceName?: string; readonly strategy?: string; readonly maxTokens?: number; readonly overlap?: number; readonly unit?: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticEmbedFact { readonly name: string; readonly corpusName: string; readonly model?: string; readonly dims?: number; readonly metric?: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticCorpusFact { readonly name: string; readonly title?: string; readonly tenant?: string; readonly refresh?: string; readonly sources: readonly RagSemanticSourceFact[]; readonly chunking: readonly RagSemanticChunkingFact[]; readonly embeds: readonly RagSemanticEmbedFact[]; readonly loc?: RagSemanticLocation; } export interface RagSemanticRetrieverFact { readonly name: string; readonly corpusName: string; readonly embedName?: string; readonly mode?: string; readonly topK?: number; readonly minScore?: number; readonly rerank?: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticVectorStoreFact { readonly name: string; readonly kind?: string; readonly dims?: number; readonly metric?: string; readonly path?: string; readonly url?: string; readonly table?: string; readonly namespace?: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticIndexFact { readonly name: string; readonly corpusName: string; readonly storeName: string; readonly embedName?: string; readonly chunkingName?: string; readonly refresh?: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticRuntimeRetrieveFact { readonly name: string; readonly indexName: string; readonly ragName?: string; readonly queryParam?: string; readonly query?: string; readonly queryKind?: 'literal' | 'expression'; readonly as?: string; readonly topK?: number; readonly minScore?: number; readonly outputShape?: string; readonly outputItemShape?: string; readonly requireCitations?: boolean; readonly effectiveRequiresCitations: boolean; readonly loc?: RagSemanticLocation; } export interface RagSemanticGroundingFact { readonly name?: string; readonly ragName?: string; readonly requireCitations: boolean; readonly policy?: string; readonly maxContext?: number; readonly loc?: RagSemanticLocation; } export interface RagSemanticEvalFact { readonly name?: string; readonly ragName?: string; readonly metric?: string; readonly threshold?: number; readonly mode?: string; readonly caseCount?: number; readonly assertCount?: number; readonly cases?: readonly RagSemanticEvalCaseFact[]; readonly loc?: RagSemanticLocation; } export interface RagSemanticEvalCaseFact { readonly name: string; readonly ragName?: string; readonly evalName?: string; readonly query: string; readonly tags: readonly string[]; readonly expected: { readonly topK?: number; readonly minScore?: number; readonly chunkCount?: number; readonly sources?: readonly string[]; }; readonly asserts: readonly RagSemanticEvalAssertFact[]; readonly loc?: RagSemanticLocation; } export interface RagSemanticEvalAssertFact { readonly ragName?: string; readonly evalName?: string; readonly caseName?: string; readonly kind: string; readonly target: 'retrieved-chunk' | 'retrieved-chunks' | 'grounding' | 'latency'; readonly op: 'eq' | 'gte' | 'lte' | 'contains' | 'glob' | 'present'; readonly value?: string | number | boolean; readonly required: boolean; readonly loc?: RagSemanticLocation; } export interface RagSemanticAnswerSpanFact { readonly start: number; readonly end: number; readonly chunkIds: readonly string[]; readonly required: boolean; readonly loc?: RagSemanticLocation; } export interface RagSemanticAnswerEvidencePolicyFact { readonly minRetrievedChunks?: number; readonly minTopScore?: number; } export interface RagSemanticAnswerContractFact { readonly name: string; readonly ragName?: string; readonly query: string; readonly answer: string; readonly prompt?: string; readonly requireCitations: boolean; readonly minGroundingCoverage?: number; readonly minCitedChunks?: number; readonly evidencePolicy?: RagSemanticAnswerEvidencePolicyFact; readonly abstained?: boolean; readonly allowAbstain?: boolean; readonly abstainAnswer?: string; readonly spans: readonly RagSemanticAnswerSpanFact[]; readonly loc?: RagSemanticLocation; } export interface RagSemanticPipelineFact { readonly name: string; readonly retrieverName: string; readonly prompt?: string; readonly answer?: string; readonly citations: boolean; readonly groundings: readonly RagSemanticGroundingFact[]; readonly evals: readonly RagSemanticEvalFact[]; readonly answerContracts: readonly RagSemanticAnswerContractFact[]; readonly loc?: RagSemanticLocation; } export interface RagSemanticMcpRetrievalFact { readonly containerKind?: 'tool' | 'prompt'; readonly containerName?: string; readonly targetKind: 'retriever' | 'rag'; readonly targetName: string; readonly name?: string; readonly queryParam?: string; readonly query?: string; readonly as?: string; readonly topK?: number; readonly minScore?: number; readonly requireGrounding: boolean; readonly outputShape?: string; readonly outputItemShape?: string; readonly requireCitations?: boolean; readonly effectiveRequiresCitations: boolean; readonly provenance?: string; readonly citationField?: string; readonly sourceField?: string; readonly scoreField?: string; readonly contractStatus: 'absent' | 'valid' | 'invalid'; readonly loc?: RagSemanticLocation; } export interface RagSemanticResourceFeedFact { readonly corpusName?: string; readonly sourceName?: string; readonly resourceName: string; readonly uri: string; readonly loc?: RagSemanticLocation; } export interface RagSemanticFacts { readonly corpora: readonly RagSemanticCorpusFact[]; readonly vectorStores: readonly RagSemanticVectorStoreFact[]; readonly indexes: readonly RagSemanticIndexFact[]; readonly retrievers: readonly RagSemanticRetrieverFact[]; readonly pipelines: readonly RagSemanticPipelineFact[]; readonly runtimeRetrievals: readonly RagSemanticRuntimeRetrieveFact[]; readonly mcpRetrievals: readonly RagSemanticMcpRetrievalFact[]; readonly resourceFeedsCorpora: readonly RagSemanticResourceFeedFact[]; readonly unresolvedCorpusRefs: readonly string[]; readonly unresolvedVectorStoreRefs: readonly string[]; readonly unresolvedIndexRefs: readonly string[]; readonly unresolvedChunkingRefs: readonly string[]; readonly unresolvedRetrieverRefs: readonly string[]; readonly unresolvedEmbedRefs: readonly string[]; readonly unresolvedRagRefs: readonly string[]; readonly unresolvedSourceRefs: readonly string[]; readonly unresolvedResourceRefs: readonly string[]; } /** * Run semantic validation on an IR tree. * Returns an empty array when the tree is valid. */ export declare function validateSemantics(root: IRNode): SemanticViolation[]; export declare function validateClassSemantics(root: IRNode | readonly IRNode[]): SemanticViolation[]; export declare function validateRagSemantics(root: IRNode | readonly IRNode[]): SemanticViolation[]; export declare function collectRagSemanticFacts(root: IRNode | readonly IRNode[]): RagSemanticFacts; export type ClassMemberKind = 'field' | 'method' | 'getter' | 'setter'; export interface ClassInfo { node: IRNode; rootIndex: number; name: string; baseName?: string; implementsNames: string[]; implementsMalformed: boolean; members: ClassMemberInfo[]; constructors: IRNode[]; } export interface ClassMemberInfo { node: IRNode; owner: string; name: string; kind: ClassMemberKind; static: boolean; private: boolean; async: boolean; stream: boolean; generator: boolean; type?: string; returns?: string; paramTypes: readonly string[]; arity: number; } export declare const RAG_MCP_RETRIEVE_OUTPUT_SHAPE = "RetrievedChunk[]"; export declare const RAG_MCP_RETRIEVE_OUTPUT_ITEM_SHAPE = "RetrievedChunk"; export declare const RAG_RUNTIME_RETRIEVE_OUTPUT_SHAPE = "RetrievedChunk[]"; export declare const RAG_RUNTIME_RETRIEVE_OUTPUT_ITEM_SHAPE = "RetrievedChunk"; export declare function collectClassInfos(root: IRNode, rootIndex?: number): ClassInfo[]; export declare function collectClassSemanticFacts(root: IRNode | readonly IRNode[]): ClassSemanticFacts; /** * Liskov substitutability check for a member override against its base member. * * Runs ONLY when kinds are strictly equal (method/method, getter/getter, * setter/setter). Mixed accessor pairs (getter overriding setter, or vice * versa) and fields return null (skip) to preserve existing behavior. For * methods, it assumes arity has already matched (arity-mismatch fires first). * * Variance rules: * - Return position is COVARIANT: an override may narrow the return type * (override.returns must be a subtype of base.returns). A non-subtype is a * 'return-mismatch'. * - Param positions are CONTRAVARIANT: an override may widen a param type * (base.paramTypes[i] must be a subtype of override.paramTypes[i]). A * non-subtype is a 'param-mismatch'. * * 'unknown' subtype results (gradual typing — primitives, unannotated, or * non-class names) are skipped, so the check produces zero false positives. */ export declare function checkOverrideVariance(member: ClassMemberInfo, baseMember: ClassMemberInfo, classByName: ReadonlyMap): 'return-mismatch' | 'param-mismatch' | null; /** * Nominal subtype check: is `sub` a (non-strict) subtype of `sup`? * - undefined on either side → 'unknown' (gradual: caller skips). * - sub === sup → true. * - either name not a known class in classByName → 'unknown' (primitives / * external / unresolved types are not compared). * - else cycle-safe walk of sub's baseName chain; reaching sup → true; chain * ends or cycles without reaching sup → false. */ export declare function isNominalSubtype(sub: string | undefined, sup: string | undefined, classByName: ReadonlyMap): true | false | 'unknown'; export declare function moduleRuntimeBindingNames(moduleNode: IRNode): Set; export declare function moduleAmbientRuntimeBindingNames(moduleNode: IRNode): Set;