@lucern/graph-primitives 0.1.0-alpha.2
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.
- package/README.md +29 -0
- package/dist/beliefDecay-Q_26RTc-.d.ts +72 -0
- package/dist/beliefDecay.d.ts +2 -0
- package/dist/beliefDecay.js +1628 -0
- package/dist/beliefDecay.js.map +1 -0
- package/dist/beliefEvidenceLinks-42FlR48t.d.ts +77 -0
- package/dist/beliefEvidenceLinks.d.ts +1 -0
- package/dist/beliefEvidenceLinks.js +1978 -0
- package/dist/beliefEvidenceLinks.js.map +1 -0
- package/dist/beliefLifecycle-C-AehZgF.d.ts +43 -0
- package/dist/beliefLifecycle.d.ts +1 -0
- package/dist/beliefLifecycle.js +98 -0
- package/dist/beliefLifecycle.js.map +1 -0
- package/dist/confidencePropagationDispatch.d.ts +46 -0
- package/dist/confidencePropagationDispatch.js +744 -0
- package/dist/confidencePropagationDispatch.js.map +1 -0
- package/dist/contradictions-Hdwl7zid.d.ts +71 -0
- package/dist/contradictions.d.ts +1 -0
- package/dist/contradictions.js +1557 -0
- package/dist/contradictions.js.map +1 -0
- package/dist/convex.d.ts +23 -0
- package/dist/convex.js +17 -0
- package/dist/convex.js.map +1 -0
- package/dist/edgeValidation-CeI0wc0r.d.ts +35 -0
- package/dist/edgeValidation.d.ts +2 -0
- package/dist/edgeValidation.js +307 -0
- package/dist/edgeValidation.js.map +1 -0
- package/dist/edges/contains.d.ts +6 -0
- package/dist/edges/contains.js +14 -0
- package/dist/edges/contains.js.map +1 -0
- package/dist/edges/contradicts.d.ts +6 -0
- package/dist/edges/contradicts.js +183 -0
- package/dist/edges/contradicts.js.map +1 -0
- package/dist/edges/dependsOn.d.ts +6 -0
- package/dist/edges/dependsOn.js +240 -0
- package/dist/edges/dependsOn.js.map +1 -0
- package/dist/edges/derivedFrom.d.ts +6 -0
- package/dist/edges/derivedFrom.js +14 -0
- package/dist/edges/derivedFrom.js.map +1 -0
- package/dist/edges/elaborates.d.ts +6 -0
- package/dist/edges/elaborates.js +100 -0
- package/dist/edges/elaborates.js.map +1 -0
- package/dist/edges/index.d.ts +3 -0
- package/dist/edges/index.js +556 -0
- package/dist/edges/index.js.map +1 -0
- package/dist/edges/informs.d.ts +6 -0
- package/dist/edges/informs.js +112 -0
- package/dist/edges/informs.js.map +1 -0
- package/dist/edges/propagationTypes.d.ts +39 -0
- package/dist/edges/propagationTypes.js +17 -0
- package/dist/edges/propagationTypes.js.map +1 -0
- package/dist/edges/refutes.d.ts +6 -0
- package/dist/edges/refutes.js +108 -0
- package/dist/edges/refutes.js.map +1 -0
- package/dist/edges/supports.d.ts +6 -0
- package/dist/edges/supports.js +193 -0
- package/dist/edges/supports.js.map +1 -0
- package/dist/edges/tests.d.ts +6 -0
- package/dist/edges/tests.js +14 -0
- package/dist/edges/tests.js.map +1 -0
- package/dist/edges/utils.d.ts +12 -0
- package/dist/edges/utils.js +188 -0
- package/dist/edges/utils.js.map +1 -0
- package/dist/embeddingTrigger.d.ts +24 -0
- package/dist/embeddingTrigger.js +24 -0
- package/dist/embeddingTrigger.js.map +1 -0
- package/dist/entityBridge-DMaKooYn.d.ts +59 -0
- package/dist/entityBridge.d.ts +1 -0
- package/dist/entityBridge.js +663 -0
- package/dist/entityBridge.js.map +1 -0
- package/dist/entityLifecycle-BkhRJ-XI.d.ts +69 -0
- package/dist/entityLifecycle.d.ts +1 -0
- package/dist/entityLifecycle.js +2083 -0
- package/dist/entityLifecycle.js.map +1 -0
- package/dist/entityValidation-KLZ_Xl2D.d.ts +50 -0
- package/dist/entityValidation.d.ts +3 -0
- package/dist/entityValidation.js +71 -0
- package/dist/entityValidation.js.map +1 -0
- package/dist/epistemicAnswers-DSP1slZ9.d.ts +67 -0
- package/dist/epistemicAnswers.d.ts +1 -0
- package/dist/epistemicAnswers.js +1650 -0
- package/dist/epistemicAnswers.js.map +1 -0
- package/dist/epistemicBeliefs-DtFVTp-k.d.ts +377 -0
- package/dist/epistemicBeliefs.d.ts +5 -0
- package/dist/epistemicBeliefs.js +6386 -0
- package/dist/epistemicBeliefs.js.map +1 -0
- package/dist/epistemicContractHelpers.d.ts +1 -0
- package/dist/epistemicContractHelpers.js +320 -0
- package/dist/epistemicContractHelpers.js.map +1 -0
- package/dist/epistemicContracts.d.ts +77 -0
- package/dist/epistemicContracts.js +8436 -0
- package/dist/epistemicContracts.js.map +1 -0
- package/dist/epistemicEdges-DcA8ErUG.d.ts +191 -0
- package/dist/epistemicEdges.d.ts +2 -0
- package/dist/epistemicEdges.js +2749 -0
- package/dist/epistemicEdges.js.map +1 -0
- package/dist/epistemicEvidence-Bo638XDP.d.ts +128 -0
- package/dist/epistemicEvidence.d.ts +3 -0
- package/dist/epistemicEvidence.js +3282 -0
- package/dist/epistemicEvidence.js.map +1 -0
- package/dist/epistemicHelpers-Bd9xbaib.d.ts +329 -0
- package/dist/epistemicHelpers.d.ts +4 -0
- package/dist/epistemicHelpers.js +999 -0
- package/dist/epistemicHelpers.js.map +1 -0
- package/dist/epistemicLinking-CyeLOIzN.d.ts +35 -0
- package/dist/epistemicLinking.d.ts +1 -0
- package/dist/epistemicLinking.js +1391 -0
- package/dist/epistemicLinking.js.map +1 -0
- package/dist/epistemicNodes-BpD6Koud.d.ts +167 -0
- package/dist/epistemicNodes.d.ts +2 -0
- package/dist/epistemicNodes.js +2942 -0
- package/dist/epistemicNodes.js.map +1 -0
- package/dist/epistemicQuestions-CmEeY6zQ.d.ts +214 -0
- package/dist/epistemicQuestions.d.ts +3 -0
- package/dist/epistemicQuestions.js +4993 -0
- package/dist/epistemicQuestions.js.map +1 -0
- package/dist/epistemicSources-ZazxHOK1.d.ts +25 -0
- package/dist/epistemicSources.d.ts +1 -0
- package/dist/epistemicSources.js +2025 -0
- package/dist/epistemicSources.js.map +1 -0
- package/dist/evaluators/index.d.ts +9 -0
- package/dist/evaluators/index.js +8440 -0
- package/dist/evaluators/index.js.map +1 -0
- package/dist/evaluators/lintCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/lintCheckerEvaluator.js +155 -0
- package/dist/evaluators/lintCheckerEvaluator.js.map +1 -0
- package/dist/evaluators/sentryCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/sentryCheckerEvaluator.js +126 -0
- package/dist/evaluators/sentryCheckerEvaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +27 -0
- package/dist/evaluators/shared.js +92 -0
- package/dist/evaluators/shared.js.map +1 -0
- package/dist/evaluators/testRunnerEvaluator.d.ts +17 -0
- package/dist/evaluators/testRunnerEvaluator.js +232 -0
- package/dist/evaluators/testRunnerEvaluator.js.map +1 -0
- package/dist/evaluators/tscCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/tscCheckerEvaluator.js +189 -0
- package/dist/evaluators/tscCheckerEvaluator.js.map +1 -0
- package/dist/globalId-DKh9d_uD.d.ts +20 -0
- package/dist/globalId.d.ts +1 -0
- package/dist/globalId.js +15 -0
- package/dist/globalId.js.map +1 -0
- package/dist/graphTypes-CpgIuCdo.d.ts +52 -0
- package/dist/graphTypes.d.ts +1 -0
- package/dist/graphTypes.js +120 -0
- package/dist/graphTypes.js.map +1 -0
- package/dist/helpers-BYHIk5vU.d.ts +27 -0
- package/dist/helpers.d.ts +4 -0
- package/dist/helpers.js +313 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index-Dct1T70K.d.ts +25 -0
- package/dist/index-Dq-7R-gi.d.ts +31 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +22294 -0
- package/dist/index.js.map +1 -0
- package/dist/invariantEnforcement.d.ts +52 -0
- package/dist/invariantEnforcement.js +231 -0
- package/dist/invariantEnforcement.js.map +1 -0
- package/dist/logicalRoleInference-CJxqWi3u.d.ts +16 -0
- package/dist/logicalRoleInference.d.ts +3 -0
- package/dist/logicalRoleInference.js +64 -0
- package/dist/logicalRoleInference.js.map +1 -0
- package/dist/matcherFeedbackUtils.d.ts +33 -0
- package/dist/matcherFeedbackUtils.js +95 -0
- package/dist/matcherFeedbackUtils.js.map +1 -0
- package/dist/ontology-matching-Buhu23ss.d.ts +48 -0
- package/dist/ontology-matching.d.ts +2 -0
- package/dist/ontology-matching.js +346 -0
- package/dist/ontology-matching.js.map +1 -0
- package/dist/ontologyApproval-Ba0Jjk1k.d.ts +26 -0
- package/dist/ontologyApproval.d.ts +1 -0
- package/dist/ontologyApproval.js +78 -0
- package/dist/ontologyApproval.js.map +1 -0
- package/dist/ontologyDefinitions.d.ts +72 -0
- package/dist/ontologyDefinitions.js +635 -0
- package/dist/ontologyDefinitions.js.map +1 -0
- package/dist/ontologyHelpers.d.ts +79 -0
- package/dist/ontologyHelpers.js +81 -0
- package/dist/ontologyHelpers.js.map +1 -0
- package/dist/ontologyRegistry-B67rPJ16.d.ts +31 -0
- package/dist/ontologyRegistry.d.ts +1 -0
- package/dist/ontologyRegistry.js +296 -0
- package/dist/ontologyRegistry.js.map +1 -0
- package/dist/projectionReconciliation-CxrXYGaB.d.ts +20 -0
- package/dist/projectionReconciliation.d.ts +1 -0
- package/dist/projectionReconciliation.js +261 -0
- package/dist/projectionReconciliation.js.map +1 -0
- package/dist/projectionStaleness-CAdpIsaW.d.ts +51 -0
- package/dist/projectionStaleness.d.ts +1 -0
- package/dist/projectionStaleness.js +57 -0
- package/dist/projectionStaleness.js.map +1 -0
- package/dist/questionEvidenceLinks-BdQD0TkM.d.ts +34 -0
- package/dist/questionEvidenceLinks.d.ts +1 -0
- package/dist/questionEvidenceLinks.js +1690 -0
- package/dist/questionEvidenceLinks.js.map +1 -0
- package/dist/resolverTypes-CC8Ea2E2.d.ts +20 -0
- package/dist/resolverTypes.d.ts +4 -0
- package/dist/resolverTypes.js +3 -0
- package/dist/resolverTypes.js.map +1 -0
- package/dist/resolvers-Br1a6eLV.d.ts +14 -0
- package/dist/resolvers.d.ts +5 -0
- package/dist/resolvers.js +308 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/scopeResolverCompat.d.ts +26 -0
- package/dist/scopeResolverCompat.js +242 -0
- package/dist/scopeResolverCompat.js.map +1 -0
- package/dist/text-matching-CMn2WnVD.d.ts +40 -0
- package/dist/text-matching.d.ts +2 -0
- package/dist/text-matching.js +246 -0
- package/dist/text-matching.js.map +1 -0
- package/dist/topicOntologyResolver.d.ts +80 -0
- package/dist/topicOntologyResolver.js +67 -0
- package/dist/topicOntologyResolver.js.map +1 -0
- package/dist/topicProjectOverlay.d.ts +92 -0
- package/dist/topicProjectOverlay.js +249 -0
- package/dist/topicProjectOverlay.js.map +1 -0
- package/dist/topicScope-By_zp4tt.d.ts +34 -0
- package/dist/topicScope.d.ts +3 -0
- package/dist/topicScope.js +206 -0
- package/dist/topicScope.js.map +1 -0
- package/dist/workspaceIsolation.d.ts +44 -0
- package/dist/workspaceIsolation.js +950 -0
- package/dist/workspaceIsolation.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/convex.ts","../src/topicScope.ts","../src/scopeResolverCompat.ts"],"names":["normalizeScopeValue","topicId"],"mappings":"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","file":"scopeResolverCompat.js","sourcesContent":["import {\n actionGeneric,\n anyApi,\n componentsGeneric,\n httpActionGeneric,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n mutationGeneric,\n queryGeneric,\n} from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nexport const api = anyApi as any;\nexport const components = componentsGeneric() as any;\nexport const internal = anyApi as any;\n\nexport type TableNames = string;\nexport type Id<TableName extends TableNames = string> = GenericId<TableName>;\nexport type Doc<TableName extends TableNames = string> = any;\nexport type DataModel = any;\nexport type ActionCtx = any;\nexport type DatabaseReader = any;\nexport type DatabaseWriter = any;\nexport type MutationCtx = any;\nexport type QueryCtx = any;\n\nexport const action = actionGeneric as any;\nexport const httpAction = httpActionGeneric as any;\nexport const internalAction = internalActionGeneric as any;\nexport const internalMutation = internalMutationGeneric as any;\nexport const internalQuery = internalQueryGeneric as any;\nexport const mutation = mutationGeneric as any;\nexport const query = queryGeneric as any;\n","/** Topic-scope resolution helpers for graph-primitive operations. */\nimport { v } from \"convex/values\";\nimport { api as appApi } from \"./convex\";\nimport type { Id } from \"./convex\";\n\nconst LEGACY_SCOPE_FIELD = \"graphScope\" + \"ProjectId\";\n\ntype TopicDoc = Record<string, unknown> & {\n _id: Id<\"topics\">;\n globalId?: string;\n name?: string;\n depth?: number;\n createdAt?: number;\n parentTopicId?: Id<\"topics\">;\n tenantId?: string;\n workspaceId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type TopicProjectScope = {\n topicId: Id<\"topics\">;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source: \"topic\" | \"project_mapped_topic\" | \"topic_inferred\";\n};\n\ntype MaterializedTopicNodeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n metadata?: Record<string, unknown>;\n};\n\nfunction asMappedProjectId(\n topic: TopicDoc | null | undefined\n): string | undefined {\n if (!topic) {\n return;\n }\n const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);\n if (directLegacyProjectId) {\n return directLegacyProjectId;\n }\n const metadata = (topic.metadata || {}) as Record<string, unknown>;\n const candidate =\n (metadata[LEGACY_SCOPE_FIELD] as string | undefined) ||\n (metadata.legacyProjectId as string | undefined) ||\n (metadata.projectId as string | undefined) ||\n (metadata.scopeProjectId as string | undefined);\n return candidate ? (candidate as string) : undefined;\n}\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction pickPrimaryTopic(candidates: TopicDoc[]): TopicDoc | undefined {\n return [...candidates].sort((a, b) => {\n const depthA = a.depth ?? 9999;\n const depthB = b.depth ?? 9999;\n if (depthA !== depthB) {\n return depthA - depthB;\n }\n const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;\n const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;\n if (createdA !== createdB) {\n return createdA - createdB;\n }\n return String(a.name || \"\").localeCompare(String(b.name || \"\"));\n })[0];\n}\n\nasync function findTopicsByScopeAlias(ctx: any, scopeId: string): Promise<TopicDoc[]> {\n try {\n return (await ctx.db\n .query(\"topics\")\n .withIndex(\"by_graph_scope_project\", (q: any) =>\n q.eq(LEGACY_SCOPE_FIELD, scopeId)\n )\n .collect()) as TopicDoc[];\n } catch {\n // Older Lucern dev deployments can lag index backfills while still carrying\n // the underlying topics table. Scan and filter so scope resolution keeps\n // working during the rollout.\n const topics = (await ctx.db.query(\"topics\").collect()) as TopicDoc[];\n return topics.filter((topic) => {\n const normalizedGlobalId = normalizeScopeValue(topic.globalId);\n const mappedProjectId = asMappedProjectId(topic);\n return (\n String(topic._id) === scopeId ||\n normalizedGlobalId === scopeId ||\n mappedProjectId === scopeId\n );\n });\n }\n}\n\nasync function tryResolveHostTopicById(\n ctx: any,\n topicId: string\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.get as any, {\n id: topicId,\n })) ?? null) as TopicDoc | null;\n } catch {\n return null;\n }\n}\n\nasync function tryResolveHostTopicByLegacyScope(\n ctx: any,\n legacyScopeId: string\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.getByLegacyScopeId as any, {\n projectId: legacyScopeId,\n })) ?? null) as TopicDoc | null;\n } catch {\n return null;\n }\n}\n\nexport function readMaterializedTopicTableId(\n topicNode: MaterializedTopicNodeDoc | null | undefined\n): string | undefined {\n if (!topicNode) {\n return;\n }\n\n const metadata = (topicNode.metadata || {}) as Record<string, unknown>;\n const topicTableId =\n (metadata.topicTableId as string | undefined) ||\n (metadata.topicId as string | undefined);\n\n return typeof topicTableId === \"string\" && topicTableId.trim().length > 0\n ? topicTableId.trim()\n : undefined;\n}\n\n/**\n * Walk the topic parent chain to find inherited workspaceId and tenantId.\n * Mirrors the pattern used by resolveTopicOntology for ontologyId inheritance.\n * Max depth: 10 (defensive limit against pathological nesting).\n */\nasync function resolveInheritedWorkspaceScope(\n ctx: any,\n topic: TopicDoc\n): Promise<{ tenantId?: string; workspaceId?: string }> {\n const MAX_DEPTH = 10;\n let tenantId = normalizeScopeValue(topic.tenantId);\n let workspaceId = normalizeScopeValue(topic.workspaceId);\n\n if (tenantId && workspaceId) {\n return { tenantId, workspaceId };\n }\n\n let current: TopicDoc | null = topic;\n for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {\n current = (await ctx.db.get(current.parentTopicId)) as TopicDoc | null;\n if (!current) break;\n\n if (!tenantId) {\n tenantId = normalizeScopeValue(current.tenantId);\n }\n if (!workspaceId) {\n workspaceId = normalizeScopeValue(current.workspaceId);\n }\n if (tenantId && workspaceId) break;\n }\n\n return { tenantId, workspaceId };\n}\n\nexport async function resolveTopicProjectScope(\n ctx: any,\n args: { topicId?: Id<\"topics\"> | string; projectId?: string }\n): Promise<TopicProjectScope> {\n if (args.topicId) {\n // Try direct lookup, fall back to the legacy mapped-project bridge\n let topic: TopicDoc | null = null;\n try {\n topic = (await ctx.db.get(args.topicId as Id<\"topics\">)) as TopicDoc | null;\n } catch {\n // Not a valid topics table ID\n }\n if (!topic) {\n topic = await tryResolveHostTopicById(ctx, String(args.topicId));\n }\n if (!topic) {\n // Try as legacy projectId / globalId via the mapped-project bridge.\n topic =\n pickPrimaryTopic(\n await findTopicsByScopeAlias(ctx, String(args.topicId))\n ) ?? null;\n }\n if (!topic) {\n throw new Error(`Topic not found: ${String(args.topicId)}`);\n }\n const inherited = await resolveInheritedWorkspaceScope(ctx, topic);\n const mapped = asMappedProjectId(topic);\n if (mapped) {\n return {\n topicId: topic._id,\n projectId: mapped,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n return {\n topicId: topic._id,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n\n if (args.projectId) {\n let directTopic: TopicDoc | null = null;\n try {\n directTopic = (await ctx.db.get(\n args.projectId as Id<\"topics\">\n )) as TopicDoc | null;\n } catch {\n // Not a valid topics table ID, continue to legacy graph-scope lookup.\n }\n\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n const topics = await findTopicsByScopeAlias(ctx, args.projectId);\n const primary = pickPrimaryTopic(topics);\n if (primary) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, primary);\n return {\n topicId: primary._id,\n projectId: args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"project_mapped_topic\",\n };\n }\n throw new Error(\n `Legacy project scope ${String(args.projectId)} has no mapped topic.`\n );\n }\n\n throw new Error(\n \"Missing scope: provide topicId (preferred) or legacy projectId alias.\"\n );\n}\n\n/** Shared scope args for graph-primitive functions. topicId is canonical; projectId is a legacy alias. */\nexport const optionalScopeArgs = {\n projectId: v.optional(v.string()),\n topicId: v.optional(v.string()),\n} as const;\n","import { optionalScopeArgs, resolveTopicProjectScope } from \"./topicScope\";\n\nexport const scopeArgs = optionalScopeArgs;\n\nexport type ResolvedScope = Awaited<ReturnType<typeof resolveTopicProjectScope>>;\nexport type SoftResolvedScope = {\n topicId?: string;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source?: ResolvedScope[\"source\"];\n};\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nexport async function resolveScope(\n ctx: any,\n args: { topicId?: string | null; projectId?: string | null }\n): Promise<ResolvedScope | null> {\n const topicId = normalizeScopeValue(args.topicId);\n const projectId = normalizeScopeValue(args.projectId);\n if (!topicId && !projectId) {\n return null;\n }\n\n try {\n return await resolveTopicProjectScope(ctx, {\n topicId,\n projectId,\n });\n } catch {\n return null;\n }\n}\n\nexport async function resolveScopeSoft(\n ctx: any,\n args: { topicId?: string | null; projectId?: string | null }\n): Promise<SoftResolvedScope> {\n const resolved = await resolveScope(ctx, args);\n if (resolved) {\n const topicId = normalizeScopeValue(resolved.topicId);\n return {\n ...(topicId ? { topicId } : {}),\n ...(resolved.projectId ? { projectId: resolved.projectId } : {}),\n ...(resolved.tenantId ? { tenantId: resolved.tenantId } : {}),\n ...(resolved.workspaceId ? { workspaceId: resolved.workspaceId } : {}),\n ...(resolved.source ? { source: resolved.source } : {}),\n };\n }\n\n const topicId = normalizeScopeValue(args.topicId);\n const projectId = normalizeScopeValue(args.projectId);\n return {\n ...(topicId ? { topicId } : {}),\n ...(projectId ? { projectId } : {}),\n };\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { bigramTokenize, jaccardSimilarity, prepareLexicalQuery, rankWindowScore, rerankLexicalWindow, scoreLexicalSignal, scoreLexicalSignals, stemToken, tokenOverlapScore, tokenizeSearchText, wordOverlapScore, wordTokenize } from '@lucern/contracts/text-matching.contract';
|
|
2
|
+
|
|
3
|
+
type LexicalStrategy = "tokenOverlap" | "bigramJaccard" | "wordOverlap";
|
|
4
|
+
type PreparedLexicalQuery = {
|
|
5
|
+
raw: string;
|
|
6
|
+
tokens: string[];
|
|
7
|
+
words: string[];
|
|
8
|
+
bigrams: Set<string>;
|
|
9
|
+
};
|
|
10
|
+
type LexicalSignal = {
|
|
11
|
+
strategy?: LexicalStrategy;
|
|
12
|
+
text: string | null | undefined;
|
|
13
|
+
weight: number;
|
|
14
|
+
};
|
|
15
|
+
type LexicalRerankOptions = {
|
|
16
|
+
lexicalWeight?: number;
|
|
17
|
+
rankWeight?: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type textMatching_LexicalRerankOptions = LexicalRerankOptions;
|
|
21
|
+
type textMatching_LexicalSignal = LexicalSignal;
|
|
22
|
+
type textMatching_LexicalStrategy = LexicalStrategy;
|
|
23
|
+
type textMatching_PreparedLexicalQuery = PreparedLexicalQuery;
|
|
24
|
+
declare const textMatching_bigramTokenize: typeof bigramTokenize;
|
|
25
|
+
declare const textMatching_jaccardSimilarity: typeof jaccardSimilarity;
|
|
26
|
+
declare const textMatching_prepareLexicalQuery: typeof prepareLexicalQuery;
|
|
27
|
+
declare const textMatching_rankWindowScore: typeof rankWindowScore;
|
|
28
|
+
declare const textMatching_rerankLexicalWindow: typeof rerankLexicalWindow;
|
|
29
|
+
declare const textMatching_scoreLexicalSignal: typeof scoreLexicalSignal;
|
|
30
|
+
declare const textMatching_scoreLexicalSignals: typeof scoreLexicalSignals;
|
|
31
|
+
declare const textMatching_stemToken: typeof stemToken;
|
|
32
|
+
declare const textMatching_tokenOverlapScore: typeof tokenOverlapScore;
|
|
33
|
+
declare const textMatching_tokenizeSearchText: typeof tokenizeSearchText;
|
|
34
|
+
declare const textMatching_wordOverlapScore: typeof wordOverlapScore;
|
|
35
|
+
declare const textMatching_wordTokenize: typeof wordTokenize;
|
|
36
|
+
declare namespace textMatching {
|
|
37
|
+
export { type textMatching_LexicalRerankOptions as LexicalRerankOptions, type textMatching_LexicalSignal as LexicalSignal, type textMatching_LexicalStrategy as LexicalStrategy, type textMatching_PreparedLexicalQuery as PreparedLexicalQuery, textMatching_bigramTokenize as bigramTokenize, textMatching_jaccardSimilarity as jaccardSimilarity, textMatching_prepareLexicalQuery as prepareLexicalQuery, textMatching_rankWindowScore as rankWindowScore, textMatching_rerankLexicalWindow as rerankLexicalWindow, textMatching_scoreLexicalSignal as scoreLexicalSignal, textMatching_scoreLexicalSignals as scoreLexicalSignals, textMatching_stemToken as stemToken, textMatching_tokenOverlapScore as tokenOverlapScore, textMatching_tokenizeSearchText as tokenizeSearchText, textMatching_wordOverlapScore as wordOverlapScore, textMatching_wordTokenize as wordTokenize };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { type LexicalStrategy as L, type PreparedLexicalQuery as P, type LexicalSignal as a, type LexicalRerankOptions as b, textMatching as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { bigramTokenize, jaccardSimilarity, prepareLexicalQuery, rankWindowScore, rerankLexicalWindow, scoreLexicalSignal, scoreLexicalSignals, stemToken, tokenOverlapScore, tokenizeSearchText, wordOverlapScore, wordTokenize } from '@lucern/contracts/text-matching.contract';
|
|
2
|
+
export { b as LexicalRerankOptions, a as LexicalSignal, L as LexicalStrategy, P as PreparedLexicalQuery } from './text-matching-CMn2WnVD.js';
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// ../../packages/contracts/src/text-matching.contract.ts
|
|
2
|
+
var TOKEN_SPLIT_REGEX = /[^a-z0-9]+/;
|
|
3
|
+
var NON_ALPHANUMERIC_REGEX = /[^a-z0-9]/g;
|
|
4
|
+
var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
5
|
+
"the",
|
|
6
|
+
"a",
|
|
7
|
+
"an",
|
|
8
|
+
"and",
|
|
9
|
+
"or",
|
|
10
|
+
"but",
|
|
11
|
+
"in",
|
|
12
|
+
"on",
|
|
13
|
+
"at",
|
|
14
|
+
"to",
|
|
15
|
+
"for",
|
|
16
|
+
"of",
|
|
17
|
+
"with",
|
|
18
|
+
"by",
|
|
19
|
+
"from",
|
|
20
|
+
"is",
|
|
21
|
+
"it",
|
|
22
|
+
"as",
|
|
23
|
+
"be",
|
|
24
|
+
"was",
|
|
25
|
+
"are",
|
|
26
|
+
"this",
|
|
27
|
+
"that",
|
|
28
|
+
"has",
|
|
29
|
+
"had",
|
|
30
|
+
"have",
|
|
31
|
+
"not",
|
|
32
|
+
"all",
|
|
33
|
+
"can",
|
|
34
|
+
"do",
|
|
35
|
+
"its",
|
|
36
|
+
"may",
|
|
37
|
+
"will",
|
|
38
|
+
"how",
|
|
39
|
+
"what",
|
|
40
|
+
"which",
|
|
41
|
+
"who",
|
|
42
|
+
"when",
|
|
43
|
+
"where",
|
|
44
|
+
"than",
|
|
45
|
+
"then",
|
|
46
|
+
"each",
|
|
47
|
+
"into",
|
|
48
|
+
"such",
|
|
49
|
+
"any",
|
|
50
|
+
"been",
|
|
51
|
+
"if",
|
|
52
|
+
"would",
|
|
53
|
+
"about",
|
|
54
|
+
"should",
|
|
55
|
+
"these",
|
|
56
|
+
"those",
|
|
57
|
+
"their",
|
|
58
|
+
"we",
|
|
59
|
+
"our",
|
|
60
|
+
"so"
|
|
61
|
+
]);
|
|
62
|
+
function tokenizeSearchText(text) {
|
|
63
|
+
return text.toLowerCase().split(TOKEN_SPLIT_REGEX).filter((token) => token.length >= 2 && !STOP_WORDS.has(token));
|
|
64
|
+
}
|
|
65
|
+
function stemToken(word) {
|
|
66
|
+
if (word.length <= 4) {
|
|
67
|
+
return word;
|
|
68
|
+
}
|
|
69
|
+
if (word.endsWith("ation")) {
|
|
70
|
+
return word.slice(0, -5);
|
|
71
|
+
}
|
|
72
|
+
if (word.endsWith("ment")) {
|
|
73
|
+
return word.slice(0, -4);
|
|
74
|
+
}
|
|
75
|
+
if (word.endsWith("ness")) {
|
|
76
|
+
return word.slice(0, -4);
|
|
77
|
+
}
|
|
78
|
+
if (word.endsWith("ical")) {
|
|
79
|
+
return word.slice(0, -4);
|
|
80
|
+
}
|
|
81
|
+
if (word.endsWith("tion")) {
|
|
82
|
+
return word.slice(0, -4);
|
|
83
|
+
}
|
|
84
|
+
if (word.endsWith("sion")) {
|
|
85
|
+
return word.slice(0, -4);
|
|
86
|
+
}
|
|
87
|
+
if (word.endsWith("ing")) {
|
|
88
|
+
return word.slice(0, -3);
|
|
89
|
+
}
|
|
90
|
+
if (word.endsWith("ous")) {
|
|
91
|
+
return word.slice(0, -3);
|
|
92
|
+
}
|
|
93
|
+
if (word.endsWith("ive")) {
|
|
94
|
+
return word.slice(0, -3);
|
|
95
|
+
}
|
|
96
|
+
if (word.endsWith("ity")) {
|
|
97
|
+
return word.slice(0, -3);
|
|
98
|
+
}
|
|
99
|
+
if (word.endsWith("ics")) {
|
|
100
|
+
return word.slice(0, -3);
|
|
101
|
+
}
|
|
102
|
+
if (word.endsWith("ly")) {
|
|
103
|
+
return word.slice(0, -2);
|
|
104
|
+
}
|
|
105
|
+
if (word.endsWith("ed")) {
|
|
106
|
+
return word.slice(0, -2);
|
|
107
|
+
}
|
|
108
|
+
if (word.endsWith("er")) {
|
|
109
|
+
return word.slice(0, -2);
|
|
110
|
+
}
|
|
111
|
+
if (word.endsWith("es")) {
|
|
112
|
+
return word.slice(0, -2);
|
|
113
|
+
}
|
|
114
|
+
if (word.endsWith("al")) {
|
|
115
|
+
return word.slice(0, -2);
|
|
116
|
+
}
|
|
117
|
+
if (word.endsWith("ic")) {
|
|
118
|
+
return word.slice(0, -2);
|
|
119
|
+
}
|
|
120
|
+
if (word.endsWith("s") && !word.endsWith("ss")) {
|
|
121
|
+
return word.slice(0, -1);
|
|
122
|
+
}
|
|
123
|
+
return word;
|
|
124
|
+
}
|
|
125
|
+
function tokenOverlapScore(queryTokens, textTokens) {
|
|
126
|
+
if (queryTokens.length === 0 || textTokens.length === 0) {
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
const stemmedText = new Set(textTokens.map(stemToken));
|
|
130
|
+
let matchCount = 0;
|
|
131
|
+
for (const queryToken of queryTokens) {
|
|
132
|
+
const stemmedQuery = stemToken(queryToken);
|
|
133
|
+
if (stemmedText.has(stemmedQuery)) {
|
|
134
|
+
matchCount += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
for (const textToken of stemmedText) {
|
|
138
|
+
if (textToken.startsWith(stemmedQuery) || stemmedQuery.startsWith(textToken)) {
|
|
139
|
+
matchCount += 0.5;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return matchCount / queryTokens.length;
|
|
145
|
+
}
|
|
146
|
+
function bigramTokenize(text) {
|
|
147
|
+
const normalized = text.toLowerCase().replace(NON_ALPHANUMERIC_REGEX, "");
|
|
148
|
+
const bigrams = /* @__PURE__ */ new Set();
|
|
149
|
+
for (let i = 0; i < normalized.length - 1; i++) {
|
|
150
|
+
bigrams.add(normalized.slice(i, i + 2));
|
|
151
|
+
}
|
|
152
|
+
return bigrams;
|
|
153
|
+
}
|
|
154
|
+
function wordTokenize(text) {
|
|
155
|
+
return text.toLowerCase().split(TOKEN_SPLIT_REGEX).filter((token) => token.length > 1);
|
|
156
|
+
}
|
|
157
|
+
function jaccardSimilarity(setA, setB) {
|
|
158
|
+
if (setA.size === 0 && setB.size === 0) {
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
let intersectionSize = 0;
|
|
162
|
+
const smaller = setA.size <= setB.size ? setA : setB;
|
|
163
|
+
const larger = setA.size <= setB.size ? setB : setA;
|
|
164
|
+
for (const item of smaller) {
|
|
165
|
+
if (larger.has(item)) {
|
|
166
|
+
intersectionSize++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const unionSize = setA.size + setB.size - intersectionSize;
|
|
170
|
+
return unionSize === 0 ? 0 : intersectionSize / unionSize;
|
|
171
|
+
}
|
|
172
|
+
function wordOverlapScore(inputWords, typeWords) {
|
|
173
|
+
if (typeWords.length === 0) {
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
let matches = 0;
|
|
177
|
+
for (const word of typeWords) {
|
|
178
|
+
if (inputWords.includes(word)) {
|
|
179
|
+
matches++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return matches / typeWords.length;
|
|
183
|
+
}
|
|
184
|
+
function prepareLexicalQuery(query) {
|
|
185
|
+
return {
|
|
186
|
+
raw: query,
|
|
187
|
+
tokens: tokenizeSearchText(query),
|
|
188
|
+
words: wordTokenize(query),
|
|
189
|
+
bigrams: bigramTokenize(query)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function scoreLexicalSignal(query, signal) {
|
|
193
|
+
const text = signal.text?.trim();
|
|
194
|
+
if (!text) {
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
switch (signal.strategy ?? "tokenOverlap") {
|
|
198
|
+
case "bigramJaccard":
|
|
199
|
+
return jaccardSimilarity(query.bigrams, bigramTokenize(text));
|
|
200
|
+
case "wordOverlap":
|
|
201
|
+
return wordOverlapScore(query.words, wordTokenize(text));
|
|
202
|
+
default:
|
|
203
|
+
return tokenOverlapScore(query.tokens, tokenizeSearchText(text));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function scoreLexicalSignals(query, signals) {
|
|
207
|
+
let weightedScore = 0;
|
|
208
|
+
let totalWeight = 0;
|
|
209
|
+
for (const signal of signals) {
|
|
210
|
+
if (!signal.text?.trim() || signal.weight <= 0) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
weightedScore += scoreLexicalSignal(query, signal) * signal.weight;
|
|
214
|
+
totalWeight += signal.weight;
|
|
215
|
+
}
|
|
216
|
+
return totalWeight === 0 ? 0 : weightedScore / totalWeight;
|
|
217
|
+
}
|
|
218
|
+
function rankWindowScore(index, total) {
|
|
219
|
+
if (total <= 1) {
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
const clampedIndex = Math.max(0, Math.min(index, total - 1));
|
|
223
|
+
return 1 - clampedIndex / (total - 1);
|
|
224
|
+
}
|
|
225
|
+
function rerankLexicalWindow(query, items, getText, options) {
|
|
226
|
+
const preparedQuery = prepareLexicalQuery(query);
|
|
227
|
+
if (preparedQuery.tokens.length === 0 || items.length <= 1) {
|
|
228
|
+
return items;
|
|
229
|
+
}
|
|
230
|
+
const lexicalWeight = options?.lexicalWeight ?? 0.65;
|
|
231
|
+
const rankWeight = options?.rankWeight ?? 0.35;
|
|
232
|
+
return items.map((item, index) => {
|
|
233
|
+
const lexicalScore = scoreLexicalSignals(preparedQuery, [
|
|
234
|
+
{ text: getText(item) ?? "", weight: 1, strategy: "tokenOverlap" }
|
|
235
|
+
]);
|
|
236
|
+
const rankScore = rankWindowScore(index, items.length);
|
|
237
|
+
return {
|
|
238
|
+
item,
|
|
239
|
+
combinedScore: lexicalScore * lexicalWeight + rankScore * rankWeight
|
|
240
|
+
};
|
|
241
|
+
}).sort((left, right) => right.combinedScore - left.combinedScore).map(({ item }) => item);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export { bigramTokenize, jaccardSimilarity, prepareLexicalQuery, rankWindowScore, rerankLexicalWindow, scoreLexicalSignal, scoreLexicalSignals, stemToken, tokenOverlapScore, tokenizeSearchText, wordOverlapScore, wordTokenize };
|
|
245
|
+
//# sourceMappingURL=text-matching.js.map
|
|
246
|
+
//# sourceMappingURL=text-matching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../packages/contracts/src/text-matching.contract.ts"],"names":[],"mappings":"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","file":"text-matching.js","sourcesContent":["/**\n * Shared lexical matching primitives used across MCP handlers and graph utilities.\n *\n * The goal is not to replace downstream LLM scoring. It provides a fast,\n * deterministic substrate for candidate generation, reranking, and light\n * classification across belief/question/evidence/entity surfaces.\n */\n\nexport type LexicalStrategy = \"tokenOverlap\" | \"bigramJaccard\" | \"wordOverlap\";\n\nexport type PreparedLexicalQuery = {\n raw: string;\n tokens: string[];\n words: string[];\n bigrams: Set<string>;\n};\n\nexport type LexicalSignal = {\n strategy?: LexicalStrategy;\n text: string | null | undefined;\n weight: number;\n};\n\nexport type LexicalRerankOptions = {\n lexicalWeight?: number;\n rankWeight?: number;\n};\n\nconst TOKEN_SPLIT_REGEX = /[^a-z0-9]+/;\nconst NON_ALPHANUMERIC_REGEX = /[^a-z0-9]/g;\n\n/** Stop words that add noise to scoring. */\nconst STOP_WORDS = new Set([\n \"the\",\n \"a\",\n \"an\",\n \"and\",\n \"or\",\n \"but\",\n \"in\",\n \"on\",\n \"at\",\n \"to\",\n \"for\",\n \"of\",\n \"with\",\n \"by\",\n \"from\",\n \"is\",\n \"it\",\n \"as\",\n \"be\",\n \"was\",\n \"are\",\n \"this\",\n \"that\",\n \"has\",\n \"had\",\n \"have\",\n \"not\",\n \"all\",\n \"can\",\n \"do\",\n \"its\",\n \"may\",\n \"will\",\n \"how\",\n \"what\",\n \"which\",\n \"who\",\n \"when\",\n \"where\",\n \"than\",\n \"then\",\n \"each\",\n \"into\",\n \"such\",\n \"any\",\n \"been\",\n \"if\",\n \"would\",\n \"about\",\n \"should\",\n \"these\",\n \"those\",\n \"their\",\n \"we\",\n \"our\",\n \"so\",\n]);\n\n/** Tokenize a string into lowercase words, removing stop words. */\nexport function tokenizeSearchText(text: string): string[] {\n return text\n .toLowerCase()\n .split(TOKEN_SPLIT_REGEX)\n .filter((token) => token.length >= 2 && !STOP_WORDS.has(token));\n}\n\n/** Simple stemmer: strip common English suffixes for fuzzy matching. */\nexport function stemToken(word: string): string {\n if (word.length <= 4) {\n return word;\n }\n if (word.endsWith(\"ation\")) {\n return word.slice(0, -5);\n }\n if (word.endsWith(\"ment\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"ness\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"ical\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"tion\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"sion\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"ing\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ous\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ive\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ity\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ics\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ly\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"ed\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"er\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"es\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"al\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"ic\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"s\") && !word.endsWith(\"ss\")) {\n return word.slice(0, -1);\n }\n return word;\n}\n\n/** Compute token overlap score between query tokens and text tokens. */\nexport function tokenOverlapScore(\n queryTokens: string[],\n textTokens: string[]\n): number {\n if (queryTokens.length === 0 || textTokens.length === 0) {\n return 0;\n }\n\n const stemmedText = new Set(textTokens.map(stemToken));\n let matchCount = 0;\n\n for (const queryToken of queryTokens) {\n const stemmedQuery = stemToken(queryToken);\n\n if (stemmedText.has(stemmedQuery)) {\n matchCount += 1;\n continue;\n }\n\n for (const textToken of stemmedText) {\n if (\n textToken.startsWith(stemmedQuery) ||\n stemmedQuery.startsWith(textToken)\n ) {\n matchCount += 0.5;\n break;\n }\n }\n }\n\n return matchCount / queryTokens.length;\n}\n\n/**\n * Extract character bigrams from text. Normalizes to lowercase, removes\n * non-alphanumeric characters, and generates overlapping pairs.\n */\nexport function bigramTokenize(text: string): Set<string> {\n const normalized = text.toLowerCase().replace(NON_ALPHANUMERIC_REGEX, \"\");\n const bigrams = new Set<string>();\n for (let i = 0; i < normalized.length - 1; i++) {\n bigrams.add(normalized.slice(i, i + 2));\n }\n return bigrams;\n}\n\n/**\n * Extract word-level tokens from text (for coarser matching).\n * Normalizes to lowercase, splits on non-alphanumeric.\n */\nexport function wordTokenize(text: string): string[] {\n return text\n .toLowerCase()\n .split(TOKEN_SPLIT_REGEX)\n .filter((token) => token.length > 1);\n}\n\n/** Jaccard similarity between two sets: |A ∩ B| / |A ∪ B|. */\nexport function jaccardSimilarity(\n setA: Set<string>,\n setB: Set<string>\n): number {\n if (setA.size === 0 && setB.size === 0) {\n return 0;\n }\n\n let intersectionSize = 0;\n const smaller = setA.size <= setB.size ? setA : setB;\n const larger = setA.size <= setB.size ? setB : setA;\n\n for (const item of smaller) {\n if (larger.has(item)) {\n intersectionSize++;\n }\n }\n\n const unionSize = setA.size + setB.size - intersectionSize;\n return unionSize === 0 ? 0 : intersectionSize / unionSize;\n}\n\n/** Exact word overlap score: fraction of type words found in input text. */\nexport function wordOverlapScore(\n inputWords: string[],\n typeWords: string[]\n): number {\n if (typeWords.length === 0) {\n return 0;\n }\n let matches = 0;\n for (const word of typeWords) {\n if (inputWords.includes(word)) {\n matches++;\n }\n }\n return matches / typeWords.length;\n}\n\n/** Pre-compute reusable lexical structures for a query. */\nexport function prepareLexicalQuery(query: string): PreparedLexicalQuery {\n return {\n raw: query,\n tokens: tokenizeSearchText(query),\n words: wordTokenize(query),\n bigrams: bigramTokenize(query),\n };\n}\n\n/** Score a single lexical signal against a prepared query. */\nexport function scoreLexicalSignal(\n query: PreparedLexicalQuery,\n signal: LexicalSignal\n): number {\n const text = signal.text?.trim();\n if (!text) {\n return 0;\n }\n\n switch (signal.strategy ?? \"tokenOverlap\") {\n case \"bigramJaccard\":\n return jaccardSimilarity(query.bigrams, bigramTokenize(text));\n case \"wordOverlap\":\n return wordOverlapScore(query.words, wordTokenize(text));\n default:\n return tokenOverlapScore(query.tokens, tokenizeSearchText(text));\n }\n}\n\n/** Weighted lexical score across multiple textual signals. */\nexport function scoreLexicalSignals(\n query: PreparedLexicalQuery,\n signals: LexicalSignal[]\n): number {\n let weightedScore = 0;\n let totalWeight = 0;\n\n for (const signal of signals) {\n if (!signal.text?.trim() || signal.weight <= 0) {\n continue;\n }\n weightedScore += scoreLexicalSignal(query, signal) * signal.weight;\n totalWeight += signal.weight;\n }\n\n return totalWeight === 0 ? 0 : weightedScore / totalWeight;\n}\n\n/** Map a candidate's original rank position into a 0..1 prior. */\nexport function rankWindowScore(index: number, total: number): number {\n if (total <= 1) {\n return 1;\n }\n const clampedIndex = Math.max(0, Math.min(index, total - 1));\n return 1 - clampedIndex / (total - 1);\n}\n\n/** Rerank a candidate window by lexical overlap while preserving original-rank prior. */\nexport function rerankLexicalWindow<T>(\n query: string,\n items: T[],\n getText: (item: T) => string | null | undefined,\n options?: LexicalRerankOptions\n): T[] {\n const preparedQuery = prepareLexicalQuery(query);\n if (preparedQuery.tokens.length === 0 || items.length <= 1) {\n return items;\n }\n\n const lexicalWeight = options?.lexicalWeight ?? 0.65;\n const rankWeight = options?.rankWeight ?? 0.35;\n\n return items\n .map((item, index) => {\n const lexicalScore = scoreLexicalSignals(preparedQuery, [\n { text: getText(item) ?? \"\", weight: 1, strategy: \"tokenOverlap\" },\n ]);\n const rankScore = rankWindowScore(index, items.length);\n\n return {\n item,\n combinedScore: lexicalScore * lexicalWeight + rankScore * rankWeight,\n };\n })\n .sort((left, right) => right.combinedScore - left.combinedScore)\n .map(({ item }) => item);\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Id } from './convex.js';
|
|
2
|
+
import 'convex/values';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Topic Ontology Resolution — Hybrid Inheritance
|
|
6
|
+
*
|
|
7
|
+
* Resolves the effective ontology for a topic by walking the parent chain.
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
* - If the topic has an ontologyId, return its ontology definition.
|
|
11
|
+
* - Otherwise, walk up the parent chain until an ancestor with an ontologyId is found.
|
|
12
|
+
* - Returns null if no ancestor in the chain has an ontology binding.
|
|
13
|
+
*
|
|
14
|
+
* This is a helper function callable from within Convex mutation/query handlers.
|
|
15
|
+
* For the public query API, see topics.resolveTopicOntology.
|
|
16
|
+
*
|
|
17
|
+
* @module graph-primitives/topicOntologyResolver
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
type OntologyVer = {
|
|
21
|
+
_id: Id<"ontologyVersions">;
|
|
22
|
+
ontologyId: Id<"ontologyDefinitions">;
|
|
23
|
+
version: string;
|
|
24
|
+
status: "draft" | "published" | "deprecated";
|
|
25
|
+
entityTypes: Array<{
|
|
26
|
+
value: string;
|
|
27
|
+
label: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
}>;
|
|
30
|
+
edgeTypes: Array<{
|
|
31
|
+
value: string;
|
|
32
|
+
label: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
}>;
|
|
35
|
+
publishedAt?: number;
|
|
36
|
+
};
|
|
37
|
+
type ResolvedTopicOntology = {
|
|
38
|
+
ontologyId: Id<"ontologyDefinitions">;
|
|
39
|
+
ontologyKey: string;
|
|
40
|
+
ontologyName: string;
|
|
41
|
+
tier: string;
|
|
42
|
+
source: "direct" | "inherited";
|
|
43
|
+
sourceTopicId: Id<"topics">;
|
|
44
|
+
/** Valid entity type values from the latest published version */
|
|
45
|
+
validEntityTypes: string[];
|
|
46
|
+
/** Valid edge type values from the latest published version */
|
|
47
|
+
validEdgeTypes: string[];
|
|
48
|
+
/** The published version, if any */
|
|
49
|
+
publishedVersion: OntologyVer | null;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the effective ontology for a topic.
|
|
53
|
+
*
|
|
54
|
+
* @param ctx - Convex mutation/query context with db access
|
|
55
|
+
* @param topicId - The topic to resolve the ontology for
|
|
56
|
+
* @returns The resolved ontology or null if none is bound in the ancestor chain
|
|
57
|
+
*/
|
|
58
|
+
declare function resolveTopicOntologyInternal(ctx: {
|
|
59
|
+
db: any;
|
|
60
|
+
}, topicId: Id<"topics">): Promise<ResolvedTopicOntology | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Validate that a nodeType is allowed by the resolved ontology for a topic.
|
|
63
|
+
*
|
|
64
|
+
* Returns { valid: true } if:
|
|
65
|
+
* - The topic has no bound ontology (no constraint)
|
|
66
|
+
* - The nodeType is in the ontology's published entity types
|
|
67
|
+
*
|
|
68
|
+
* Returns { valid: false, error } if:
|
|
69
|
+
* - The topic has a bound ontology and the nodeType is not in its entity types
|
|
70
|
+
*/
|
|
71
|
+
declare function validateEntityTypeForTopic(ctx: {
|
|
72
|
+
db: any;
|
|
73
|
+
}, topicId: Id<"topics">, nodeType: string): Promise<{
|
|
74
|
+
valid: true;
|
|
75
|
+
} | {
|
|
76
|
+
valid: false;
|
|
77
|
+
error: string;
|
|
78
|
+
}>;
|
|
79
|
+
|
|
80
|
+
export { type ResolvedTopicOntology, resolveTopicOntologyInternal, validateEntityTypeForTopic };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/topicOntologyResolver.ts
|
|
2
|
+
var MAX_RESOLUTION_DEPTH = 10;
|
|
3
|
+
async function resolveTopicOntologyInternal(ctx, topicId) {
|
|
4
|
+
let current = await ctx.db.get(topicId);
|
|
5
|
+
if (!current) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const startTopicId = topicId;
|
|
9
|
+
for (let i = 0; i < MAX_RESOLUTION_DEPTH && current; i++) {
|
|
10
|
+
if (current.ontologyId) {
|
|
11
|
+
const ontologyDef = await ctx.db.get(
|
|
12
|
+
current.ontologyId
|
|
13
|
+
);
|
|
14
|
+
if (!ontologyDef || ontologyDef.status === "archived") {
|
|
15
|
+
if (current.parentTopicId) {
|
|
16
|
+
current = await ctx.db.get(
|
|
17
|
+
current.parentTopicId
|
|
18
|
+
);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const versions = await ctx.db.query("ontologyVersions").withIndex(
|
|
24
|
+
"by_ontologyId",
|
|
25
|
+
(q) => q.eq("ontologyId", current?.ontologyId)
|
|
26
|
+
).collect();
|
|
27
|
+
const published = versions.filter((v) => v.status === "published").sort((a, b) => (b.publishedAt ?? 0) - (a.publishedAt ?? 0));
|
|
28
|
+
const latestPublished = published[0] ?? null;
|
|
29
|
+
return {
|
|
30
|
+
ontologyId: ontologyDef._id,
|
|
31
|
+
ontologyKey: ontologyDef.ontologyKey,
|
|
32
|
+
ontologyName: ontologyDef.name,
|
|
33
|
+
tier: ontologyDef.tier,
|
|
34
|
+
source: current._id === startTopicId ? "direct" : "inherited",
|
|
35
|
+
sourceTopicId: current._id,
|
|
36
|
+
validEntityTypes: latestPublished ? latestPublished.entityTypes.map((et) => et.value) : [],
|
|
37
|
+
validEdgeTypes: latestPublished ? latestPublished.edgeTypes.map((et) => et.value) : [],
|
|
38
|
+
publishedVersion: latestPublished
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (!current.parentTopicId) {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
current = await ctx.db.get(current.parentTopicId);
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
async function validateEntityTypeForTopic(ctx, topicId, nodeType) {
|
|
49
|
+
const resolved = await resolveTopicOntologyInternal(ctx, topicId);
|
|
50
|
+
if (!resolved) {
|
|
51
|
+
return { valid: true };
|
|
52
|
+
}
|
|
53
|
+
if (resolved.validEntityTypes.length === 0) {
|
|
54
|
+
return { valid: true };
|
|
55
|
+
}
|
|
56
|
+
if (resolved.validEntityTypes.includes(nodeType)) {
|
|
57
|
+
return { valid: true };
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
valid: false,
|
|
61
|
+
error: `Entity type "${nodeType}" is not defined in the ontology "${resolved.ontologyKey}" (${resolved.ontologyName}). Valid entity types: ${resolved.validEntityTypes.join(", ")}. Source: ${resolved.source} from topic ${resolved.sourceTopicId}.`
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { resolveTopicOntologyInternal, validateEntityTypeForTopic };
|
|
66
|
+
//# sourceMappingURL=topicOntologyResolver.js.map
|
|
67
|
+
//# sourceMappingURL=topicOntologyResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/topicOntologyResolver.ts"],"names":[],"mappings":"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","file":"topicOntologyResolver.js","sourcesContent":["/**\n * Topic Ontology Resolution — Hybrid Inheritance\n *\n * Resolves the effective ontology for a topic by walking the parent chain.\n *\n * Strategy:\n * - If the topic has an ontologyId, return its ontology definition.\n * - Otherwise, walk up the parent chain until an ancestor with an ontologyId is found.\n * - Returns null if no ancestor in the chain has an ontology binding.\n *\n * This is a helper function callable from within Convex mutation/query handlers.\n * For the public query API, see topics.resolveTopicOntology.\n *\n * @module graph-primitives/topicOntologyResolver\n */\n\nimport type { Id } from \"./convex\";\n\n// Minimal topic shape needed for resolution (avoids importing full generated types)\ntype TopicDoc = {\n _id: Id<\"topics\">;\n name: string;\n depth: number;\n ontologyId?: Id<\"ontologyDefinitions\">;\n parentTopicId?: Id<\"topics\">;\n};\n\ntype OntologyDef = {\n _id: Id<\"ontologyDefinitions\">;\n ontologyKey: string;\n name: string;\n tier: \"platform\" | \"pack\" | \"tenant\";\n status: \"draft\" | \"active\" | \"deprecated\" | \"archived\";\n};\n\ntype OntologyVer = {\n _id: Id<\"ontologyVersions\">;\n ontologyId: Id<\"ontologyDefinitions\">;\n version: string;\n status: \"draft\" | \"published\" | \"deprecated\";\n entityTypes: Array<{ value: string; label: string; description?: string }>;\n edgeTypes: Array<{ value: string; label: string; description?: string }>;\n publishedAt?: number;\n};\n\nexport type ResolvedTopicOntology = {\n ontologyId: Id<\"ontologyDefinitions\">;\n ontologyKey: string;\n ontologyName: string;\n tier: string;\n source: \"direct\" | \"inherited\";\n sourceTopicId: Id<\"topics\">;\n /** Valid entity type values from the latest published version */\n validEntityTypes: string[];\n /** Valid edge type values from the latest published version */\n validEdgeTypes: string[];\n /** The published version, if any */\n publishedVersion: OntologyVer | null;\n};\n\nconst MAX_RESOLUTION_DEPTH = 10;\n\n/**\n * Resolve the effective ontology for a topic.\n *\n * @param ctx - Convex mutation/query context with db access\n * @param topicId - The topic to resolve the ontology for\n * @returns The resolved ontology or null if none is bound in the ancestor chain\n */\nexport async function resolveTopicOntologyInternal(\n ctx: { db: any },\n topicId: Id<\"topics\">\n): Promise<ResolvedTopicOntology | null> {\n let current = (await ctx.db.get(topicId)) as TopicDoc | null;\n if (!current) {\n return null;\n }\n\n const startTopicId = topicId;\n\n for (let i = 0; i < MAX_RESOLUTION_DEPTH && current; i++) {\n if (current.ontologyId) {\n const ontologyDef = (await ctx.db.get(\n current.ontologyId\n )) as OntologyDef | null;\n if (!ontologyDef || ontologyDef.status === \"archived\") {\n // Ontology was archived or deleted — continue walking up\n if (current.parentTopicId) {\n current = (await ctx.db.get(\n current.parentTopicId\n )) as TopicDoc | null;\n continue;\n }\n return null;\n }\n\n // Fetch the latest published version for this ontology\n const versions = (await ctx.db\n .query(\"ontologyVersions\")\n .withIndex(\"by_ontologyId\", (q: any) =>\n q.eq(\"ontologyId\", current?.ontologyId!)\n )\n .collect()) as OntologyVer[];\n\n const published = versions\n .filter((v) => v.status === \"published\")\n .sort((a, b) => (b.publishedAt ?? 0) - (a.publishedAt ?? 0));\n\n const latestPublished = published[0] ?? null;\n\n return {\n ontologyId: ontologyDef._id,\n ontologyKey: ontologyDef.ontologyKey,\n ontologyName: ontologyDef.name,\n tier: ontologyDef.tier,\n source: current._id === startTopicId ? \"direct\" : \"inherited\",\n sourceTopicId: current._id,\n validEntityTypes: latestPublished\n ? latestPublished.entityTypes.map((et) => et.value)\n : [],\n validEdgeTypes: latestPublished\n ? latestPublished.edgeTypes.map((et) => et.value)\n : [],\n publishedVersion: latestPublished,\n };\n }\n\n // No ontologyId on this topic — walk up\n if (!current.parentTopicId) {\n break;\n }\n current = (await ctx.db.get(current.parentTopicId)) as TopicDoc | null;\n }\n\n return null;\n}\n\n/**\n * Validate that a nodeType is allowed by the resolved ontology for a topic.\n *\n * Returns { valid: true } if:\n * - The topic has no bound ontology (no constraint)\n * - The nodeType is in the ontology's published entity types\n *\n * Returns { valid: false, error } if:\n * - The topic has a bound ontology and the nodeType is not in its entity types\n */\nexport async function validateEntityTypeForTopic(\n ctx: { db: any },\n topicId: Id<\"topics\">,\n nodeType: string\n): Promise<{ valid: true } | { valid: false; error: string }> {\n const resolved = await resolveTopicOntologyInternal(ctx, topicId);\n\n // No ontology bound — all entity types are allowed\n if (!resolved) {\n return { valid: true };\n }\n\n // No published version — ontology exists but has no content yet, allow all\n if (resolved.validEntityTypes.length === 0) {\n return { valid: true };\n }\n\n // Check if nodeType is in the ontology's entity types\n if (resolved.validEntityTypes.includes(nodeType)) {\n return { valid: true };\n }\n\n return {\n valid: false,\n error: `Entity type \"${nodeType}\" is not defined in the ontology \"${resolved.ontologyKey}\" (${resolved.ontologyName}). Valid entity types: ${resolved.validEntityTypes.join(\", \")}. Source: ${resolved.source} from topic ${resolved.sourceTopicId}.`,\n };\n}\n"]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
type OverlayIdMode = "legacy" | "topic";
|
|
2
|
+
type LegacyProjectThesis = {
|
|
3
|
+
statement: string;
|
|
4
|
+
confidence: number;
|
|
5
|
+
lastUpdated: number;
|
|
6
|
+
};
|
|
7
|
+
type LegacyPillarImportance = "critical" | "major" | "minor" | "not_applicable";
|
|
8
|
+
type LegacyThesisPillarConfig = {
|
|
9
|
+
pillarImportance?: Record<string, LegacyPillarImportance | undefined>;
|
|
10
|
+
configuredAt?: number;
|
|
11
|
+
configuredBy?: string;
|
|
12
|
+
aiSuggestion?: {
|
|
13
|
+
suggestedAt: number;
|
|
14
|
+
reasoning: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
type LegacyBeliefArchitecture = {
|
|
18
|
+
overallMaturity: number;
|
|
19
|
+
pillarScores: Array<Record<string, unknown>>;
|
|
20
|
+
lastCalculated: number;
|
|
21
|
+
};
|
|
22
|
+
type LegacyOntologyClassification = {
|
|
23
|
+
valueChains: Array<Record<string, unknown>>;
|
|
24
|
+
functions: Array<Record<string, unknown>>;
|
|
25
|
+
overallConfidence: number;
|
|
26
|
+
classifiedAt: number;
|
|
27
|
+
};
|
|
28
|
+
type TopicDocLike = Record<string, unknown> & {
|
|
29
|
+
_id: string;
|
|
30
|
+
_creationTime?: number;
|
|
31
|
+
globalId?: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
type?: string;
|
|
35
|
+
tenantId?: string;
|
|
36
|
+
workspaceId?: string;
|
|
37
|
+
status?: string;
|
|
38
|
+
visibility?: string;
|
|
39
|
+
createdBy?: string;
|
|
40
|
+
createdAt?: number;
|
|
41
|
+
updatedAt?: number;
|
|
42
|
+
metadata?: Record<string, unknown>;
|
|
43
|
+
};
|
|
44
|
+
type TopicProjectOverlay = Record<string, unknown> & {
|
|
45
|
+
_id: string;
|
|
46
|
+
projectId: string;
|
|
47
|
+
topicId: string;
|
|
48
|
+
storageProjectId: string;
|
|
49
|
+
legacyProjectId?: string;
|
|
50
|
+
name: string;
|
|
51
|
+
type: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
ownerId: string;
|
|
54
|
+
sharedWith: string[];
|
|
55
|
+
visibility: "private" | "team" | "firm" | "external" | "public";
|
|
56
|
+
tenantId?: string;
|
|
57
|
+
workspaceId?: string;
|
|
58
|
+
status: "active" | "archived" | "watching";
|
|
59
|
+
tags: string[];
|
|
60
|
+
chatCount: number;
|
|
61
|
+
artifactCount: number;
|
|
62
|
+
lastActivityAt: number;
|
|
63
|
+
thesis?: LegacyProjectThesis;
|
|
64
|
+
wedgeHypothesis?: string;
|
|
65
|
+
founderArchetype?: string;
|
|
66
|
+
investmentCriteria?: string[];
|
|
67
|
+
sprintPhase?: "pre_sprint" | "readiness_check" | "thesis_crystallization" | "sprint_planning" | "active_sprint" | "theme_assembly" | "evolution";
|
|
68
|
+
currentSprintIndex?: number;
|
|
69
|
+
thesisPillarConfig?: LegacyThesisPillarConfig;
|
|
70
|
+
beliefArchitecture?: LegacyBeliefArchitecture;
|
|
71
|
+
ontologyClassification?: LegacyOntologyClassification;
|
|
72
|
+
_creationTime: number;
|
|
73
|
+
createdAt: number;
|
|
74
|
+
updatedAt: number;
|
|
75
|
+
};
|
|
76
|
+
declare function materializeTopicProjectOverlay(topic: TopicDocLike, idMode?: OverlayIdMode): TopicProjectOverlay;
|
|
77
|
+
declare function resolveTopicProjectOverlay(ctx: any, scopeId: string, options?: {
|
|
78
|
+
idMode?: OverlayIdMode;
|
|
79
|
+
projectLikeOnly?: boolean;
|
|
80
|
+
}): Promise<TopicProjectOverlay | null>;
|
|
81
|
+
declare function listTopicProjectOverlays(ctx: any, options?: {
|
|
82
|
+
idMode?: OverlayIdMode;
|
|
83
|
+
projectLikeOnly?: boolean;
|
|
84
|
+
}): Promise<TopicProjectOverlay[]>;
|
|
85
|
+
declare function patchTopicProjectOverlay(ctx: any, scopeId: string, value: Record<string, unknown>): Promise<TopicProjectOverlay | null>;
|
|
86
|
+
declare function matchesTopicProjectOverlayAccess(accessibleProjectIds: Set<string>, project: {
|
|
87
|
+
topicId: string;
|
|
88
|
+
legacyProjectId?: string;
|
|
89
|
+
storageProjectId?: string;
|
|
90
|
+
}): boolean;
|
|
91
|
+
|
|
92
|
+
export { type TopicProjectOverlay, listTopicProjectOverlays, matchesTopicProjectOverlayAccess, materializeTopicProjectOverlay, patchTopicProjectOverlay, resolveTopicProjectOverlay };
|