@cleocode/cleo 2026.4.51 → 2026.4.53

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/cli/index.js CHANGED
@@ -9600,11 +9600,14 @@ var init_brain_schema = __esm({
9600
9600
  source: text("source").notNull(),
9601
9601
  /** Estimated tokens consumed by this retrieval. */
9602
9602
  tokensUsed: integer("tokens_used"),
9603
+ /** Session ID (soft FK to tasks.db sessions). Enables grouping retrievals by session for STDP analysis. */
9604
+ sessionId: text("session_id"),
9603
9605
  createdAt: text("created_at").notNull().default(sql2`(datetime('now'))`)
9604
9606
  },
9605
9607
  (table) => [
9606
9608
  index("idx_retrieval_log_created").on(table.createdAt),
9607
- index("idx_retrieval_log_source").on(table.source)
9609
+ index("idx_retrieval_log_source").on(table.source),
9610
+ index("idx_retrieval_log_session").on(table.sessionId)
9608
9611
  ]
9609
9612
  );
9610
9613
  brainPlasticityEvents = sqliteTable(
@@ -11139,44 +11142,6 @@ var init_platform_paths = __esm({
11139
11142
  });
11140
11143
 
11141
11144
  // packages/core/src/paths.ts
11142
- var paths_exports = {};
11143
- __export(paths_exports, {
11144
- getAgentOutputsAbsolute: () => getAgentOutputsAbsolute,
11145
- getAgentOutputsDir: () => getAgentOutputsDir,
11146
- getAgentsHome: () => getAgentsHome,
11147
- getArchivePath: () => getArchivePath,
11148
- getBackupDir: () => getBackupDir,
11149
- getClaudeAgentsDir: () => getClaudeAgentsDir,
11150
- getClaudeMemDbPath: () => getClaudeMemDbPath,
11151
- getCleoCacheDir: () => getCleoCacheDir,
11152
- getCleoCantWorkflowsDir: () => getCleoCantWorkflowsDir,
11153
- getCleoConfigDir: () => getCleoConfigDir,
11154
- getCleoDir: () => getCleoDir,
11155
- getCleoDirAbsolute: () => getCleoDirAbsolute,
11156
- getCleoDocsDir: () => getCleoDocsDir,
11157
- getCleoGlobalAgentsDir: () => getCleoGlobalAgentsDir,
11158
- getCleoGlobalJustfilePath: () => getCleoGlobalJustfilePath,
11159
- getCleoGlobalRecipesDir: () => getCleoGlobalRecipesDir,
11160
- getCleoHome: () => getCleoHome,
11161
- getCleoLogDir: () => getCleoLogDir,
11162
- getCleoPiExtensionsDir: () => getCleoPiExtensionsDir,
11163
- getCleoSchemasDir: () => getCleoSchemasDir,
11164
- getCleoTempDir: () => getCleoTempDir,
11165
- getCleoTemplatesDir: () => getCleoTemplatesDir,
11166
- getCleoTemplatesTildePath: () => getCleoTemplatesTildePath,
11167
- getConfigPath: () => getConfigPath,
11168
- getGlobalConfigPath: () => getGlobalConfigPath,
11169
- getLogPath: () => getLogPath,
11170
- getManifestArchivePath: () => getManifestArchivePath,
11171
- getManifestPath: () => getManifestPath,
11172
- getProjectRoot: () => getProjectRoot,
11173
- getSessionsPath: () => getSessionsPath,
11174
- getTaskPath: () => getTaskPath,
11175
- isAbsolutePath: () => isAbsolutePath,
11176
- isProjectInitialized: () => isProjectInitialized,
11177
- resolveProjectPath: () => resolveProjectPath,
11178
- worktreeScope: () => worktreeScope
11179
- });
11180
11145
  import { AsyncLocalStorage } from "node:async_hooks";
11181
11146
  import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
11182
11147
  import { homedir } from "node:os";
@@ -11195,9 +11160,6 @@ function getCleoTemplatesDir() {
11195
11160
  function getCleoSchemasDir() {
11196
11161
  return join4(getCleoHome(), "schemas");
11197
11162
  }
11198
- function getCleoDocsDir() {
11199
- return join4(getCleoHome(), "docs");
11200
- }
11201
11163
  function getCleoDir(cwd) {
11202
11164
  if (cwd) {
11203
11165
  return getCleoDirAbsolute(cwd);
@@ -11269,15 +11231,6 @@ function getTaskPath(cwd) {
11269
11231
  function getConfigPath(cwd) {
11270
11232
  return join4(getCleoDirAbsolute(cwd), "config.json");
11271
11233
  }
11272
- function getSessionsPath(cwd) {
11273
- return join4(getCleoDirAbsolute(cwd), "sessions.json");
11274
- }
11275
- function getArchivePath(cwd) {
11276
- return join4(getCleoDirAbsolute(cwd), "tasks-archive.json");
11277
- }
11278
- function getLogPath(cwd) {
11279
- return join4(getCleoDirAbsolute(cwd), "logs", "cleo.log");
11280
- }
11281
11234
  function getBackupDir(cwd) {
11282
11235
  return join4(getCleoDirAbsolute(cwd), "backups", "operational");
11283
11236
  }
@@ -14330,8 +14283,8 @@ async function cleanupMigrationArtifacts(backupPath) {
14330
14283
  }
14331
14284
  async function validateSqliteDatabase(dbPath) {
14332
14285
  try {
14333
- const { createRequire: createRequire19 } = await import("node:module");
14334
- const _req = createRequire19(import.meta.url);
14286
+ const { createRequire: createRequire20 } = await import("node:module");
14287
+ const _req = createRequire20(import.meta.url);
14335
14288
  const { DatabaseSync: DatabaseSync10 } = _req("node:sqlite");
14336
14289
  const db = new DatabaseSync10(dbPath, { readOnly: true });
14337
14290
  const integrityRow = db.prepare("PRAGMA integrity_check").get();
@@ -14952,7 +14905,7 @@ function clearEmbeddingProvider() {
14952
14905
  currentProvider = null;
14953
14906
  }
14954
14907
  async function embedText(text3) {
14955
- if (!currentProvider || !currentProvider.isAvailable()) return null;
14908
+ if (!currentProvider?.isAvailable()) return null;
14956
14909
  return currentProvider.embed(text3);
14957
14910
  }
14958
14911
  function isEmbeddingAvailable() {
@@ -22823,7 +22776,7 @@ function parseIdPrefix(id) {
22823
22776
  return null;
22824
22777
  }
22825
22778
  async function searchSimilar(query, projectRoot, limit) {
22826
- if (!query || !query.trim()) return [];
22779
+ if (!query?.trim()) return [];
22827
22780
  if (!isEmbeddingAvailable()) return [];
22828
22781
  const maxResults = limit ?? 10;
22829
22782
  const queryVector = await embedText(query);
@@ -50370,7 +50323,7 @@ async function computeLastSession(projectRoot, scopeFilter) {
50370
50323
  const accessor = await getAccessor(projectRoot);
50371
50324
  const allSessions = await accessor.loadSessions();
50372
50325
  const session = allSessions.find((s3) => s3.id === sessionId);
50373
- if (!session || !session.endedAt) return null;
50326
+ if (!session?.endedAt) return null;
50374
50327
  let duration3 = 0;
50375
50328
  if (session.startedAt) {
50376
50329
  duration3 = Math.round(
@@ -51557,10 +51510,17 @@ async function searchBrainCompact(projectRoot, params) {
51557
51510
  setImmediate(() => {
51558
51511
  incrementCitationCounts(projectRoot, returnedIds).catch(() => {
51559
51512
  });
51560
- logRetrieval(projectRoot, query, returnedIds, "find-rrf", results2.length * 50).catch(
51561
- () => {
51562
- }
51563
- );
51513
+ getCurrentSessionId(projectRoot).then((sessionId) => {
51514
+ return logRetrieval(
51515
+ projectRoot,
51516
+ query,
51517
+ returnedIds,
51518
+ "find-rrf",
51519
+ results2.length * 50,
51520
+ sessionId
51521
+ );
51522
+ }).catch(() => {
51523
+ });
51564
51524
  });
51565
51525
  }
51566
51526
  return { results: results2, total: results2.length, tokensEstimated: results2.length * 50 };
@@ -51623,7 +51583,16 @@ async function searchBrainCompact(projectRoot, params) {
51623
51583
  setImmediate(() => {
51624
51584
  incrementCitationCounts(projectRoot, returnedIds).catch(() => {
51625
51585
  });
51626
- logRetrieval(projectRoot, query, returnedIds, "find", results.length * 50).catch(() => {
51586
+ getCurrentSessionId(projectRoot).then((sessionId) => {
51587
+ return logRetrieval(
51588
+ projectRoot,
51589
+ query,
51590
+ returnedIds,
51591
+ "find",
51592
+ results.length * 50,
51593
+ sessionId
51594
+ );
51595
+ }).catch(() => {
51627
51596
  });
51628
51597
  });
51629
51598
  }
@@ -51811,13 +51780,16 @@ async function fetchBrainEntries(projectRoot, params) {
51811
51780
  setImmediate(() => {
51812
51781
  incrementCitationCounts(projectRoot, fetchedIds).catch(() => {
51813
51782
  });
51814
- logRetrieval(
51815
- projectRoot,
51816
- fetchedIds.join(","),
51817
- fetchedIds,
51818
- "fetch",
51819
- results.length * 500
51820
- ).catch(() => {
51783
+ getCurrentSessionId(projectRoot).then((sessionId) => {
51784
+ return logRetrieval(
51785
+ projectRoot,
51786
+ fetchedIds.join(","),
51787
+ fetchedIds,
51788
+ "fetch",
51789
+ results.length * 500,
51790
+ sessionId
51791
+ );
51792
+ }).catch(() => {
51821
51793
  });
51822
51794
  });
51823
51795
  }
@@ -52235,6 +52207,15 @@ async function retrieveWithBudget(projectRoot, query, tokenBudget = 500, options
52235
52207
  excluded
52236
52208
  };
52237
52209
  }
52210
+ async function getCurrentSessionId(projectRoot) {
52211
+ try {
52212
+ const { sessionStatus: sessionStatus3 } = await Promise.resolve().then(() => (init_sessions2(), sessions_exports2));
52213
+ const session = await sessionStatus3(projectRoot);
52214
+ return session?.id;
52215
+ } catch {
52216
+ return void 0;
52217
+ }
52218
+ }
52238
52219
  async function incrementCitationCounts(projectRoot, ids) {
52239
52220
  if (ids.length === 0) return;
52240
52221
  const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
@@ -52261,13 +52242,13 @@ async function incrementCitationCounts(projectRoot, ids) {
52261
52242
  }
52262
52243
  }
52263
52244
  }
52264
- async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed) {
52245
+ async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed, sessionId) {
52265
52246
  if (entryIds.length === 0) return;
52266
52247
  const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
52267
52248
  await getBrainDb2(projectRoot);
52268
52249
  const nativeDb = getBrainNativeDb2();
52269
52250
  if (!nativeDb) return;
52270
- const createSql = "CREATE TABLE IF NOT EXISTS brain_retrieval_log (id INTEGER PRIMARY KEY AUTOINCREMENT,query TEXT NOT NULL,entry_ids TEXT NOT NULL,entry_count INTEGER NOT NULL,source TEXT NOT NULL,tokens_used INTEGER,created_at TEXT NOT NULL DEFAULT (datetime('now')))";
52251
+ const createSql = "CREATE TABLE IF NOT EXISTS brain_retrieval_log (id INTEGER PRIMARY KEY AUTOINCREMENT,query TEXT NOT NULL,entry_ids TEXT NOT NULL,entry_count INTEGER NOT NULL,source TEXT NOT NULL,tokens_used INTEGER,session_id TEXT,created_at TEXT NOT NULL DEFAULT (datetime('now')))";
52271
52252
  try {
52272
52253
  nativeDb.prepare(createSql).run();
52273
52254
  } catch {
@@ -52275,8 +52256,15 @@ async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed) {
52275
52256
  }
52276
52257
  try {
52277
52258
  nativeDb.prepare(
52278
- "INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used) VALUES (?, ?, ?, ?, ?)"
52279
- ).run(query, entryIds.join(","), entryIds.length, source, tokensUsed ?? null);
52259
+ "INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used, session_id) VALUES (?, ?, ?, ?, ?, ?)"
52260
+ ).run(
52261
+ query,
52262
+ entryIds.join(","),
52263
+ entryIds.length,
52264
+ source,
52265
+ tokensUsed ?? null,
52266
+ sessionId ?? null
52267
+ );
52280
52268
  } catch {
52281
52269
  }
52282
52270
  }
@@ -56018,6 +56006,7 @@ __export(scaffold_exports, {
56018
56006
  checkConfig: () => checkConfig,
56019
56007
  checkGitignore: () => checkGitignore,
56020
56008
  checkGlobalHome: () => checkGlobalHome,
56009
+ checkGlobalIdentity: () => checkGlobalIdentity,
56021
56010
  checkGlobalTemplates: () => checkGlobalTemplates,
56022
56011
  checkLogDir: () => checkLogDir,
56023
56012
  checkMemoryBridge: () => checkMemoryBridge,
@@ -56034,6 +56023,7 @@ __export(scaffold_exports, {
56034
56023
  ensureContributorMcp: () => ensureContributorMcp,
56035
56024
  ensureGitignore: () => ensureGitignore,
56036
56025
  ensureGlobalHome: () => ensureGlobalHome,
56026
+ ensureGlobalIdentity: () => ensureGlobalIdentity,
56037
56027
  ensureGlobalScaffold: () => ensureGlobalScaffold,
56038
56028
  ensureGlobalTemplates: () => ensureGlobalTemplates,
56039
56029
  ensureProjectContext: () => ensureProjectContext,
@@ -56051,6 +56041,7 @@ import { execFile as execFile3 } from "node:child_process";
56051
56041
  import { randomUUID as randomUUID2 } from "node:crypto";
56052
56042
  import { existsSync as existsSync40, constants as fsConstants3, readFileSync as readFileSync26, statSync as statSync8 } from "node:fs";
56053
56043
  import { access as access3, copyFile as copyFile2, mkdir as mkdir6, readdir as readdir2, readFile as readFile7, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
56044
+ import { createRequire as createRequire9 } from "node:module";
56054
56045
  import { homedir as getHomedir } from "node:os";
56055
56046
  import { dirname as dirname10, join as join42, resolve as resolve5 } from "node:path";
56056
56047
  import { fileURLToPath as fileURLToPath4 } from "node:url";
@@ -56906,6 +56897,102 @@ async function ensureCleoOsHub() {
56906
56897
  details: `pi-extensions: ${piResult.copied} created/${piResult.kept} kept, global-recipes: ${recipesResult.copied} created/${recipesResult.kept} kept`
56907
56898
  };
56908
56899
  }
56900
+ function resolveIdentitySourcePath() {
56901
+ const monorepoPath = join42(
56902
+ process.cwd(),
56903
+ "packages",
56904
+ "cleo-os",
56905
+ "starter-bundle",
56906
+ "CLEOOS-IDENTITY.md"
56907
+ );
56908
+ if (existsSync40(monorepoPath)) return monorepoPath;
56909
+ try {
56910
+ const require2 = createRequire9(import.meta.url);
56911
+ const pkgJson = require2.resolve("@cleocode/cleo-os/package.json");
56912
+ const pkgDir = pkgJson.replace(/\/package\.json$/, "");
56913
+ const installedPath = join42(pkgDir, "starter-bundle", "CLEOOS-IDENTITY.md");
56914
+ if (existsSync40(installedPath)) return installedPath;
56915
+ } catch {
56916
+ }
56917
+ return null;
56918
+ }
56919
+ async function ensureGlobalIdentity(forceRefresh = false) {
56920
+ const sourcePath = resolveIdentitySourcePath();
56921
+ if (!sourcePath) {
56922
+ return {
56923
+ action: "skipped",
56924
+ path: "",
56925
+ details: "CLEOOS-IDENTITY.md source not found in monorepo or installed package"
56926
+ };
56927
+ }
56928
+ const cleoHome = getCleoHome();
56929
+ const dst = join42(cleoHome, "CLEOOS-IDENTITY.md");
56930
+ try {
56931
+ await mkdir6(cleoHome, { recursive: true });
56932
+ } catch (err) {
56933
+ return {
56934
+ action: "skipped",
56935
+ path: dst,
56936
+ details: `Failed to create global cleo home: ${err instanceof Error ? err.message : String(err)}`
56937
+ };
56938
+ }
56939
+ if (existsSync40(dst) && !forceRefresh) {
56940
+ return { action: "skipped", path: dst, details: "identity already present" };
56941
+ }
56942
+ const existedBefore = existsSync40(dst);
56943
+ try {
56944
+ const content = readFileSync26(sourcePath, "utf-8");
56945
+ await writeFile6(dst, content);
56946
+ return {
56947
+ action: existedBefore ? "repaired" : "created",
56948
+ path: dst,
56949
+ details: `from ${sourcePath}`
56950
+ };
56951
+ } catch (err) {
56952
+ return {
56953
+ action: "skipped",
56954
+ path: dst,
56955
+ details: `Failed to write identity: ${err instanceof Error ? err.message : String(err)}`
56956
+ };
56957
+ }
56958
+ }
56959
+ function checkGlobalIdentity() {
56960
+ const cleoHome = getCleoHome();
56961
+ const identityPath = join42(cleoHome, "CLEOOS-IDENTITY.md");
56962
+ if (!existsSync40(identityPath)) {
56963
+ return {
56964
+ id: "global_identity",
56965
+ category: "global",
56966
+ status: "failed",
56967
+ message: "Global CLEOOS-IDENTITY.md not found \u2014 orchestrator persona missing",
56968
+ details: { path: identityPath, exists: false },
56969
+ fix: "cleo upgrade (auto-deploys identity)"
56970
+ };
56971
+ }
56972
+ let size = 0;
56973
+ try {
56974
+ size = statSync8(identityPath).size;
56975
+ } catch {
56976
+ }
56977
+ if (size === 0) {
56978
+ return {
56979
+ id: "global_identity",
56980
+ category: "global",
56981
+ status: "failed",
56982
+ message: "Global CLEOOS-IDENTITY.md exists but is empty",
56983
+ details: { path: identityPath, exists: true, size: 0 },
56984
+ fix: "cleo upgrade --refresh-identity"
56985
+ };
56986
+ }
56987
+ return {
56988
+ id: "global_identity",
56989
+ category: "global",
56990
+ status: "passed",
56991
+ message: "Global CLEOOS-IDENTITY.md present",
56992
+ details: { path: identityPath, exists: true, size },
56993
+ fix: ""
56994
+ };
56995
+ }
56909
56996
  function checkGlobalHome() {
56910
56997
  const cleoHome = getCleoHome();
56911
56998
  if (!existsSync40(cleoHome)) {
@@ -58851,7 +58938,7 @@ function prepareSpawnMulti(skillNames, tokenValues, cwd) {
58851
58938
  const skillName = skillNames[i];
58852
58939
  const isPrimary = i === 0;
58853
58940
  const skill = findSkill(skillName, cwd);
58854
- if (!skill || !skill.content) {
58941
+ if (!skill?.content) {
58855
58942
  continue;
58856
58943
  }
58857
58944
  let content = isPrimary ? skill.content : loadProgressive(skill.content);
@@ -63304,7 +63391,7 @@ var init_agent_outputs = __esm({
63304
63391
  // packages/core/src/migration/checksum.ts
63305
63392
  import { createHash as createHash8 } from "node:crypto";
63306
63393
  import { readFileSync as readFileSync37 } from "node:fs";
63307
- import { createRequire as createRequire9 } from "node:module";
63394
+ import { createRequire as createRequire10 } from "node:module";
63308
63395
  async function computeChecksum2(filePath) {
63309
63396
  const content = readFileSync37(filePath);
63310
63397
  return createHash8("sha256").update(content).digest("hex");
@@ -63350,7 +63437,7 @@ var _require9, DatabaseSync4;
63350
63437
  var init_checksum = __esm({
63351
63438
  "packages/core/src/migration/checksum.ts"() {
63352
63439
  "use strict";
63353
- _require9 = createRequire9(import.meta.url);
63440
+ _require9 = createRequire10(import.meta.url);
63354
63441
  ({ DatabaseSync: DatabaseSync4 } = _require9("node:sqlite"));
63355
63442
  }
63356
63443
  });
@@ -74367,7 +74454,7 @@ async function injectProtocol(skillContent, taskId, tokenValues, cwd, tier) {
74367
74454
  }
74368
74455
  async function orchestratorSpawnSkill(taskId, skillName, tokenValues, cwd, tier) {
74369
74456
  const skill = findSkill(skillName, cwd);
74370
- if (!skill || !skill.content) {
74457
+ if (!skill?.content) {
74371
74458
  throw new CleoError(4 /* NOT_FOUND */, `Skill not found: ${skillName}`, {
74372
74459
  fix: `Check skills directory for ${skillName}/SKILL.md`
74373
74460
  });
@@ -74937,7 +75024,7 @@ async function buildPrompt(taskId, templateName = "TASK-EXECUTOR", cwd, tier) {
74937
75024
  throw new CleoError(4 /* NOT_FOUND */, `Task ${taskId} not found`);
74938
75025
  }
74939
75026
  const skill = findSkill(templateName, cwd);
74940
- if (!skill || !skill.content) {
75027
+ if (!skill?.content) {
74941
75028
  const { canonical } = mapSkillName(templateName);
74942
75029
  throw new CleoError(4 /* NOT_FOUND */, `Skill template ${templateName} not found`, {
74943
75030
  fix: `Expected at skills/${canonical}/SKILL.md`
@@ -77732,7 +77819,7 @@ async function analyzeArchive(opts, accessor) {
77732
77819
  const acc = accessor ?? await getAccessor(opts.cwd);
77733
77820
  const data = await acc.loadArchive();
77734
77821
  const reportType = opts.report ?? "summary";
77735
- if (!data || !data.archivedTasks?.length) {
77822
+ if (!data?.archivedTasks?.length) {
77736
77823
  return {
77737
77824
  report: reportType,
77738
77825
  filters: null,
@@ -79528,7 +79615,7 @@ __export(parser_exports, {
79528
79615
  parseFile: () => parseFile2
79529
79616
  });
79530
79617
  import { readFileSync as readFileSync67 } from "node:fs";
79531
- import { createRequire as createRequire10 } from "node:module";
79618
+ import { createRequire as createRequire11 } from "node:module";
79532
79619
  import { relative as relative11 } from "node:path";
79533
79620
  function tryRequire2(id) {
79534
79621
  try {
@@ -79729,7 +79816,7 @@ var init_parser4 = __esm({
79729
79816
  "packages/core/src/code/parser.ts"() {
79730
79817
  "use strict";
79731
79818
  init_tree_sitter_languages2();
79732
- _require10 = createRequire10(import.meta.url);
79819
+ _require10 = createRequire11(import.meta.url);
79733
79820
  _ParserClass2 = null;
79734
79821
  _QueryClass2 = null;
79735
79822
  _parserInstance2 = null;
@@ -79835,7 +79922,7 @@ __export(dependencies_exports, {
79835
79922
  getDependencySpecs: () => getDependencySpecs
79836
79923
  });
79837
79924
  import { execFileSync as execFileSync10 } from "node:child_process";
79838
- import { createRequire as createRequire11 } from "node:module";
79925
+ import { createRequire as createRequire12 } from "node:module";
79839
79926
  import { dirname as dirname19 } from "node:path";
79840
79927
  import { fileURLToPath as fileURLToPath5 } from "node:url";
79841
79928
  function tryExec(cmd, args, timeoutMs = 3e3) {
@@ -80108,7 +80195,7 @@ var init_dependencies = __esm({
80108
80195
  "packages/core/src/system/dependencies.ts"() {
80109
80196
  "use strict";
80110
80197
  init_platform();
80111
- _require11 = createRequire11(import.meta.url);
80198
+ _require11 = createRequire12(import.meta.url);
80112
80199
  _dirname = dirname19(fileURLToPath5(import.meta.url));
80113
80200
  DEPENDENCY_SPECS = [
80114
80201
  // ── Required ────────────────────────────────────────────────────────────
@@ -80180,7 +80267,7 @@ var init_dependencies = __esm({
80180
80267
  // packages/core/src/system/health.ts
80181
80268
  import { execFileSync as execFileSync11 } from "node:child_process";
80182
80269
  import { existsSync as existsSync92, readFileSync as readFileSync68, statSync as statSync19 } from "node:fs";
80183
- import { createRequire as createRequire12 } from "node:module";
80270
+ import { createRequire as createRequire13 } from "node:module";
80184
80271
  import { join as join94 } from "node:path";
80185
80272
  function resolveStructuredLogPath(cleoDir) {
80186
80273
  const defaultPath = join94(cleoDir, "logs", "cleo.log");
@@ -80721,6 +80808,7 @@ async function coreDoctorReport(projectRoot) {
80721
80808
  });
80722
80809
  checks.push(mapCheckResult(checkGlobalHome()));
80723
80810
  checks.push(mapCheckResult(checkGlobalTemplates()));
80811
+ checks.push(mapCheckResult(checkGlobalIdentity()));
80724
80812
  checks.push(mapSchemaCheckResult(checkGlobalSchemas()));
80725
80813
  checks.push(mapCheckResult(checkLogDir(projectRoot)));
80726
80814
  const hookResults = await checkGitHooks(projectRoot);
@@ -81152,7 +81240,7 @@ var init_health = __esm({
81152
81240
  init_checks3();
81153
81241
  init_dependencies();
81154
81242
  init_storage_preflight();
81155
- _require12 = createRequire12(import.meta.url);
81243
+ _require12 = createRequire13(import.meta.url);
81156
81244
  databaseSyncCtor = (() => {
81157
81245
  try {
81158
81246
  return _require12("node:sqlite").DatabaseSync;
@@ -85793,16 +85881,12 @@ function allEpicChildrenVerified(epicId, tasks2) {
85793
85881
  if (children.length === 0) return false;
85794
85882
  const incomplete = children.filter((t) => t.status !== "done");
85795
85883
  if (incomplete.length > 0) return false;
85796
- const unverified = children.filter(
85797
- (t) => t.status === "done" && (!t.verification || !t.verification.passed)
85798
- );
85884
+ const unverified = children.filter((t) => t.status === "done" && !t.verification?.passed);
85799
85885
  return unverified.length === 0;
85800
85886
  }
85801
85887
  function allSiblingsVerified(parentId, tasks2) {
85802
85888
  const siblings = tasks2.filter((t) => t.parentId === parentId);
85803
- const unverifiedDone = siblings.filter(
85804
- (t) => t.status === "done" && (!t.verification || !t.verification.passed)
85805
- );
85889
+ const unverifiedDone = siblings.filter((t) => t.status === "done" && !t.verification?.passed);
85806
85890
  const incomplete = siblings.filter(
85807
85891
  (t) => t.status === "pending" || t.status === "active" || t.status === "blocked"
85808
85892
  );
@@ -86526,8 +86610,8 @@ import { platform as platform4 } from "node:os";
86526
86610
  import { basename as basename17, dirname as dirname23, join as join108 } from "node:path";
86527
86611
  async function resolveSeedAgentsDir() {
86528
86612
  try {
86529
- const { createRequire: createRequire19 } = await import("node:module");
86530
- const req = createRequire19(import.meta.url);
86613
+ const { createRequire: createRequire20 } = await import("node:module");
86614
+ const req = createRequire20(import.meta.url);
86531
86615
  const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
86532
86616
  const agentsPkgRoot = dirname23(agentsPkgMain);
86533
86617
  const candidate = join108(agentsPkgRoot, "seed-agents");
@@ -86554,8 +86638,8 @@ async function resolveSeedAgentsDir() {
86554
86638
  async function initAgentDefinition(created, warnings) {
86555
86639
  let agentSourceDir = null;
86556
86640
  try {
86557
- const { createRequire: createRequire19 } = await import("node:module");
86558
- const req = createRequire19(import.meta.url);
86641
+ const { createRequire: createRequire20 } = await import("node:module");
86642
+ const req = createRequire20(import.meta.url);
86559
86643
  const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
86560
86644
  const agentsPkgRoot = dirname23(agentsPkgMain);
86561
86645
  const candidate = join108(agentsPkgRoot, "cleo-subagent");
@@ -86621,8 +86705,8 @@ async function initCoreSkills(created, warnings) {
86621
86705
  const packageRoot = getPackageRoot();
86622
86706
  let ctSkillsRoot = null;
86623
86707
  try {
86624
- const { createRequire: createRequire19 } = await import("node:module");
86625
- const req = createRequire19(import.meta.url);
86708
+ const { createRequire: createRequire20 } = await import("node:module");
86709
+ const req = createRequire20(import.meta.url);
86626
86710
  const skillsPkgMain = req.resolve("@cleocode/skills/package.json");
86627
86711
  const skillsPkgRoot = dirname23(skillsPkgMain);
86628
86712
  if (existsSync108(join108(skillsPkgRoot, "skills.json"))) {
@@ -87130,8 +87214,8 @@ async function deployStarterBundle(cleoDir, created, warnings) {
87130
87214
  if (hasCantFiles) return;
87131
87215
  let starterBundleSrc = null;
87132
87216
  try {
87133
- const { createRequire: createRequire19 } = await import("node:module");
87134
- const req = createRequire19(import.meta.url);
87217
+ const { createRequire: createRequire20 } = await import("node:module");
87218
+ const req = createRequire20(import.meta.url);
87135
87219
  const cleoOsPkgMain = req.resolve("@cleocode/cleo-os/package.json");
87136
87220
  const cleoOsPkgRoot = dirname23(cleoOsPkgMain);
87137
87221
  const candidate = join108(cleoOsPkgRoot, "starter-bundle");
@@ -87171,20 +87255,20 @@ async function deployStarterBundle(cleoDir, created, warnings) {
87171
87255
  }
87172
87256
  }
87173
87257
  }
87174
- const identitySrc = join108(starterBundleSrc, "CLEOOS-IDENTITY.md");
87175
- const identityDst = join108(cleoDir, "CLEOOS-IDENTITY.md");
87176
- if (existsSync108(identitySrc) && !existsSync108(identityDst)) {
87177
- await copyFile4(identitySrc, identityDst);
87178
- }
87179
87258
  try {
87180
- const { getCleoHome: getCleoHome2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
87181
- const globalIdentityDst = join108(getCleoHome2(), "CLEOOS-IDENTITY.md");
87182
- if (existsSync108(identitySrc) && !existsSync108(globalIdentityDst)) {
87183
- await copyFile4(identitySrc, globalIdentityDst);
87259
+ const { ensureGlobalIdentity: ensureGlobalIdentity2 } = await Promise.resolve().then(() => (init_scaffold(), scaffold_exports));
87260
+ const identityResult = await ensureGlobalIdentity2();
87261
+ if (identityResult.action === "created") {
87262
+ created.push(`identity: ${identityResult.path}`);
87263
+ } else if (identityResult.action === "skipped" && identityResult.details) {
87264
+ warnings.push(`identity skipped: ${identityResult.details}`);
87184
87265
  }
87185
- } catch {
87266
+ } catch (err) {
87267
+ warnings.push(`identity deploy failed: ${err instanceof Error ? err.message : String(err)}`);
87186
87268
  }
87187
- created.push("starter-bundle: team + agent .cant files + identity deployed to .cleo/");
87269
+ created.push(
87270
+ "starter-bundle: team + agent .cant files deployed to .cleo/ (identity at global XDG)"
87271
+ );
87188
87272
  }
87189
87273
  var DIR_SYMLINK_TYPE2;
87190
87274
  var init_init = __esm({
@@ -87208,7 +87292,7 @@ var init_init = __esm({
87208
87292
  // packages/core/src/sessions/context-alert.ts
87209
87293
  import { existsSync as existsSync109, readFileSync as readFileSync80, writeFileSync as writeFileSync20 } from "node:fs";
87210
87294
  import { join as join109 } from "node:path";
87211
- function getCurrentSessionId(cwd) {
87295
+ function getCurrentSessionId2(cwd) {
87212
87296
  if (process.env.CLEO_SESSION) return process.env.CLEO_SESSION;
87213
87297
  const sessionFile = join109(getCleoDir(cwd), ".current-session");
87214
87298
  if (existsSync109(sessionFile)) {
@@ -87242,7 +87326,7 @@ function createCliMeta(operation, duration_ms = 0) {
87242
87326
  duration_ms,
87243
87327
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
87244
87328
  };
87245
- const sessionId = getCurrentSessionId();
87329
+ const sessionId = getCurrentSessionId2();
87246
87330
  if (sessionId) {
87247
87331
  meta3["sessionId"] = sessionId;
87248
87332
  }
@@ -90912,6 +90996,160 @@ var init_brain_backfill = __esm({
90912
90996
  }
90913
90997
  });
90914
90998
 
90999
+ // packages/core/src/memory/brain-export.ts
91000
+ async function exportBrainAsGexf(projectRoot) {
91001
+ const db = await getBrainDb(projectRoot);
91002
+ let nodes = [];
91003
+ let edges = [];
91004
+ try {
91005
+ nodes = await db.select({
91006
+ id: brainPageNodes.id,
91007
+ nodeType: brainPageNodes.nodeType,
91008
+ label: brainPageNodes.label,
91009
+ qualityScore: brainPageNodes.qualityScore,
91010
+ contentHash: brainPageNodes.contentHash,
91011
+ lastActivityAt: brainPageNodes.lastActivityAt,
91012
+ metadataJson: brainPageNodes.metadataJson,
91013
+ createdAt: brainPageNodes.createdAt,
91014
+ updatedAt: brainPageNodes.updatedAt
91015
+ }).from(brainPageNodes);
91016
+ } catch {
91017
+ nodes = [];
91018
+ }
91019
+ try {
91020
+ const rawEdges = await db.select({
91021
+ fromId: brainPageEdges.fromId,
91022
+ toId: brainPageEdges.toId,
91023
+ edgeType: brainPageEdges.edgeType,
91024
+ weight: brainPageEdges.weight,
91025
+ createdAt: brainPageEdges.createdAt
91026
+ }).from(brainPageEdges);
91027
+ edges = rawEdges.map((e) => ({ ...e, provenance: null }));
91028
+ } catch {
91029
+ edges = [];
91030
+ }
91031
+ const gexf = buildGexfDocument(nodes, edges);
91032
+ return {
91033
+ success: true,
91034
+ format: "gexf",
91035
+ nodeCount: nodes.length,
91036
+ edgeCount: edges.length,
91037
+ content: gexf,
91038
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
91039
+ };
91040
+ }
91041
+ async function exportBrainAsJson(projectRoot) {
91042
+ const db = await getBrainDb(projectRoot);
91043
+ let nodes = [];
91044
+ let edges = [];
91045
+ try {
91046
+ nodes = await db.select({
91047
+ id: brainPageNodes.id,
91048
+ nodeType: brainPageNodes.nodeType,
91049
+ label: brainPageNodes.label,
91050
+ qualityScore: brainPageNodes.qualityScore,
91051
+ contentHash: brainPageNodes.contentHash,
91052
+ lastActivityAt: brainPageNodes.lastActivityAt,
91053
+ metadataJson: brainPageNodes.metadataJson,
91054
+ createdAt: brainPageNodes.createdAt,
91055
+ updatedAt: brainPageNodes.updatedAt
91056
+ }).from(brainPageNodes);
91057
+ } catch {
91058
+ nodes = [];
91059
+ }
91060
+ try {
91061
+ const rawEdges = await db.select({
91062
+ fromId: brainPageEdges.fromId,
91063
+ toId: brainPageEdges.toId,
91064
+ edgeType: brainPageEdges.edgeType,
91065
+ weight: brainPageEdges.weight,
91066
+ createdAt: brainPageEdges.createdAt
91067
+ }).from(brainPageEdges);
91068
+ edges = rawEdges.map((e) => ({ ...e, provenance: null }));
91069
+ } catch {
91070
+ edges = [];
91071
+ }
91072
+ return {
91073
+ success: true,
91074
+ format: "json",
91075
+ nodeCount: nodes.length,
91076
+ edgeCount: edges.length,
91077
+ nodes,
91078
+ edges,
91079
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
91080
+ };
91081
+ }
91082
+ function buildGexfDocument(nodes, edges) {
91083
+ const lines = [
91084
+ '<?xml version="1.0" encoding="UTF-8"?>',
91085
+ '<gexf xmlns="http://www.gexf.net/1.3draft" version="1.3">',
91086
+ ' <meta lastmodifieddate="' + (/* @__PURE__ */ new Date()).toISOString() + '">',
91087
+ " <creator>CLEO Brain Export (T626-M6)</creator>",
91088
+ " <description>Living brain knowledge graph (brain_page_nodes + brain_page_edges)</description>",
91089
+ " </meta>",
91090
+ ' <graph mode="static" defaultedgetype="directed">'
91091
+ ];
91092
+ lines.push(' <attributes class="node">');
91093
+ lines.push(' <attribute id="node_type" title="Node Type" type="string"/>');
91094
+ lines.push(' <attribute id="quality_score" title="Quality Score" type="double"/>');
91095
+ lines.push(' <attribute id="content_hash" title="Content Hash" type="string"/>');
91096
+ lines.push(' <attribute id="last_activity_at" title="Last Activity" type="string"/>');
91097
+ lines.push(' <attribute id="created_at" title="Created At" type="string"/>');
91098
+ lines.push(" </attributes>");
91099
+ lines.push(' <attributes class="edge">');
91100
+ lines.push(' <attribute id="edge_type" title="Edge Type" type="string"/>');
91101
+ lines.push(' <attribute id="provenance" title="Provenance" type="string"/>');
91102
+ lines.push(' <attribute id="created_at" title="Created At" type="string"/>');
91103
+ lines.push(" </attributes>");
91104
+ lines.push(" <nodes>");
91105
+ for (const node of nodes) {
91106
+ lines.push(` <node id="${escapeXml(node.id)}" label="${escapeXml(node.label)}">`);
91107
+ lines.push(" <attvalues>");
91108
+ lines.push(` <attvalue for="node_type" value="${escapeXml(node.nodeType)}"/>`);
91109
+ lines.push(` <attvalue for="quality_score" value="${node.qualityScore ?? 0.5}"/>`);
91110
+ if (node.contentHash) {
91111
+ lines.push(` <attvalue for="content_hash" value="${escapeXml(node.contentHash)}"/>`);
91112
+ }
91113
+ lines.push(
91114
+ ` <attvalue for="last_activity_at" value="${escapeXml(node.lastActivityAt)}"/>`
91115
+ );
91116
+ lines.push(` <attvalue for="created_at" value="${escapeXml(node.createdAt)}"/>`);
91117
+ lines.push(" </attvalues>");
91118
+ lines.push(" </node>");
91119
+ }
91120
+ lines.push(" </nodes>");
91121
+ lines.push(" <edges>");
91122
+ for (let i = 0; i < edges.length; i++) {
91123
+ const edge = edges[i];
91124
+ const weight = edge.weight ?? 1;
91125
+ lines.push(
91126
+ ` <edge id="${i}" source="${escapeXml(edge.fromId)}" target="${escapeXml(edge.toId)}" weight="${weight}">`
91127
+ );
91128
+ lines.push(" <attvalues>");
91129
+ lines.push(` <attvalue for="edge_type" value="${escapeXml(edge.edgeType)}"/>`);
91130
+ if (edge.provenance) {
91131
+ lines.push(` <attvalue for="provenance" value="${escapeXml(edge.provenance)}"/>`);
91132
+ }
91133
+ lines.push(` <attvalue for="created_at" value="${escapeXml(edge.createdAt)}"/>`);
91134
+ lines.push(" </attvalues>");
91135
+ lines.push(" </edge>");
91136
+ }
91137
+ lines.push(" </edges>");
91138
+ lines.push(" </graph>");
91139
+ lines.push("</gexf>");
91140
+ return lines.join("\n");
91141
+ }
91142
+ function escapeXml(text3) {
91143
+ return text3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
91144
+ }
91145
+ var init_brain_export = __esm({
91146
+ "packages/core/src/memory/brain-export.ts"() {
91147
+ "use strict";
91148
+ init_brain_schema();
91149
+ init_brain_sqlite();
91150
+ }
91151
+ });
91152
+
90915
91153
  // packages/core/src/memory/brain-maintenance.ts
90916
91154
  async function runBrainMaintenance(projectRoot, options) {
90917
91155
  const {
@@ -91162,7 +91400,7 @@ var init_brain_purge = __esm({
91162
91400
 
91163
91401
  // packages/core/src/memory/claude-mem-migration.ts
91164
91402
  import { existsSync as existsSync111 } from "node:fs";
91165
- import { createRequire as createRequire13 } from "node:module";
91403
+ import { createRequire as createRequire14 } from "node:module";
91166
91404
  function typedAll3(db, sql16) {
91167
91405
  return db.prepare(sql16).all();
91168
91406
  }
@@ -91321,7 +91559,7 @@ Use --source <path> to specify a custom location.`
91321
91559
  }
91322
91560
  try {
91323
91561
  for (const row of batch) {
91324
- if (!row.learned || !row.learned.trim()) {
91562
+ if (!row.learned?.trim()) {
91325
91563
  continue;
91326
91564
  }
91327
91565
  const learnId = `CML-${row.id}`;
@@ -91392,7 +91630,7 @@ var init_claude_mem_migration = __esm({
91392
91630
  init_paths();
91393
91631
  init_brain_sqlite();
91394
91632
  init_brain_search();
91395
- _require13 = createRequire13(import.meta.url);
91633
+ _require13 = createRequire14(import.meta.url);
91396
91634
  ({ DatabaseSync: DatabaseSync5 } = _require13("node:sqlite"));
91397
91635
  VALID_OBSERVATION_TYPES = /* @__PURE__ */ new Set([
91398
91636
  "discovery",
@@ -97146,7 +97384,7 @@ var init_t310_readiness = __esm({
97146
97384
  // packages/core/src/store/backup-pack.ts
97147
97385
  import crypto5 from "node:crypto";
97148
97386
  import fs4 from "node:fs";
97149
- import { createRequire as createRequire14 } from "node:module";
97387
+ import { createRequire as createRequire15 } from "node:module";
97150
97388
  import os2 from "node:os";
97151
97389
  import path4 from "node:path";
97152
97390
  function resolveContractsSchemasDir() {
@@ -97586,7 +97824,7 @@ var init_backup_pack = __esm({
97586
97824
  init_nexus_sqlite();
97587
97825
  init_signaldock_sqlite();
97588
97826
  init_t310_readiness();
97589
- _require14 = createRequire14(import.meta.url);
97827
+ _require14 = createRequire15(import.meta.url);
97590
97828
  ({ DatabaseSync: DatabaseSync6 } = _require14("node:sqlite"));
97591
97829
  }
97592
97830
  });
@@ -97655,7 +97893,7 @@ var init_cleanup_legacy = __esm({
97655
97893
 
97656
97894
  // packages/core/src/store/migrate-signaldock-to-conduit.ts
97657
97895
  import { existsSync as existsSync117, mkdirSync as mkdirSync27, renameSync as renameSync9, unlinkSync as unlinkSync9 } from "node:fs";
97658
- import { createRequire as createRequire15 } from "node:module";
97896
+ import { createRequire as createRequire16 } from "node:module";
97659
97897
  import { join as join115 } from "node:path";
97660
97898
  function needsSignaldockToConduitMigration(projectRoot) {
97661
97899
  const legacyPath = join115(projectRoot, ".cleo", "signaldock.db");
@@ -97995,7 +98233,7 @@ var init_migrate_signaldock_to_conduit = __esm({
97995
98233
  init_conduit_sqlite();
97996
98234
  init_global_salt();
97997
98235
  init_signaldock_sqlite();
97998
- _require15 = createRequire15(import.meta.url);
98236
+ _require15 = createRequire16(import.meta.url);
97999
98237
  ({ DatabaseSync: DatabaseSync7 } = _require15("node:sqlite"));
98000
98238
  PROJECT_TIER_TABLES = [
98001
98239
  "messages",
@@ -98701,7 +98939,7 @@ function measureDependencyDepth(taskId, taskMap, visited = /* @__PURE__ */ new S
98701
98939
  if (visited.has(taskId)) return 0;
98702
98940
  visited.add(taskId);
98703
98941
  const task = taskMap.get(taskId);
98704
- if (!task || !task.depends || task.depends.length === 0) return 0;
98942
+ if (!task?.depends || task.depends.length === 0) return 0;
98705
98943
  let maxDepth = 0;
98706
98944
  for (const depId of task.depends) {
98707
98945
  const depth = 1 + measureDependencyDepth(depId, taskMap, visited);
@@ -99055,7 +99293,7 @@ async function coreTaskUnarchive(projectRoot, taskId, params) {
99055
99293
  throw new Error(`Task '${taskId}' already exists in active tasks`);
99056
99294
  }
99057
99295
  const archive = await accessor.loadArchive();
99058
- if (!archive || !archive.archivedTasks) {
99296
+ if (!archive?.archivedTasks) {
99059
99297
  throw new Error("No archive file found");
99060
99298
  }
99061
99299
  const taskIndex = archive.archivedTasks.findIndex((t) => t.id === taskId);
@@ -101118,6 +101356,16 @@ async function runUpgrade(options = {}) {
101118
101356
  }
101119
101357
  } catch {
101120
101358
  }
101359
+ try {
101360
+ const { ensureGlobalIdentity: ensureGlobalIdentity2 } = await Promise.resolve().then(() => (init_scaffold(), scaffold_exports));
101361
+ const identityResult = await ensureGlobalIdentity2();
101362
+ actions.push({
101363
+ action: "global_identity",
101364
+ status: identityResult.action === "created" || identityResult.action === "repaired" ? "applied" : "skipped",
101365
+ details: `${identityResult.path} (${identityResult.details ?? identityResult.action})`
101366
+ });
101367
+ } catch {
101368
+ }
101121
101369
  try {
101122
101370
  const skillsCreated = [];
101123
101371
  const skillsWarnings = [];
@@ -110919,7 +111167,7 @@ var require__ = __commonJS({
110919
111167
  // packages/core/src/store/backup-unpack.ts
110920
111168
  import crypto6 from "node:crypto";
110921
111169
  import fs6 from "node:fs";
110922
- import { createRequire as createRequire16 } from "node:module";
111170
+ import { createRequire as createRequire17 } from "node:module";
110923
111171
  import os3 from "node:os";
110924
111172
  import path6 from "node:path";
110925
111173
  import { default as addFormatsImport2 } from "ajv-formats";
@@ -111188,7 +111436,7 @@ var init_backup_unpack = __esm({
111188
111436
  import__ = __toESM(require__(), 1);
111189
111437
  init_index_min();
111190
111438
  init_backup_crypto();
111191
- _require16 = createRequire16(import.meta.url);
111439
+ _require16 = createRequire17(import.meta.url);
111192
111440
  ({ DatabaseSync: DatabaseSync8 } = _require16("node:sqlite"));
111193
111441
  ajv2020Mod = import__.default;
111194
111442
  Ajv2020 = typeof ajv2020Mod.default === "function" ? ajv2020Mod.default : import__.default;
@@ -112512,7 +112760,7 @@ var init_api_key_kdf = __esm({
112512
112760
  // packages/core/src/store/agent-registry-accessor.ts
112513
112761
  import { randomBytes as randomBytes17 } from "node:crypto";
112514
112762
  import { existsSync as existsSync127, mkdirSync as mkdirSync32, readFileSync as readFileSync96, statSync as statSync21, writeFileSync as writeFileSync23 } from "node:fs";
112515
- import { createRequire as createRequire17 } from "node:module";
112763
+ import { createRequire as createRequire18 } from "node:module";
112516
112764
  import { join as join123 } from "node:path";
112517
112765
  function readMachineKey() {
112518
112766
  const keyPath = join123(getCleoHome(), "machine-key");
@@ -112807,7 +113055,7 @@ var init_agent_registry_accessor = __esm({
112807
113055
  init_conduit_sqlite();
112808
113056
  init_global_salt();
112809
113057
  init_signaldock_sqlite();
112810
- _require17 = createRequire17(import.meta.url);
113058
+ _require17 = createRequire18(import.meta.url);
112811
113059
  ({ DatabaseSync: DatabaseSync9 } = _require17("node:sqlite"));
112812
113060
  MACHINE_KEY_LENGTH = 32;
112813
113061
  AgentRegistryAccessor = class {
@@ -113440,6 +113688,8 @@ __export(internal_exports, {
113440
113688
  ensureSqliteDb: () => ensureSqliteDb,
113441
113689
  estimateContext: () => estimateContext,
113442
113690
  executeTransfer: () => executeTransfer,
113691
+ exportBrainAsGexf: () => exportBrainAsGexf,
113692
+ exportBrainAsJson: () => exportBrainAsJson,
113443
113693
  exportSnapshot: () => exportSnapshot,
113444
113694
  exportTasks: () => exportTasks,
113445
113695
  exportTasksPackage: () => exportTasksPackage,
@@ -113509,7 +113759,7 @@ __export(internal_exports, {
113509
113759
  getConfigValue: () => getConfigValue,
113510
113760
  getContextDrift: () => getContextDrift,
113511
113761
  getCriticalPath: () => getCriticalPath,
113512
- getCurrentSessionId: () => getCurrentSessionId,
113762
+ getCurrentSessionId: () => getCurrentSessionId2,
113513
113763
  getDashboard: () => getDashboard,
113514
113764
  getDb: () => getDb,
113515
113765
  getDecisionLog: () => getDecisionLog,
@@ -114017,6 +114267,7 @@ var init_internal = __esm({
114017
114267
  init_stages();
114018
114268
  init_tessera_engine();
114019
114269
  init_brain_backfill();
114270
+ init_brain_export();
114020
114271
  init_brain_lifecycle();
114021
114272
  init_brain_maintenance();
114022
114273
  init_brain_purge();
@@ -131522,7 +131773,7 @@ __export(cli_exports, {
131522
131773
  });
131523
131774
  import { randomUUID as randomUUID14 } from "node:crypto";
131524
131775
  import { existsSync as existsSync130 } from "node:fs";
131525
- import { createRequire as createRequire18 } from "node:module";
131776
+ import { createRequire as createRequire19 } from "node:module";
131526
131777
  import { dirname as dirname27, join as join127 } from "node:path";
131527
131778
  import { fileURLToPath as fileURLToPath7 } from "node:url";
131528
131779
  import { catalog as catalog4, registerSkillLibraryFromPath } from "@cleocode/caamp";
@@ -131531,7 +131782,7 @@ function ensureCaampLibrary() {
131531
131782
  try {
131532
131783
  let skillsRoot = null;
131533
131784
  try {
131534
- const req = createRequire18(import.meta.url);
131785
+ const req = createRequire19(import.meta.url);
131535
131786
  const skillsPkgJson = req.resolve("@cleocode/skills/package.json");
131536
131787
  const candidate = dirname27(skillsPkgJson);
131537
131788
  if (existsSync130(join127(candidate, "skills.json"))) {
@@ -136332,6 +136583,47 @@ Recent Events (newest first, limit=${limit})`);
136332
136583
  process.exit(1);
136333
136584
  }
136334
136585
  });
136586
+ brain.command("export").description("Export brain graph as GEXF (Gephi) or JSON format").option(
136587
+ "--format <format>",
136588
+ "Export format: gexf (Gephi standard) or json (flat arrays)",
136589
+ "gexf"
136590
+ ).option("--output <file>", "Write to file instead of stdout (optional)").action(async (opts) => {
136591
+ const root = getProjectRoot();
136592
+ const format = opts.format ?? "gexf";
136593
+ if (format !== "gexf" && format !== "json") {
136594
+ console.error(`Invalid format: ${format}. Use 'gexf' or 'json'.`);
136595
+ process.exit(1);
136596
+ }
136597
+ try {
136598
+ let content;
136599
+ let nodeCount;
136600
+ let edgeCount;
136601
+ if (format === "gexf") {
136602
+ const result = await exportBrainAsGexf(root);
136603
+ content = result.content;
136604
+ nodeCount = result.nodeCount;
136605
+ edgeCount = result.edgeCount;
136606
+ } else {
136607
+ const result = await exportBrainAsJson(root);
136608
+ content = JSON.stringify(result, null, 2);
136609
+ nodeCount = result.nodeCount;
136610
+ edgeCount = result.edgeCount;
136611
+ }
136612
+ if (opts.output) {
136613
+ const fs11 = await import("node:fs");
136614
+ fs11.writeFileSync(opts.output, content, "utf-8");
136615
+ console.log(
136616
+ `Exported to ${opts.output}: ${nodeCount} nodes, ${edgeCount} edges (${format.toUpperCase()})`
136617
+ );
136618
+ } else {
136619
+ console.log(content);
136620
+ }
136621
+ } catch (err) {
136622
+ const message = err instanceof Error ? err.message : String(err);
136623
+ console.error(`Brain export failed: ${message}`);
136624
+ process.exit(1);
136625
+ }
136626
+ });
136335
136627
  }
136336
136628
 
136337
136629
  // packages/cleo/src/cli/commands/briefing.ts
@@ -139643,6 +139935,175 @@ var NODE_KIND_PRIORITY = {
139643
139935
  file: 40,
139644
139936
  folder: 41
139645
139937
  };
139938
+ function generateGexf(nodes, relations) {
139939
+ const nodeById = /* @__PURE__ */ new Map();
139940
+ for (const n of nodes) {
139941
+ nodeById.set(String(n["id"]), n);
139942
+ }
139943
+ const kindColors = {
139944
+ function: "#3498db",
139945
+ // blue
139946
+ method: "#2980b9",
139947
+ // darker blue
139948
+ class: "#e74c3c",
139949
+ // red
139950
+ interface: "#e67e22",
139951
+ // orange
139952
+ file: "#95a5a6",
139953
+ // gray
139954
+ folder: "#34495e",
139955
+ // dark gray
139956
+ community: "#9b59b6",
139957
+ // purple
139958
+ process: "#1abc9c",
139959
+ // teal
139960
+ import: "#f39c12",
139961
+ // amber
139962
+ default: "#7f8c8d"
139963
+ // medium gray
139964
+ };
139965
+ const getNodeColor = (kind) => {
139966
+ return kindColors[kind] ?? kindColors["default"];
139967
+ };
139968
+ let gexf = '<?xml version="1.0" encoding="UTF-8"?>\n';
139969
+ gexf += '<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:viz="http://www.gexf.net/1.2draft/viz" version="1.2">\n';
139970
+ gexf += ' <meta lastmodifieddate="' + (/* @__PURE__ */ new Date()).toISOString().split("T")[0] + '">\n';
139971
+ gexf += " <creator>CLEO nexus export</creator>\n";
139972
+ gexf += " <description>Code intelligence graph from CLEO nexus</description>\n";
139973
+ gexf += " </meta>\n";
139974
+ gexf += ' <graph mode="static" defaultedgetype="directed">\n';
139975
+ gexf += ' <attributes class="node">\n';
139976
+ gexf += ' <attribute id="kind" title="Node Kind" type="string" />\n';
139977
+ gexf += ' <attribute id="filePath" title="File Path" type="string" />\n';
139978
+ gexf += ' <attribute id="language" title="Language" type="string" />\n';
139979
+ gexf += ' <attribute id="startLine" title="Start Line" type="integer" />\n';
139980
+ gexf += ' <attribute id="endLine" title="End Line" type="integer" />\n';
139981
+ gexf += ' <attribute id="isExported" title="Is Exported" type="boolean" />\n';
139982
+ gexf += ' <attribute id="projectId" title="Project ID" type="string" />\n';
139983
+ gexf += " </attributes>\n";
139984
+ gexf += ' <attributes class="edge">\n';
139985
+ gexf += ' <attribute id="relationType" title="Relation Type" type="string" />\n';
139986
+ gexf += ' <attribute id="confidence" title="Confidence" type="double" />\n';
139987
+ gexf += ' <attribute id="reason" title="Reason" type="string" />\n';
139988
+ gexf += " </attributes>\n";
139989
+ gexf += " <nodes>\n";
139990
+ for (const node of nodes) {
139991
+ const nodeId = String(node["id"]).replace(/[<>"'&]/g, (c) => {
139992
+ const map2 = {
139993
+ "<": "&lt;",
139994
+ ">": "&gt;",
139995
+ '"': "&quot;",
139996
+ "'": "&apos;",
139997
+ "&": "&amp;"
139998
+ };
139999
+ return map2[c];
140000
+ });
140001
+ const label = String(node["label"] ?? node["id"]);
140002
+ const kind = String(node["kind"] ?? "unknown");
140003
+ const color = getNodeColor(kind);
140004
+ gexf += ` <node id="${nodeId}" label="${escapeXml2(label)}">
140005
+ `;
140006
+ gexf += ` <viz:color r="${hexToRgb(color).r}" g="${hexToRgb(color).g}" b="${hexToRgb(color).b}" />
140007
+ `;
140008
+ gexf += " <attvalues>\n";
140009
+ gexf += ` <attvalue id="kind" value="${escapeXml2(kind)}" />
140010
+ `;
140011
+ if (node["filePath"]) {
140012
+ gexf += ` <attvalue id="filePath" value="${escapeXml2(String(node["filePath"]))}" />
140013
+ `;
140014
+ }
140015
+ if (node["language"]) {
140016
+ gexf += ` <attvalue id="language" value="${escapeXml2(String(node["language"]))}" />
140017
+ `;
140018
+ }
140019
+ if (node["startLine"] != null) {
140020
+ gexf += ` <attvalue id="startLine" value="${node["startLine"]}" />
140021
+ `;
140022
+ }
140023
+ if (node["endLine"] != null) {
140024
+ gexf += ` <attvalue id="endLine" value="${node["endLine"]}" />
140025
+ `;
140026
+ }
140027
+ if (node["isExported"] != null) {
140028
+ gexf += ` <attvalue id="isExported" value="${node["isExported"] ? "true" : "false"}" />
140029
+ `;
140030
+ }
140031
+ if (node["projectId"]) {
140032
+ gexf += ` <attvalue id="projectId" value="${escapeXml2(String(node["projectId"]))}" />
140033
+ `;
140034
+ }
140035
+ gexf += " </attvalues>\n";
140036
+ gexf += " </node>\n";
140037
+ }
140038
+ gexf += " </nodes>\n";
140039
+ gexf += " <edges>\n";
140040
+ for (let i = 0; i < relations.length; i++) {
140041
+ const rel = relations[i];
140042
+ const sourceId = String(rel["sourceId"]).replace(/[<>"'&]/g, (c) => {
140043
+ const map2 = {
140044
+ "<": "&lt;",
140045
+ ">": "&gt;",
140046
+ '"': "&quot;",
140047
+ "'": "&apos;",
140048
+ "&": "&amp;"
140049
+ };
140050
+ return map2[c];
140051
+ });
140052
+ const targetId = String(rel["targetId"]).replace(/[<>"'&]/g, (c) => {
140053
+ const map2 = {
140054
+ "<": "&lt;",
140055
+ ">": "&gt;",
140056
+ '"': "&quot;",
140057
+ "'": "&apos;",
140058
+ "&": "&amp;"
140059
+ };
140060
+ return map2[c];
140061
+ });
140062
+ if (!nodeById.has(String(rel["sourceId"])) || !nodeById.has(String(rel["targetId"]))) {
140063
+ continue;
140064
+ }
140065
+ const confidence = typeof rel["confidence"] === "number" ? rel["confidence"] : 1;
140066
+ const relationType = String(rel["type"] ?? "unknown");
140067
+ const reason = rel["reason"] ? String(rel["reason"]) : "";
140068
+ gexf += ` <edge id="e${i}" source="${sourceId}" target="${targetId}" weight="${confidence}">
140069
+ `;
140070
+ gexf += " <attvalues>\n";
140071
+ gexf += ` <attvalue id="relationType" value="${escapeXml2(relationType)}" />
140072
+ `;
140073
+ gexf += ` <attvalue id="confidence" value="${confidence}" />
140074
+ `;
140075
+ if (reason) {
140076
+ gexf += ` <attvalue id="reason" value="${escapeXml2(reason)}" />
140077
+ `;
140078
+ }
140079
+ gexf += " </attvalues>\n";
140080
+ gexf += " </edge>\n";
140081
+ }
140082
+ gexf += " </edges>\n";
140083
+ gexf += " </graph>\n";
140084
+ gexf += "</gexf>\n";
140085
+ return gexf;
140086
+ }
140087
+ function escapeXml2(str) {
140088
+ return String(str).replace(/[<>"'&]/g, (c) => {
140089
+ const map2 = {
140090
+ "<": "&lt;",
140091
+ ">": "&gt;",
140092
+ '"': "&quot;",
140093
+ "'": "&apos;",
140094
+ "&": "&amp;"
140095
+ };
140096
+ return map2[c];
140097
+ });
140098
+ }
140099
+ function hexToRgb(hex3) {
140100
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex3);
140101
+ return result ? {
140102
+ r: parseInt(result[1], 16),
140103
+ g: parseInt(result[2], 16),
140104
+ b: parseInt(result[3], 16)
140105
+ } : { r: 127, g: 140, b: 141 };
140106
+ }
139646
140107
  function sortMatchingNodes(nodes, symbolName) {
139647
140108
  const lowerSymbol = symbolName.toLowerCase();
139648
140109
  return [...nodes].sort((a, b2) => {
@@ -140877,6 +141338,84 @@ function registerNexusCommand(program) {
140877
141338
  process.exitCode = 1;
140878
141339
  }
140879
141340
  });
141341
+ nexus.command("export").description("Export nexus graph to GEXF (Gephi) or JSON format").option("--format <format>", "Output format: gexf, json", "gexf").option("--output <file>", "Output file path (stdout if omitted)").option("--project <id>", "Filter by project ID (exports all projects if omitted)").action(async (opts) => {
141342
+ const startTime = Date.now();
141343
+ const format = opts["format"] ?? "gexf";
141344
+ const outputFile = opts["output"];
141345
+ const projectFilter = opts["project"];
141346
+ try {
141347
+ const { getNexusDb: getNexusDb2, nexusSchema } = await import("@cleocode/core/store/nexus-sqlite");
141348
+ const db = await getNexusDb2();
141349
+ let allNodes = [];
141350
+ let allRelations = [];
141351
+ try {
141352
+ allNodes = db.select().from(nexusSchema.nexusNodes).all();
141353
+ allRelations = db.select().from(nexusSchema.nexusRelations).all();
141354
+ } catch {
141355
+ }
141356
+ const nodes = projectFilter ? allNodes.filter((n) => n["projectId"] === projectFilter) : allNodes;
141357
+ const relations = projectFilter ? allRelations.filter((r) => r["projectId"] === projectFilter) : allRelations;
141358
+ let output = "";
141359
+ if (format === "json") {
141360
+ output = JSON.stringify(
141361
+ {
141362
+ nodes: nodes.map((n) => ({
141363
+ id: n["id"],
141364
+ kind: n["kind"],
141365
+ label: n["label"],
141366
+ name: n["name"],
141367
+ filePath: n["filePath"],
141368
+ language: n["language"],
141369
+ isExported: n["isExported"],
141370
+ startLine: n["startLine"],
141371
+ endLine: n["endLine"],
141372
+ projectId: n["projectId"]
141373
+ })),
141374
+ edges: relations.map((r) => ({
141375
+ id: r["id"],
141376
+ source: r["sourceId"],
141377
+ target: r["targetId"],
141378
+ type: r["type"],
141379
+ confidence: r["confidence"],
141380
+ reason: r["reason"]
141381
+ }))
141382
+ },
141383
+ null,
141384
+ 2
141385
+ );
141386
+ } else if (format === "gexf") {
141387
+ output = generateGexf(nodes, relations);
141388
+ } else {
141389
+ process.stderr.write(
141390
+ `[nexus] Error: Unknown format '${format}'. Supported: gexf, json
141391
+ `
141392
+ );
141393
+ process.exitCode = 1;
141394
+ return;
141395
+ }
141396
+ if (outputFile) {
141397
+ const { writeFileSync: writeFileSync26 } = await import("node:fs");
141398
+ writeFileSync26(outputFile, output, "utf-8");
141399
+ process.stdout.write(
141400
+ `[nexus] Exported to ${outputFile} (${nodes.length} nodes, ${relations.length} edges)
141401
+ `
141402
+ );
141403
+ } else {
141404
+ process.stdout.write(output);
141405
+ if (!output.endsWith("\n")) process.stdout.write("\n");
141406
+ }
141407
+ const durationMs = Date.now() - startTime;
141408
+ if (outputFile) {
141409
+ process.stderr.write(`[nexus] Export completed in ${durationMs}ms
141410
+ `);
141411
+ }
141412
+ } catch (err) {
141413
+ const msg = err instanceof Error ? err.message : String(err);
141414
+ process.stderr.write(`[nexus] Error: ${msg}
141415
+ `);
141416
+ process.exitCode = 1;
141417
+ }
141418
+ });
140880
141419
  nexus.command("diff").description(
140881
141420
  "Compare NEXUS index state between two git commits \u2014 shows new/removed relations and broken call chains"
140882
141421
  ).option("--before <sha>", 'Git SHA or ref for the "before" snapshot (default: HEAD~1)').option("--after <sha>", 'Git SHA or ref for the "after" snapshot (default: HEAD)', "HEAD").option("--path <dir>", "Repository directory to analyze (default: cwd)").option("--json", "Output result as JSON (LAFS envelope format)").option("--project-id <id>", "Override the project ID (default: auto-detected from path)").action(async (opts) => {