@lucern/mcp 0.3.0-alpha.2 → 0.3.0-alpha.3

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/dist/runtime.js CHANGED
@@ -3,10 +3,6 @@ import * as path2 from 'path';
3
3
  import { basename, extname } from 'path';
4
4
  import { z } from 'zod';
5
5
  import { v } from 'convex/values';
6
- import { internal, components, api as api$1 } from '@lucern/reasoning-kernel/adapters/convex';
7
- import 'stream';
8
- import { AsyncLocalStorage } from 'async_hooks';
9
- import { ConvexHttpClient } from 'convex/browser';
10
6
  import 'crypto';
11
7
  import * as os from 'os';
12
8
 
@@ -2054,6 +2050,40 @@ defineTable({
2054
2050
  { kind: "index", name: "by_tier_window_end", columns: ["tier", "windowEndMs"] }
2055
2051
  ]
2056
2052
  });
2053
+ defineTable({
2054
+ name: "oauthDeviceCodes",
2055
+ component: "mc",
2056
+ category: "identity",
2057
+ shape: z.object({
2058
+ "deviceCodeHash": z.string(),
2059
+ "userCode": z.string(),
2060
+ "clientId": z.string(),
2061
+ "scope": z.string(),
2062
+ "status": z.enum(["pending", "approved", "denied", "expired", "consumed"]),
2063
+ "expiresAt": z.number(),
2064
+ "intervalSeconds": z.number(),
2065
+ "lastPolledAt": z.number().optional(),
2066
+ "slowDownCount": z.number().optional(),
2067
+ "clerkUserId": z.string().optional(),
2068
+ "tenantId": idOf("tenants").optional(),
2069
+ "workspaceId": z.string().optional(),
2070
+ "principalId": z.string().optional(),
2071
+ "role": z.string().optional(),
2072
+ "scopes": z.array(z.string()).optional(),
2073
+ "sessionId": z.string().optional(),
2074
+ "approvedAt": z.number().optional(),
2075
+ "deniedAt": z.number().optional(),
2076
+ "consumedAt": z.number().optional(),
2077
+ "createdAt": z.number(),
2078
+ "updatedAt": z.number()
2079
+ }),
2080
+ indices: [
2081
+ { kind: "index", name: "by_deviceCodeHash", columns: ["deviceCodeHash"] },
2082
+ { kind: "index", name: "by_userCode", columns: ["userCode"] },
2083
+ { kind: "index", name: "by_status_expiresAt", columns: ["status", "expiresAt"] },
2084
+ { kind: "index", name: "by_sessionId", columns: ["sessionId"] }
2085
+ ]
2086
+ });
2057
2087
  defineTable({
2058
2088
  name: "servicePrincipalKeys",
2059
2089
  component: "mc",
@@ -11680,354 +11710,14 @@ new Map(
11680
11710
  // ../contracts/src/v1/topics/v1.ts
11681
11711
  var ROOT_TOPIC_ID = "n17tm38rwet7wqgzrmwahyt1z582590y";
11682
11712
 
11683
- // ../server-core/src/kernelApi.ts
11684
- var REQUIRED_KERNEL_API_REF_SUFFIXES = [
11685
- "contradictions.create",
11686
- "contradictions.getById",
11687
- "contradictions.getByTopic",
11688
- "epistemicAnswers.create",
11689
- "epistemicAnswers.getLatestForQuestion",
11690
- "epistemicBeliefs.archive",
11691
- "epistemicBeliefs.batchUpdateCriticality",
11692
- "epistemicBeliefs.create",
11693
- "epistemicBeliefs.forkBelief",
11694
- "epistemicBeliefs.getById",
11695
- "epistemicBeliefs.getByTopic",
11696
- "epistemicBeliefs.getConfidenceHistory",
11697
- "epistemicBeliefs.getLineage",
11698
- "epistemicBeliefs.getRelationships",
11699
- "epistemicBeliefs.linkBeliefs",
11700
- "epistemicBeliefs.linkEvidence",
11701
- "epistemicBeliefs.modulateConfidence",
11702
- "epistemicBeliefs.reassignBeliefsTopic",
11703
- "epistemicBeliefs.refineBelief",
11704
- "epistemicBeliefs.unlinkEvidence",
11705
- "epistemicBeliefs.updateCriticality",
11706
- "epistemicBeliefs.updateRationale",
11707
- "epistemicBeliefs.updateStatus",
11708
- "epistemicContracts.createEpistemicContract",
11709
- "epistemicContracts.evaluateContract",
11710
- "epistemicContracts.getContractStatus",
11711
- "epistemicEdges.batchCreate",
11712
- "epistemicEdges.create",
11713
- "epistemicEdges.deleteEdges",
11714
- "epistemicEdges.getBySourceNode",
11715
- "epistemicEdges.getByTopicAndType",
11716
- "epistemicEdges.remove",
11717
- "epistemicEdges.removeBetween",
11718
- "epistemicEdges.update",
11719
- "epistemicEvidence.create",
11720
- "epistemicEvidence.flagAsIncorrect",
11721
- "epistemicEvidence.getById",
11722
- "epistemicEvidence.getByTopic",
11723
- "epistemicEvidence.getForBelief",
11724
- "epistemicEvidence.remove",
11725
- "epistemicEvidence.update",
11726
- "epistemicEvidence.updateStatus",
11727
- "epistemicEvidence.updateVerificationStatus",
11728
- "epistemicNodes.get",
11729
- "epistemicNodes.getByGlobalId",
11730
- "epistemicQuestions.addQuestion",
11731
- "epistemicQuestions.advanceToConviction",
11732
- "epistemicQuestions.create",
11733
- "epistemicQuestions.createBatch",
11734
- "epistemicQuestions.deleteQuestion",
11735
- "epistemicQuestions.finalizeConviction",
11736
- "epistemicQuestions.getById",
11737
- "epistemicQuestions.getByTopic",
11738
- "epistemicQuestions.internalCreate",
11739
- "epistemicQuestions.updateConviction",
11740
- "epistemicQuestions.updatePriority",
11741
- "epistemicQuestions.updateQuestion",
11742
- "epistemicQuestions.updateStatus",
11743
- "evidenceClassifier.classifyEvidence",
11744
- "evidenceClassifier.classifyEvidenceBatch",
11745
- "graphAnalysisCache.getCachedAnalysis",
11746
- "graphIntelligence.analyzeProject",
11747
- "neo4jEdgeAPI.getGraphNeighborhood",
11748
- "neo4jQueries.getConfirmationBiasScore",
11749
- "ontologyDefinitions.archiveOntologyDefinition",
11750
- "ontologyDefinitions.createOntologyDefinition",
11751
- "ontologyDefinitions.createOntologyVersion",
11752
- "ontologyDefinitions.deprecateOntologyVersion",
11753
- "ontologyDefinitions.getOntologyDefinition",
11754
- "ontologyDefinitions.getOntologyDefinitionByKey",
11755
- "ontologyDefinitions.getPublishedVersion",
11756
- "ontologyDefinitions.listOntologyDefinitions",
11757
- "ontologyDefinitions.publishOntologyVersion",
11758
- "ontologyDefinitions.resolveEffectiveOntology",
11759
- "ontologyDefinitions.updateOntologyDefinition",
11760
- "policy.filterByPermission",
11761
- "questionEvidenceLinks.create",
11762
- "questionEvidenceLinks.getEvidenceWithDetails",
11763
- "tasks.complete",
11764
- "tasks.create",
11765
- "tasks.get",
11766
- "tasks.getByTopic",
11767
- "tasks.getByWorktree",
11768
- "tasks.update",
11769
- "topics.bulkCreate",
11770
- "topics.checkAccess",
11771
- "topics.create",
11772
- "topics.get",
11773
- "topics.getTree",
11774
- "topics.list",
11775
- "topics.listByOntology",
11776
- "topics.remove",
11777
- "topics.resolveTopicOntology",
11778
- "topics.update",
11779
- "worktrees.activate",
11780
- "worktrees.advancePhase",
11781
- "worktrees.bulkCreate",
11782
- "worktrees.complete",
11783
- "worktrees.create",
11784
- "worktrees.get",
11785
- "worktrees.list",
11786
- "worktrees.listAll",
11787
- "worktrees.patchState",
11788
- "worktrees.setPhase",
11789
- "worktrees.updateMetadata",
11790
- "worktrees.updateTargets"
11791
- ];
11792
- var KERNEL_API_REF_MANIFEST = REQUIRED_KERNEL_API_REF_SUFFIXES.map((path3) => ({
11793
- path: `api.${path3}`,
11794
- componentPath: `components.lucern.${path3}`
11795
- }));
11796
- var GLOBAL_KEY = "__LUCERN_SERVER_CORE_KERNEL_API_BINDING__";
11797
- function store() {
11798
- return globalThis;
11799
- }
11800
- function registerKernelApi(nextBinding) {
11801
- assertKernelApiBinding(nextBinding);
11802
- store()[GLOBAL_KEY] = nextBinding;
11803
- }
11804
- function getBinding() {
11805
- const current = store()[GLOBAL_KEY];
11806
- if (!current) {
11807
- throw new Error(
11808
- "Server-core kernelApi not registered. Call registerKernelApi({api, components, internal}) at host boot."
11809
- );
11810
- }
11811
- return current;
11812
- }
11813
- function readPath(root, path3) {
11814
- let cursor = root;
11815
- for (const part of path3) {
11816
- if (cursor == null || typeof cursor !== "object") {
11817
- return void 0;
11818
- }
11819
- cursor = cursor[part];
11820
- }
11821
- return cursor;
11822
- }
11823
- function resolveApiPath(binding, which, path3) {
11824
- return readPath(binding[which], path3);
11825
- }
11826
- function validateKernelApiBinding(binding) {
11827
- const missing = [];
11828
- const resolved = [];
11829
- for (const entry of KERNEL_API_REF_MANIFEST) {
11830
- const suffix = entry.path.split(".").slice(1);
11831
- const reference = resolveApiPath(binding, "api", suffix);
11832
- if (reference === void 0) {
11833
- missing.push(entry);
11834
- } else {
11835
- resolved.push(entry);
11836
- }
11837
- }
11838
- return {
11839
- ok: missing.length === 0,
11840
- missing,
11841
- resolved
11842
- };
11843
- }
11844
- function assertKernelApiBinding(binding) {
11845
- const result = validateKernelApiBinding(binding);
11846
- if (!result.ok) {
11847
- const refs = result.missing.map((entry) => entry.path).join(", ");
11848
- throw new Error(
11849
- `Server-core kernelApi binding is missing required refs: ${refs}`
11850
- );
11851
- }
11852
- }
11853
- function makeProxy(which, path3 = []) {
11854
- return new Proxy({}, {
11855
- get(_target, prop) {
11856
- if (typeof prop !== "string") {
11857
- return void 0;
11858
- }
11859
- const nextPath = [...path3, prop];
11860
- const resolved = resolveApiPath(getBinding(), which, nextPath);
11861
- return resolved === void 0 ? makeProxy(which, nextPath) : resolved;
11862
- }
11863
- });
11864
- }
11865
- var api = makeProxy("api");
11866
- makeProxy("components");
11867
- makeProxy("internal");
11868
-
11869
- // ../../apps/mcp-server/src/kernelApi.ts
11870
- registerKernelApi({
11871
- api: api$1,
11872
- components: components,
11873
- internal: internal
11713
+ // ../../apps/mcp-server/src/runtime-context.ts
11714
+ var runtimeContext = Object.freeze({
11715
+ transportKind: "stdio"
11874
11716
  });
11875
- var api2 = api$1;
11876
- var components2 = components;
11877
- function isQuietMcpBoot() {
11878
- return process.env.LUCERN_MCP_QUIET === "1";
11879
- }
11880
- function logMcpInfo(message) {
11881
- if (!isQuietMcpBoot()) {
11882
- console.error(message);
11883
- }
11717
+ function getMcpRuntimeContext() {
11718
+ return runtimeContext;
11884
11719
  }
11885
11720
 
11886
- // ../../apps/mcp-server/src/convex-client.ts
11887
- var _requestScopedClient = new AsyncLocalStorage();
11888
- function runWithScopedClient(client, fn) {
11889
- return _requestScopedClient.run(client, fn);
11890
- }
11891
- function createAdminClient(url, deployKey) {
11892
- const client = new ConvexHttpClient(url);
11893
- client.setAdminAuth(deployKey);
11894
- return client;
11895
- }
11896
- var _lucernClient = null;
11897
- function getLucernClient() {
11898
- const scoped = _requestScopedClient.getStore();
11899
- if (scoped) {
11900
- return scoped;
11901
- }
11902
- if (_lucernClient) {
11903
- return _lucernClient;
11904
- }
11905
- const url = process.env.LUCERN_CONVEX_URL;
11906
- const key = process.env.LUCERN_DEPLOY_KEY;
11907
- if (!url) {
11908
- throw new Error(
11909
- "LUCERN_CONVEX_URL is required. Ensure LUCERN_API_KEY is set in .env.lucern"
11910
- );
11911
- }
11912
- if (!key) {
11913
- throw new Error(
11914
- "LUCERN_DEPLOY_KEY is required. Ensure LUCERN_API_KEY is set in .env.lucern"
11915
- );
11916
- }
11917
- _lucernClient = new ConvexHttpClient(url);
11918
- _lucernClient.setAdminAuth(key);
11919
- logMcpInfo(`[lucern-graph] Lucern client initialized \u2192 ${url}`);
11920
- return _lucernClient;
11921
- }
11922
- var MCP_META_KEYS = [
11923
- "mcpSessionId",
11924
- "mcpToolName",
11925
- "runtimeToolName",
11926
- "runtimePackKey",
11927
- "runtimePackInstallScope"
11928
- ];
11929
- var mutationRuntimeCache = /* @__PURE__ */ new Map();
11930
- var packInstallScopeCache = /* @__PURE__ */ new Map();
11931
- async function resolvePackInstallScope(packKey) {
11932
- const normalizedPackKey = packKey.trim();
11933
- if (!normalizedPackKey) {
11934
- return;
11935
- }
11936
- let cached = packInstallScopeCache.get(normalizedPackKey);
11937
- if (!cached) {
11938
- cached = (async () => {
11939
- const packDefinition = await mcAdminQuery(
11940
- "packs:getPackDefinition",
11941
- {
11942
- packKey: normalizedPackKey
11943
- }
11944
- );
11945
- const installScope = packDefinition?.installScope;
11946
- if (installScope === "tenant" || installScope === "workspace") {
11947
- return installScope;
11948
- }
11949
- throw new Error(
11950
- `[mcp-runtime] Pack "${normalizedPackKey}" is missing a valid installScope`
11951
- );
11952
- })();
11953
- packInstallScopeCache.set(normalizedPackKey, cached);
11954
- }
11955
- return await cached;
11956
- }
11957
- async function resolveMutationRuntimeFields(toolName) {
11958
- if (typeof toolName !== "string" || toolName.trim().length === 0) {
11959
- return null;
11960
- }
11961
- const normalizedToolName = toolName.trim();
11962
- let cached = mutationRuntimeCache.get(normalizedToolName);
11963
- if (!cached) {
11964
- cached = (async () => {
11965
- const tools = await adminQuery("toolAccess:listToolRegistry", {});
11966
- const tool = tools.find(
11967
- (candidate) => candidate?.toolName === normalizedToolName && candidate?.isActive !== false && candidate?.status !== "deprecated" && candidate?.status !== "disabled"
11968
- );
11969
- const packKey = typeof tool?.packKey === "string" ? tool.packKey.trim() : "";
11970
- if (!packKey) {
11971
- return { runtimeToolName: normalizedToolName };
11972
- }
11973
- return {
11974
- runtimeToolName: normalizedToolName,
11975
- runtimePackKey: packKey,
11976
- runtimePackInstallScope: await resolvePackInstallScope(packKey)
11977
- };
11978
- })();
11979
- mutationRuntimeCache.set(normalizedToolName, cached);
11980
- }
11981
- return await cached;
11982
- }
11983
- async function adminMutation(fn, args) {
11984
- const cleanArgs = { ...args };
11985
- if (cleanArgs.runtimeToolName === void 0 && cleanArgs.runtimePackKey === void 0 && cleanArgs.runtimePackInstallScope === void 0) {
11986
- const runtimeFields = await resolveMutationRuntimeFields(args?.mcpToolName);
11987
- if (runtimeFields) {
11988
- Object.assign(cleanArgs, runtimeFields);
11989
- }
11990
- }
11991
- for (const key of MCP_META_KEYS) {
11992
- delete cleanArgs[key];
11993
- }
11994
- return getLucernClient().mutation(fn, cleanArgs);
11995
- }
11996
- async function adminQuery(fn, args) {
11997
- return getLucernClient().query(fn, args);
11998
- }
11999
- var _mcClient = null;
12000
- var _mcClientChecked = false;
12001
- function getMcClient() {
12002
- if (_mcClientChecked) {
12003
- return _mcClient;
12004
- }
12005
- const url = process.env.MC_CONVEX_URL;
12006
- const key = process.env.MC_DEPLOY_KEY;
12007
- if (url && key) {
12008
- _mcClient = new ConvexHttpClient(url);
12009
- _mcClient.setAdminAuth(key);
12010
- logMcpInfo(`[lucern-graph] Master Control client initialized \u2192 ${url}`);
12011
- } else {
12012
- logMcpInfo(
12013
- "[lucern-graph] Master Control client not configured (no MC_CONVEX_URL). Methodology packs will use hardcoded fallback."
12014
- );
12015
- }
12016
- _mcClientChecked = true;
12017
- return _mcClient;
12018
- }
12019
- async function mcAdminQuery(fn, args) {
12020
- const c = getMcClient();
12021
- if (!c) {
12022
- throw new Error(
12023
- "Master Control client not configured (set MC_CONVEX_URL + MC_DEPLOY_KEY)"
12024
- );
12025
- }
12026
- return c.query(fn, args);
12027
- }
12028
- process.env.LUCERN_AGENT_IDENTITY || "agent:claude-code";
12029
- crypto.randomUUID();
12030
-
12031
11721
  // ../../apps/mcp-server/src/scope.ts
12032
11722
  var defaultTopicId = null;
12033
11723
  var PUBLIC_TOPIC_PREFIX = "top_";
@@ -12059,6 +11749,31 @@ function readLucernJson() {
12059
11749
  function isNonEmptyString(value) {
12060
11750
  return typeof value === "string" && value.trim().length > 0;
12061
11751
  }
11752
+ function getLucernClient() {
11753
+ const client = getMcpRuntimeContext().lucernClient;
11754
+ if (!client) {
11755
+ throw new Error("[scope] Lucern SDK client is not initialized.");
11756
+ }
11757
+ return client;
11758
+ }
11759
+ function unwrapGatewayData(value) {
11760
+ if (!value || typeof value !== "object") {
11761
+ return null;
11762
+ }
11763
+ const record = value;
11764
+ const data = record.data;
11765
+ if (data && typeof data === "object" && !Array.isArray(data)) {
11766
+ return data;
11767
+ }
11768
+ return record;
11769
+ }
11770
+ function readRecordId(record) {
11771
+ if (!record) {
11772
+ return void 0;
11773
+ }
11774
+ const candidate = record._id ?? record.id ?? record.topicId ?? record.nodeId;
11775
+ return isNonEmptyString(candidate) ? candidate : void 0;
11776
+ }
12062
11777
  function readTopicMappedProjectId(topic) {
12063
11778
  const metadata = topic.metadata || {};
12064
11779
  const candidate = metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
@@ -12070,27 +11785,23 @@ async function tryGetTopicById(topicId) {
12070
11785
  return null;
12071
11786
  }
12072
11787
  try {
12073
- const topic = await adminQuery(components2.lucern.topics.get, {
12074
- id: normalizedTopicId
12075
- });
12076
- return topic || null;
11788
+ return unwrapGatewayData(await getLucernClient().topics.get(normalizedTopicId));
12077
11789
  } catch {
12078
11790
  return null;
12079
11791
  }
12080
11792
  }
12081
11793
  async function tryGetNodeById(nodeId) {
12082
11794
  try {
12083
- const node = await adminQuery(api2.epistemicNodes.getInternal, {
12084
- nodeId
12085
- });
12086
- return node || null;
11795
+ return unwrapGatewayData(await getLucernClient().nodes.get({ nodeId }));
12087
11796
  } catch {
12088
11797
  return null;
12089
11798
  }
12090
11799
  }
12091
11800
  async function findTopicByMappedProjectId(legacyScopeId) {
12092
11801
  try {
12093
- const topics2 = await adminQuery(components2.lucern.topics.list, {});
11802
+ const response = await getLucernClient().topics.list({});
11803
+ const data = unwrapGatewayData(response);
11804
+ const topics2 = Array.isArray(data?.topics) ? data.topics : Array.isArray(data?.items) ? data.items : [];
12094
11805
  return topics2.find((topic) => readTopicMappedProjectId(topic) === legacyScopeId) || null;
12095
11806
  } catch {
12096
11807
  return null;
@@ -12124,7 +11835,7 @@ async function resolveTopicScopeId(scopeId, toolName) {
12124
11835
  if (!resolved) {
12125
11836
  const mappedTopic = normalizedScopeId ? await findTopicByMappedProjectId(normalizedScopeId) : null;
12126
11837
  if (mappedTopic) {
12127
- resolved = String(mappedTopic._id);
11838
+ resolved = readRecordId(mappedTopic);
12128
11839
  }
12129
11840
  }
12130
11841
  if (!resolved) {
@@ -12323,314 +12034,6 @@ var beliefHandlers = {
12323
12034
  }
12324
12035
  };
12325
12036
 
12326
- // ../../apps/mcp-server/src/handlers/bootstrap-session.ts
12327
- function slugify(name) {
12328
- return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
12329
- }
12330
- async function resolveBeliefs(nodeIds) {
12331
- const results = [];
12332
- for (const nodeId of nodeIds) {
12333
- try {
12334
- const node = await adminQuery(api2.epistemicNodes.get, {
12335
- nodeId
12336
- });
12337
- if (!node) {
12338
- continue;
12339
- }
12340
- results.push({
12341
- nodeId,
12342
- text: String(node.canonicalText || "").slice(0, 200),
12343
- confidence: typeof node.confidence === "number" ? node.confidence : null
12344
- });
12345
- } catch {
12346
- }
12347
- }
12348
- return results;
12349
- }
12350
- async function resolveQuestions(nodeIds) {
12351
- const results = [];
12352
- for (const nodeId of nodeIds) {
12353
- try {
12354
- const node = await adminQuery(api2.epistemicNodes.get, {
12355
- nodeId
12356
- });
12357
- if (!node) {
12358
- continue;
12359
- }
12360
- const metadata = node.metadata || {};
12361
- results.push({
12362
- nodeId,
12363
- text: String(node.canonicalText || "").slice(0, 200),
12364
- status: String(metadata.questionStatus || node.status || "open"),
12365
- priority: String(metadata.priority || "medium")
12366
- });
12367
- } catch {
12368
- }
12369
- }
12370
- return results;
12371
- }
12372
- async function beginBuildSession(args) {
12373
- const worktreeId = typeof args.worktreeId === "string" ? args.worktreeId : void 0;
12374
- if (!worktreeId) {
12375
- throw new Error("[begin_build_session] worktreeId is required");
12376
- }
12377
- const branch = typeof args.branch === "string" && args.branch.trim().length > 0 ? args.branch.trim() : void 0;
12378
- const branchBase = typeof args.branchBase === "string" && args.branchBase.trim().length > 0 ? args.branchBase.trim() : "staging";
12379
- const prBase = typeof args.prBase === "string" && args.prBase.trim().length > 0 ? args.prBase.trim() : "staging";
12380
- const sessionMode = typeof args.sessionMode === "string" && args.sessionMode.trim().length > 0 ? args.sessionMode.trim() : "async";
12381
- const activateIfPlanning = args.activateIfPlanning !== false;
12382
- const worktree = await adminQuery(components2.lucern.worktrees.get, {
12383
- worktreeId
12384
- });
12385
- if (!worktree) {
12386
- throw new Error(`Worktree ${worktreeId} not found`);
12387
- }
12388
- const worktreeName = String(worktree.name || "Untitled");
12389
- const topicId = String(worktree.topicId || "");
12390
- const campaign = typeof worktree.campaign === "number" ? worktree.campaign : null;
12391
- const lane = String(worktree.lane || "unlaned");
12392
- const laneOrderInCampaign = typeof worktree.laneOrderInCampaign === "number" ? worktree.laneOrderInCampaign : null;
12393
- const orderInLane = typeof worktree.orderInLane === "number" ? worktree.orderInLane : null;
12394
- const gate = String(worktree.gate || "");
12395
- const hypothesis = String(worktree.hypothesis || worktree.beliefFocus || "");
12396
- let status = String(worktree.status || "planning");
12397
- const dependsOn = worktree.dependsOn || [];
12398
- const blocks = worktree.blocks || [];
12399
- const targetBeliefIds = worktree.targetBeliefIds || [];
12400
- const targetQuestionIds = worktree.targetQuestionIds || [];
12401
- if (activateIfPlanning && status === "planning") {
12402
- try {
12403
- await adminMutation(components2.lucern.worktrees.activate, {
12404
- worktreeId
12405
- });
12406
- status = "active";
12407
- } catch {
12408
- }
12409
- }
12410
- let topicName = "Unknown";
12411
- try {
12412
- const topic = await adminQuery(components2.lucern.topics.get, {
12413
- id: topicId
12414
- });
12415
- if (topic) {
12416
- topicName = String(topic.name || "Unknown");
12417
- }
12418
- } catch {
12419
- }
12420
- const allBeliefs = await resolveBeliefs(targetBeliefIds);
12421
- const topBeliefs = allBeliefs.slice().sort((left, right) => (right.confidence ?? -1) - (left.confidence ?? -1)).slice(0, 8);
12422
- const allQuestions = await resolveQuestions(targetQuestionIds);
12423
- const openQuestions = [];
12424
- const resolvedDecisions = [];
12425
- for (const question of allQuestions) {
12426
- const questionStatus = question.status.toLowerCase();
12427
- if (questionStatus === "answered" || questionStatus === "resolved") {
12428
- let decision = "(decision recorded \u2014 call get_answer for details)";
12429
- try {
12430
- const answer = await adminQuery(
12431
- api2.epistemicAnswers.getLatestForQuestion,
12432
- {
12433
- questionNodeId: question.nodeId
12434
- }
12435
- );
12436
- if (answer) {
12437
- decision = String(
12438
- answer.answerText || answer.canonicalText || decision
12439
- ).slice(0, 200);
12440
- }
12441
- } catch {
12442
- try {
12443
- const node = await adminQuery(api2.epistemicNodes.get, {
12444
- nodeId: question.nodeId
12445
- });
12446
- if (node?._id) {
12447
- const answer = await adminQuery(
12448
- api2.epistemicAnswers.getLatestForQuestion,
12449
- {
12450
- questionNodeId: node._id
12451
- }
12452
- );
12453
- if (answer) {
12454
- decision = String(
12455
- answer.answerText || answer.canonicalText || decision
12456
- ).slice(0, 200);
12457
- }
12458
- }
12459
- } catch {
12460
- }
12461
- }
12462
- resolvedDecisions.push({
12463
- question: question.text.slice(0, 150),
12464
- decision
12465
- });
12466
- continue;
12467
- }
12468
- openQuestions.push({
12469
- nodeId: question.nodeId,
12470
- text: question.text,
12471
- priority: question.priority
12472
- });
12473
- }
12474
- try {
12475
- const topicQuestions = await adminQuery(api2.epistemicQuestions.getByTopic, {
12476
- topicId,
12477
- userId: "system",
12478
- limit: 20
12479
- }).catch(() => []);
12480
- for (const question of Array.isArray(topicQuestions) ? topicQuestions : []) {
12481
- const metadata = question.metadata || {};
12482
- const questionStatus = String(
12483
- metadata.questionStatus || question.status || "open"
12484
- ).toLowerCase();
12485
- if ((questionStatus === "open" || questionStatus === "in_progress") && !targetQuestionIds.includes(String(question._id))) {
12486
- openQuestions.push({
12487
- nodeId: String(question._id),
12488
- text: String(question.canonicalText || "").slice(0, 200),
12489
- priority: String(metadata.priority || "medium")
12490
- });
12491
- }
12492
- }
12493
- } catch {
12494
- }
12495
- const dependencies = [];
12496
- for (const dependencyId of dependsOn.slice(0, 5)) {
12497
- try {
12498
- const dependency = await adminQuery(components2.lucern.worktrees.get, {
12499
- worktreeId: dependencyId
12500
- });
12501
- dependencies.push({
12502
- worktreeId: dependencyId,
12503
- title: String(dependency?.name || "Unknown"),
12504
- status: String(dependency?.status || "unknown")
12505
- });
12506
- } catch {
12507
- dependencies.push({
12508
- worktreeId: dependencyId,
12509
- title: "Unknown",
12510
- status: "unknown"
12511
- });
12512
- }
12513
- }
12514
- const unblocks = [];
12515
- for (const blockedId of blocks.slice(0, 5)) {
12516
- try {
12517
- const blocked = await adminQuery(components2.lucern.worktrees.get, {
12518
- worktreeId: blockedId
12519
- });
12520
- unblocks.push({
12521
- worktreeId: blockedId,
12522
- title: String(blocked?.name || "Unknown")
12523
- });
12524
- } catch {
12525
- unblocks.push({
12526
- worktreeId: blockedId,
12527
- title: "Unknown"
12528
- });
12529
- }
12530
- }
12531
- const effectiveBranch = branch || `codex/${slugify(worktreeName)}`;
12532
- const incompleteDependencies = dependencies.filter(
12533
- (dependency) => dependency.status !== "completed" && dependency.status !== "merged"
12534
- );
12535
- const mergeOrderNotes = incompleteDependencies.length > 0 ? `Blocked by: ${incompleteDependencies.map((dependency) => dependency.title).join(", ")}` : "none";
12536
- const requiredDocs = [
12537
- "docs/api/EK-13-api-sdk-architecture.md",
12538
- "docs/api/EK-13.1.5-repo-architecture-blueprint.md",
12539
- "docs/api/EK-13.1-contract-authority.md",
12540
- "docs/development/handoff-contract.md"
12541
- ];
12542
- const focus = hypothesis ? `${hypothesis.split(".")[0]}.` : `Complete ${worktreeName}`;
12543
- const exitCriteria = gate ? [`Gate: ${gate}`] : [];
12544
- exitCriteria.push(
12545
- "All namespace surfaces end-to-end: contract \u2192 domain \u2192 HTTP \u2192 SDK \u2192 MCP \u2192 test",
12546
- "All code lands in target-state paths under lucern/",
12547
- "PR targets staging, not main"
12548
- );
12549
- const keyFiles = [
12550
- "app/api/platform/v1/_lib/gateway.ts",
12551
- "modules/access-control/src/principalContext.ts",
12552
- "lucern/packages/sdk/src/coreClient.ts",
12553
- "lucern/packages/sdk/src/identityClient.ts",
12554
- "lucern/contracts/src/sdk-methods.contract.ts",
12555
- "app/api/platform/v1/identity/"
12556
- ];
12557
- const pillarKeywords = [
12558
- "Pillar 1",
12559
- "Pillar 2",
12560
- "Pillar 3",
12561
- "Pillar 4",
12562
- "Pillar 5",
12563
- "Pillar 6",
12564
- "Pillar 7",
12565
- "Pillar 8",
12566
- "8 innovation pillars"
12567
- ];
12568
- const pillarBeliefs = [];
12569
- for (const belief of allBeliefs) {
12570
- for (const keyword of pillarKeywords) {
12571
- if (!belief.text.includes(keyword)) {
12572
- continue;
12573
- }
12574
- const pillarMatch = belief.text.match(/Pillar \d+ \([^)]+\)/);
12575
- pillarBeliefs.push({
12576
- pillar: pillarMatch ? pillarMatch[0] : keyword,
12577
- text: belief.text.slice(0, 250),
12578
- nodeId: belief.nodeId
12579
- });
12580
- break;
12581
- }
12582
- }
12583
- const visionDocs = [
12584
- {
12585
- path: "docs/product/core-value-propositions.md",
12586
- description: "8 innovation pillars through developer, marketing, and investor lenses"
12587
- },
12588
- {
12589
- path: "docs/product/five-domains.md",
12590
- description: "5 product domains: MC, Tenant, Developer, Reasoning Control, Reasoning"
12591
- },
12592
- {
12593
- path: "docs/product/innovation-pillars.md",
12594
- description: "The 8 pillars that define what makes Lucern unique"
12595
- },
12596
- {
12597
- path: "docs/product/vision-to-roadmap-bridge.md",
12598
- description: "Where each pillar is today vs. where it goes \u2014 the north star trajectory"
12599
- }
12600
- ];
12601
- return {
12602
- topicId,
12603
- topicName,
12604
- worktreeId,
12605
- worktreeName,
12606
- branch: effectiveBranch,
12607
- branchBase,
12608
- prBase,
12609
- campaign,
12610
- lane,
12611
- laneOrderInCampaign,
12612
- orderInLane,
12613
- gate,
12614
- hypothesis,
12615
- focus,
12616
- status,
12617
- sessionMode,
12618
- targetBeliefIds,
12619
- targetQuestionIds,
12620
- topBeliefs,
12621
- openQuestions,
12622
- resolvedDecisions,
12623
- exitCriteria,
12624
- requiredDocs,
12625
- keyFiles,
12626
- pillarBeliefs,
12627
- visionDocs,
12628
- dependencies,
12629
- unblocks,
12630
- mergeOrderNotes
12631
- };
12632
- }
12633
-
12634
12037
  // ../../apps/mcp-server/src/handlers/bootstrap.ts
12635
12038
  var bootstrapHandlers = {
12636
12039
  async generate_session_handoff(args, ctx) {
@@ -12639,7 +12042,9 @@ var bootstrapHandlers = {
12639
12042
  );
12640
12043
  },
12641
12044
  async begin_build_session(args, ctx) {
12642
- return beginBuildSession(args);
12045
+ return formatSdkResult(
12046
+ await getSdkClient(ctx).mcp.beginBuildSession(args)
12047
+ );
12643
12048
  }
12644
12049
  };
12645
12050
 
@@ -12995,19 +12400,16 @@ var engineeringVerificationHandlers = {
12995
12400
  "evaluate_engineering_contract requires at least one verification payload."
12996
12401
  );
12997
12402
  }
12998
- const result = await adminMutation(
12999
- "epistemicContracts:evaluateEngineeringContracts",
13000
- {
12403
+ return formatSdkResult(
12404
+ await getSdkClient(ctx).mcp.evaluateEngineeringContract({
13001
12405
  beliefNodeId: args.beliefNodeId,
13002
12406
  trigger: args.trigger,
13003
12407
  testOutput: args.testOutput,
13004
12408
  tscOutput: args.tscOutput,
13005
12409
  lintOutput: args.lintOutput,
13006
- sentryData: args.sentryData,
13007
- authenticatedUserId: ctx.userId
13008
- }
12410
+ sentryData: args.sentryData
12411
+ })
13009
12412
  );
13010
- return result;
13011
12413
  }
13012
12414
  };
13013
12415
 
@@ -13960,6 +13362,47 @@ var intelligenceHandlers = {
13960
13362
  get_graph_structure_analysis: graphHandlers.get_graph_structure_analysis,
13961
13363
  get_falsification_questions: graphHandlers.get_falsification_questions
13962
13364
  };
13365
+ var GLOBAL_KEY = "__LUCERN_SERVER_CORE_KERNEL_API_BINDING__";
13366
+ function store() {
13367
+ return globalThis;
13368
+ }
13369
+ function getBinding() {
13370
+ const current = store()[GLOBAL_KEY];
13371
+ if (!current) {
13372
+ throw new Error(
13373
+ "Server-core kernelApi not registered. Call registerKernelApi({api, components, internal}) at host boot."
13374
+ );
13375
+ }
13376
+ return current;
13377
+ }
13378
+ function readPath(root, path3) {
13379
+ let cursor = root;
13380
+ for (const part of path3) {
13381
+ if (cursor == null || typeof cursor !== "object") {
13382
+ return void 0;
13383
+ }
13384
+ cursor = cursor[part];
13385
+ }
13386
+ return cursor;
13387
+ }
13388
+ function resolveApiPath(binding, which, path3) {
13389
+ return readPath(binding[which], path3);
13390
+ }
13391
+ function makeProxy(which, path3 = []) {
13392
+ return new Proxy({}, {
13393
+ get(_target, prop) {
13394
+ if (typeof prop !== "string") {
13395
+ return void 0;
13396
+ }
13397
+ const nextPath = [...path3, prop];
13398
+ const resolved = resolveApiPath(getBinding(), which, nextPath);
13399
+ return resolved === void 0 ? makeProxy(which, nextPath) : resolved;
13400
+ }
13401
+ });
13402
+ }
13403
+ var api = makeProxy("api");
13404
+ makeProxy("components");
13405
+ makeProxy("internal");
13963
13406
 
13964
13407
  // ../server-core/src/mcp-context-tools.ts
13965
13408
  function requireMcpConvex(authContext, label) {
@@ -15025,16 +14468,16 @@ function buildInputData(args) {
15025
14468
  var researchVerificationHandlers = {
15026
14469
  async evaluate_research_contract(args, ctx) {
15027
14470
  const inputData = buildInputData(args);
15028
- const result = await adminMutation(
15029
- api2.contracts.evaluateContractsForTrigger,
15030
- {
14471
+ return formatSdkResult(
14472
+ await getSdkClient(ctx).mcp.evaluateResearchContract({
15031
14473
  beliefNodeId: args.beliefNodeId,
15032
14474
  trigger: typeof args.trigger === "string" && args.trigger.length > 0 ? args.trigger : "event_driven",
15033
- ...inputData ? { inputData } : {},
15034
- authenticatedUserId: ctx.userId
15035
- }
14475
+ metricData: inputData?.metricData,
14476
+ referenceCheckData: inputData?.referenceCheckData,
14477
+ marketIndexData: inputData?.marketIndexData,
14478
+ temporalData: inputData?.temporalData
14479
+ })
15036
14480
  );
15037
- return result;
15038
14481
  }
15039
14482
  };
15040
14483
 
@@ -15586,6 +15029,20 @@ function recordWrite(toolName, topicId, sessionId = "default") {
15586
15029
  existing.push(record);
15587
15030
  sessionWritesBySession.set(sessionId, existing);
15588
15031
  }
15032
+ async function checkGatewayWritePolicy(args) {
15033
+ const client = args.authCtx.lucernClient;
15034
+ const checkWritePolicy2 = client?.mcp?.checkWritePolicy;
15035
+ if (!checkWritePolicy2) {
15036
+ throw new Error("Lucern SDK MCP write-policy client is not initialized.");
15037
+ }
15038
+ const response = await checkWritePolicy2({
15039
+ topicId: args.topicId,
15040
+ workspaceId: args.authCtx.workspaceId,
15041
+ role: args.authCtx.role,
15042
+ toolName: args.toolName
15043
+ });
15044
+ return response.data ?? null;
15045
+ }
15589
15046
  function buildRateLimitExplanation(args) {
15590
15047
  const summary = `Denied ${args.toolName}: session write limit ${args.currentCount}/${args.maxWritesPerSession} reached for the matched write policy.`;
15591
15048
  return {
@@ -15623,10 +15080,10 @@ async function checkWritePolicy(toolName, topicId, authCtx) {
15623
15080
  return { allowed: true, permission: "allow", reason: "read_only_tool" };
15624
15081
  }
15625
15082
  try {
15626
- const result = await adminQuery("mcpWritePolicy:checkAccess", {
15083
+ const result = await checkGatewayWritePolicy({
15627
15084
  topicId: topicId ?? void 0,
15628
- role: authCtx.role,
15629
- toolName
15085
+ toolName,
15086
+ authCtx
15630
15087
  });
15631
15088
  if (!result) {
15632
15089
  return {
@@ -15692,9 +15149,11 @@ async function checkWritePolicy(toolName, topicId, authCtx) {
15692
15149
  };
15693
15150
  }
15694
15151
  }
15152
+
15153
+ // ../../apps/mcp-server/src/credentials.ts
15695
15154
  var LUCERN_HOME = path2.join(os.homedir(), ".lucern");
15696
15155
  path2.join(LUCERN_HOME, "credentials");
15697
15156
 
15698
- export { buildHandlerMap, checkWritePolicy, createAdminClient, isMutationTool, recordWrite, runWithScopedClient };
15157
+ export { buildHandlerMap, checkWritePolicy, isMutationTool, recordWrite };
15699
15158
  //# sourceMappingURL=runtime.js.map
15700
15159
  //# sourceMappingURL=runtime.js.map