@cleocode/cleo 2026.4.27 → 2026.4.29

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
@@ -1571,10 +1571,10 @@ var init_subquery = __esm({
1571
1571
  init_entity();
1572
1572
  Subquery = class {
1573
1573
  static [entityKind] = "Subquery";
1574
- constructor(sql12, fields, alias, isWith = false, usedTables = []) {
1574
+ constructor(sql13, fields, alias, isWith = false, usedTables = []) {
1575
1575
  this._ = {
1576
1576
  brand: "Subquery",
1577
- sql: sql12,
1577
+ sql: sql13,
1578
1578
  selectedFields: fields,
1579
1579
  alias,
1580
1580
  isWith,
@@ -1925,7 +1925,7 @@ var init_sql = __esm({
1925
1925
  return new SQL([new StringChunk(str)]);
1926
1926
  }
1927
1927
  _sql.raw = raw;
1928
- function join131(chunks, separator) {
1928
+ function join132(chunks, separator) {
1929
1929
  const result = [];
1930
1930
  for (const [i, chunk] of chunks.entries()) {
1931
1931
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -1933,7 +1933,7 @@ var init_sql = __esm({
1933
1933
  }
1934
1934
  return new SQL(result);
1935
1935
  }
1936
- _sql.join = join131;
1936
+ _sql.join = join132;
1937
1937
  function identifier(value) {
1938
1938
  return new Name(value);
1939
1939
  }
@@ -1954,8 +1954,8 @@ var init_sql = __esm({
1954
1954
  isSelectionField = false;
1955
1955
  /** @internal */
1956
1956
  origin;
1957
- constructor(sql12, fieldAlias) {
1958
- this.sql = sql12;
1957
+ constructor(sql13, fieldAlias) {
1958
+ this.sql = sql13;
1959
1959
  this.fieldAlias = fieldAlias;
1960
1960
  }
1961
1961
  getSQL() {
@@ -2659,17 +2659,17 @@ var init_custom = __esm({
2659
2659
  mapFromJsonValue(value) {
2660
2660
  return typeof this.mapJson === "function" ? this.mapJson(value) : this.mapFromDriverValue(value);
2661
2661
  }
2662
- jsonSelectIdentifier(identifier, sql12) {
2663
- if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier, sql12);
2662
+ jsonSelectIdentifier(identifier, sql13) {
2663
+ if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier, sql13);
2664
2664
  const rawType = this.getSQLType().toLowerCase();
2665
2665
  const parenPos = rawType.indexOf("(");
2666
2666
  switch (parenPos + 1 ? rawType.slice(0, parenPos) : rawType) {
2667
2667
  case "numeric":
2668
2668
  case "decimal":
2669
2669
  case "bigint":
2670
- return sql12`cast(${identifier} as text)`;
2670
+ return sql13`cast(${identifier} as text)`;
2671
2671
  case "blob":
2672
- return sql12`hex(${identifier})`;
2672
+ return sql13`hex(${identifier})`;
2673
2673
  default:
2674
2674
  return identifier;
2675
2675
  }
@@ -3837,8 +3837,8 @@ var init_custom2 = __esm({
3837
3837
  mapFromJsonValue(value) {
3838
3838
  return typeof this.mapJson === "function" ? this.mapJson(value) : this.mapFromDriverValue(value);
3839
3839
  }
3840
- jsonSelectIdentifier(identifier, sql12, arrayDimensions) {
3841
- if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier, sql12, arrayDimensions);
3840
+ jsonSelectIdentifier(identifier, sql13, arrayDimensions) {
3841
+ if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier, sql13, arrayDimensions);
3842
3842
  const rawType = this.getSQLType().toLowerCase();
3843
3843
  const parenPos = rawType.indexOf("(");
3844
3844
  switch (parenPos + 1 ? rawType.slice(0, parenPos) : rawType) {
@@ -3848,7 +3848,7 @@ var init_custom2 = __esm({
3848
3848
  case "numeric":
3849
3849
  case "bigint": {
3850
3850
  const arrVal = "[]".repeat(arrayDimensions ?? 0);
3851
- return sql12`${identifier}::text${sql12.raw(arrVal).if(arrayDimensions)}`;
3851
+ return sql13`${identifier}::text${sql13.raw(arrVal).if(arrayDimensions)}`;
3852
3852
  }
3853
3853
  default:
3854
3854
  return identifier;
@@ -6707,7 +6707,7 @@ var init_select2 = __esm({
6707
6707
  const baseTableName = this.tableName;
6708
6708
  const tableName = getTableLikeName(table);
6709
6709
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
6710
- if (typeof tableName === "string" && this.config.joins?.some((join131) => join131.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
6710
+ if (typeof tableName === "string" && this.config.joins?.some((join132) => join132.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
6711
6711
  if (!this.isPartialSelect) {
6712
6712
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
6713
6713
  if (typeof tableName === "string" && !is(table, SQL)) {
@@ -7729,8 +7729,8 @@ var init_dialect = __esm({
7729
7729
  const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
7730
7730
  return sql`${withSql}insert into ${table} ${insertOrder} ${valuesSql}${onConflict?.length ? sql.join(onConflict) : void 0}${returningSql}`;
7731
7731
  }
7732
- sqlToQuery(sql12, invokeSource) {
7733
- return sql12.toQuery({
7732
+ sqlToQuery(sql13, invokeSource) {
7733
+ return sql13.toQuery({
7734
7734
  casing: this.casing,
7735
7735
  escapeName: this.escapeName,
7736
7736
  escapeParam: this.escapeParam,
@@ -7992,7 +7992,7 @@ var init_dialect = __esm({
7992
7992
  if (!joins2) return;
7993
7993
  const withEntries = Object.entries(joins2).filter(([_2, v2]) => v2);
7994
7994
  if (!withEntries.length) return;
7995
- return sql.join(withEntries.map(([k2, join131]) => {
7995
+ return sql.join(withEntries.map(([k2, join132]) => {
7996
7996
  const relation = tableConfig.relations[k2];
7997
7997
  const isSingle2 = is(relation, One3);
7998
7998
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -8003,7 +8003,7 @@ var init_dialect = __esm({
8003
8003
  table: targetTable,
8004
8004
  mode: isSingle2 ? "first" : "many",
8005
8005
  schema,
8006
- queryConfig: join131,
8006
+ queryConfig: join132,
8007
8007
  tableConfig: schema[relation.targetTableName],
8008
8008
  relationWhere: filter,
8009
8009
  isNested: true,
@@ -8017,7 +8017,7 @@ var init_dialect = __esm({
8017
8017
  key: k2,
8018
8018
  selection: innerQuery.selection,
8019
8019
  isArray: !isSingle2,
8020
- isOptional: (relation.optional ?? false) || join131 !== true && !!join131.where
8020
+ isOptional: (relation.optional ?? false) || join132 !== true && !!join132.where
8021
8021
  });
8022
8022
  const jsonColumns = sql.join(innerQuery.selection.map((s3) => {
8023
8023
  return sql`${sql.raw(this.escapeString(s3.key))}, ${s3.selection ? sql`${jsonb2}(${sql.identifier(s3.key)})` : sql.identifier(s3.key)}`;
@@ -8416,7 +8416,7 @@ var init_update = __esm({
8416
8416
  createJoin(joinType) {
8417
8417
  return ((table, on) => {
8418
8418
  const tableName = getTableLikeName(table);
8419
- if (typeof tableName === "string" && this.config.joins.some((join131) => join131.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
8419
+ if (typeof tableName === "string" && this.config.joins.some((join132) => join132.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
8420
8420
  if (typeof on === "function") {
8421
8421
  const from = this.config.from ? is(table, SQLiteTable) ? table[Table.Symbol.Columns] : is(table, Subquery) ? table._.selectedFields : is(table, SQLiteViewBase) ? table[ViewBaseConfig].selectedFields : void 0 : void 0;
8422
8422
  on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
@@ -8827,8 +8827,8 @@ var init_db = __esm({
8827
8827
  });
8828
8828
 
8829
8829
  // node_modules/.pnpm/drizzle-orm@1.0.0-beta.19-d95b7a4_@sinclair+typebox@0.34.49_@types+mssql@9.1.9_@azure+c_7d603f9dc53f6bedf2f8e8db5954b691/node_modules/drizzle-orm/cache/core/cache.js
8830
- async function hashQuery(sql12, params) {
8831
- const dataToHash = `${sql12}-${JSON.stringify(params, (_2, v2) => typeof v2 === "bigint" ? `${v2}n` : v2)}`;
8830
+ async function hashQuery(sql13, params) {
8831
+ const dataToHash = `${sql13}-${JSON.stringify(params, (_2, v2) => typeof v2 === "bigint" ? `${v2}n` : v2)}`;
8832
8832
  const data = new TextEncoder().encode(dataToHash);
8833
8833
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
8834
8834
  return [...new Uint8Array(hashBuffer)].map((b2) => b2.toString(16).padStart(2, "0")).join("");
@@ -9007,8 +9007,8 @@ var init_session3 = __esm({
9007
9007
  values(query) {
9008
9008
  return this.prepareOneTimeQuery(this.dialect.sqlToQuery(query), void 0, "run", false).values();
9009
9009
  }
9010
- async count(sql12) {
9011
- return (await this.values(sql12))[0][0];
9010
+ async count(sql13) {
9011
+ return (await this.values(sql13))[0][0];
9012
9012
  }
9013
9013
  /** @internal */
9014
9014
  extractRawValuesValueFromBatchResult(_result) {
@@ -11102,8 +11102,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
11102
11102
  const dbEntries = nativeDb.prepare('SELECT hash FROM "__drizzle_migrations"').all();
11103
11103
  const hasOrphanedEntries = dbEntries.some((e) => !localHashes.has(e.hash));
11104
11104
  if (hasOrphanedEntries) {
11105
- const log11 = getLogger(logSubsystem);
11106
- log11.warn(
11105
+ const log12 = getLogger(logSubsystem);
11106
+ log12.warn(
11107
11107
  { orphaned: dbEntries.filter((e) => !localHashes.has(e.hash)).length },
11108
11108
  `Detected stale migration journal entries from a previous CLEO version. Reconciling.`
11109
11109
  );
@@ -11135,8 +11135,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
11135
11135
  return cols.some((c) => c.name === column);
11136
11136
  });
11137
11137
  if (allColumnsExist) {
11138
- const log11 = getLogger(logSubsystem);
11139
- log11.warn(
11138
+ const log12 = getLogger(logSubsystem);
11139
+ log12.warn(
11140
11140
  { migration: migration.name, columns: alterMatches },
11141
11141
  `Detected partially-applied migration ${migration.name} \u2014 columns exist but journal entry missing. Auto-reconciling.`
11142
11142
  );
@@ -11181,8 +11181,8 @@ function ensureColumns(nativeDb, tableName, requiredColumns, logSubsystem) {
11181
11181
  const existingCols = new Set(columns.map((c) => c.name));
11182
11182
  for (const req of requiredColumns) {
11183
11183
  if (!existingCols.has(req.name)) {
11184
- const log11 = getLogger(logSubsystem);
11185
- log11.warn(
11184
+ const log12 = getLogger(logSubsystem);
11185
+ log12.warn(
11186
11186
  { column: req.name },
11187
11187
  `Adding missing column ${tableName}.${req.name} via ALTER TABLE`
11188
11188
  );
@@ -11301,12 +11301,12 @@ function detachAgentFromProject(db, agentId) {
11301
11301
  }
11302
11302
  function listProjectAgentRefs(db, opts) {
11303
11303
  const enabledOnly = opts?.enabledOnly ?? true;
11304
- const sql12 = enabledOnly ? `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
11304
+ const sql13 = enabledOnly ? `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
11305
11305
  FROM project_agent_refs WHERE enabled = 1
11306
11306
  ORDER BY attached_at DESC` : `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
11307
11307
  FROM project_agent_refs
11308
11308
  ORDER BY attached_at DESC`;
11309
- const rows = db.prepare(sql12).all();
11309
+ const rows = db.prepare(sql13).all();
11310
11310
  return rows.map((r) => ({
11311
11311
  agentId: r.agent_id,
11312
11312
  attachedAt: r.attached_at,
@@ -13395,7 +13395,7 @@ function getDbPath(cwd) {
13395
13395
  return join10(getCleoDirAbsolute(cwd), DB_FILENAME2);
13396
13396
  }
13397
13397
  async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13398
- const log11 = getLogger("sqlite");
13398
+ const log12 = getLogger("sqlite");
13399
13399
  try {
13400
13400
  const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks").get();
13401
13401
  const taskCount = countResult?.cnt ?? 0;
@@ -13416,7 +13416,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13416
13416
  if (backupTaskCount < MIN_BACKUP_TASK_COUNT) {
13417
13417
  return;
13418
13418
  }
13419
- log11.warn(
13419
+ log12.warn(
13420
13420
  { dbPath, backupPath: newestBackup.path, backupTasks: backupTaskCount },
13421
13421
  `Empty database detected with ${backupTaskCount}-task backup available. Auto-recovering from backup. This likely happened because git-tracked WAL/SHM files were overwritten during a branch switch (T5188).`
13422
13422
  );
@@ -13434,7 +13434,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13434
13434
  const tempPath = dbPath + ".recovery-tmp";
13435
13435
  copyFileSync4(newestBackup.path, tempPath);
13436
13436
  renameSync(tempPath, dbPath);
13437
- log11.info(
13437
+ log12.info(
13438
13438
  { dbPath, backupPath: newestBackup.path, restoredTasks: backupTaskCount },
13439
13439
  "Database auto-recovered from backup successfully."
13440
13440
  );
@@ -13444,7 +13444,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13444
13444
  runMigrations(restoredNativeDb, restoredDb);
13445
13445
  _db = restoredDb;
13446
13446
  } catch (err) {
13447
- log11.error({ err, dbPath }, "Auto-recovery from backup failed. Continuing with empty database.");
13447
+ log12.error({ err, dbPath }, "Auto-recovery from backup failed. Continuing with empty database.");
13448
13448
  }
13449
13449
  }
13450
13450
  async function getDb(cwd) {
@@ -13478,7 +13478,7 @@ async function getDb(cwd) {
13478
13478
  const { execFileSync: execFileSync19 } = await import("node:child_process");
13479
13479
  const gitCwd = resolve3(dbPath, "..", "..");
13480
13480
  const filesToCheck = [dbPath, dbPath + "-wal", dbPath + "-shm"];
13481
- const log11 = getLogger("sqlite");
13481
+ const log12 = getLogger("sqlite");
13482
13482
  for (const fileToCheck of filesToCheck) {
13483
13483
  try {
13484
13484
  execFileSync19("git", ["ls-files", "--error-unmatch", fileToCheck], {
@@ -13487,7 +13487,7 @@ async function getDb(cwd) {
13487
13487
  });
13488
13488
  const basename19 = fileToCheck.split(/[\\/]/).pop();
13489
13489
  const relPath = fileToCheck.replace(gitCwd + sep, "");
13490
- log11.warn(
13490
+ log12.warn(
13491
13491
  { path: fileToCheck },
13492
13492
  `${basename19} is tracked by project git \u2014 this risks data loss on branch switch. Resolution (ADR-013 \xA79): \`git rm --cached ${relPath}\` and rely on \`.cleo/backups/sqlite/\` snapshots + \`cleo backup add\` for recovery.`
13493
13493
  );
@@ -15244,8 +15244,8 @@ async function cleanupMigrationArtifacts(backupPath) {
15244
15244
  }
15245
15245
  async function validateSqliteDatabase(dbPath) {
15246
15246
  try {
15247
- const { createRequire: createRequire13 } = await import("node:module");
15248
- const _req = createRequire13(import.meta.url);
15247
+ const { createRequire: createRequire14 } = await import("node:module");
15248
+ const _req = createRequire14(import.meta.url);
15249
15249
  const { DatabaseSync: DatabaseSync10 } = _req("node:sqlite");
15250
15250
  const db = new DatabaseSync10(dbPath, { readOnly: true });
15251
15251
  const integrityRow = db.prepare("PRAGMA integrity_check").get();
@@ -17270,7 +17270,7 @@ function collectAdrFiles(dir) {
17270
17270
  }
17271
17271
  async function syncAdrsToDb(projectRoot) {
17272
17272
  const adrsDir = join20(projectRoot, ".cleo", "adrs");
17273
- const result = { inserted: 0, updated: 0, skipped: 0, errors: [] };
17273
+ const result = { inserted: 0, updated: 0, skipped: 0, errors: [], warnings: [] };
17274
17274
  if (!existsSync18(adrsDir)) {
17275
17275
  return result;
17276
17276
  }
@@ -17288,9 +17288,36 @@ async function syncAdrsToDb(projectRoot) {
17288
17288
  const fm = record2.frontmatter;
17289
17289
  const dbRelPath = `.cleo/adrs/${relPath}`;
17290
17290
  const content = readFileSync6(filePath, "utf-8");
17291
- const supersedesId = fm.Supersedes ? extractAdrIdFromRef(fm.Supersedes) : null;
17292
- const supersededById = fm["Superseded By"] ? extractAdrIdFromRef(fm["Superseded By"]) : null;
17293
- const amendsId = fm.Amends ? extractAdrIdFromRef(fm.Amends) : null;
17291
+ let supersedesId = fm.Supersedes ? extractAdrIdFromRef(fm.Supersedes) : null;
17292
+ let supersededById = fm["Superseded By"] ? extractAdrIdFromRef(fm["Superseded By"]) : null;
17293
+ let amendsId = fm.Amends ? extractAdrIdFromRef(fm.Amends) : null;
17294
+ if (supersedesId) {
17295
+ const exists2 = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq17(architectureDecisions.id, supersedesId)).all();
17296
+ if (exists2.length === 0) {
17297
+ result.warnings.push(
17298
+ `${record2.id}: supersedes target ${supersedesId} not found in DB, setting to null`
17299
+ );
17300
+ supersedesId = null;
17301
+ }
17302
+ }
17303
+ if (supersededById) {
17304
+ const exists2 = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq17(architectureDecisions.id, supersededById)).all();
17305
+ if (exists2.length === 0) {
17306
+ result.warnings.push(
17307
+ `${record2.id}: supersededBy target ${supersededById} not found in DB, setting to null`
17308
+ );
17309
+ supersededById = null;
17310
+ }
17311
+ }
17312
+ if (amendsId) {
17313
+ const exists2 = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq17(architectureDecisions.id, amendsId)).all();
17314
+ if (exists2.length === 0) {
17315
+ result.warnings.push(
17316
+ `${record2.id}: amends target ${amendsId} not found in DB, setting to null`
17317
+ );
17318
+ amendsId = null;
17319
+ }
17320
+ }
17294
17321
  const rowBase = {
17295
17322
  id: record2.id,
17296
17323
  title: record2.title,
@@ -17320,6 +17347,13 @@ async function syncAdrsToDb(projectRoot) {
17320
17347
  await db.delete(adrTaskLinks).where(eq17(adrTaskLinks.adrId, record2.id));
17321
17348
  if (fm["Related Tasks"]) {
17322
17349
  for (const taskId of parseTaskIds2(fm["Related Tasks"])) {
17350
+ const taskExists2 = await db.select({ id: tasks.id }).from(tasks).where(eq17(tasks.id, taskId)).all();
17351
+ if (taskExists2.length === 0) {
17352
+ result.warnings.push(
17353
+ `${record2.id}: related task ${taskId} not found in DB, skipping link`
17354
+ );
17355
+ continue;
17356
+ }
17323
17357
  await db.insert(adrTaskLinks).values({ adrId: record2.id, taskId, linkType: "related" });
17324
17358
  }
17325
17359
  }
@@ -20687,8 +20721,7 @@ function taskListItemNext(taskId) {
20687
20721
  }
20688
20722
  function sessionListItemNext(sessionId) {
20689
20723
  return {
20690
- show: `cleo session show ${sessionId}`,
20691
- serialize: `cleo session serialize ${sessionId}`
20724
+ show: `cleo session show ${sessionId}`
20692
20725
  };
20693
20726
  }
20694
20727
  function sessionStartNext() {
@@ -20942,8 +20975,8 @@ function checkFts5Available(nativeDb) {
20942
20975
  }
20943
20976
  return _fts5Available;
20944
20977
  }
20945
- function execDDL(nativeDb, sql12) {
20946
- nativeDb.prepare(sql12).run();
20978
+ function execDDL(nativeDb, sql13) {
20979
+ nativeDb.prepare(sql13).run();
20947
20980
  }
20948
20981
  function ensureFts5Tables(nativeDb) {
20949
20982
  if (!checkFts5Available(nativeDb)) {
@@ -22058,8 +22091,8 @@ __export(memory_bridge_exports, {
22058
22091
  });
22059
22092
  import { existsSync as existsSync30, mkdirSync as mkdirSync8, readFileSync as readFileSync17, writeFileSync as writeFileSync3 } from "node:fs";
22060
22093
  import { join as join33 } from "node:path";
22061
- function typedAll2(db, sql12, ...params) {
22062
- return db.prepare(sql12).all(...params);
22094
+ function typedAll2(db, sql13, ...params) {
22095
+ return db.prepare(sql13).all(...params);
22063
22096
  }
22064
22097
  async function generateMemoryBridgeContent(projectRoot, config2) {
22065
22098
  const cfg = { ...DEFAULT_CONFIG, ...config2 };
@@ -38789,9 +38822,9 @@ async function readProjectMeta(projectPath) {
38789
38822
  }
38790
38823
  async function readProjectId(projectPath) {
38791
38824
  try {
38792
- const { readFileSync: readFileSync102, existsSync: existsSync131 } = await import("node:fs");
38825
+ const { readFileSync: readFileSync102, existsSync: existsSync133 } = await import("node:fs");
38793
38826
  const infoPath = join64(projectPath, ".cleo", "project-info.json");
38794
- if (!existsSync131(infoPath)) return "";
38827
+ if (!existsSync133(infoPath)) return "";
38795
38828
  const data = JSON.parse(readFileSync102(infoPath, "utf-8"));
38796
38829
  return typeof data.projectId === "string" ? data.projectId : "";
38797
38830
  } catch {
@@ -40033,7 +40066,7 @@ var init_sharing = __esm({
40033
40066
 
40034
40067
  // packages/core/src/reconciliation/link-store.ts
40035
40068
  import { randomUUID as randomUUID5 } from "node:crypto";
40036
- import { and as and8, eq as eq11 } from "drizzle-orm";
40069
+ import { and as and8, eq as eq11, sql as sql11 } from "drizzle-orm";
40037
40070
  async function getLinksByProvider(providerId, cwd) {
40038
40071
  const db = await getDb(cwd);
40039
40072
  const rows = await db.select().from(externalTaskLinks).where(eq11(externalTaskLinks.providerId, providerId));
@@ -40054,7 +40087,46 @@ async function getLinksByTaskId(taskId, cwd) {
40054
40087
  const rows = await db.select().from(externalTaskLinks).where(eq11(externalTaskLinks.taskId, taskId));
40055
40088
  return rows.map(rowToLink);
40056
40089
  }
40090
+ async function ensureExternalTaskLinksTable(cwd) {
40091
+ const db = await getDb(cwd);
40092
+ try {
40093
+ db.run(
40094
+ sql11.raw(`
40095
+ CREATE TABLE IF NOT EXISTS external_task_links (
40096
+ id text PRIMARY KEY NOT NULL,
40097
+ task_id text NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
40098
+ provider_id text NOT NULL,
40099
+ external_id text NOT NULL,
40100
+ external_url text,
40101
+ external_title text,
40102
+ link_type text NOT NULL,
40103
+ sync_direction text NOT NULL DEFAULT 'inbound',
40104
+ metadata_json text DEFAULT '{}',
40105
+ linked_at text NOT NULL DEFAULT (datetime('now')),
40106
+ last_sync_at text
40107
+ )
40108
+ `)
40109
+ );
40110
+ db.run(
40111
+ sql11.raw(
40112
+ `CREATE UNIQUE INDEX IF NOT EXISTS uq_ext_links_task_provider_external ON external_task_links(task_id, provider_id, external_id)`
40113
+ )
40114
+ );
40115
+ db.run(
40116
+ sql11.raw(`CREATE INDEX IF NOT EXISTS idx_ext_links_task_id ON external_task_links(task_id)`)
40117
+ );
40118
+ db.run(
40119
+ sql11.raw(
40120
+ `CREATE INDEX IF NOT EXISTS idx_ext_links_provider_id ON external_task_links(provider_id)`
40121
+ )
40122
+ );
40123
+ } catch (err) {
40124
+ log6.warn({ err }, "Failed to ensure external_task_links table exists");
40125
+ throw err;
40126
+ }
40127
+ }
40057
40128
  async function createLink(params, cwd) {
40129
+ await ensureExternalTaskLinksTable(cwd);
40058
40130
  const db = await getDb(cwd);
40059
40131
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
40060
40132
  const id = randomUUID5();
@@ -40117,11 +40189,14 @@ function rowToLink(row) {
40117
40189
  lastSyncAt: row.lastSyncAt
40118
40190
  };
40119
40191
  }
40192
+ var log6;
40120
40193
  var init_link_store = __esm({
40121
40194
  "packages/core/src/reconciliation/link-store.ts"() {
40122
40195
  "use strict";
40196
+ init_logger();
40123
40197
  init_sqlite2();
40124
40198
  init_tasks_schema();
40199
+ log6 = getLogger("link-store");
40125
40200
  }
40126
40201
  });
40127
40202
 
@@ -40222,48 +40297,55 @@ async function executeTransferInternal(params) {
40222
40297
  return result;
40223
40298
  }
40224
40299
  let linksCreated = 0;
40225
- const targetAccessor = await getAccessor(targetProject.path);
40226
- const { tasks: targetTasks } = await targetAccessor.queryTasks({});
40227
- const targetTaskIds = new Set(targetTasks.map((t) => t.id));
40228
- for (const entry of entries) {
40229
- if (importResult.idRemap[entry.sourceId] && targetTaskIds.has(entry.targetId)) {
40230
- await createLink(
40231
- {
40232
- taskId: entry.targetId,
40233
- providerId: `nexus:${sourceProject.name}`,
40234
- externalId: entry.sourceId,
40235
- externalTitle: entry.title,
40236
- linkType: "transferred",
40237
- syncDirection: "inbound",
40238
- metadata: {
40239
- transferMode: mode,
40240
- transferScope: scope,
40241
- sourceProject: sourceProject.name,
40242
- transferredAt: (/* @__PURE__ */ new Date()).toISOString()
40243
- }
40244
- },
40245
- targetProject.path
40246
- );
40247
- linksCreated++;
40248
- await createLink(
40249
- {
40250
- taskId: entry.sourceId,
40251
- providerId: `nexus:${targetProject.name}`,
40252
- externalId: entry.targetId,
40253
- externalTitle: entry.title,
40254
- linkType: "transferred",
40255
- syncDirection: "outbound",
40256
- metadata: {
40257
- transferMode: mode,
40258
- transferScope: scope,
40259
- targetProject: targetProject.name,
40260
- transferredAt: (/* @__PURE__ */ new Date()).toISOString()
40261
- }
40262
- },
40263
- sourceProject.path
40264
- );
40265
- linksCreated++;
40300
+ try {
40301
+ const targetAccessor = await getAccessor(targetProject.path);
40302
+ const { tasks: targetTasks } = await targetAccessor.queryTasks({});
40303
+ const targetTaskIds = new Set(targetTasks.map((t) => t.id));
40304
+ for (const entry of entries) {
40305
+ if (importResult.idRemap[entry.sourceId] && targetTaskIds.has(entry.targetId)) {
40306
+ await createLink(
40307
+ {
40308
+ taskId: entry.targetId,
40309
+ providerId: `nexus:${sourceProject.name}`,
40310
+ externalId: entry.sourceId,
40311
+ externalTitle: entry.title,
40312
+ linkType: "transferred",
40313
+ syncDirection: "inbound",
40314
+ metadata: {
40315
+ transferMode: mode,
40316
+ transferScope: scope,
40317
+ sourceProject: sourceProject.name,
40318
+ transferredAt: (/* @__PURE__ */ new Date()).toISOString()
40319
+ }
40320
+ },
40321
+ targetProject.path
40322
+ );
40323
+ linksCreated++;
40324
+ await createLink(
40325
+ {
40326
+ taskId: entry.sourceId,
40327
+ providerId: `nexus:${targetProject.name}`,
40328
+ externalId: entry.targetId,
40329
+ externalTitle: entry.title,
40330
+ linkType: "transferred",
40331
+ syncDirection: "outbound",
40332
+ metadata: {
40333
+ transferMode: mode,
40334
+ transferScope: scope,
40335
+ targetProject: targetProject.name,
40336
+ transferredAt: (/* @__PURE__ */ new Date()).toISOString()
40337
+ }
40338
+ },
40339
+ sourceProject.path
40340
+ );
40341
+ linksCreated++;
40342
+ }
40266
40343
  }
40344
+ } catch (err) {
40345
+ log7.warn(
40346
+ { err, linksCreated },
40347
+ "Failed to create external_task_links during transfer \u2014 tasks were transferred successfully but provenance links could not be written"
40348
+ );
40267
40349
  }
40268
40350
  result.linksCreated = linksCreated;
40269
40351
  try {
@@ -40288,7 +40370,7 @@ async function executeTransferInternal(params) {
40288
40370
  })
40289
40371
  });
40290
40372
  } catch (err) {
40291
- log6.warn({ err }, "nexus transfer audit write failed");
40373
+ log7.warn({ err }, "nexus transfer audit write failed");
40292
40374
  }
40293
40375
  if (mode === "move") {
40294
40376
  let archived = 0;
@@ -40301,7 +40383,7 @@ async function executeTransferInternal(params) {
40301
40383
  });
40302
40384
  archived++;
40303
40385
  } catch (err) {
40304
- log6.warn({ err, taskId: entry.sourceId }, "failed to archive source task after transfer");
40386
+ log7.warn({ err, taskId: entry.sourceId }, "failed to archive source task after transfer");
40305
40387
  }
40306
40388
  }
40307
40389
  }
@@ -40339,14 +40421,14 @@ async function executeTransferInternal(params) {
40339
40421
  }
40340
40422
  }
40341
40423
  } catch (err) {
40342
- log6.warn({ err }, "brain observation transfer failed");
40424
+ log7.warn({ err }, "brain observation transfer failed");
40343
40425
  }
40344
40426
  result.brainObservationsTransferred = brainTransferred;
40345
40427
  result.manifest.brainObservationsTransferred = brainTransferred;
40346
40428
  }
40347
40429
  return result;
40348
40430
  }
40349
- var log6;
40431
+ var log7;
40350
40432
  var init_transfer = __esm({
40351
40433
  "packages/core/src/nexus/transfer.ts"() {
40352
40434
  "use strict";
@@ -40359,7 +40441,7 @@ var init_transfer = __esm({
40359
40441
  init_export2();
40360
40442
  init_permissions();
40361
40443
  init_registry3();
40362
- log6 = getLogger("nexus:transfer");
40444
+ log7 = getLogger("nexus:transfer");
40363
40445
  }
40364
40446
  });
40365
40447
 
@@ -41259,8 +41341,8 @@ async function loadProjectACL(projectPath) {
41259
41341
  async function logAclFailure(projectPath) {
41260
41342
  try {
41261
41343
  const { getLogger: getLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
41262
- const log11 = getLogger2("nexus.acl");
41263
- log11.warn({ projectPath }, "Failed to load ACL configuration, defaulting to deny-all");
41344
+ const log12 = getLogger2("nexus.acl");
41345
+ log12.warn({ projectPath }, "Failed to load ACL configuration, defaulting to deny-all");
41264
41346
  } catch {
41265
41347
  }
41266
41348
  }
@@ -41405,9 +41487,9 @@ async function executeOperation(operation, taskId, projectPath, accessor, direct
41405
41487
  async function logRouteAudit(directive, projectName, taskId, operation, success2, error48) {
41406
41488
  try {
41407
41489
  const { getLogger: getLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
41408
- const log11 = getLogger2("nexus.route");
41490
+ const log12 = getLogger2("nexus.route");
41409
41491
  const level = success2 ? "info" : "warn";
41410
- log11[level](
41492
+ log12[level](
41411
41493
  {
41412
41494
  directive: directive.verb,
41413
41495
  agentId: directive.agentId,
@@ -47726,8 +47808,11 @@ function sanitizeParams(params, projectRoot, context) {
47726
47808
  continue;
47727
47809
  }
47728
47810
  if (typeof value === "string" && (key === "path" || key === "file") && projectRoot) {
47729
- sanitized[key] = sanitizePath(value, projectRoot);
47730
- continue;
47811
+ const allowExternalPath = context?.domain === "nexus" && (context?.operation === "register" || context?.operation === "reconcile");
47812
+ if (!allowExternalPath) {
47813
+ sanitized[key] = sanitizePath(value, projectRoot);
47814
+ continue;
47815
+ }
47731
47816
  }
47732
47817
  if (typeof value === "string" && (key === "title" || key === "description" || key === "content")) {
47733
47818
  const maxLen = key === "title" ? 200 : DEFAULT_MAX_CONTENT_LENGTH;
@@ -50259,8 +50344,8 @@ async function initializeSpawnAdapters(manifests) {
50259
50344
  if (!manifest.capabilities?.supportsSpawn) continue;
50260
50345
  if (spawnRegistry.hasAdapterForProvider(manifest.provider)) continue;
50261
50346
  try {
50262
- const { join: join131 } = await import("node:path");
50263
- const modulePath = join131(manifest.packagePath, manifest.entryPoint);
50347
+ const { join: join132 } = await import("node:path");
50348
+ const modulePath = join132(manifest.packagePath, manifest.entryPoint);
50264
50349
  const adapterModule = await import(modulePath);
50265
50350
  let SpawnProviderClass;
50266
50351
  for (const [exportName, exportValue] of Object.entries(adapterModule)) {
@@ -50415,7 +50500,7 @@ async function queryTasks(cwd, since) {
50415
50500
  }).from(tasks2).where(conditions.length > 0 ? and13(...conditions) : void 0).all();
50416
50501
  return rows;
50417
50502
  } catch (err) {
50418
- log7.warn({ err }, "Failed to query tasks for workflow telemetry");
50503
+ log8.warn({ err }, "Failed to query tasks for workflow telemetry");
50419
50504
  return [];
50420
50505
  }
50421
50506
  }
@@ -50449,7 +50534,7 @@ async function queryCompletionAuditRows(cwd, since) {
50449
50534
  return isComplete;
50450
50535
  });
50451
50536
  } catch (err) {
50452
- log7.warn({ err }, "Failed to query audit log for workflow telemetry");
50537
+ log8.warn({ err }, "Failed to query audit log for workflow telemetry");
50453
50538
  return [];
50454
50539
  }
50455
50540
  }
@@ -50674,12 +50759,12 @@ async function getWorkflowComplianceReport(opts) {
50674
50759
  }
50675
50760
  };
50676
50761
  }
50677
- var log7;
50762
+ var log8;
50678
50763
  var init_workflow_telemetry = __esm({
50679
50764
  "packages/core/src/stats/workflow-telemetry.ts"() {
50680
50765
  "use strict";
50681
50766
  init_logger();
50682
- log7 = getLogger("workflow-telemetry");
50767
+ log8 = getLogger("workflow-telemetry");
50683
50768
  }
50684
50769
  });
50685
50770
 
@@ -51265,13 +51350,22 @@ function rowToStickyNote3(row) {
51265
51350
  }
51266
51351
  async function listStickies(params, projectRoot) {
51267
51352
  const accessor = await getBrainAccessor(projectRoot);
51353
+ const hasTagFilter = params.tags && params.tags.length > 0;
51268
51354
  const rows = await accessor.findStickyNotes({
51269
51355
  status: params.status,
51270
51356
  color: params.color,
51271
51357
  priority: params.priority,
51272
- limit: params.limit
51358
+ limit: hasTagFilter ? void 0 : params.limit
51273
51359
  });
51274
- return rows.map(rowToStickyNote3);
51360
+ let notes = rows.map(rowToStickyNote3);
51361
+ if (hasTagFilter) {
51362
+ const requiredTags = params.tags;
51363
+ notes = notes.filter((note) => requiredTags.every((t) => note.tags.includes(t)));
51364
+ if (params.limit && notes.length > params.limit) {
51365
+ notes = notes.slice(0, params.limit);
51366
+ }
51367
+ }
51368
+ return notes;
51275
51369
  }
51276
51370
  var init_list2 = __esm({
51277
51371
  "packages/core/src/sticky/list.ts"() {
@@ -51984,7 +52078,7 @@ import { createGzip } from "node:zlib";
51984
52078
  async function pruneAuditLog(cleoDir, config2) {
51985
52079
  try {
51986
52080
  if (!config2.auditRetentionDays || config2.auditRetentionDays <= 0) {
51987
- log8.debug("auditRetentionDays is 0 or unset; skipping audit prune");
52081
+ log9.debug("auditRetentionDays is 0 or unset; skipping audit prune");
51988
52082
  return { rowsArchived: 0, rowsDeleted: 0 };
51989
52083
  }
51990
52084
  const cutoff = new Date(Date.now() - config2.auditRetentionDays * 864e5).toISOString();
@@ -51995,7 +52089,7 @@ async function pruneAuditLog(cleoDir, config2) {
51995
52089
  const db = await getDb4(projectRoot);
51996
52090
  const oldRows = await db.select().from(auditLog2).where(lt4(auditLog2.timestamp, cutoff));
51997
52091
  if (oldRows.length === 0) {
51998
- log8.debug("No audit_log rows older than cutoff; nothing to prune");
52092
+ log9.debug("No audit_log rows older than cutoff; nothing to prune");
51999
52093
  return { rowsArchived: 0, rowsDeleted: 0 };
52000
52094
  }
52001
52095
  let archivePath;
@@ -52013,17 +52107,17 @@ async function pruneAuditLog(cleoDir, config2) {
52013
52107
  const inStream = Readable.from([jsonlContent]);
52014
52108
  await pipeline(inStream, gzip, outStream);
52015
52109
  rowsArchived = oldRows.length;
52016
- log8.info(
52110
+ log9.info(
52017
52111
  { archivePath, rowsArchived },
52018
52112
  `Archived ${rowsArchived} audit rows to ${archivePath}`
52019
52113
  );
52020
52114
  } catch (archiveErr) {
52021
- log8.warn({ err: archiveErr }, "Failed to archive audit rows; continuing with deletion");
52115
+ log9.warn({ err: archiveErr }, "Failed to archive audit rows; continuing with deletion");
52022
52116
  archivePath = void 0;
52023
52117
  }
52024
52118
  }
52025
52119
  await db.delete(auditLog2).where(lt4(auditLog2.timestamp, cutoff)).run();
52026
- log8.info(
52120
+ log9.info(
52027
52121
  { rowsDeleted: oldRows.length, cutoff },
52028
52122
  `Pruned ${oldRows.length} audit_log rows older than ${cutoff}`
52029
52123
  );
@@ -52033,16 +52127,16 @@ async function pruneAuditLog(cleoDir, config2) {
52033
52127
  archivePath
52034
52128
  };
52035
52129
  } catch (err) {
52036
- log8.warn({ err }, "audit log pruning failed");
52130
+ log9.warn({ err }, "audit log pruning failed");
52037
52131
  return { rowsArchived: 0, rowsDeleted: 0 };
52038
52132
  }
52039
52133
  }
52040
- var log8;
52134
+ var log9;
52041
52135
  var init_audit_prune = __esm({
52042
52136
  "packages/core/src/audit-prune.ts"() {
52043
52137
  "use strict";
52044
52138
  init_logger();
52045
- log8 = getLogger("prune");
52139
+ log9 = getLogger("prune");
52046
52140
  }
52047
52141
  });
52048
52142
 
@@ -73615,8 +73709,8 @@ import { platform as platform4 } from "node:os";
73615
73709
  import { basename as basename17, dirname as dirname21, join as join105 } from "node:path";
73616
73710
  async function resolveSeedAgentsDir() {
73617
73711
  try {
73618
- const { createRequire: createRequire13 } = await import("node:module");
73619
- const req = createRequire13(import.meta.url);
73712
+ const { createRequire: createRequire14 } = await import("node:module");
73713
+ const req = createRequire14(import.meta.url);
73620
73714
  const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
73621
73715
  const agentsPkgRoot = dirname21(agentsPkgMain);
73622
73716
  const candidate = join105(agentsPkgRoot, "seed-agents");
@@ -73643,8 +73737,8 @@ async function resolveSeedAgentsDir() {
73643
73737
  async function initAgentDefinition(created, warnings) {
73644
73738
  let agentSourceDir = null;
73645
73739
  try {
73646
- const { createRequire: createRequire13 } = await import("node:module");
73647
- const req = createRequire13(import.meta.url);
73740
+ const { createRequire: createRequire14 } = await import("node:module");
73741
+ const req = createRequire14(import.meta.url);
73648
73742
  const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
73649
73743
  const agentsPkgRoot = dirname21(agentsPkgMain);
73650
73744
  const candidate = join105(agentsPkgRoot, "cleo-subagent");
@@ -73702,7 +73796,7 @@ async function initMcpServer(_projectRoot, _created, _warnings) {
73702
73796
  }
73703
73797
  async function initCoreSkills(created, warnings) {
73704
73798
  try {
73705
- const { getInstalledProviders: getInstalledProviders4, installSkill: installSkill3, registerSkillLibraryFromPath } = await import("@cleocode/caamp");
73799
+ const { getInstalledProviders: getInstalledProviders4, installSkill: installSkill3, registerSkillLibraryFromPath: registerSkillLibraryFromPath2 } = await import("@cleocode/caamp");
73706
73800
  const providers = getInstalledProviders4();
73707
73801
  if (providers.length === 0) {
73708
73802
  return;
@@ -73710,8 +73804,8 @@ async function initCoreSkills(created, warnings) {
73710
73804
  const packageRoot = getPackageRoot();
73711
73805
  let ctSkillsRoot = null;
73712
73806
  try {
73713
- const { createRequire: createRequire13 } = await import("node:module");
73714
- const req = createRequire13(import.meta.url);
73807
+ const { createRequire: createRequire14 } = await import("node:module");
73808
+ const req = createRequire14(import.meta.url);
73715
73809
  const skillsPkgMain = req.resolve("@cleocode/skills/package.json");
73716
73810
  const skillsPkgRoot = dirname21(skillsPkgMain);
73717
73811
  if (existsSync106(join105(skillsPkgRoot, "skills.json"))) {
@@ -73738,13 +73832,13 @@ async function initCoreSkills(created, warnings) {
73738
73832
  return;
73739
73833
  }
73740
73834
  try {
73741
- registerSkillLibraryFromPath(ctSkillsRoot);
73835
+ registerSkillLibraryFromPath2(ctSkillsRoot);
73742
73836
  } catch {
73743
73837
  warnings.push("Failed to register skill library with CAAMP");
73744
73838
  }
73745
73839
  const catalogPath = join105(ctSkillsRoot, "skills.json");
73746
- const catalog4 = JSON.parse(readFileSync74(catalogPath, "utf-8"));
73747
- const skills = catalog4.skills ?? [];
73840
+ const catalog5 = JSON.parse(readFileSync74(catalogPath, "utf-8"));
73841
+ const skills = catalog5.skills ?? [];
73748
73842
  const coreSkills = skills.filter((s3) => s3.tier <= 2);
73749
73843
  const installed = [];
73750
73844
  for (const skill of coreSkills) {
@@ -74090,8 +74184,8 @@ async function initProject(opts = {}) {
74090
74184
  if (!hasCantFiles) {
74091
74185
  let starterBundleSrc = null;
74092
74186
  try {
74093
- const { createRequire: createRequire13 } = await import("node:module");
74094
- const req = createRequire13(import.meta.url);
74187
+ const { createRequire: createRequire14 } = await import("node:module");
74188
+ const req = createRequire14(import.meta.url);
74095
74189
  const cleoOsPkgMain = req.resolve("@cleocode/cleo-os/package.json");
74096
74190
  const cleoOsPkgRoot = dirname21(cleoOsPkgMain);
74097
74191
  const candidate = join105(cleoOsPkgRoot, "starter-bundle");
@@ -74464,8 +74558,8 @@ async function bootstrapGlobalCleo(options) {
74464
74558
  }
74465
74559
  async function writeTemplateTo(content, destPath, isDryRun) {
74466
74560
  if (isDryRun) return false;
74467
- const { dirname: dirname29 } = await import("node:path");
74468
- await mkdir17(dirname29(destPath), { recursive: true });
74561
+ const { dirname: dirname30 } = await import("node:path");
74562
+ await mkdir17(dirname30(destPath), { recursive: true });
74469
74563
  await writeFile12(destPath, content);
74470
74564
  return true;
74471
74565
  }
@@ -75180,7 +75274,6 @@ var init_cleo = __esm({
75180
75274
  // packages/core/src/index.ts
75181
75275
  var init_src2 = __esm({
75182
75276
  "packages/core/src/index.ts"() {
75183
- "use strict";
75184
75277
  init_src();
75185
75278
  init_adapters();
75186
75279
  init_admin();
@@ -77763,8 +77856,8 @@ var init_brain_maintenance = __esm({
77763
77856
  // packages/core/src/memory/claude-mem-migration.ts
77764
77857
  import { existsSync as existsSync110 } from "node:fs";
77765
77858
  import { createRequire as createRequire8 } from "node:module";
77766
- function typedAll3(db, sql12) {
77767
- return db.prepare(sql12).all();
77859
+ function typedAll3(db, sql13) {
77860
+ return db.prepare(sql13).all();
77768
77861
  }
77769
77862
  function mapObservationType(type) {
77770
77863
  if (VALID_OBSERVATION_TYPES.has(type)) {
@@ -83906,7 +83999,7 @@ var init_backup_pack = __esm({
83906
83999
  import fs5 from "node:fs";
83907
84000
  import path4 from "node:path";
83908
84001
  function detectAndRemoveLegacyGlobalFiles(cleoHomeOverride) {
83909
- const log11 = getLogger("cleanup-legacy");
84002
+ const log12 = getLogger("cleanup-legacy");
83910
84003
  const cleoHome = cleoHomeOverride ?? getCleoHome();
83911
84004
  const removed = [];
83912
84005
  const errors = [];
@@ -83916,30 +84009,30 @@ function detectAndRemoveLegacyGlobalFiles(cleoHomeOverride) {
83916
84009
  if (fs5.existsSync(fullPath)) {
83917
84010
  fs5.unlinkSync(fullPath);
83918
84011
  removed.push(fileName);
83919
- log11.info({ file: fullPath }, "Removed legacy global file");
84012
+ log12.info({ file: fullPath }, "Removed legacy global file");
83920
84013
  }
83921
84014
  } catch (err) {
83922
84015
  const message = err instanceof Error ? err.message : String(err);
83923
84016
  errors.push({ file: fileName, error: message });
83924
- log11.warn({ file: fullPath, error: message }, "Failed to remove legacy global file");
84017
+ log12.warn({ file: fullPath, error: message }, "Failed to remove legacy global file");
83925
84018
  }
83926
84019
  }
83927
84020
  return { removed, errors };
83928
84021
  }
83929
84022
  function detectAndRemoveStrayProjectNexus(projectRoot) {
83930
- const log11 = getLogger("cleanup-legacy");
84023
+ const log12 = getLogger("cleanup-legacy");
83931
84024
  const strayPath = path4.join(projectRoot, ".cleo", "nexus.db");
83932
84025
  if (fs5.existsSync(strayPath)) {
83933
84026
  try {
83934
84027
  fs5.unlinkSync(strayPath);
83935
- log11.warn(
84028
+ log12.warn(
83936
84029
  { path: strayPath },
83937
84030
  "Removed stray project-tier nexus.db (violates ADR-036 global-only contract)"
83938
84031
  );
83939
84032
  return { removed: true, path: strayPath };
83940
84033
  } catch (err) {
83941
84034
  const message = err instanceof Error ? err.message : String(err);
83942
- log11.warn(
84035
+ log12.warn(
83943
84036
  { path: strayPath, error: message },
83944
84037
  "Failed to remove stray project-tier nexus.db \u2014 manual deletion may be required"
83945
84038
  );
@@ -84010,7 +84103,7 @@ function brokenTimestamp() {
84010
84103
  return `${now2.getFullYear()}${pad2(now2.getMonth() + 1)}${pad2(now2.getDate())}-${pad2(now2.getHours())}${pad2(now2.getMinutes())}${pad2(now2.getSeconds())}-${pad3(now2.getMilliseconds())}`;
84011
84104
  }
84012
84105
  function migrateSignaldockToConduit(projectRoot) {
84013
- const log11 = getLogger("migrate-signaldock-to-conduit");
84106
+ const log12 = getLogger("migrate-signaldock-to-conduit");
84014
84107
  const legacyPath = join113(projectRoot, ".cleo", "signaldock.db");
84015
84108
  const conduitPath = join113(projectRoot, ".cleo", "conduit.db");
84016
84109
  const globalSignaldockPath = join113(getCleoHome(), "signaldock.db");
@@ -84027,13 +84120,13 @@ function migrateSignaldockToConduit(projectRoot) {
84027
84120
  if (!needsSignaldockToConduitMigration(projectRoot)) {
84028
84121
  return result;
84029
84122
  }
84030
- log11.info({ projectRoot, legacyPath }, "T310 migration: starting signaldock.db \u2192 conduit.db");
84123
+ log12.info({ projectRoot, legacyPath }, "T310 migration: starting signaldock.db \u2192 conduit.db");
84031
84124
  let legacy = null;
84032
84125
  try {
84033
84126
  legacy = new DatabaseSync7(legacyPath, { readOnly: true });
84034
84127
  } catch (err) {
84035
84128
  const message = err instanceof Error ? err.message : String(err);
84036
- log11.error({ legacyPath, error: message }, "T310 migration: cannot open legacy signaldock.db");
84129
+ log12.error({ legacyPath, error: message }, "T310 migration: cannot open legacy signaldock.db");
84037
84130
  result.errors.push({ step: "step-2-open-legacy", error: message });
84038
84131
  result.status = "failed";
84039
84132
  return result;
@@ -84041,7 +84134,7 @@ function migrateSignaldockToConduit(projectRoot) {
84041
84134
  try {
84042
84135
  if (!integrityCheckPasses(legacy)) {
84043
84136
  const msg = "Legacy signaldock.db failed PRAGMA integrity_check. Migration aborted \u2014 no changes written. Recovery: inspect the database with sqlite3 and attempt manual repair before re-running.";
84044
- log11.error({ legacyPath }, msg);
84137
+ log12.error({ legacyPath }, msg);
84045
84138
  result.errors.push({ step: "step-3-legacy-integrity", error: msg });
84046
84139
  result.status = "failed";
84047
84140
  legacy.close();
@@ -84049,7 +84142,7 @@ function migrateSignaldockToConduit(projectRoot) {
84049
84142
  }
84050
84143
  } catch (err) {
84051
84144
  const message = err instanceof Error ? err.message : String(err);
84052
- log11.error({ legacyPath, error: message }, "T310 migration: integrity_check threw on legacy DB");
84145
+ log12.error({ legacyPath, error: message }, "T310 migration: integrity_check threw on legacy DB");
84053
84146
  result.errors.push({ step: "step-3-legacy-integrity", error: message });
84054
84147
  result.status = "failed";
84055
84148
  legacy.close();
@@ -84067,7 +84160,7 @@ function migrateSignaldockToConduit(projectRoot) {
84067
84160
  getGlobalSalt();
84068
84161
  } catch (err) {
84069
84162
  const message = err instanceof Error ? err.message : String(err);
84070
- log11.error({ error: message }, "T310 migration: getGlobalSalt failed \u2014 migration aborted");
84163
+ log12.error({ error: message }, "T310 migration: getGlobalSalt failed \u2014 migration aborted");
84071
84164
  result.errors.push({ step: "step-6-global-salt", error: message });
84072
84165
  result.status = "failed";
84073
84166
  legacy.close();
@@ -84081,7 +84174,7 @@ function migrateSignaldockToConduit(projectRoot) {
84081
84174
  conduit.exec("PRAGMA foreign_keys = OFF");
84082
84175
  } catch (err) {
84083
84176
  const message = err instanceof Error ? err.message : String(err);
84084
- log11.error({ conduitPath, error: message }, "T310 migration: failed to create conduit.db");
84177
+ log12.error({ conduitPath, error: message }, "T310 migration: failed to create conduit.db");
84085
84178
  result.errors.push({ step: "step-7-create-conduit", error: message });
84086
84179
  result.status = "failed";
84087
84180
  legacy.close();
@@ -84127,7 +84220,7 @@ function migrateSignaldockToConduit(projectRoot) {
84127
84220
  result.agentsCopied = agentsCountForConduit;
84128
84221
  } catch (err) {
84129
84222
  const message = err instanceof Error ? err.message : String(err);
84130
- log11.error({ error: message }, "T310 migration: conduit.db write failed \u2014 rolling back");
84223
+ log12.error({ error: message }, "T310 migration: conduit.db write failed \u2014 rolling back");
84131
84224
  result.errors.push({ step: "step-8-conduit-write", error: message });
84132
84225
  result.status = "failed";
84133
84226
  try {
@@ -84148,7 +84241,7 @@ function migrateSignaldockToConduit(projectRoot) {
84148
84241
  try {
84149
84242
  if (!integrityCheckPasses(conduit)) {
84150
84243
  const msg = "conduit.db failed PRAGMA integrity_check after write";
84151
- log11.error({ conduitPath }, msg);
84244
+ log12.error({ conduitPath }, msg);
84152
84245
  result.errors.push({ step: "step-10-conduit-integrity", error: msg });
84153
84246
  result.status = "failed";
84154
84247
  conduit.close();
@@ -84163,7 +84256,7 @@ function migrateSignaldockToConduit(projectRoot) {
84163
84256
  }
84164
84257
  } catch (err) {
84165
84258
  const message = err instanceof Error ? err.message : String(err);
84166
- log11.error({ error: message }, "T310 migration: conduit.db integrity_check threw");
84259
+ log12.error({ error: message }, "T310 migration: conduit.db integrity_check threw");
84167
84260
  result.errors.push({ step: "step-10-conduit-integrity", error: message });
84168
84261
  result.status = "failed";
84169
84262
  if (conduit) {
@@ -84185,7 +84278,7 @@ function migrateSignaldockToConduit(projectRoot) {
84185
84278
  globalDb.exec("PRAGMA foreign_keys = OFF");
84186
84279
  } catch (err) {
84187
84280
  const message = err instanceof Error ? err.message : String(err);
84188
- log11.error(
84281
+ log12.error(
84189
84282
  { globalSignaldockPath, error: message },
84190
84283
  "T310 migration: cannot open global signaldock.db"
84191
84284
  );
@@ -84224,7 +84317,7 @@ function migrateSignaldockToConduit(projectRoot) {
84224
84317
  result.agentsCopied = agentsCopiedToGlobal;
84225
84318
  } catch (err) {
84226
84319
  const message = err instanceof Error ? err.message : String(err);
84227
- log11.error(
84320
+ log12.error(
84228
84321
  { error: message },
84229
84322
  "T310 migration: global signaldock.db write failed \u2014 rolling back"
84230
84323
  );
@@ -84242,7 +84335,7 @@ function migrateSignaldockToConduit(projectRoot) {
84242
84335
  try {
84243
84336
  if (!integrityCheckPasses(globalDb)) {
84244
84337
  const msg = "Global signaldock.db failed PRAGMA integrity_check after write";
84245
- log11.error({ globalSignaldockPath }, msg);
84338
+ log12.error({ globalSignaldockPath }, msg);
84246
84339
  result.errors.push({ step: "step-14-global-integrity", error: msg });
84247
84340
  result.status = "failed";
84248
84341
  globalDb.close();
@@ -84257,7 +84350,7 @@ function migrateSignaldockToConduit(projectRoot) {
84257
84350
  }
84258
84351
  } catch (err) {
84259
84352
  const message = err instanceof Error ? err.message : String(err);
84260
- log11.error({ error: message }, "T310 migration: global signaldock.db integrity_check threw");
84353
+ log12.error({ error: message }, "T310 migration: global signaldock.db integrity_check threw");
84261
84354
  result.errors.push({ step: "step-14-global-integrity", error: message });
84262
84355
  result.status = "failed";
84263
84356
  if (globalDb) {
@@ -84276,21 +84369,21 @@ function migrateSignaldockToConduit(projectRoot) {
84276
84369
  result.bakPath = bakPath;
84277
84370
  } catch (err) {
84278
84371
  const message = err instanceof Error ? err.message : String(err);
84279
- log11.error(
84372
+ log12.error(
84280
84373
  { legacyPath, bakPath, error: message },
84281
84374
  "T310 migration: rename to .pre-t310.bak failed \u2014 legacy file left in place (harmless)"
84282
84375
  );
84283
84376
  result.errors.push({ step: "step-16-rename-bak", error: message });
84284
84377
  }
84285
- log11.info(
84378
+ log12.info(
84286
84379
  { projectRoot, agentsCopied: result.agentsCopied, conduitPath, bakPath: result.bakPath },
84287
84380
  `T310 migration complete: ${result.agentsCopied} agents migrated to global, conduit.db created`
84288
84381
  );
84289
- log11.warn(
84382
+ log12.warn(
84290
84383
  {},
84291
84384
  "T310 migration: API keys have been re-keyed. External systems holding old API keys (CI env vars, remote agent configs) must be updated."
84292
84385
  );
84293
- log11.info(
84386
+ log12.info(
84294
84387
  { legacyPath, bakPath: result.bakPath, conduitPath },
84295
84388
  "T310 migration recovery: if problems occur, rename .pre-t310.bak to signaldock.db and delete conduit.db to re-run migration."
84296
84389
  );
@@ -84524,7 +84617,7 @@ async function validateAndRepairSequence(cwd, config2 = {}) {
84524
84617
  }
84525
84618
  const repair = await repairSequence(cwd);
84526
84619
  if (repair.repaired) {
84527
- log9.warn(
84620
+ log10.warn(
84528
84621
  { oldCounter: repair.oldCounter, newCounter: repair.newCounter },
84529
84622
  "Sequence repaired"
84530
84623
  );
@@ -84553,7 +84646,7 @@ async function triggerCheckpoint(context, cwd, config2 = {}) {
84553
84646
  try {
84554
84647
  await gitCheckpoint("auto", context, cwd);
84555
84648
  } catch (err) {
84556
- log9.warn({ err }, "Checkpoint failed (non-fatal)");
84649
+ log10.warn({ err }, "Checkpoint failed (non-fatal)");
84557
84650
  }
84558
84651
  vacuumIntoBackup({ cwd }).catch(() => {
84559
84652
  });
@@ -84591,16 +84684,16 @@ async function safeDeleteTask(deleteFn, taskId, cwd, config2 = {}) {
84591
84684
  return result;
84592
84685
  }
84593
84686
  async function forceCheckpointBeforeOperation(operation, cwd) {
84594
- log9.info({ operation }, "Forcing checkpoint before operation");
84687
+ log10.info({ operation }, "Forcing checkpoint before operation");
84595
84688
  try {
84596
84689
  await gitCheckpoint("manual", `pre-${operation}`, cwd);
84597
84690
  } catch (err) {
84598
- log9.error({ err }, "Failed to create pre-operation checkpoint");
84691
+ log10.error({ err }, "Failed to create pre-operation checkpoint");
84599
84692
  }
84600
84693
  vacuumIntoBackup({ cwd, force: true }).catch(() => {
84601
84694
  });
84602
84695
  }
84603
- var log9, DEFAULT_CONFIG2, SafetyError;
84696
+ var log10, DEFAULT_CONFIG2, SafetyError;
84604
84697
  var init_data_safety = __esm({
84605
84698
  "packages/core/src/store/data-safety.ts"() {
84606
84699
  "use strict";
@@ -84610,7 +84703,7 @@ var init_data_safety = __esm({
84610
84703
  init_sqlite2();
84611
84704
  init_sqlite_backup();
84612
84705
  init_tasks_schema();
84613
- log9 = getLogger("data-safety");
84706
+ log10 = getLogger("data-safety");
84614
84707
  DEFAULT_CONFIG2 = {
84615
84708
  verifyWrites: true,
84616
84709
  detectCollisions: true,
@@ -84653,7 +84746,7 @@ __export(task_store_exports, {
84653
84746
  updateTask: () => updateTask2,
84654
84747
  updateTaskSafe: () => updateTaskSafe
84655
84748
  });
84656
- import { and as and12, asc as asc4, count as count3, eq as eq16, inArray as inArray6, isNull as isNull5, ne as ne4, sql as sql11 } from "drizzle-orm";
84749
+ import { and as and12, asc as asc4, count as count3, eq as eq16, inArray as inArray6, isNull as isNull5, ne as ne4, sql as sql12 } from "drizzle-orm";
84657
84750
  async function insertTaskRow(task, cwd) {
84658
84751
  const db = await getDb(cwd);
84659
84752
  const row = taskToRow(task);
@@ -84756,7 +84849,7 @@ async function findTasks2(query, limit = 20, cwd) {
84756
84849
  const rows = await db.select().from(tasks).where(
84757
84850
  and12(
84758
84851
  ne4(tasks.status, "archived"),
84759
- sql11`(${tasks.id} LIKE ${pattern} OR ${tasks.title} LIKE ${pattern} OR ${tasks.description} LIKE ${pattern})`
84852
+ sql12`(${tasks.id} LIKE ${pattern} OR ${tasks.title} LIKE ${pattern} OR ${tasks.description} LIKE ${pattern})`
84760
84853
  )
84761
84854
  ).limit(limit).all();
84762
84855
  return rows.map(rowToTask);
@@ -85771,11 +85864,11 @@ async function coreTaskHistory(projectRoot, taskId, limit) {
85771
85864
  try {
85772
85865
  const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
85773
85866
  const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
85774
- const { sql: sql12 } = await import("drizzle-orm");
85867
+ const { sql: sql13 } = await import("drizzle-orm");
85775
85868
  const db = await getDb4(projectRoot);
85776
85869
  const maxRows = limit && limit > 0 ? limit : 100;
85777
85870
  const rows = await db.all(
85778
- sql12`SELECT * FROM ${auditLog2}
85871
+ sql13`SELECT * FROM ${auditLog2}
85779
85872
  WHERE ${auditLog2.taskId} = ${taskId}
85780
85873
  ORDER BY ${auditLog2.timestamp} DESC
85781
85874
  LIMIT ${maxRows}`
@@ -86698,10 +86791,10 @@ async function repairMissingSizes(cwd, dryRun) {
86698
86791
  async function repairMissingCompletedAt(cwd, dryRun) {
86699
86792
  const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
86700
86793
  const { tasks: tasks2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
86701
- const { sql: sql12 } = await import("drizzle-orm");
86794
+ const { sql: sql13 } = await import("drizzle-orm");
86702
86795
  const db = await getDb4(cwd);
86703
86796
  const affected = await db.select({ id: tasks2.id }).from(tasks2).where(
86704
- sql12`(${tasks2.status} = 'done' OR ${tasks2.status} = 'cancelled') AND ${tasks2.completedAt} IS NULL`
86797
+ sql13`(${tasks2.status} = 'done' OR ${tasks2.status} = 'cancelled') AND ${tasks2.completedAt} IS NULL`
86705
86798
  );
86706
86799
  if (affected.length === 0) {
86707
86800
  return {
@@ -86719,7 +86812,7 @@ async function repairMissingCompletedAt(cwd, dryRun) {
86719
86812
  }
86720
86813
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
86721
86814
  await db.update(tasks2).set({ completedAt: now2 }).where(
86722
- sql12`(${tasks2.status} = 'done' OR ${tasks2.status} = 'cancelled') AND ${tasks2.completedAt} IS NULL`
86815
+ sql13`(${tasks2.status} = 'done' OR ${tasks2.status} = 'cancelled') AND ${tasks2.completedAt} IS NULL`
86723
86816
  );
86724
86817
  return {
86725
86818
  action: "fix_completed_at",
@@ -86730,8 +86823,8 @@ async function repairMissingCompletedAt(cwd, dryRun) {
86730
86823
  async function repairMissingColumns(cwd, dryRun) {
86731
86824
  const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
86732
86825
  const db = await getDb4(cwd);
86733
- const { sql: sql12 } = await import("drizzle-orm");
86734
- const columns = db.all(sql12`PRAGMA table_info(tasks)`);
86826
+ const { sql: sql13 } = await import("drizzle-orm");
86827
+ const columns = db.all(sql13`PRAGMA table_info(tasks)`);
86735
86828
  const existingCols = new Set(columns.map((c) => c.name));
86736
86829
  const missingCols = ["pipeline_stage"].filter((c) => !existingCols.has(c));
86737
86830
  if (missingCols.length === 0) {
@@ -86749,7 +86842,7 @@ async function repairMissingColumns(cwd, dryRun) {
86749
86842
  };
86750
86843
  }
86751
86844
  for (const col of missingCols) {
86752
- db.run(sql12.raw(`ALTER TABLE tasks ADD COLUMN ${col} text`));
86845
+ db.run(sql13.raw(`ALTER TABLE tasks ADD COLUMN ${col} text`));
86753
86846
  }
86754
86847
  return {
86755
86848
  action: "fix_missing_columns",
@@ -94290,11 +94383,11 @@ var require_core = __commonJS({
94290
94383
  Ajv4.ValidationError = validation_error_1.default;
94291
94384
  Ajv4.MissingRefError = ref_error_1.default;
94292
94385
  exports.default = Ajv4;
94293
- function checkOptions(checkOpts, options, msg, log11 = "error") {
94386
+ function checkOptions(checkOpts, options, msg, log12 = "error") {
94294
94387
  for (const key in checkOpts) {
94295
94388
  const opt = key;
94296
94389
  if (opt in options)
94297
- this.logger[log11](`${msg}: option ${key}. ${checkOpts[opt]}`);
94390
+ this.logger[log12](`${msg}: option ${key}. ${checkOpts[opt]}`);
94298
94391
  }
94299
94392
  }
94300
94393
  function getSchEnv(keyRef) {
@@ -104539,6 +104632,7 @@ var init_error = __esm({
104539
104632
  E_ID_COLLISION: 22,
104540
104633
  // Session Errors (30-39)
104541
104634
  E_SESSION_EXISTS: 30,
104635
+ E_SESSION_CONFLICT: 30,
104542
104636
  E_SESSION_NOT_FOUND: 31,
104543
104637
  E_SCOPE_CONFLICT: 32,
104544
104638
  E_SCOPE_INVALID: 33,
@@ -105140,7 +105234,7 @@ async function taskWorkHistory2(projectRoot) {
105140
105234
  }
105141
105235
  async function sessionStart(projectRoot, params) {
105142
105236
  try {
105143
- let accessor = await getAccessor(projectRoot);
105237
+ const accessor = await getAccessor(projectRoot);
105144
105238
  let scope;
105145
105239
  try {
105146
105240
  scope = parseScope2(params.scope);
@@ -105155,8 +105249,14 @@ async function sessionStart(projectRoot, params) {
105155
105249
  }
105156
105250
  const existingActive = await accessor.getActiveSession();
105157
105251
  if (existingActive) {
105158
- await sessionEnd(projectRoot);
105159
- accessor = await getAccessor(projectRoot);
105252
+ return engineError(
105253
+ "E_SESSION_CONFLICT",
105254
+ `An active session already exists (${existingActive.id}). End it first with 'cleo session end'.`,
105255
+ {
105256
+ fix: "Run 'cleo session end' before starting a new session.",
105257
+ details: { activeSessionId: existingActive.id }
105258
+ }
105259
+ );
105160
105260
  }
105161
105261
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
105162
105262
  const sessionId = generateSessionId2();
@@ -105429,7 +105529,16 @@ async function sessionSuspend(projectRoot, sessionId, reason) {
105429
105529
  }
105430
105530
  async function sessionRecordDecision(projectRoot, params) {
105431
105531
  try {
105432
- const result = await recordDecision(projectRoot, params);
105532
+ let resolvedSessionId = params.sessionId;
105533
+ if (!resolvedSessionId) {
105534
+ const accessor = await getAccessor(projectRoot);
105535
+ const activeSession = await accessor.getActiveSession();
105536
+ resolvedSessionId = activeSession?.id ?? "default";
105537
+ }
105538
+ const result = await recordDecision(projectRoot, {
105539
+ ...params,
105540
+ sessionId: resolvedSessionId
105541
+ });
105433
105542
  return { success: true, data: result };
105434
105543
  } catch (err) {
105435
105544
  return cleoErrorToEngineError(err, "E_INVALID_INPUT", "Failed to record decision");
@@ -105931,8 +106040,7 @@ async function orchestrateParallelStart(epicId, wave, projectRoot) {
105931
106040
  const result = await startParallelExecution(epicId, wave, root, accessor);
105932
106041
  return { success: true, data: result };
105933
106042
  } catch (err) {
105934
- const code = err.code ?? "E_GENERAL";
105935
- return engineError(code, err.message);
106043
+ return cleoErrorToEngineError(err, "E_GENERAL", "Failed to start parallel execution");
105936
106044
  }
105937
106045
  }
105938
106046
  async function orchestrateParallelEnd(epicId, wave, projectRoot) {
@@ -105955,8 +106063,7 @@ async function orchestrateParallelEnd(epicId, wave, projectRoot) {
105955
106063
  }
105956
106064
  return { success: true, data: result };
105957
106065
  } catch (err) {
105958
- const code = err.code ?? "E_GENERAL";
105959
- return engineError(code, err.message);
106066
+ return cleoErrorToEngineError(err, "E_GENERAL", "Failed to end parallel execution");
105960
106067
  }
105961
106068
  }
105962
106069
  async function orchestrateHandoff(params, projectRoot) {
@@ -106879,6 +106986,18 @@ async function systemLabels(projectRoot) {
106879
106986
  async function systemArchiveStats(projectRoot, params) {
106880
106987
  try {
106881
106988
  const accessor = await getAccessor(projectRoot);
106989
+ if (params?.report && params.report !== "summary") {
106990
+ const result2 = await analyzeArchive(
106991
+ {
106992
+ report: params.report,
106993
+ since: params.since,
106994
+ until: params.until,
106995
+ cwd: projectRoot
106996
+ },
106997
+ accessor
106998
+ );
106999
+ return { success: true, data: result2 };
107000
+ }
106882
107001
  const result = await getArchiveStats({ period: params?.period, cwd: projectRoot }, accessor);
106883
107002
  return { success: true, data: result };
106884
107003
  } catch (err) {
@@ -106895,10 +107014,10 @@ async function systemLog(projectRoot, filters) {
106895
107014
  }
106896
107015
  async function queryAuditLogSqlite(projectRoot, filters) {
106897
107016
  try {
106898
- const { join: join131 } = await import("node:path");
106899
- const { existsSync: existsSync131 } = await import("node:fs");
106900
- const dbPath = join131(projectRoot, ".cleo", "tasks.db");
106901
- if (!existsSync131(dbPath)) {
107017
+ const { join: join132 } = await import("node:path");
107018
+ const { existsSync: existsSync133 } = await import("node:fs");
107019
+ const dbPath = join132(projectRoot, ".cleo", "tasks.db");
107020
+ if (!existsSync133(dbPath)) {
106902
107021
  const offset = filters?.offset ?? 0;
106903
107022
  const limit = filters?.limit ?? 20;
106904
107023
  return {
@@ -106908,27 +107027,27 @@ async function queryAuditLogSqlite(projectRoot, filters) {
106908
107027
  }
106909
107028
  const { getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
106910
107029
  const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
106911
- const { sql: sql12 } = await import("drizzle-orm");
107030
+ const { sql: sql13 } = await import("drizzle-orm");
106912
107031
  const db = await getDb4(projectRoot);
106913
107032
  try {
106914
107033
  const conditions = [];
106915
107034
  if (filters?.operation) {
106916
107035
  conditions.push(
106917
- sql12`(${auditLog2.action} = ${filters.operation} OR ${auditLog2.operation} = ${filters.operation})`
107036
+ sql13`(${auditLog2.action} = ${filters.operation} OR ${auditLog2.operation} = ${filters.operation})`
106918
107037
  );
106919
107038
  }
106920
107039
  if (filters?.taskId) {
106921
- conditions.push(sql12`${auditLog2.taskId} = ${filters.taskId}`);
107040
+ conditions.push(sql13`${auditLog2.taskId} = ${filters.taskId}`);
106922
107041
  }
106923
107042
  if (filters?.since) {
106924
- conditions.push(sql12`${auditLog2.timestamp} >= ${filters.since}`);
107043
+ conditions.push(sql13`${auditLog2.timestamp} >= ${filters.since}`);
106925
107044
  }
106926
107045
  if (filters?.until) {
106927
- conditions.push(sql12`${auditLog2.timestamp} <= ${filters.until}`);
107046
+ conditions.push(sql13`${auditLog2.timestamp} <= ${filters.until}`);
106928
107047
  }
106929
- const whereClause = conditions.length > 0 ? sql12.join(conditions, sql12` AND `) : sql12`1=1`;
107048
+ const whereClause = conditions.length > 0 ? sql13.join(conditions, sql13` AND `) : sql13`1=1`;
106930
107049
  const countResult = await db.all(
106931
- sql12`SELECT count(*) as cnt FROM ${auditLog2} WHERE ${whereClause}`
107050
+ sql13`SELECT count(*) as cnt FROM ${auditLog2} WHERE ${whereClause}`
106932
107051
  );
106933
107052
  const total = countResult[0]?.cnt ?? 0;
106934
107053
  if (total === 0) {
@@ -106945,7 +107064,7 @@ async function queryAuditLogSqlite(projectRoot, filters) {
106945
107064
  const offset = filters?.offset ?? 0;
106946
107065
  const limit = filters?.limit ?? 20;
106947
107066
  const rows = await db.all(
106948
- sql12`SELECT * FROM ${auditLog2}
107067
+ sql13`SELECT * FROM ${auditLog2}
106949
107068
  WHERE ${whereClause}
106950
107069
  ORDER BY ${auditLog2.timestamp} DESC
106951
107070
  LIMIT ${limit} OFFSET ${offset}`
@@ -108074,7 +108193,7 @@ async function taskTree(projectRoot, taskId) {
108074
108193
  const result = await coreTaskTree(projectRoot, taskId);
108075
108194
  return { success: true, data: result };
108076
108195
  } catch (err) {
108077
- return cleoErrorToEngineError(err, "E_NOT_INITIALIZED", "Task database not initialized");
108196
+ return cleoErrorToEngineError(err, "E_NOT_FOUND", "Task not found");
108078
108197
  }
108079
108198
  }
108080
108199
  async function taskRelates(projectRoot, taskId) {
@@ -108154,7 +108273,7 @@ async function taskCancel(projectRoot, taskId, reason) {
108154
108273
  const result = await coreTaskCancel(projectRoot, taskId, { reason });
108155
108274
  return { success: true, data: result };
108156
108275
  } catch (err) {
108157
- return cleoErrorToEngineError(err, "E_INTERNAL", "Failed to cancel task");
108276
+ return cleoErrorToEngineError(err, "E_NOT_FOUND", "Failed to cancel task");
108158
108277
  }
108159
108278
  }
108160
108279
  async function taskComplexityEstimate(projectRoot, params) {
@@ -108322,10 +108441,10 @@ var init_template_parser2 = __esm({
108322
108441
  });
108323
108442
 
108324
108443
  // packages/cleo/src/dispatch/engines/validate-engine.ts
108325
- function validateSchemaOp(type, data, projectRoot) {
108444
+ async function validateSchemaOp(type, data, projectRoot) {
108326
108445
  try {
108327
108446
  const root = projectRoot || resolveProjectRoot();
108328
- const result = coreValidateSchema(type, data, root);
108447
+ const result = await coreValidateSchema(type, data, root);
108329
108448
  return { success: true, data: result };
108330
108449
  } catch (err) {
108331
108450
  const message = err instanceof Error ? err.message : String(err);
@@ -109087,7 +109206,7 @@ var init_admin2 = __esm({
109087
109206
  "admin",
109088
109207
  operation,
109089
109208
  "E_NOT_AVAILABLE",
109090
- "Job manager not initialized",
109209
+ "Job manager not available. Background jobs require a running CLEO daemon or long-lived process. Start one with `cleo daemon start` or use `cleo admin health` to check system status.",
109091
109210
  startTime
109092
109211
  );
109093
109212
  }
@@ -109130,7 +109249,7 @@ var init_admin2 = __esm({
109130
109249
  "admin",
109131
109250
  operation,
109132
109251
  "E_NOT_AVAILABLE",
109133
- "Job manager not initialized",
109252
+ "Job manager not available. Background jobs require a running CLEO daemon or long-lived process. Start one with `cleo daemon start` or use `cleo admin health` to check system status.",
109134
109253
  startTime
109135
109254
  );
109136
109255
  }
@@ -109588,7 +109707,7 @@ var init_admin2 = __esm({
109588
109707
  "admin",
109589
109708
  operation,
109590
109709
  "E_NOT_AVAILABLE",
109591
- "Job manager not initialized",
109710
+ "Job manager not available. Background jobs require a running CLEO daemon or long-lived process. Start one with `cleo daemon start` or use `cleo admin health` to check system status.",
109592
109711
  startTime
109593
109712
  );
109594
109713
  }
@@ -109651,10 +109770,17 @@ var init_admin2 = __esm({
109651
109770
  };
109652
109771
  }
109653
109772
  const result = await syncAdrsToDb(projectRoot);
109773
+ const hasErrors2 = result.errors.length > 0;
109654
109774
  return {
109655
109775
  meta: dispatchMeta("mutate", "admin", operation, startTime),
109656
- success: true,
109657
- data: result
109776
+ success: !hasErrors2,
109777
+ data: result,
109778
+ ...hasErrors2 ? {
109779
+ error: {
109780
+ code: "E_ADR_SYNC",
109781
+ message: `${result.errors.length} ADR sync error(s) occurred`
109782
+ }
109783
+ } : {}
109658
109784
  };
109659
109785
  }
109660
109786
  // Merged: import + snapshot.import + import.tasks → import via scope param (T5615)
@@ -109988,7 +110114,7 @@ var init_check = __esm({
109988
110114
  startTime
109989
110115
  );
109990
110116
  }
109991
- const result = validateSchemaOp(type, params?.data, projectRoot);
110117
+ const result = await validateSchemaOp(type, params?.data, projectRoot);
109992
110118
  return wrapResult(result, "query", "check", operation, startTime);
109993
110119
  }
109994
110120
  case "task": {
@@ -110032,12 +110158,26 @@ var init_check = __esm({
110032
110158
  case "compliance.summary": {
110033
110159
  const detail = params?.detail;
110034
110160
  const limit = params?.limit;
110161
+ const summaryType = params?.type ?? "summary";
110035
110162
  if (detail) {
110036
110163
  const result2 = validateComplianceViolations(limit, projectRoot);
110037
110164
  return wrapResult(result2, "query", "check", operation, startTime);
110038
110165
  }
110039
110166
  const result = validateComplianceSummary(projectRoot);
110040
- return wrapResult(result, "query", "check", operation, startTime);
110167
+ if (!result.success || !result.data) {
110168
+ return wrapResult(result, "query", "check", operation, startTime);
110169
+ }
110170
+ const enrichedResult = {
110171
+ ...result,
110172
+ data: {
110173
+ ...result.data,
110174
+ view: summaryType,
110175
+ ...params?.taskId ? { taskId: params.taskId } : {},
110176
+ ...params?.days ? { days: params.days } : {},
110177
+ ...params?.global ? { global: params.global } : {}
110178
+ }
110179
+ };
110180
+ return wrapResult(enrichedResult, "query", "check", operation, startTime);
110041
110181
  }
110042
110182
  case "test": {
110043
110183
  const format = params?.format;
@@ -110221,7 +110361,12 @@ var init_check = __esm({
110221
110361
  return wrapResult(result, "query", "check", operation, startTime);
110222
110362
  }
110223
110363
  case "archive.stats": {
110224
- const result = await systemArchiveStats(projectRoot);
110364
+ const result = await systemArchiveStats(projectRoot, {
110365
+ period: params?.period,
110366
+ report: params?.report,
110367
+ since: params?.since,
110368
+ until: params?.until
110369
+ });
110225
110370
  return wrapResult(result, "query", "check", operation, startTime);
110226
110371
  }
110227
110372
  // T5405: WarpChain validation
@@ -111265,7 +111410,7 @@ async function nexusUnregisterProject(name2) {
111265
111410
  await nexusUnregister(name2);
111266
111411
  return engineSuccess({ message: `Project unregistered: ${name2}` });
111267
111412
  } catch (error48) {
111268
- return engineError("E_INTERNAL", error48 instanceof Error ? error48.message : String(error48));
111413
+ return cleoErrorToEngineError(error48, "E_INTERNAL", `Failed to unregister project: ${name2}`);
111269
111414
  }
111270
111415
  }
111271
111416
  async function nexusSyncProject(name2) {
@@ -111739,16 +111884,16 @@ var init_nexus2 = __esm({
111739
111884
  async function orchestrateClassify(request, context, projectRoot) {
111740
111885
  try {
111741
111886
  const { getCleoCantWorkflowsDir: getCleoCantWorkflowsDir2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
111742
- const { readFileSync: readFileSync102, readdirSync: readdirSync42, existsSync: existsSync131 } = await import("node:fs");
111743
- const { join: join131 } = await import("node:path");
111887
+ const { readFileSync: readFileSync102, readdirSync: readdirSync42, existsSync: existsSync133 } = await import("node:fs");
111888
+ const { join: join132 } = await import("node:path");
111744
111889
  const workflowsDir = getCleoCantWorkflowsDir2();
111745
111890
  const combined = `${request} ${context ?? ""}`.toLowerCase();
111746
111891
  const matches = [];
111747
- if (existsSync131(workflowsDir)) {
111892
+ if (existsSync133(workflowsDir)) {
111748
111893
  const files = readdirSync42(workflowsDir).filter((f2) => f2.endsWith(".cant"));
111749
111894
  for (const file2 of files) {
111750
111895
  try {
111751
- const src = readFileSync102(join131(workflowsDir, file2), "utf-8");
111896
+ const src = readFileSync102(join132(workflowsDir, file2), "utf-8");
111752
111897
  const teamMatch = /^team\s+(\S+):/m.exec(src);
111753
111898
  if (!teamMatch) continue;
111754
111899
  const teamName = teamMatch[1];
@@ -111763,12 +111908,12 @@ async function orchestrateClassify(request, context, projectRoot) {
111763
111908
  }
111764
111909
  }
111765
111910
  }
111766
- const localCantDir = join131(projectRoot, ".cleo", "workflows");
111767
- if (existsSync131(localCantDir)) {
111911
+ const localCantDir = join132(projectRoot, ".cleo", "workflows");
111912
+ if (existsSync133(localCantDir)) {
111768
111913
  const files = readdirSync42(localCantDir).filter((f2) => f2.endsWith(".cant"));
111769
111914
  for (const file2 of files) {
111770
111915
  try {
111771
- const src = readFileSync102(join131(localCantDir, file2), "utf-8");
111916
+ const src = readFileSync102(join132(localCantDir, file2), "utf-8");
111772
111917
  const teamMatch = /^team\s+(\S+):/m.exec(src);
111773
111918
  if (!teamMatch) continue;
111774
111919
  const teamName = teamMatch[1];
@@ -113826,17 +113971,19 @@ var init_sticky2 = __esm({
113826
113971
  try {
113827
113972
  switch (operation) {
113828
113973
  case "list": {
113974
+ const tags = params?.tags;
113829
113975
  const filters = {
113830
113976
  status: params?.status,
113831
113977
  color: params?.color,
113832
- priority: params?.priority
113978
+ priority: params?.priority,
113979
+ tags
113833
113980
  };
113834
113981
  const result = await stickyList(projectRoot, filters);
113835
113982
  if (!result.success) {
113836
113983
  return wrapResult(result, "query", "sticky", operation, startTime);
113837
113984
  }
113838
113985
  const filteredStickies = result.data?.stickies ?? [];
113839
- const hasFilter = filters.status !== void 0 || filters.color !== void 0 || filters.priority !== void 0;
113986
+ const hasFilter = filters.status !== void 0 || filters.color !== void 0 || filters.priority !== void 0 || tags !== void 0 && tags.length > 0;
113840
113987
  const totalResult = hasFilter ? await stickyList(projectRoot, {}) : result;
113841
113988
  if (!totalResult.success) {
113842
113989
  return wrapResult(totalResult, "query", "sticky", operation, startTime);
@@ -114602,6 +114749,9 @@ async function toolsSkillFind(query) {
114602
114749
  }
114603
114750
  function toolsSkillDispatch(name2) {
114604
114751
  try {
114752
+ if (!catalog3.isCatalogAvailable()) {
114753
+ return engineError("E_CONFIG_ERROR", CATALOG_UNAVAILABLE_MSG, CATALOG_UNAVAILABLE_OPTS);
114754
+ }
114605
114755
  const matrix = catalog3.getDispatchMatrix();
114606
114756
  const entry = {
114607
114757
  byTaskType: Object.entries(matrix.by_task_type).filter(([, skill]) => skill === name2).map(([k2]) => k2),
@@ -114615,6 +114765,9 @@ function toolsSkillDispatch(name2) {
114615
114765
  }
114616
114766
  async function toolsSkillVerify(name2) {
114617
114767
  try {
114768
+ if (!catalog3.isCatalogAvailable()) {
114769
+ return engineError("E_CONFIG_ERROR", CATALOG_UNAVAILABLE_MSG, CATALOG_UNAVAILABLE_OPTS);
114770
+ }
114618
114771
  const installed = await discoverSkill2(`${getCanonicalSkillsDir4()}/${name2}`);
114619
114772
  const catalogEntry = catalog3.getSkill(name2);
114620
114773
  return engineSuccess({
@@ -114629,6 +114782,9 @@ async function toolsSkillVerify(name2) {
114629
114782
  }
114630
114783
  function toolsSkillDependencies(name2) {
114631
114784
  try {
114785
+ if (!catalog3.isCatalogAvailable()) {
114786
+ return engineError("E_CONFIG_ERROR", CATALOG_UNAVAILABLE_MSG, CATALOG_UNAVAILABLE_OPTS);
114787
+ }
114632
114788
  const direct = catalog3.getSkillDependencies(name2);
114633
114789
  const tree = catalog3.resolveDependencyTree([name2]);
114634
114790
  return engineSuccess({ skill: name2, direct, tree });
@@ -115001,6 +115157,9 @@ async function toolsAdapterActivate(projectRoot, id) {
115001
115157
  if (!manager.getManifest(id)) {
115002
115158
  manager.discover();
115003
115159
  }
115160
+ if (!manager.getManifest(id)) {
115161
+ return engineError("E_NOT_FOUND", `Adapter not found: ${id}`);
115162
+ }
115004
115163
  const adapter = await manager.activate(id);
115005
115164
  return engineSuccess({
115006
115165
  id,
@@ -115025,11 +115184,20 @@ async function toolsAdapterDispose(projectRoot, id) {
115025
115184
  return engineError("E_INTERNAL", error48 instanceof Error ? error48.message : String(error48));
115026
115185
  }
115027
115186
  }
115187
+ var CATALOG_UNAVAILABLE_MSG, CATALOG_UNAVAILABLE_OPTS;
115028
115188
  var init_tools_engine = __esm({
115029
115189
  "packages/cleo/src/dispatch/engines/tools-engine.ts"() {
115030
115190
  "use strict";
115031
115191
  init_internal();
115032
115192
  init_error();
115193
+ CATALOG_UNAVAILABLE_MSG = "Skill catalog not available. The CAAMP skill library could not be loaded. Run `cleo init` to set up the skill library, or set CAAMP_SKILL_LIBRARY env var.";
115194
+ CATALOG_UNAVAILABLE_OPTS = {
115195
+ fix: "cleo init",
115196
+ alternatives: [
115197
+ { action: "Set env var", command: "export CAAMP_SKILL_LIBRARY=/path/to/skills" },
115198
+ { action: "Use filesystem-based commands", command: "cleo skills list" }
115199
+ ]
115200
+ };
115033
115201
  }
115034
115202
  });
115035
115203
 
@@ -115885,7 +116053,7 @@ async function writeToSqlite(entry, requestId) {
115885
116053
  };
115886
116054
  const parsed = AuditLogInsertSchema2.safeParse(payload);
115887
116055
  if (!parsed.success) {
115888
- log10.warn(
116056
+ log11.warn(
115889
116057
  { issues: parsed.error.issues },
115890
116058
  "Audit payload failed Zod validation; skipping insert"
115891
116059
  );
@@ -115894,7 +116062,7 @@ async function writeToSqlite(entry, requestId) {
115894
116062
  const db = await getDb4(process.cwd());
115895
116063
  await db.insert(auditLog2).values(parsed.data).run();
115896
116064
  } catch (err) {
115897
- log10.warn({ err }, "Failed to write audit entry to SQLite");
116065
+ log11.warn({ err }, "Failed to write audit entry to SQLite");
115898
116066
  }
115899
116067
  }
115900
116068
  function createAudit() {
@@ -115925,7 +116093,7 @@ function createAudit() {
115925
116093
  },
115926
116094
  error: response.error?.message
115927
116095
  };
115928
- log10.info(
116096
+ log11.info(
115929
116097
  {
115930
116098
  domain: entry.domain,
115931
116099
  operation: entry.operation,
@@ -115942,20 +116110,20 @@ function createAudit() {
115942
116110
  await writeToSqlite(entry, req.requestId);
115943
116111
  } else {
115944
116112
  writeToSqlite(entry, req.requestId).catch((err) => {
115945
- log10.error({ err }, "Failed to persist audit entry to SQLite");
116113
+ log11.error({ err }, "Failed to persist audit entry to SQLite");
115946
116114
  });
115947
116115
  }
115948
116116
  return response;
115949
116117
  };
115950
116118
  }
115951
- var log10, cachedProjectHash;
116119
+ var log11, cachedProjectHash;
115952
116120
  var init_audit3 = __esm({
115953
116121
  "packages/cleo/src/dispatch/middleware/audit.ts"() {
115954
116122
  "use strict";
115955
116123
  init_internal();
115956
116124
  init_config3();
115957
116125
  init_internal();
115958
- log10 = getLogger("audit");
116126
+ log11 = getLogger("audit");
115959
116127
  }
115960
116128
  });
115961
116129
 
@@ -116106,6 +116274,38 @@ __export(cli_exports, {
116106
116274
  resetCliDispatcher: () => resetCliDispatcher
116107
116275
  });
116108
116276
  import { randomUUID as randomUUID13 } from "node:crypto";
116277
+ import { existsSync as existsSync128 } from "node:fs";
116278
+ import { createRequire as createRequire13 } from "node:module";
116279
+ import { dirname as dirname25, join as join124 } from "node:path";
116280
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
116281
+ import { catalog as catalog4, registerSkillLibraryFromPath } from "@cleocode/caamp";
116282
+ function ensureCaampLibrary() {
116283
+ if (catalog4.isCatalogAvailable()) return;
116284
+ try {
116285
+ let skillsRoot = null;
116286
+ try {
116287
+ const req = createRequire13(import.meta.url);
116288
+ const skillsPkgJson = req.resolve("@cleocode/skills/package.json");
116289
+ const candidate = dirname25(skillsPkgJson);
116290
+ if (existsSync128(join124(candidate, "skills.json"))) {
116291
+ skillsRoot = candidate;
116292
+ }
116293
+ } catch {
116294
+ }
116295
+ if (!skillsRoot) {
116296
+ const thisFile = fileURLToPath5(import.meta.url);
116297
+ const packageRoot = join124(dirname25(thisFile), "..", "..", "..", "..", "..");
116298
+ const candidate = join124(packageRoot, "packages", "skills");
116299
+ if (existsSync128(join124(candidate, "skills.json"))) {
116300
+ skillsRoot = candidate;
116301
+ }
116302
+ }
116303
+ if (skillsRoot) {
116304
+ registerSkillLibraryFromPath(skillsRoot);
116305
+ }
116306
+ } catch {
116307
+ }
116308
+ }
116109
116309
  function getCliDispatcher() {
116110
116310
  if (!_dispatcher) {
116111
116311
  _dispatcher = createCliDispatcher();
@@ -116122,6 +116322,7 @@ async function lookupCliSession() {
116122
116322
  }
116123
116323
  }
116124
116324
  function createCliDispatcher() {
116325
+ ensureCaampLibrary();
116125
116326
  const handlers = createDomainHandlers();
116126
116327
  return new Dispatcher({
116127
116328
  handlers,
@@ -116314,8 +116515,8 @@ var init_cli = __esm({
116314
116515
  // packages/cleo/src/cli/index.ts
116315
116516
  init_internal();
116316
116517
  import { readFileSync as readFileSync101 } from "node:fs";
116317
- import { dirname as dirname28, join as join130 } from "node:path";
116318
- import { fileURLToPath as fileURLToPath5 } from "node:url";
116518
+ import { dirname as dirname29, join as join131 } from "node:path";
116519
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
116319
116520
 
116320
116521
  // node_modules/.pnpm/citty@0.2.1/node_modules/citty/dist/_chunks/libs/scule.mjs
116321
116522
  var NUMBER_CHAR_RE = /\d/;
@@ -116910,7 +117111,7 @@ var COMMAND_GROUPS = [
116910
117111
  },
116911
117112
  {
116912
117113
  name: "Memory & Notes",
116913
- commands: ["memory", "brain", "observe", "refresh-memory", "sticky", "reason"]
117114
+ commands: ["memory", "brain", "refresh-memory", "sticky", "reason"]
116914
117115
  },
116915
117116
  {
116916
117117
  name: "Analysis & Stats",
@@ -117397,7 +117598,9 @@ var ADD_PARAMS = [
117397
117598
  }
117398
117599
  ];
117399
117600
  function registerAddCommand(program) {
117400
- const cmd = program.command("add").description(buildOperationHelp("tasks.add", "Create a new task", ADD_PARAMS));
117601
+ const cmd = program.command("add").description(
117602
+ buildOperationHelp("tasks.add", "Create a new task (requires active session)", ADD_PARAMS)
117603
+ );
117401
117604
  applyParamDefsToCommand(cmd, ADD_PARAMS, "tasks.add");
117402
117605
  cmd.option("--add-phase", "Create new phase if it does not exist").option("--desc <desc>", "Task description (alias for --description)").option("--dry-run", "Show what would be created without making changes").action(async (title, opts) => {
117403
117606
  const params = { title };
@@ -117469,7 +117672,7 @@ function registerAddCommand(program) {
117469
117672
  // packages/cleo/src/cli/commands/add-batch.ts
117470
117673
  init_cli();
117471
117674
  init_renderers();
117472
- import { readFileSync as readFileSync95 } from "node:fs";
117675
+ import { existsSync as existsSync129, readFileSync as readFileSync95 } from "node:fs";
117473
117676
  function registerAddBatchCommand(program) {
117474
117677
  program.command("add-batch").description("Create multiple tasks atomically from a JSON file").option("--file <path>", "Path to JSON file (array of task objects). Use - for stdin.").option("--parent <parentId>", "Default parent for all tasks (overridden by per-task parent)").option("--dry-run", "Preview what would be created without making changes").action(async (opts) => {
117475
117678
  const filePath = opts["file"];
@@ -117482,7 +117685,33 @@ function registerAddBatchCommand(program) {
117482
117685
  chunks.push(chunk);
117483
117686
  }
117484
117687
  raw = Buffer.concat(chunks).toString("utf-8");
117688
+ if (!raw.trim()) {
117689
+ cliError(
117690
+ "No input provided. Pass --file <path> or pipe JSON to stdin.",
117691
+ "E_VALIDATION",
117692
+ {
117693
+ name: "E_VALIDATION",
117694
+ fix: "cleo add-batch --file tasks.json"
117695
+ },
117696
+ { operation: "tasks.add-batch" }
117697
+ );
117698
+ process.exit(2);
117699
+ return;
117700
+ }
117485
117701
  } else {
117702
+ if (!existsSync129(filePath)) {
117703
+ cliError(
117704
+ `File not found: ${filePath}`,
117705
+ "E_NOT_FOUND",
117706
+ {
117707
+ name: "E_NOT_FOUND",
117708
+ fix: `Verify the file path exists: ${filePath}`
117709
+ },
117710
+ { operation: "tasks.add-batch" }
117711
+ );
117712
+ process.exit(2);
117713
+ return;
117714
+ }
117486
117715
  raw = readFileSync95(filePath, "utf-8");
117487
117716
  }
117488
117717
  let tasks2;
@@ -117490,12 +117719,28 @@ function registerAddBatchCommand(program) {
117490
117719
  const parsed = JSON.parse(raw);
117491
117720
  tasks2 = Array.isArray(parsed) ? parsed : [parsed];
117492
117721
  } catch {
117493
- process.stderr.write("Error: Invalid JSON input. Expected an array of task objects.\n");
117722
+ cliError(
117723
+ "Invalid JSON input. Expected an array of task objects.",
117724
+ "E_VALIDATION",
117725
+ {
117726
+ name: "E_VALIDATION",
117727
+ fix: "Ensure the input is a valid JSON array of task objects"
117728
+ },
117729
+ { operation: "tasks.add-batch" }
117730
+ );
117494
117731
  process.exit(2);
117495
117732
  return;
117496
117733
  }
117497
117734
  if (tasks2.length === 0) {
117498
- process.stderr.write("Error: No tasks in input.\n");
117735
+ cliError(
117736
+ "No tasks in input.",
117737
+ "E_VALIDATION",
117738
+ {
117739
+ name: "E_VALIDATION",
117740
+ fix: "Provide at least one task object in the JSON array"
117741
+ },
117742
+ { operation: "tasks.add-batch" }
117743
+ );
117499
117744
  process.exit(2);
117500
117745
  return;
117501
117746
  }
@@ -117772,12 +118017,12 @@ function registerAgentCommand(program) {
117772
118017
  transportConfig: {},
117773
118018
  isActive: true
117774
118019
  });
117775
- const { existsSync: existsSync131, mkdirSync: mkdirSync31, writeFileSync: writeFileSync24 } = await import("node:fs");
117776
- const { join: join131 } = await import("node:path");
117777
- const cantDir = join131(".cleo", "agents");
117778
- const cantPath = join131(cantDir, `${agentId}.cant`);
118020
+ const { existsSync: existsSync133, mkdirSync: mkdirSync31, writeFileSync: writeFileSync24 } = await import("node:fs");
118021
+ const { join: join132 } = await import("node:path");
118022
+ const cantDir = join132(".cleo", "agents");
118023
+ const cantPath = join132(cantDir, `${agentId}.cant`);
117779
118024
  let cantScaffolded = false;
117780
- if (!existsSync131(cantPath)) {
118025
+ if (!existsSync133(cantPath)) {
117781
118026
  mkdirSync31(cantDir, { recursive: true });
117782
118027
  const role = classification ?? "specialist";
117783
118028
  const cantContent = `---
@@ -117837,7 +118082,7 @@ agent ${agentId}:
117837
118082
  data: {
117838
118083
  agentId: credential.agentId,
117839
118084
  displayName: credential.displayName,
117840
- cantFile: cantScaffolded ? cantPath : existsSync131(cantPath) ? cantPath : null,
118085
+ cantFile: cantScaffolded ? cantPath : existsSync133(cantPath) ? cantPath : null,
117841
118086
  cantScaffolded
117842
118087
  }
117843
118088
  },
@@ -117917,8 +118162,8 @@ agent ${agentId}:
117917
118162
  try {
117918
118163
  const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
117919
118164
  const { createRuntime } = await import("@cleocode/runtime");
117920
- const { existsSync: existsSync131, readFileSync: readFileSync102 } = await import("node:fs");
117921
- const { join: join131 } = await import("node:path");
118165
+ const { existsSync: existsSync133, readFileSync: readFileSync102 } = await import("node:fs");
118166
+ const { join: join132 } = await import("node:path");
117922
118167
  await getDb4();
117923
118168
  const registry2 = new AgentRegistryAccessor2(process.cwd());
117924
118169
  const credential = await registry2.get(agentId);
@@ -117938,8 +118183,8 @@ agent ${agentId}:
117938
118183
  }
117939
118184
  let profile = null;
117940
118185
  let cantValidation = null;
117941
- const cantPath = opts["cant"] ?? join131(".cleo", "agents", `${agentId}.cant`);
117942
- if (existsSync131(cantPath)) {
118186
+ const cantPath = opts["cant"] ?? join132(".cleo", "agents", `${agentId}.cant`);
118187
+ if (existsSync133(cantPath)) {
117943
118188
  profile = readFileSync102(cantPath, "utf-8");
117944
118189
  try {
117945
118190
  const cantModule = await import("@cleocode/cant");
@@ -118335,8 +118580,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
118335
118580
  try {
118336
118581
  const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
118337
118582
  const { createRuntime } = await import("@cleocode/runtime");
118338
- const { existsSync: existsSync131 } = await import("node:fs");
118339
- const { join: join131 } = await import("node:path");
118583
+ const { existsSync: existsSync133 } = await import("node:fs");
118584
+ const { join: join132 } = await import("node:path");
118340
118585
  const { execFile: execFile9 } = await import("node:child_process");
118341
118586
  const { promisify: promisify9 } = await import("node:util");
118342
118587
  const execFileAsync6 = promisify9(execFile9);
@@ -118356,8 +118601,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
118356
118601
  }
118357
118602
  await registry2.update(agentId, { isActive: true });
118358
118603
  await registry2.markUsed(agentId);
118359
- const cantPath = join131(".cleo", "agents", `${agentId}.cant`);
118360
- const hasProfile = existsSync131(cantPath);
118604
+ const cantPath = join132(".cleo", "agents", `${agentId}.cant`);
118605
+ const hasProfile = existsSync133(cantPath);
118361
118606
  const runtime = await createRuntime(registry2, {
118362
118607
  agentId,
118363
118608
  pollIntervalMs: 5e3,
@@ -118980,12 +119225,12 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
118980
119225
  });
118981
119226
  agent.command("install <path>").description("Install an agent from a .cantz archive or agent directory").option("--global", "Install to global tier (~/.local/share/cleo/cant/agents/)").action(async (sourcePath, opts) => {
118982
119227
  try {
118983
- const { existsSync: existsSync131, mkdirSync: mkdirSync31, cpSync, readFileSync: readFileSync102, rmSync: rmSync3, statSync: statSync22 } = await import("node:fs");
118984
- const { join: join131, basename: basename19, resolve: resolve16 } = await import("node:path");
119228
+ const { existsSync: existsSync133, mkdirSync: mkdirSync31, cpSync, readFileSync: readFileSync102, rmSync: rmSync3, statSync: statSync22 } = await import("node:fs");
119229
+ const { join: join132, basename: basename19, resolve: resolve16 } = await import("node:path");
118985
119230
  const { homedir: homedir7 } = await import("node:os");
118986
119231
  const { tmpdir: tmpdir3 } = await import("node:os");
118987
119232
  const resolvedPath = resolve16(sourcePath);
118988
- if (!existsSync131(resolvedPath)) {
119233
+ if (!existsSync133(resolvedPath)) {
118989
119234
  cliOutput(
118990
119235
  {
118991
119236
  success: false,
@@ -119005,7 +119250,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119005
119250
  const isCantzArchive = resolvedPath.endsWith(".cantz") && statSync22(resolvedPath).isFile();
119006
119251
  if (isCantzArchive) {
119007
119252
  const { execFileSync: execFileSync19 } = await import("node:child_process");
119008
- tempDir = join131(tmpdir3(), `cleo-agent-install-${Date.now()}`);
119253
+ tempDir = join132(tmpdir3(), `cleo-agent-install-${Date.now()}`);
119009
119254
  mkdirSync31(tempDir, { recursive: true });
119010
119255
  try {
119011
119256
  execFileSync19("unzip", ["-o", "-q", resolvedPath, "-d", tempDir], {
@@ -119029,7 +119274,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119029
119274
  }
119030
119275
  const { readdirSync: readdirSync42 } = await import("node:fs");
119031
119276
  const topLevel = readdirSync42(tempDir).filter((entry) => {
119032
- const entryPath = join131(tempDir, entry);
119277
+ const entryPath = join132(tempDir, entry);
119033
119278
  return statSync22(entryPath).isDirectory();
119034
119279
  });
119035
119280
  if (topLevel.length !== 1) {
@@ -119048,7 +119293,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119048
119293
  return;
119049
119294
  }
119050
119295
  agentName = topLevel[0];
119051
- agentDir = join131(tempDir, agentName);
119296
+ agentDir = join132(tempDir, agentName);
119052
119297
  } else if (statSync22(resolvedPath).isDirectory()) {
119053
119298
  agentDir = resolvedPath;
119054
119299
  agentName = basename19(resolvedPath);
@@ -119066,8 +119311,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119066
119311
  process.exitCode = 6;
119067
119312
  return;
119068
119313
  }
119069
- const personaPath = join131(agentDir, "persona.cant");
119070
- if (!existsSync131(personaPath)) {
119314
+ const personaPath = join132(agentDir, "persona.cant");
119315
+ if (!existsSync133(personaPath)) {
119071
119316
  if (tempDir) rmSync3(tempDir, { recursive: true, force: true });
119072
119317
  cliOutput(
119073
119318
  {
@@ -119086,12 +119331,12 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119086
119331
  let targetRoot;
119087
119332
  if (isGlobal) {
119088
119333
  const home = homedir7();
119089
- const xdgData = process.env["XDG_DATA_HOME"] ?? join131(home, ".local", "share");
119090
- targetRoot = join131(xdgData, "cleo", "cant", "agents");
119334
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join132(home, ".local", "share");
119335
+ targetRoot = join132(xdgData, "cleo", "cant", "agents");
119091
119336
  } else {
119092
- targetRoot = join131(process.cwd(), ".cleo", "cant", "agents");
119337
+ targetRoot = join132(process.cwd(), ".cleo", "cant", "agents");
119093
119338
  }
119094
- const targetDir = join131(targetRoot, agentName);
119339
+ const targetDir = join132(targetRoot, agentName);
119095
119340
  mkdirSync31(targetRoot, { recursive: true });
119096
119341
  cpSync(agentDir, targetDir, { recursive: true, force: true });
119097
119342
  if (tempDir) {
@@ -119099,7 +119344,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119099
119344
  }
119100
119345
  let registered = false;
119101
119346
  try {
119102
- const persona = readFileSync102(join131(targetDir, "persona.cant"), "utf-8");
119347
+ const persona = readFileSync102(join132(targetDir, "persona.cant"), "utf-8");
119103
119348
  const descMatch = persona.match(/description:\s*"([^"]+)"/);
119104
119349
  const displayName = descMatch?.[1] ?? agentName;
119105
119350
  const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
@@ -119146,11 +119391,11 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119146
119391
  });
119147
119392
  agent.command("pack <dir>").description("Package an agent directory as a .cantz archive").action(async (dir) => {
119148
119393
  try {
119149
- const { existsSync: existsSync131, statSync: statSync22 } = await import("node:fs");
119150
- const { resolve: resolve16, basename: basename19, dirname: dirname29 } = await import("node:path");
119394
+ const { existsSync: existsSync133, statSync: statSync22 } = await import("node:fs");
119395
+ const { resolve: resolve16, basename: basename19, dirname: dirname30 } = await import("node:path");
119151
119396
  const { execFileSync: execFileSync19 } = await import("node:child_process");
119152
119397
  const resolvedDir = resolve16(dir);
119153
- if (!existsSync131(resolvedDir) || !statSync22(resolvedDir).isDirectory()) {
119398
+ if (!existsSync133(resolvedDir) || !statSync22(resolvedDir).isDirectory()) {
119154
119399
  cliOutput(
119155
119400
  {
119156
119401
  success: false,
@@ -119164,9 +119409,9 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119164
119409
  process.exitCode = 4;
119165
119410
  return;
119166
119411
  }
119167
- const { join: join131 } = await import("node:path");
119168
- const personaPath = join131(resolvedDir, "persona.cant");
119169
- if (!existsSync131(personaPath)) {
119412
+ const { join: join132 } = await import("node:path");
119413
+ const personaPath = join132(resolvedDir, "persona.cant");
119414
+ if (!existsSync133(personaPath)) {
119170
119415
  cliOutput(
119171
119416
  {
119172
119417
  success: false,
@@ -119183,7 +119428,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119183
119428
  const agentName = basename19(resolvedDir);
119184
119429
  const archiveName = `${agentName}.cantz`;
119185
119430
  const archivePath = resolve16(archiveName);
119186
- const parentDir = dirname29(resolvedDir);
119431
+ const parentDir = dirname30(resolvedDir);
119187
119432
  try {
119188
119433
  execFileSync19("zip", ["-r", archivePath, agentName], {
119189
119434
  cwd: parentDir,
@@ -119213,7 +119458,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119213
119458
  if (entry.isFile()) {
119214
119459
  fileCount++;
119215
119460
  } else if (entry.isDirectory()) {
119216
- countFiles2(join131(dirPath, entry.name));
119461
+ countFiles2(join132(dirPath, entry.name));
119217
119462
  }
119218
119463
  }
119219
119464
  };
@@ -119240,8 +119485,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119240
119485
  });
119241
119486
  agent.command("create").description("Scaffold a new agent package with persona.cant and manifest.json").requiredOption("--name <name>", "Agent name (kebab-case)").requiredOption("--role <role>", "Agent role: orchestrator, lead, worker, or docs-worker").option("--tier <tier>", "Agent tier: low, mid, or high (defaults based on role)").option("--team <teamName>", "Team this agent belongs to").option("--domain <description>", "Domain description for file permissions and context").option("--global", "Create in global tier (~/.local/share/cleo/cant/agents/)").option("--seed-brain", "Create expertise/mental-model-seed.md and seed a BRAIN observation").option("--parent <parentAgent>", "Parent agent name in the hierarchy").action(async (opts) => {
119242
119487
  try {
119243
- const { existsSync: existsSync131, mkdirSync: mkdirSync31, writeFileSync: writeFileSync24 } = await import("node:fs");
119244
- const { join: join131 } = await import("node:path");
119488
+ const { existsSync: existsSync133, mkdirSync: mkdirSync31, writeFileSync: writeFileSync24 } = await import("node:fs");
119489
+ const { join: join132 } = await import("node:path");
119245
119490
  const { homedir: homedir7 } = await import("node:os");
119246
119491
  const name2 = opts["name"];
119247
119492
  const role = opts["role"];
@@ -119301,13 +119546,13 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119301
119546
  let targetRoot;
119302
119547
  if (isGlobal) {
119303
119548
  const home = homedir7();
119304
- const xdgData = process.env["XDG_DATA_HOME"] ?? join131(home, ".local", "share");
119305
- targetRoot = join131(xdgData, "cleo", "cant", "agents");
119549
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join132(home, ".local", "share");
119550
+ targetRoot = join132(xdgData, "cleo", "cant", "agents");
119306
119551
  } else {
119307
- targetRoot = join131(process.cwd(), ".cleo", "cant", "agents");
119552
+ targetRoot = join132(process.cwd(), ".cleo", "cant", "agents");
119308
119553
  }
119309
- const agentDir = join131(targetRoot, name2);
119310
- if (existsSync131(agentDir)) {
119554
+ const agentDir = join132(targetRoot, name2);
119555
+ if (existsSync133(agentDir)) {
119311
119556
  cliOutput(
119312
119557
  {
119313
119558
  success: false,
@@ -119331,29 +119576,29 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
119331
119576
  domain: domain2,
119332
119577
  parent
119333
119578
  });
119334
- writeFileSync24(join131(agentDir, "persona.cant"), personaContent, "utf-8");
119579
+ writeFileSync24(join132(agentDir, "persona.cant"), personaContent, "utf-8");
119335
119580
  const manifest = generateManifest2({ name: name2, role, tier, domain: domain2 });
119336
119581
  writeFileSync24(
119337
- join131(agentDir, "manifest.json"),
119582
+ join132(agentDir, "manifest.json"),
119338
119583
  `${JSON.stringify(manifest, null, 2)}
119339
119584
  `,
119340
119585
  "utf-8"
119341
119586
  );
119342
119587
  const createdFiles = [
119343
- join131(agentDir, "persona.cant"),
119344
- join131(agentDir, "manifest.json")
119588
+ join132(agentDir, "persona.cant"),
119589
+ join132(agentDir, "manifest.json")
119345
119590
  ];
119346
119591
  if (team) {
119347
119592
  const teamConfigContent = generateTeamConfig(name2, role, team);
119348
- writeFileSync24(join131(agentDir, "team-config.cant"), teamConfigContent, "utf-8");
119349
- createdFiles.push(join131(agentDir, "team-config.cant"));
119593
+ writeFileSync24(join132(agentDir, "team-config.cant"), teamConfigContent, "utf-8");
119594
+ createdFiles.push(join132(agentDir, "team-config.cant"));
119350
119595
  }
119351
119596
  if (seedBrain) {
119352
- const expertiseDir = join131(agentDir, "expertise");
119597
+ const expertiseDir = join132(agentDir, "expertise");
119353
119598
  mkdirSync31(expertiseDir, { recursive: true });
119354
119599
  const seedContent = generateMentalModelSeed(name2, role, domain2);
119355
- writeFileSync24(join131(expertiseDir, "mental-model-seed.md"), seedContent, "utf-8");
119356
- createdFiles.push(join131(expertiseDir, "mental-model-seed.md"));
119600
+ writeFileSync24(join132(expertiseDir, "mental-model-seed.md"), seedContent, "utf-8");
119601
+ createdFiles.push(join132(expertiseDir, "mental-model-seed.md"));
119357
119602
  try {
119358
119603
  const { execFile: execFile9 } = await import("node:child_process");
119359
119604
  const { promisify: promisify9 } = await import("node:util");
@@ -119760,10 +120005,6 @@ function capitalizeFirst(str) {
119760
120005
  return str.charAt(0).toUpperCase() + str.slice(1);
119761
120006
  }
119762
120007
 
119763
- // packages/cleo/src/cli/commands/agents.ts
119764
- function registerAgentsCommand(_program) {
119765
- }
119766
-
119767
120008
  // packages/cleo/src/cli/commands/analyze.ts
119768
120009
  init_cli();
119769
120010
  function registerAnalyzeCommand(program) {
@@ -119813,6 +120054,7 @@ function registerArchiveStatsCommand(program) {
119813
120054
 
119814
120055
  // packages/cleo/src/cli/commands/backfill.ts
119815
120056
  init_internal();
120057
+ init_renderers();
119816
120058
  function registerBackfillCommand(program) {
119817
120059
  program.command("backfill").description(
119818
120060
  "Retroactively add acceptance criteria and verification metadata to existing tasks"
@@ -119847,17 +120089,35 @@ function registerBackfillCommand(program) {
119847
120089
  process.stdout.write("\n");
119848
120090
  }
119849
120091
  if (result.processed === 0 && result.skipped === 0 && result.errors === 0) {
119850
- console.log(
119851
- "No observations to embed (provider unavailable or nothing to backfill)."
120092
+ cliOutput(
120093
+ {
120094
+ processed: 0,
120095
+ skipped: 0,
120096
+ errors: 0,
120097
+ message: "No observations to embed (provider unavailable or nothing to backfill)."
120098
+ },
120099
+ { command: "backfill", operation: "admin.backfill", message: "Nothing to embed" }
119852
120100
  );
119853
120101
  return;
119854
120102
  }
119855
- console.log(
119856
- `Processed ${result.processed}, skipped ${result.skipped}, errors ${result.errors}`
120103
+ cliOutput(
120104
+ { processed: result.processed, skipped: result.skipped, errors: result.errors },
120105
+ {
120106
+ command: "backfill",
120107
+ operation: "admin.backfill",
120108
+ message: `Processed ${result.processed}, skipped ${result.skipped}, errors ${result.errors}`
120109
+ }
119857
120110
  );
119858
120111
  } catch (err) {
119859
120112
  const message = err instanceof Error ? err.message : String(err);
119860
- console.error(`Embedding backfill failed: ${message}`);
120113
+ cliError(
120114
+ `Embedding backfill failed: ${message}`,
120115
+ "E_INTERNAL",
120116
+ {
120117
+ name: "E_INTERNAL"
120118
+ },
120119
+ { operation: "admin.backfill" }
120120
+ );
119861
120121
  process.exit(1);
119862
120122
  }
119863
120123
  return;
@@ -119866,55 +120126,40 @@ function registerBackfillCommand(program) {
119866
120126
  const rollback = !!opts.rollback;
119867
120127
  const taskIds = opts.tasks?.trim() ? opts.tasks.split(",").map((s3) => s3.trim()).filter(Boolean) : void 0;
119868
120128
  if (!dryRun && !rollback && !process.env["CLEO_NONINTERACTIVE"]) {
119869
- console.log(
119870
- "\u26A0 Backfill will modify tasks in-place. Run with --dry-run first to preview changes."
120129
+ process.stderr.write(
120130
+ "Warning: Backfill will modify tasks in-place. Run with --dry-run first to preview changes.\n Set CLEO_NONINTERACTIVE=1 or pass --dry-run to suppress this warning.\n\n"
119871
120131
  );
119872
- console.log(" Set CLEO_NONINTERACTIVE=1 or pass --dry-run to suppress this warning.\n");
119873
- }
119874
- if (dryRun) {
119875
- console.log("[dry run] No changes will be made.\n");
119876
- }
119877
- if (rollback) {
119878
- console.log("[rollback] Reverting previously backfilled tasks.\n");
119879
120132
  }
119880
120133
  try {
119881
120134
  const result = await backfillTasks(root, { dryRun, rollback, taskIds });
119882
- console.log(`Scanned: ${result.tasksScanned} task(s)`);
119883
- console.log(`Changed: ${result.tasksChanged} task(s)`);
120135
+ const output = {
120136
+ dryRun,
120137
+ rollback,
120138
+ tasksScanned: result.tasksScanned,
120139
+ tasksChanged: result.tasksChanged,
120140
+ changes: result.changes
120141
+ };
119884
120142
  if (!rollback) {
119885
- console.log(` AC added: ${result.acAdded}`);
119886
- console.log(` Verification added: ${result.verificationAdded}`);
119887
- }
119888
- if (result.changes.length === 0) {
119889
- console.log("\nNothing to do \u2014 all tasks already have AC and verification metadata.");
119890
- return;
119891
- }
119892
- console.log("\nDetails:");
119893
- for (const change of result.changes) {
119894
- const parts = [];
119895
- if (change.addedAc) parts.push("AC");
119896
- if (change.addedVerification) parts.push("verification");
119897
- if (change.addedNote) parts.push("note");
119898
- if (change.rolledBack && change.rolledBack.length > 0) {
119899
- parts.push(`rolled back [${change.rolledBack.join(", ")}]`);
119900
- }
119901
- console.log(` ${change.taskId}: ${change.title}`);
119902
- console.log(` Actions: ${parts.join(", ")}`);
119903
- if (change.addedAc && change.generatedAc.length > 0) {
119904
- console.log(" Generated AC:");
119905
- for (const ac of change.generatedAc) {
119906
- console.log(` - ${ac}`);
119907
- }
119908
- }
119909
- }
119910
- if (dryRun) {
119911
- console.log("\n[dry run] Run without --dry-run to apply these changes.");
119912
- } else {
119913
- console.log("\nBackfill complete.");
119914
- }
120143
+ output["acAdded"] = result.acAdded;
120144
+ output["verificationAdded"] = result.verificationAdded;
120145
+ }
120146
+ const messagePrefix = dryRun ? "[dry run] " : rollback ? "[rollback] " : "";
120147
+ const messageSuffix = result.changes.length === 0 ? "Nothing to do \u2014 all tasks already have AC and verification metadata." : `Scanned ${result.tasksScanned}, changed ${result.tasksChanged} task(s).`;
120148
+ cliOutput(output, {
120149
+ command: "backfill",
120150
+ operation: "admin.backfill",
120151
+ message: `${messagePrefix}${messageSuffix}`
120152
+ });
119915
120153
  } catch (err) {
119916
120154
  const message = err instanceof Error ? err.message : String(err);
119917
- console.error(`Backfill failed: ${message}`);
120155
+ cliError(
120156
+ `Backfill failed: ${message}`,
120157
+ "E_INTERNAL",
120158
+ {
120159
+ name: "E_INTERNAL"
120160
+ },
120161
+ { operation: "admin.backfill" }
120162
+ );
119918
120163
  process.exit(1);
119919
120164
  }
119920
120165
  }
@@ -120219,7 +120464,9 @@ async function promptPassphrase() {
120219
120464
  }
120220
120465
  function registerBackupCommand(program) {
120221
120466
  const backup = program.command("backup").description("Add backup of todo files or list available backups");
120222
- backup.command("add").alias("create").description("Add a new backup of all CLEO data files").option("--destination <dir>", "Backup destination directory").option("--global", "Also snapshot global-tier databases (nexus.db)").action(async (opts) => {
120467
+ backup.command("add").alias("create").description(
120468
+ "Add a new backup of all CLEO data files (backup create is an alias for backup add)"
120469
+ ).option("--destination <dir>", "Backup destination directory").option("--global", "Also snapshot global-tier databases (nexus.db)").action(async (opts) => {
120223
120470
  await dispatchFromCli(
120224
120471
  "mutate",
120225
120472
  "admin",
@@ -120622,7 +120869,7 @@ function registerBrainCommand(program) {
120622
120869
  init_cli();
120623
120870
  function registerBriefingCommand(program) {
120624
120871
  program.command("briefing").description(
120625
- "Show composite session-start context (handoff, focus, next tasks, bugs, blockers, epics)"
120872
+ "Session resume context: last handoff, current task, next tasks, bugs, blockers, epics, and memory. Use at session start to restore context."
120626
120873
  ).option("-s, --scope <scope>", "Scope filter (global or epic:T###)").option("--max-next <n>", "Maximum next tasks to show", "5").option("--max-bugs <n>", "Maximum bugs to show", "10").option("--max-blocked <n>", "Maximum blocked tasks to show", "10").option("--max-epics <n>", "Maximum active epics to show", "5").action(async (opts) => {
120627
120874
  const scope = opts["scope"];
120628
120875
  const maxNextTasks = parseInt(opts["maxNext"], 10);
@@ -120656,7 +120903,7 @@ var SEVERITY_MAP = {
120656
120903
  };
120657
120904
  var VALID_SEVERITIES = Object.keys(SEVERITY_MAP);
120658
120905
  function registerBugCommand(program) {
120659
- program.command("bug <title>").description("Create a bug report task with severity mapping").option("-s, --severity <level>", "Severity level (P0, P1, P2, P3) - required", "P2").option("-e, --epic <id>", "Epic ID to link as parent (optional)").option("-d, --description <desc>", "Bug description").option("--dry-run", "Show what would be created without making changes").action(async (title, opts) => {
120906
+ program.command("bug <title>").description("Create a bug report task with severity mapping (requires active session)").option("-s, --severity <level>", "Severity level (P0, P1, P2, P3) - required", "P2").option("-e, --epic <id>", "Epic ID to link as parent (optional)").option("-d, --description <desc>", "Bug description").option("--dry-run", "Show what would be created without making changes").action(async (title, opts) => {
120660
120907
  const severity = opts["severity"] || "P2";
120661
120908
  if (!VALID_SEVERITIES.includes(severity)) {
120662
120909
  console.error(
@@ -120721,8 +120968,8 @@ function registerCancelCommand(program) {
120721
120968
 
120722
120969
  // packages/cleo/src/cli/commands/cant.ts
120723
120970
  init_renderers();
120724
- import { existsSync as existsSync128, mkdirSync as mkdirSync29, readFileSync as readFileSync96, writeFileSync as writeFileSync22 } from "node:fs";
120725
- import { dirname as dirname25, isAbsolute as isAbsolute3, join as join124, resolve as resolve15 } from "node:path";
120971
+ import { existsSync as existsSync130, mkdirSync as mkdirSync29, readFileSync as readFileSync96, writeFileSync as writeFileSync22 } from "node:fs";
120972
+ import { dirname as dirname26, isAbsolute as isAbsolute3, join as join125, resolve as resolve15 } from "node:path";
120726
120973
  function registerCantCommand(program) {
120727
120974
  const cant = program.command("cant").description("CANT DSL tooling");
120728
120975
  cant.command("parse <file>").description("Parse a .cant file and emit the AST").action(async (file2) => {
@@ -120782,21 +121029,12 @@ function registerCantCommand(program) {
120782
121029
  process.exitCode = 1;
120783
121030
  }
120784
121031
  });
120785
- cant.command("migrate <file>").description("Convert markdown instruction files to .cant format").option("--write", "Write .cant files to disk (default: dry-run preview)").option("--dry-run", "Preview conversion without writing files (default behavior)").option("--output-dir <dir>", "Output directory for .cant files (default: .cleo/agents/)").option("--verbose", "Show detailed conversion log").option("--json", "Output results as JSON").action(
121032
+ cant.command("migrate <file>").description("Convert markdown instruction files to .cant format").option("--write", "Write .cant files to disk (default: dry-run preview)").option("--dry-run", "Preview conversion without writing files (default behavior)").option("--output-dir <dir>", "Output directory for .cant files (default: .cleo/agents/)").option("--verbose", "Show detailed conversion log").action(
120786
121033
  async (file2, opts) => {
120787
- const isJson = !!opts.json;
120788
121034
  const isWrite = !!opts.write && !opts.dryRun;
120789
121035
  const isVerbose = !!opts.verbose;
120790
121036
  const filePath = isAbsolute3(file2) ? file2 : resolve15(process.cwd(), file2);
120791
- if (!existsSync128(filePath)) {
120792
- const errMsg = `File not found: ${filePath}`;
120793
- if (isJson) {
120794
- console.log(JSON.stringify({ error: errMsg }));
120795
- } else {
120796
- console.error(errMsg);
120797
- }
120798
- process.exit(1);
120799
- }
121037
+ if (!ensureExists(filePath, "cant.migrate")) return;
120800
121038
  try {
120801
121039
  const mod = await loadMigrateEngine();
120802
121040
  const content = readFileSync96(filePath, "utf-8");
@@ -120805,43 +121043,43 @@ function registerCantCommand(program) {
120805
121043
  verbose: isVerbose,
120806
121044
  outputDir: opts.outputDir
120807
121045
  });
120808
- if (isJson) {
120809
- console.log(JSON.stringify(result, null, 2));
120810
- return;
120811
- }
120812
121046
  if (isWrite) {
120813
121047
  const projectRoot = process.cwd();
120814
121048
  let written = 0;
120815
121049
  for (const outputFile of result.outputFiles) {
120816
- const outputPath = isAbsolute3(outputFile.path) ? outputFile.path : join124(projectRoot, outputFile.path);
120817
- mkdirSync29(dirname25(outputPath), { recursive: true });
121050
+ const outputPath = isAbsolute3(outputFile.path) ? outputFile.path : join125(projectRoot, outputFile.path);
121051
+ mkdirSync29(dirname26(outputPath), { recursive: true });
120818
121052
  writeFileSync22(outputPath, outputFile.content, "utf-8");
120819
121053
  written++;
120820
- if (isVerbose) {
120821
- console.log(` Created: ${outputFile.path} (${outputFile.kind})`);
120822
- }
120823
- }
120824
- console.log(`Wrote ${written} .cant file(s).`);
120825
- console.log(result.summary);
120826
- if (result.unconverted.length > 0) {
120827
- console.log("");
120828
- console.log(`${result.unconverted.length} section(s) need manual conversion.`);
120829
- for (const section of result.unconverted) {
120830
- console.log(` Lines ${section.lineStart}-${section.lineEnd}: ${section.reason}`);
120831
- }
120832
121054
  }
121055
+ cliOutput(
121056
+ {
121057
+ inputFile: result.inputFile,
121058
+ filesWritten: written,
121059
+ outputFiles: result.outputFiles.map((f2) => ({ path: f2.path, kind: f2.kind })),
121060
+ unconverted: result.unconverted,
121061
+ summary: result.summary
121062
+ },
121063
+ { command: "cant-migrate", operation: "cant.migrate" }
121064
+ );
120833
121065
  } else {
120834
- const diffOutput = mod.showDiff(result, process.stdout.isTTY ?? false);
120835
- console.log(diffOutput);
121066
+ cliOutput(
121067
+ {
121068
+ inputFile: result.inputFile,
121069
+ dryRun: true,
121070
+ outputFiles: result.outputFiles.map((f2) => ({
121071
+ path: f2.path,
121072
+ kind: f2.kind
121073
+ })),
121074
+ unconverted: result.unconverted,
121075
+ summary: result.summary
121076
+ },
121077
+ { command: "cant-migrate", operation: "cant.migrate" }
121078
+ );
120836
121079
  }
120837
121080
  } catch (err) {
120838
- const message = err instanceof Error ? err.message : String(err);
120839
- if (isJson) {
120840
- console.log(JSON.stringify({ error: message }));
120841
- } else {
120842
- console.error(`Migration failed: ${message}`);
120843
- }
120844
- process.exit(1);
121081
+ emitFailure("cant.migrate", "E_MIGRATION_FAILED", err);
121082
+ process.exitCode = 1;
120845
121083
  }
120846
121084
  }
120847
121085
  );
@@ -120850,7 +121088,7 @@ function resolveFilePath(file2) {
120850
121088
  return isAbsolute3(file2) ? file2 : resolve15(process.cwd(), file2);
120851
121089
  }
120852
121090
  function ensureExists(filePath, operation) {
120853
- if (existsSync128(filePath)) return true;
121091
+ if (existsSync130(filePath)) return true;
120854
121092
  cliError(`File not found: ${filePath}`, "E_FILE_READ");
120855
121093
  process.exitCode = 3;
120856
121094
  if (process.env["CLEO_DEBUG"]) {
@@ -121167,28 +121405,6 @@ function registerUnclaimCommand(program) {
121167
121405
  });
121168
121406
  }
121169
121407
 
121170
- // packages/cleo/src/cli/commands/commands.ts
121171
- init_cli();
121172
- function registerCommandsCommand(program) {
121173
- program.command("commands [command]").description("List and query available CLEO commands (delegates to admin help)").option("-c, --category <category>", "Filter by category").option("-r, --relevance <level>", "Filter by agent relevance").option("--tier <n>", "Help tier level (0=basic, 1=extended, 2=full)", parseInt).action(async (commandName, opts) => {
121174
- console.error(
121175
- "[DEPRECATED] cleo commands now delegates to admin.help.\nUse: cleo help (CLI)\n"
121176
- );
121177
- await dispatchFromCli(
121178
- "query",
121179
- "admin",
121180
- "help",
121181
- {
121182
- tier: opts["tier"] ?? 0,
121183
- domain: commandName,
121184
- category: opts["category"],
121185
- relevance: opts["relevance"]
121186
- },
121187
- { command: "commands", operation: "admin.help" }
121188
- );
121189
- });
121190
- }
121191
-
121192
121408
  // packages/cleo/src/cli/commands/complete.ts
121193
121409
  init_cli();
121194
121410
  init_renderers();
@@ -121230,7 +121446,13 @@ var COMPLETE_PARAMS = [
121230
121446
  }
121231
121447
  ];
121232
121448
  function registerCompleteCommand(program) {
121233
- const cmd = program.command("complete").alias("done").description(buildOperationHelp("tasks.complete", "Mark a task as completed", COMPLETE_PARAMS));
121449
+ const cmd = program.command("complete").alias("done").description(
121450
+ buildOperationHelp(
121451
+ "tasks.complete",
121452
+ "Mark a task as completed (requires active session)",
121453
+ COMPLETE_PARAMS
121454
+ )
121455
+ );
121234
121456
  applyParamDefsToCommand(cmd, COMPLETE_PARAMS, "tasks.complete");
121235
121457
  cmd.action(async (taskId, opts) => {
121236
121458
  const response = await dispatchRaw("mutate", "tasks", "complete", {
@@ -121315,14 +121537,14 @@ function registerComplianceCommand(program) {
121315
121537
  { command: "compliance" }
121316
121538
  );
121317
121539
  });
121318
- compliance.command("audit <epicId>").description("Check compliance for specific epic tasks").option("--since <date>", "Filter from date").action(async (epicId, opts) => {
121540
+ compliance.command("audit <taskId>").description("Check compliance for a specific task and its subtasks").option("--since <date>", "Filter from date").action(async (taskId, opts) => {
121319
121541
  await dispatchFromCli(
121320
121542
  "query",
121321
121543
  "check",
121322
121544
  "compliance.summary",
121323
121545
  {
121324
121546
  type: "audit",
121325
- epicId,
121547
+ taskId,
121326
121548
  since: opts["since"]
121327
121549
  },
121328
121550
  { command: "compliance" }
@@ -121369,7 +121591,7 @@ function registerComplianceCommand(program) {
121369
121591
  (val, prev) => [...prev, val],
121370
121592
  []
121371
121593
  ).action(async (taskId, result, opts) => {
121372
- const rawViolations = opts["violation"];
121594
+ const rawViolations = opts["violation"] ?? [];
121373
121595
  const violations = rawViolations.map((v2) => {
121374
121596
  const [code, severity, ...rest] = v2.split(":");
121375
121597
  return {
@@ -121438,44 +121660,20 @@ function registerConfigCommand(program) {
121438
121660
  });
121439
121661
  }
121440
121662
 
121441
- // packages/cleo/src/cli/commands/consensus.ts
121442
- init_cli();
121443
- function registerConsensusCommand(program) {
121444
- const consensus = program.command("consensus").description("Validate consensus protocol compliance for multi-agent decision tasks");
121445
- consensus.command("validate <taskId>").description("Validate consensus protocol compliance for task").option("--strict", "Exit with error code on violations").option("--voting-matrix <file>", "Path to voting matrix JSON file").action(async (taskId, opts) => {
121446
- await dispatchFromCli(
121447
- "query",
121448
- "check",
121449
- "protocol",
121450
- {
121451
- protocolType: "consensus",
121452
- mode: "task",
121453
- taskId,
121454
- strict: opts["strict"],
121455
- votingMatrixFile: opts["votingMatrix"]
121456
- },
121457
- { command: "consensus" }
121458
- );
121459
- });
121460
- consensus.command("check <manifestFile>").description("Validate manifest entry directly").option("--strict", "Exit with error code on violations").option("--voting-matrix <file>", "Path to voting matrix JSON file").action(async (manifestFile, opts) => {
121461
- await dispatchFromCli(
121462
- "query",
121463
- "check",
121464
- "protocol",
121465
- {
121466
- protocolType: "consensus",
121467
- mode: "manifest",
121468
- manifestFile,
121469
- strict: opts["strict"],
121470
- votingMatrixFile: opts["votingMatrix"]
121471
- },
121472
- { command: "consensus" }
121473
- );
121474
- });
121475
- }
121476
-
121477
121663
  // packages/cleo/src/cli/commands/context.ts
121664
+ init_src();
121665
+ init_internal();
121478
121666
  init_cli();
121667
+ init_system_engine();
121668
+ init_renderers();
121669
+ var STATUS_EXIT_CODE = {
121670
+ ok: 0 /* SUCCESS */,
121671
+ warning: 50 /* CONTEXT_WARNING */,
121672
+ caution: 51 /* CONTEXT_CAUTION */,
121673
+ critical: 52 /* CONTEXT_CRITICAL */,
121674
+ emergency: 53 /* CONTEXT_EMERGENCY */,
121675
+ stale: 54 /* CONTEXT_STALE */
121676
+ };
121479
121677
  function registerContextCommand(program) {
121480
121678
  const context = program.command("context").description("Monitor context window usage for agent safeguard system");
121481
121679
  context.command("status", { isDefault: true }).description("Show current context state (default)").option("--session <id>", "Check specific CLEO session").action(async (opts) => {
@@ -121490,69 +121688,38 @@ function registerContextCommand(program) {
121490
121688
  { command: "context" }
121491
121689
  );
121492
121690
  });
121493
- context.command("check").description("Check threshold, return exit code for scripting").option("--session <id>", "Check specific CLEO session").action(async (opts) => {
121494
- await dispatchFromCli(
121495
- "query",
121496
- "admin",
121497
- "context",
121498
- {
121499
- action: "check",
121500
- session: opts["session"]
121501
- },
121502
- { command: "context" }
121503
- );
121504
- });
121505
- context.command("list").description("List all context state files (multi-session)").action(async () => {
121506
- await dispatchFromCli(
121507
- "query",
121508
- "admin",
121509
- "context",
121510
- {
121511
- action: "list"
121512
- },
121513
- { command: "context" }
121514
- );
121515
- });
121516
- }
121517
-
121518
- // packages/cleo/src/cli/commands/contribution.ts
121519
- init_cli();
121520
- function registerContributionCommand(program) {
121521
- const contribution = program.command("contribution").description("Validate contribution protocol compliance for shared codebase work");
121522
- contribution.command("validate <taskId>").description("Validate contribution protocol compliance for task").option("--strict", "Exit with error code on violations").action(async (taskId, opts) => {
121523
- await dispatchFromCli(
121524
- "query",
121525
- "check",
121526
- "protocol",
121527
- {
121528
- protocolType: "contribution",
121529
- mode: "task",
121530
- taskId,
121531
- strict: opts["strict"]
121532
- },
121533
- { command: "contribution" }
121534
- );
121535
- });
121536
- contribution.command("check <manifestFile>").description("Validate manifest entry directly").option("--strict", "Exit with error code on violations").action(async (manifestFile, opts) => {
121537
- await dispatchFromCli(
121538
- "query",
121539
- "check",
121540
- "protocol",
121541
- {
121542
- protocolType: "contribution",
121543
- mode: "manifest",
121544
- manifestFile,
121545
- strict: opts["strict"]
121546
- },
121547
- { command: "contribution" }
121548
- );
121691
+ context.command("check").description(
121692
+ "Check context window state \u2014 exits non-zero when threshold exceeded (for scripting)"
121693
+ ).option("--session <id>", "Check specific CLEO session").action(async (opts) => {
121694
+ const cwd = resolveProjectRoot();
121695
+ const result = systemContext(cwd, {
121696
+ session: opts["session"]
121697
+ });
121698
+ if (!result.success) {
121699
+ console.error(result.error?.message ?? "Context check failed");
121700
+ process.exit(1 /* GENERAL_ERROR */);
121701
+ return;
121702
+ }
121703
+ const data = result.data;
121704
+ if (!data) {
121705
+ console.error("Context check returned no data");
121706
+ process.exit(1 /* GENERAL_ERROR */);
121707
+ return;
121708
+ }
121709
+ cliOutput(data, { command: "context", operation: "admin.context" });
121710
+ const exitCode = STATUS_EXIT_CODE[data.status] ?? 0 /* SUCCESS */;
121711
+ if (exitCode !== 0 /* SUCCESS */) {
121712
+ process.exit(exitCode);
121713
+ }
121549
121714
  });
121550
121715
  }
121551
121716
 
121552
121717
  // packages/cleo/src/cli/commands/current.ts
121553
121718
  init_cli();
121554
121719
  function registerCurrentCommand(program) {
121555
- program.command("current").description("Show the current task being worked on").action(async () => {
121720
+ program.command("current").description(
121721
+ "Show the current task being worked on. Returns: {currentTask: string|null, currentPhase: string|null}"
121722
+ ).action(async () => {
121556
121723
  await dispatchFromCli("query", "tasks", "current", {}, { command: "current" });
121557
121724
  });
121558
121725
  }
@@ -121560,43 +121727,15 @@ function registerCurrentCommand(program) {
121560
121727
  // packages/cleo/src/cli/commands/dash.ts
121561
121728
  init_cli();
121562
121729
  function registerDashCommand(program) {
121563
- program.command("dash").description("Project dashboard with status summary, phase progress, recent activity").option("-c, --compact", "Condensed single-line view").option("--period <days>", "Stats period in days", "7").option("--no-chart", "Disable ASCII charts/progress bars").option("--sections <list>", "Comma-separated list of sections to show").option("-v, --verbose", "Show full task details").action(async () => {
121564
- await dispatchFromCli("query", "admin", "dash", {}, { command: "dash" });
121565
- });
121566
- }
121567
-
121568
- // packages/cleo/src/cli/commands/decomposition.ts
121569
- init_cli();
121570
- function registerDecompositionCommand(program) {
121571
- const decomposition = program.command("decomposition").description("Validate decomposition protocol compliance for epic breakdown tasks");
121572
- decomposition.command("validate <taskId>").description("Validate decomposition protocol compliance for task").option("--strict", "Exit with error code on violations").option("--epic <id>", "Specify parent epic ID").action(async (taskId, opts) => {
121573
- await dispatchFromCli(
121574
- "query",
121575
- "check",
121576
- "protocol",
121577
- {
121578
- protocolType: "decomposition",
121579
- mode: "task",
121580
- taskId,
121581
- strict: opts["strict"],
121582
- epicId: opts["epic"]
121583
- },
121584
- { command: "decomposition" }
121585
- );
121586
- });
121587
- decomposition.command("check <manifestFile>").description("Validate manifest entry directly").option("--strict", "Exit with error code on violations").option("--epic <id>", "Specify parent epic ID").action(async (manifestFile, opts) => {
121730
+ program.command("dash").description(
121731
+ "Project health dashboard: status summary, phase progress, recent activity, high priority tasks. Use for overall project status."
121732
+ ).option("--blocked-limit <n>", "Max blocked tasks to show", parseInt).action(async (opts) => {
121588
121733
  await dispatchFromCli(
121589
121734
  "query",
121590
- "check",
121591
- "protocol",
121592
- {
121593
- protocolType: "decomposition",
121594
- mode: "manifest",
121595
- manifestFile,
121596
- strict: opts["strict"],
121597
- epicId: opts["epic"]
121598
- },
121599
- { command: "decomposition" }
121735
+ "admin",
121736
+ "dash",
121737
+ { blockedTasksLimit: opts["blockedLimit"] },
121738
+ { command: "dash" }
121600
121739
  );
121601
121740
  });
121602
121741
  }
@@ -121654,7 +121793,7 @@ function registerDepsCommand(program) {
121654
121793
  { command: "deps", operation: "tasks.depends" }
121655
121794
  );
121656
121795
  });
121657
- deps.command("waves [epicId]").description("Group tasks into parallelizable execution waves").action(async (epicId) => {
121796
+ deps.command("waves <epicId>").description("Group tasks into parallelizable execution waves").action(async (epicId) => {
121658
121797
  await dispatchFromCli(
121659
121798
  "query",
121660
121799
  "orchestrate",
@@ -121732,15 +121871,15 @@ function registerDetectCommand(program) {
121732
121871
  // packages/cleo/src/cli/commands/detect-drift.ts
121733
121872
  init_src();
121734
121873
  init_renderers();
121735
- import { existsSync as existsSync129, readdirSync as readdirSync41, readFileSync as readFileSync98 } from "node:fs";
121736
- import { dirname as dirname26, join as join125 } from "node:path";
121874
+ import { existsSync as existsSync131, readdirSync as readdirSync41, readFileSync as readFileSync98 } from "node:fs";
121875
+ import { dirname as dirname27, join as join126 } from "node:path";
121737
121876
  function findProjectRoot() {
121738
121877
  let currentDir = process.cwd();
121739
121878
  while (currentDir !== "/") {
121740
- if (existsSync129(join125(currentDir, "package.json"))) {
121879
+ if (existsSync131(join126(currentDir, "package.json"))) {
121741
121880
  return currentDir;
121742
121881
  }
121743
- const parent = dirname26(currentDir);
121882
+ const parent = dirname27(currentDir);
121744
121883
  if (parent === currentDir) break;
121745
121884
  currentDir = parent;
121746
121885
  }
@@ -121749,7 +121888,8 @@ function findProjectRoot() {
121749
121888
  function registerDetectDriftCommand(program) {
121750
121889
  program.command("detect-drift").description("Detect documentation drift against TypeScript source of truth").action(async () => {
121751
121890
  const projectRoot = findProjectRoot();
121752
- const isCleoRepo = existsSync129(join125(projectRoot, "src", "cli", "commands")) || existsSync129(join125(projectRoot, "packages", "cleo", "src"));
121891
+ const isCleoRepo = existsSync131(join126(projectRoot, "packages", "cleo", "src"));
121892
+ const cleoSrcRoot = isCleoRepo ? join126(projectRoot, "packages", "cleo", "src") : join126(projectRoot, "src");
121753
121893
  const safeRead = (filePath) => {
121754
121894
  try {
121755
121895
  return readFileSync98(filePath, "utf-8");
@@ -121763,8 +121903,8 @@ function registerDetectDriftCommand(program) {
121763
121903
  checks: [],
121764
121904
  recommendations: []
121765
121905
  };
121766
- const injPath = join125(projectRoot, ".cleo", "templates", "CLEO-INJECTION.md");
121767
- if (existsSync129(injPath)) {
121906
+ const injPath = join126(projectRoot, ".cleo", "templates", "CLEO-INJECTION.md");
121907
+ if (existsSync131(injPath)) {
121768
121908
  const content = safeRead(injPath);
121769
121909
  userResult.checks.push({
121770
121910
  name: "Agent injection",
@@ -121815,27 +121955,27 @@ function registerDetectDriftCommand(program) {
121815
121955
  }
121816
121956
  };
121817
121957
  try {
121818
- const specPath = join125(projectRoot, "docs", "specs", "CLEO-OPERATIONS-REFERENCE.md");
121819
- const registryPath = join125(projectRoot, "src", "dispatch", "registry.ts");
121820
- const dispatchDomainsDir = join125(projectRoot, "src", "dispatch", "domains");
121821
- if (!existsSync129(specPath)) {
121822
- addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATIONS-REFERENCE.md missing", [
121958
+ const specPath = join126(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
121959
+ const registryPath = join126(cleoSrcRoot, "dispatch", "registry.ts");
121960
+ const dispatchDomainsDir = join126(cleoSrcRoot, "dispatch", "domains");
121961
+ if (!existsSync131(specPath)) {
121962
+ addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATION-CONSTITUTION.md missing", [
121823
121963
  {
121824
121964
  severity: "error",
121825
121965
  category: "spec",
121826
121966
  message: "Operations reference specification not found",
121827
121967
  file: specPath,
121828
- recommendation: "Create docs/specs/CLEO-OPERATIONS-REFERENCE.md with canonical operation definitions"
121968
+ recommendation: "Create docs/specs/CLEO-OPERATION-CONSTITUTION.md with canonical operation definitions"
121829
121969
  }
121830
121970
  ]);
121831
- } else if (!existsSync129(registryPath) || !existsSync129(dispatchDomainsDir)) {
121971
+ } else if (!existsSync131(registryPath) || !existsSync131(dispatchDomainsDir)) {
121832
121972
  addCheck("Gateway-to-spec sync", "fail", "Dispatch registry or domains missing", [
121833
121973
  {
121834
121974
  severity: "error",
121835
121975
  category: "implementation",
121836
121976
  message: "Dispatch registry or domains directory not found",
121837
121977
  file: registryPath,
121838
- recommendation: "Verify src/dispatch/registry.ts and src/dispatch/domains/ exist"
121978
+ recommendation: "Verify packages/cleo/src/dispatch/registry.ts and packages/cleo/src/dispatch/domains/ exist"
121839
121979
  }
121840
121980
  ]);
121841
121981
  } else {
@@ -121892,23 +122032,23 @@ function registerDetectDriftCommand(program) {
121892
122032
  ]);
121893
122033
  }
121894
122034
  try {
121895
- const cliDir = join125(projectRoot, "src", "cli", "commands");
121896
- const coreDir = join125(projectRoot, "src", "core");
121897
- if (!existsSync129(cliDir)) {
122035
+ const cliDir = join126(cleoSrcRoot, "cli", "commands");
122036
+ const coreDir = isCleoRepo ? join126(projectRoot, "packages", "core", "src") : join126(projectRoot, "src", "core");
122037
+ if (!existsSync131(cliDir)) {
121898
122038
  addCheck("CLI-to-core sync", "fail", "CLI commands directory missing", [
121899
122039
  {
121900
122040
  severity: "error",
121901
122041
  category: "structure",
121902
- message: "src/cli/commands/ directory not found",
122042
+ message: `${cliDir} directory not found`,
121903
122043
  recommendation: "Verify TypeScript source structure is intact"
121904
122044
  }
121905
122045
  ]);
121906
- } else if (!existsSync129(coreDir)) {
122046
+ } else if (!existsSync131(coreDir)) {
121907
122047
  addCheck("CLI-to-core sync", "fail", "Core directory missing", [
121908
122048
  {
121909
122049
  severity: "error",
121910
122050
  category: "structure",
121911
- message: "src/core/ directory not found",
122051
+ message: `${coreDir} directory not found`,
121912
122052
  recommendation: "Verify TypeScript source structure is intact"
121913
122053
  }
121914
122054
  ]);
@@ -121922,13 +122062,13 @@ function registerDetectDriftCommand(program) {
121922
122062
  addCheck("CLI-to-core sync", "fail", `Error: ${getErrorMessage(e)}`);
121923
122063
  }
121924
122064
  try {
121925
- const domainsDir = join125(projectRoot, "src", "dispatch", "domains");
121926
- if (!existsSync129(domainsDir)) {
122065
+ const domainsDir = join126(cleoSrcRoot, "dispatch", "domains");
122066
+ if (!existsSync131(domainsDir)) {
121927
122067
  addCheck("Domain handler coverage", "fail", "Dispatch domains directory missing", [
121928
122068
  {
121929
122069
  severity: "error",
121930
122070
  category: "structure",
121931
- message: "src/dispatch/domains/ not found",
122071
+ message: `${domainsDir} not found`,
121932
122072
  recommendation: "Verify dispatch domain handlers are in place"
121933
122073
  }
121934
122074
  ]);
@@ -121940,13 +122080,13 @@ function registerDetectDriftCommand(program) {
121940
122080
  addCheck("Domain handler coverage", "fail", `Error: ${getErrorMessage(e)}`);
121941
122081
  }
121942
122082
  try {
121943
- const matrixPath = join125(projectRoot, "src", "dispatch", "lib", "capability-matrix.ts");
121944
- if (!existsSync129(matrixPath)) {
122083
+ const matrixPath = join126(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
122084
+ if (!existsSync131(matrixPath)) {
121945
122085
  addCheck("Capability matrix", "fail", "Capability matrix missing", [
121946
122086
  {
121947
122087
  severity: "error",
121948
122088
  category: "configuration",
121949
- message: "src/dispatch/lib/capability-matrix.ts not found",
122089
+ message: `${matrixPath} not found`,
121950
122090
  recommendation: "Create capability matrix to document supported operations"
121951
122091
  }
121952
122092
  ]);
@@ -121957,8 +122097,8 @@ function registerDetectDriftCommand(program) {
121957
122097
  addCheck("Capability matrix", "fail", `Error: ${getErrorMessage(e)}`);
121958
122098
  }
121959
122099
  try {
121960
- const schemaPath = join125(projectRoot, "src", "store", "schema.ts");
121961
- if (!existsSync129(schemaPath)) {
122100
+ const schemaPath = join126(projectRoot, "src", "store", "schema.ts");
122101
+ if (!existsSync131(schemaPath)) {
121962
122102
  addCheck("Schema validation", "fail", "Schema definition missing", [
121963
122103
  {
121964
122104
  severity: "error",
@@ -121992,10 +122132,10 @@ function registerDetectDriftCommand(program) {
121992
122132
  addCheck("Schema validation", "fail", `Error: ${getErrorMessage(e)}`);
121993
122133
  }
121994
122134
  try {
121995
- const visionPath = join125(projectRoot, "docs", "concepts", "CLEO-VISION.md");
121996
- const specPath = join125(projectRoot, "docs", "specs", "PORTABLE-BRAIN-SPEC.md");
122135
+ const visionPath = join126(projectRoot, "docs", "concepts", "CLEO-VISION.md");
122136
+ const specPath = join126(projectRoot, "docs", "specs", "PORTABLE-BRAIN-SPEC.md");
121997
122137
  const issues = [];
121998
- if (!existsSync129(visionPath)) {
122138
+ if (!existsSync131(visionPath)) {
121999
122139
  issues.push({
122000
122140
  severity: "error",
122001
122141
  category: "vision",
@@ -122004,7 +122144,7 @@ function registerDetectDriftCommand(program) {
122004
122144
  recommendation: "Create docs/concepts/CLEO-VISION.md with project vision"
122005
122145
  });
122006
122146
  }
122007
- if (!existsSync129(specPath)) {
122147
+ if (!existsSync131(specPath)) {
122008
122148
  issues.push({
122009
122149
  severity: "error",
122010
122150
  category: "spec",
@@ -122048,8 +122188,8 @@ function registerDetectDriftCommand(program) {
122048
122188
  addCheck("Canonical identity", "fail", `Error: ${getErrorMessage(e)}`);
122049
122189
  }
122050
122190
  try {
122051
- const injectionPath = join125(projectRoot, ".cleo", "templates", "CLEO-INJECTION.md");
122052
- if (!existsSync129(injectionPath)) {
122191
+ const injectionPath = join126(projectRoot, ".cleo", "templates", "CLEO-INJECTION.md");
122192
+ if (!existsSync131(injectionPath)) {
122053
122193
  addCheck("Agent injection", "fail", "Agent injection template missing", [
122054
122194
  {
122055
122195
  severity: "error",
@@ -122078,14 +122218,14 @@ function registerDetectDriftCommand(program) {
122078
122218
  addCheck("Agent injection", "fail", `Error: ${getErrorMessage(e)}`);
122079
122219
  }
122080
122220
  try {
122081
- const exitCodesPath = join125(projectRoot, "src", "types", "exit-codes.ts");
122082
- if (!existsSync129(exitCodesPath)) {
122221
+ const exitCodesPath = join126(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
122222
+ if (!existsSync131(exitCodesPath)) {
122083
122223
  addCheck("Exit codes", "fail", "Exit codes definition missing", [
122084
122224
  {
122085
122225
  severity: "error",
122086
122226
  category: "protocol",
122087
- message: "src/types/exit-codes.ts not found",
122088
- recommendation: "Create exit codes enum for CLI protocol compliance"
122227
+ message: `${exitCodesPath} not found`,
122228
+ recommendation: "Create exit codes definition for CLI protocol compliance"
122089
122229
  }
122090
122230
  ]);
122091
122231
  } else {
@@ -122098,7 +122238,6 @@ function registerDetectDriftCommand(program) {
122098
122238
  }
122099
122239
  if (result.summary.errors > 0) {
122100
122240
  result.recommendations.push("Address all ERROR-level issues before proceeding");
122101
- result.recommendations.push("Run cleo detect-drift --json for structured output");
122102
122241
  }
122103
122242
  if (result.summary.warnings > 0) {
122104
122243
  result.recommendations.push("Review WARNING-level issues for documentation improvements");
@@ -122115,9 +122254,9 @@ function registerDetectDriftCommand(program) {
122115
122254
  init_internal();
122116
122255
  init_renderers();
122117
122256
  import { readdir as readdir3, readFile as readFile21 } from "node:fs/promises";
122118
- import { join as join126 } from "node:path";
122257
+ import { join as join127 } from "node:path";
122119
122258
  async function getScriptNames(projectRoot) {
122120
- const scriptsDir = join126(projectRoot, "scripts");
122259
+ const scriptsDir = join127(projectRoot, "scripts");
122121
122260
  try {
122122
122261
  const files = await readdir3(scriptsDir);
122123
122262
  return files.filter((f2) => f2.endsWith(".sh")).map((f2) => f2.replace(".sh", "")).sort();
@@ -122126,7 +122265,7 @@ async function getScriptNames(projectRoot) {
122126
122265
  }
122127
122266
  }
122128
122267
  async function getIndexedCommands(projectRoot) {
122129
- const indexPath = join126(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
122268
+ const indexPath = join127(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
122130
122269
  const index2 = await readJson(indexPath);
122131
122270
  if (!index2) return [];
122132
122271
  return index2.commands.map((c) => c.name).sort();
@@ -122159,7 +122298,7 @@ async function runGapCheck(_projectRoot, filterId) {
122159
122298
  const reviewFiles = files.filter((f2) => f2.endsWith(".md"));
122160
122299
  for (const file2 of reviewFiles) {
122161
122300
  if (filterId && !file2.includes(filterId)) continue;
122162
- const filePath = join126(reviewDir, file2);
122301
+ const filePath = join127(reviewDir, file2);
122163
122302
  const content = await readFile21(filePath, "utf-8");
122164
122303
  const taskMatch = file2.match(/^(T\d+)/);
122165
122304
  const taskId = taskMatch ? taskMatch[1] : "UNKNOWN";
@@ -122597,7 +122736,7 @@ var FIND_PARAMS = [
122597
122736
  name: "query",
122598
122737
  type: "string",
122599
122738
  required: false,
122600
- description: "Fuzzy search query (title/description)",
122739
+ description: "Search text (required unless --id is provided)",
122601
122740
  cli: { positional: true }
122602
122741
  },
122603
122742
  {
@@ -122626,7 +122765,7 @@ var FIND_PARAMS = [
122626
122765
  name: "field",
122627
122766
  type: "string",
122628
122767
  required: false,
122629
- description: "Field to search in (title, description, etc.)",
122768
+ description: "Field to search in (title|description|notes|id)",
122630
122769
  cli: { flag: "in" }
122631
122770
  },
122632
122771
  {
@@ -122711,8 +122850,8 @@ init_src();
122711
122850
  init_src2();
122712
122851
  init_renderers();
122713
122852
  import { execFileSync as execFileSync16 } from "node:child_process";
122714
- import { existsSync as existsSync130, mkdirSync as mkdirSync30, readFileSync as readFileSync99, writeFileSync as writeFileSync23 } from "node:fs";
122715
- import { dirname as dirname27, join as join127 } from "node:path";
122853
+ import { existsSync as existsSync132, mkdirSync as mkdirSync30, readFileSync as readFileSync99, writeFileSync as writeFileSync23 } from "node:fs";
122854
+ import { dirname as dirname28, join as join128 } from "node:path";
122716
122855
  function getChangelogSource(cwd) {
122717
122856
  const configPath = getConfigPath(cwd);
122718
122857
  try {
@@ -122850,8 +122989,8 @@ function registerGenerateChangelogCommand(program) {
122850
122989
  const targetPlatform = opts["platform"];
122851
122990
  const dryRun = !!opts["dryRun"];
122852
122991
  const sourceFile = getChangelogSource();
122853
- const sourcePath = join127(getProjectRoot(), sourceFile);
122854
- if (!existsSync130(sourcePath)) {
122992
+ const sourcePath = join128(getProjectRoot(), sourceFile);
122993
+ if (!existsSync132(sourcePath)) {
122855
122994
  throw new CleoError(4 /* NOT_FOUND */, `Changelog source not found: ${sourcePath}`);
122856
122995
  }
122857
122996
  const sourceContent = readFileSync99(sourcePath, "utf-8");
@@ -122863,8 +123002,8 @@ function registerGenerateChangelogCommand(program) {
122863
123002
  const outputPath = platformConfig?.path ?? getDefaultOutputPath(targetPlatform);
122864
123003
  const content = generateForPlatform(targetPlatform, sourceContent, repoSlug, limit);
122865
123004
  if (!dryRun) {
122866
- const fullPath = join127(getProjectRoot(), outputPath);
122867
- mkdirSync30(dirname27(fullPath), { recursive: true });
123005
+ const fullPath = join128(getProjectRoot(), outputPath);
123006
+ mkdirSync30(dirname28(fullPath), { recursive: true });
122868
123007
  writeFileSync23(fullPath, content, "utf-8");
122869
123008
  }
122870
123009
  results.push({ platform: targetPlatform, path: outputPath, written: !dryRun });
@@ -122884,8 +123023,8 @@ function registerGenerateChangelogCommand(program) {
122884
123023
  limit
122885
123024
  );
122886
123025
  if (!dryRun) {
122887
- const fullPath = join127(getProjectRoot(), platformConfig.path);
122888
- mkdirSync30(dirname27(fullPath), { recursive: true });
123026
+ const fullPath = join128(getProjectRoot(), platformConfig.path);
123027
+ mkdirSync30(dirname28(fullPath), { recursive: true });
122889
123028
  writeFileSync23(fullPath, content, "utf-8");
122890
123029
  }
122891
123030
  results.push({
@@ -122929,7 +123068,8 @@ function registerGradeCommand(program) {
122929
123068
  // packages/cleo/src/cli/commands/history.ts
122930
123069
  init_cli();
122931
123070
  function registerHistoryCommand(program) {
122932
- const history = program.command("history").description("Completion timeline and productivity analytics").option("--days <n>", "Show last N days", "30").option("--since <date>", "Show completions since date (YYYY-MM-DD)").option("--until <date>", "Show completions until date (YYYY-MM-DD)").option("--no-chart", "Disable bar charts").action(async (opts) => {
123071
+ const history = program.command("history").description("Completion timeline and productivity analytics");
123072
+ history.command("log").description("Show operation audit log").option("--days <n>", "Show last N days", "30").option("--since <date>", "Show completions since date (YYYY-MM-DD)").option("--until <date>", "Show completions until date (YYYY-MM-DD)").option("--no-chart", "Disable bar charts").action(async (opts) => {
122933
123073
  await dispatchFromCli(
122934
123074
  "query",
122935
123075
  "admin",
@@ -122947,40 +123087,6 @@ function registerHistoryCommand(program) {
122947
123087
  });
122948
123088
  }
122949
123089
 
122950
- // packages/cleo/src/cli/commands/implementation.ts
122951
- init_cli();
122952
- function registerImplementationCommand(program) {
122953
- const implementation = program.command("implementation").description("Validate implementation protocol compliance for code tasks");
122954
- implementation.command("validate <taskId>").description("Validate implementation protocol compliance for task").option("--strict", "Exit with error code on violations").action(async (taskId, opts) => {
122955
- await dispatchFromCli(
122956
- "query",
122957
- "check",
122958
- "protocol",
122959
- {
122960
- protocolType: "implementation",
122961
- mode: "task",
122962
- taskId,
122963
- strict: opts["strict"]
122964
- },
122965
- { command: "implementation" }
122966
- );
122967
- });
122968
- implementation.command("check <manifestFile>").description("Validate manifest entry directly").option("--strict", "Exit with error code on violations").action(async (manifestFile, opts) => {
122969
- await dispatchFromCli(
122970
- "query",
122971
- "check",
122972
- "protocol",
122973
- {
122974
- protocolType: "implementation",
122975
- mode: "manifest",
122976
- manifestFile,
122977
- strict: opts["strict"]
122978
- },
122979
- { command: "implementation" }
122980
- );
122981
- });
122982
- }
122983
-
122984
123090
  // packages/cleo/src/cli/commands/import.ts
122985
123091
  init_cli();
122986
123092
  function registerImportCommand(program) {
@@ -123153,7 +123259,7 @@ function registerLabelsCommand(program) {
123153
123259
  await dispatchFromCli("query", "tasks", "label.list", {}, { command: "labels" });
123154
123260
  });
123155
123261
  labels.command("show <label>").description("Show tasks with specific label").action(async (label) => {
123156
- await dispatchFromCli("query", "tasks", "label.list", { label }, { command: "labels" });
123262
+ await dispatchFromCli("query", "tasks", "list", { label }, { command: "labels" });
123157
123263
  });
123158
123264
  labels.command("stats").description("Show detailed label statistics").action(async () => {
123159
123265
  await dispatchFromCli("query", "tasks", "label.list", {}, { command: "labels" });
@@ -123176,7 +123282,9 @@ function registerLifecycleCommand(program) {
123176
123282
  { command: "lifecycle" }
123177
123283
  );
123178
123284
  });
123179
- lifecycle.command("start <epicId> <stage>").description("Start a lifecycle stage").action(async (epicId, stage) => {
123285
+ lifecycle.command("start <epicId> <stage>").description(
123286
+ "Start a lifecycle stage. Valid stages: research|consensus|architecture_decision|specification|decomposition|implementation|validation|testing|release|contribution"
123287
+ ).action(async (epicId, stage) => {
123180
123288
  await dispatchFromCli(
123181
123289
  "mutate",
123182
123290
  "pipeline",
@@ -123189,7 +123297,9 @@ function registerLifecycleCommand(program) {
123189
123297
  { command: "lifecycle" }
123190
123298
  );
123191
123299
  });
123192
- lifecycle.command("complete <epicId> <stage>").description("Complete a lifecycle stage").option("--artifacts <artifacts>", "Comma-separated artifact paths").option("--notes <notes>", "Completion notes").action(async (epicId, stage, opts) => {
123300
+ lifecycle.command("complete <epicId> <stage>").description(
123301
+ "Complete a lifecycle stage. Valid stages: research|consensus|architecture_decision|specification|decomposition|implementation|validation|testing|release|contribution"
123302
+ ).option("--artifacts <artifacts>", "Comma-separated artifact paths").option("--notes <notes>", "Completion notes").action(async (epicId, stage, opts) => {
123193
123303
  await dispatchFromCli(
123194
123304
  "mutate",
123195
123305
  "pipeline",
@@ -123203,7 +123313,9 @@ function registerLifecycleCommand(program) {
123203
123313
  { command: "lifecycle" }
123204
123314
  );
123205
123315
  });
123206
- lifecycle.command("skip <epicId> <stage>").description("Skip a lifecycle stage").requiredOption("--reason <reason>", "Reason for skipping").action(async (epicId, stage, opts) => {
123316
+ lifecycle.command("skip <epicId> <stage>").description(
123317
+ "Skip a lifecycle stage. Valid stages: research|consensus|architecture_decision|specification|decomposition|implementation|validation|testing|release|contribution"
123318
+ ).requiredOption("--reason <reason>", "Reason for skipping").action(async (epicId, stage, opts) => {
123207
123319
  await dispatchFromCli(
123208
123320
  "mutate",
123209
123321
  "pipeline",
@@ -123256,7 +123368,9 @@ function registerLifecycleCommand(program) {
123256
123368
  { command: "lifecycle" }
123257
123369
  );
123258
123370
  });
123259
- lifecycle.command("reset <epicId> <stage>").description("Reset a lifecycle stage back to pending").requiredOption("--reason <reason>", "Reason for resetting the stage").action(async (epicId, stage, opts) => {
123371
+ lifecycle.command("reset <epicId> <stage>").description(
123372
+ "Reset a lifecycle stage back to pending. Valid stages: research|consensus|architecture_decision|specification|decomposition|implementation|validation|testing|release|contribution"
123373
+ ).requiredOption("--reason <reason>", "Reason for resetting the stage").action(async (epicId, stage, opts) => {
123260
123374
  await dispatchFromCli(
123261
123375
  "mutate",
123262
123376
  "pipeline",
@@ -123528,7 +123642,7 @@ function registerMemoryBrainCommand(program) {
123528
123642
  );
123529
123643
  }
123530
123644
  });
123531
- memory.command("stats").description("Show BRAIN memory statistics").option("--json", "Output as JSON").action(async () => {
123645
+ memory.command("stats").description("Show BRAIN memory statistics").action(async () => {
123532
123646
  const pResponse = await dispatchRaw("query", "memory", "pattern.find", {
123533
123647
  query: "",
123534
123648
  limit: 0
@@ -123541,10 +123655,10 @@ function registerMemoryBrainCommand(program) {
123541
123655
  if (pResponse.success) result["patterns"] = pResponse.data;
123542
123656
  if (lResponse.success) result["learnings"] = lResponse.data;
123543
123657
  if (!pResponse.success && !lResponse.success) {
123544
- handleRawError(pResponse, { command: "memory", operation: "memory.stats" });
123658
+ handleRawError(pResponse, { command: "memory-stats", operation: "memory.stats" });
123545
123659
  return;
123546
123660
  }
123547
- cliOutput(result, { command: "memory", operation: "memory.stats" });
123661
+ cliOutput(result, { command: "memory-stats", operation: "memory.stats" });
123548
123662
  });
123549
123663
  memory.command("observe <text>").description(
123550
123664
  "Save an observation to brain.db \u2014 captures facts, decisions, and discoveries for cross-session memory"
@@ -123575,7 +123689,7 @@ function registerMemoryBrainCommand(program) {
123575
123689
  { command: "memory", operation: "memory.observe" }
123576
123690
  );
123577
123691
  });
123578
- memory.command("timeline <anchor>").description("Show chronological context around an anchor observation ID").option("--before <n>", "Number of entries before anchor", parseInt).option("--after <n>", "Number of entries after anchor", parseInt).option("--json", "Output as JSON").action(async (anchor, opts) => {
123692
+ memory.command("timeline <anchor>").description("Show chronological context around an anchor observation ID").option("--before <n>", "Number of entries before anchor", parseInt).option("--after <n>", "Number of entries after anchor", parseInt).action(async (anchor, opts) => {
123579
123693
  await dispatchFromCli(
123580
123694
  "query",
123581
123695
  "memory",
@@ -123585,17 +123699,17 @@ function registerMemoryBrainCommand(program) {
123585
123699
  depthBefore: opts["before"],
123586
123700
  depthAfter: opts["after"]
123587
123701
  },
123588
- { command: "memory", operation: "memory.timeline" }
123702
+ { command: "memory-timeline", operation: "memory.timeline" }
123589
123703
  );
123590
123704
  });
123591
- memory.command("fetch <ids>").description("Fetch full details for specific observation IDs").option("--json", "Output as JSON").action(async (idsRaw, _opts) => {
123705
+ memory.command("fetch <ids>").description("Fetch full details for specific observation IDs").action(async (idsRaw) => {
123592
123706
  const ids = idsRaw.split(/[,\s]+/).map((s3) => s3.trim()).filter(Boolean);
123593
123707
  await dispatchFromCli(
123594
123708
  "query",
123595
123709
  "memory",
123596
123710
  "fetch",
123597
123711
  { ids },
123598
- { command: "memory", operation: "memory.fetch" }
123712
+ { command: "memory-fetch", operation: "memory.fetch" }
123599
123713
  );
123600
123714
  });
123601
123715
  memory.command("decision-find [query]").description("Search decisions stored in brain.db").option("--limit <n>", "Maximum results", parseInt).option("--json", "Output as JSON").action(async (query, opts) => {
@@ -123655,16 +123769,17 @@ function registerMemoryBrainCommand(program) {
123655
123769
  { command: "memory", operation: "memory.graph.neighbors" }
123656
123770
  );
123657
123771
  });
123658
- memory.command("graph-add").description("Add a node or edge to the PageIndex graph").option("--node-id <id>", "Node ID to add").option("--label <text>", "Label for the node").option("--from <id>", "Source node ID for an edge").option("--to <id>", "Target node ID for an edge").option("--edge-type <type>", "Edge relationship type").option("--json", "Output as JSON").action(async (opts) => {
123772
+ memory.command("graph-add").description("Add a node or edge to the PageIndex graph").option("--node-id <id>", "Node ID to add").option("--node-type <type>", "Node type (e.g. concept, task, file)").option("--label <text>", "Label for the node").option("--from <id>", "Source node ID for an edge").option("--to <id>", "Target node ID for an edge").option("--edge-type <type>", "Edge relationship type").option("--json", "Output as JSON").action(async (opts) => {
123659
123773
  await dispatchFromCli(
123660
123774
  "mutate",
123661
123775
  "memory",
123662
123776
  "graph.add",
123663
123777
  {
123664
123778
  ...opts["nodeId"] !== void 0 && { nodeId: opts["nodeId"] },
123779
+ ...opts["nodeType"] !== void 0 && { nodeType: opts["nodeType"] },
123665
123780
  ...opts["label"] !== void 0 && { label: opts["label"] },
123666
- ...opts["from"] !== void 0 && { from: opts["from"] },
123667
- ...opts["to"] !== void 0 && { to: opts["to"] },
123781
+ ...opts["from"] !== void 0 && { fromId: opts["from"] },
123782
+ ...opts["to"] !== void 0 && { toId: opts["to"] },
123668
123783
  ...opts["edgeType"] !== void 0 && { edgeType: opts["edgeType"] }
123669
123784
  },
123670
123785
  { command: "memory", operation: "memory.graph.add" }
@@ -123677,8 +123792,8 @@ function registerMemoryBrainCommand(program) {
123677
123792
  "graph.remove",
123678
123793
  {
123679
123794
  ...opts["nodeId"] !== void 0 && { nodeId: opts["nodeId"] },
123680
- ...opts["from"] !== void 0 && { from: opts["from"] },
123681
- ...opts["to"] !== void 0 && { to: opts["to"] }
123795
+ ...opts["from"] !== void 0 && { fromId: opts["from"] },
123796
+ ...opts["to"] !== void 0 && { toId: opts["to"] }
123682
123797
  },
123683
123798
  { command: "memory", operation: "memory.graph.remove" }
123684
123799
  );
@@ -123724,6 +123839,7 @@ function registerMemoryBrainCommand(program) {
123724
123839
  // packages/cleo/src/cli/commands/migrate-claude-mem.ts
123725
123840
  init_internal();
123726
123841
  init_cli();
123842
+ init_renderers();
123727
123843
  function registerMigrateClaudeMemCommand(program) {
123728
123844
  let migrateCmd = program.commands.find((c) => c.name() === "migrate");
123729
123845
  if (!migrateCmd) {
@@ -123750,23 +123866,26 @@ function registerMigrateClaudeMemCommand(program) {
123750
123866
  dryRun: !!opts["dryRun"],
123751
123867
  batchSize: opts["batchSize"] || void 0
123752
123868
  });
123753
- if (result.dryRun) {
123754
- console.log("[dry run] No changes made.");
123755
- }
123756
- console.log(
123757
- `Imported ${result.observationsImported} observations, ${result.learningsImported} learnings, ${result.decisionsImported} decisions (${result.observationsSkipped} skipped)`
123869
+ cliOutput(
123870
+ {
123871
+ dryRun: result.dryRun,
123872
+ observationsImported: result.observationsImported,
123873
+ learningsImported: result.learningsImported,
123874
+ decisionsImported: result.decisionsImported,
123875
+ observationsSkipped: result.observationsSkipped,
123876
+ errors: result.errors
123877
+ },
123878
+ { command: "migrate-claude-mem", operation: "migrate.claude-mem" }
123758
123879
  );
123759
123880
  if (result.errors.length > 0) {
123760
- console.error(`
123761
- ${result.errors.length} error(s):`);
123762
- for (const err of result.errors) {
123763
- console.error(` - ${err}`);
123764
- }
123765
- process.exit(1);
123881
+ process.exitCode = 1;
123766
123882
  }
123767
123883
  } catch (err) {
123768
- console.error(`Error: ${err.message}`);
123769
- process.exit(1);
123884
+ const message = err instanceof Error ? err.message : String(err);
123885
+ cliError(message, "E_MIGRATION_FAILED", void 0, {
123886
+ operation: "migrate.claude-mem"
123887
+ });
123888
+ process.exitCode = 1;
123770
123889
  }
123771
123890
  });
123772
123891
  }
@@ -123999,42 +124118,6 @@ function registerNexusCommand(program) {
123999
124118
  });
124000
124119
  }
124001
124120
 
124002
- // packages/cleo/src/cli/commands/observe.ts
124003
- init_cli();
124004
- function registerObserveCommand(program) {
124005
- program.command("observe <text>").description(
124006
- "Save an observation to brain.db \u2014 captures facts, decisions, and discoveries for cross-session memory"
124007
- ).option(
124008
- "-t, --title <title>",
124009
- "Short title for the observation (defaults to first 120 chars of text)"
124010
- ).option(
124011
- "--type <type>",
124012
- "Category: discovery (found something new), decision (choice made), bugfix (bug found/fixed), refactor (code restructured), feature (feature added), change (general change), pattern (recurring pattern), session_summary (end-of-session recap)"
124013
- ).option(
124014
- "--agent <name>",
124015
- "Name of the agent producing this observation (enables per-agent memory retrieval)"
124016
- ).option(
124017
- "--source-type <sourceType>",
124018
- "How this observation was captured: manual (typed by human/agent), auto (lifecycle hook), transcript (extracted from session)"
124019
- ).action(
124020
- async (text3, opts) => {
124021
- await dispatchFromCli(
124022
- "mutate",
124023
- "memory",
124024
- "observe",
124025
- {
124026
- text: text3,
124027
- title: opts.title,
124028
- ...opts.type !== void 0 && { type: opts.type },
124029
- ...opts.agent !== void 0 && { agent: opts.agent },
124030
- sourceType: opts.sourceType ?? "manual"
124031
- },
124032
- { command: "observe", operation: "memory.observe" }
124033
- );
124034
- }
124035
- );
124036
- }
124037
-
124038
124121
  // packages/cleo/src/cli/commands/ops.ts
124039
124122
  init_cli();
124040
124123
  function registerOpsCommand(program) {
@@ -124148,11 +124231,18 @@ function registerOrchestrateCommand(program) {
124148
124231
  { command: "orchestrate" }
124149
124232
  );
124150
124233
  });
124151
- tessera.command("instantiate <templateId> <epicId>").description("Instantiate a tessera template for an epic").option("--var <pairs...>", "Key=value variable overrides").action(async (templateId, epicId, opts) => {
124234
+ tessera.command("instantiate <templateId> <epicId>").description("Instantiate a tessera template for an epic").option("--var <pairs>", "Comma-separated key=value variable overrides (e.g. foo=bar,baz=qux)").action(async (templateId, epicId, opts) => {
124152
124235
  const variables = {};
124153
- const pairs = opts["var"];
124154
- if (Array.isArray(pairs)) {
124155
- for (const pair of pairs) {
124236
+ const raw = opts["var"];
124237
+ if (typeof raw === "string") {
124238
+ for (const pair of raw.split(",")) {
124239
+ const eqIdx = pair.indexOf("=");
124240
+ if (eqIdx > 0) {
124241
+ variables[pair.slice(0, eqIdx).trim()] = pair.slice(eqIdx + 1).trim();
124242
+ }
124243
+ }
124244
+ } else if (Array.isArray(raw)) {
124245
+ for (const pair of raw) {
124156
124246
  const eqIdx = pair.indexOf("=");
124157
124247
  if (eqIdx > 0) {
124158
124248
  variables[pair.slice(0, eqIdx)] = pair.slice(eqIdx + 1);
@@ -124194,12 +124284,12 @@ function registerOrchestrateCommand(program) {
124194
124284
  { command: "orchestrate" }
124195
124285
  );
124196
124286
  });
124197
- orch.command("fanout-status").description("Get fanout status for an epic").option("--epic <epicId>", "Epic ID to scope fanout status to").action(async (opts) => {
124287
+ orch.command("fanout-status").description("Get fanout status by manifest entry ID").requiredOption("--manifest-entry-id <id>", "Manifest entry ID returned by orchestrate.fanout").action(async (opts) => {
124198
124288
  await dispatchFromCli(
124199
124289
  "query",
124200
124290
  "orchestrate",
124201
124291
  "fanout.status",
124202
- { epicId: opts["epic"] },
124292
+ { manifestEntryId: opts["manifestEntryId"] },
124203
124293
  { command: "orchestrate" }
124204
124294
  );
124205
124295
  });
@@ -124223,11 +124313,12 @@ function registerOrchestrateCommand(program) {
124223
124313
  });
124224
124314
  orch.command("fanout <epicId>").description("Fan out tasks for an epic using parallel spawn").option("--tasks <ids>", "Comma-separated task IDs to fan out").action(async (epicId, opts) => {
124225
124315
  const taskIds = typeof opts["tasks"] === "string" ? opts["tasks"].split(",").map((s3) => s3.trim()) : void 0;
124316
+ const items = taskIds ? taskIds.map((taskId) => ({ taskId, team: "default" })) : void 0;
124226
124317
  await dispatchFromCli(
124227
124318
  "mutate",
124228
124319
  "orchestrate",
124229
124320
  "fanout",
124230
- { epicId, taskIds },
124321
+ { epicId, items },
124231
124322
  { command: "orchestrate" }
124232
124323
  );
124233
124324
  });
@@ -124254,7 +124345,7 @@ function registerOrchestrateCommand(program) {
124254
124345
  "mutate",
124255
124346
  "orchestrate",
124256
124347
  "conduit.start",
124257
- { pollInterval: opts["pollInterval"] },
124348
+ { pollIntervalMs: opts["pollInterval"] },
124258
124349
  { command: "orchestrate" }
124259
124350
  );
124260
124351
  });
@@ -124274,7 +124365,7 @@ function registerOrchestrateCommand(program) {
124274
124365
  "conduit.send",
124275
124366
  {
124276
124367
  content,
124277
- agentId: opts["to"],
124368
+ to: opts["to"],
124278
124369
  conversationId: opts["conversation"]
124279
124370
  },
124280
124371
  { command: "orchestrate" }
@@ -124286,7 +124377,9 @@ function registerOrchestrateCommand(program) {
124286
124377
  init_internal();
124287
124378
  init_renderers();
124288
124379
  function registerOtelCommand(program) {
124289
- const otel = program.command("otel").description("Token metrics tracking - view status, summary, and manage tracking data");
124380
+ const otel = program.command("otel").description(
124381
+ "Lightweight token metrics from .cleo/metrics/TOKEN_USAGE.jsonl (session-level, spawn-level events)"
124382
+ );
124290
124383
  otel.command("status").description("Show token tracking status and recent activity").action(async () => {
124291
124384
  try {
124292
124385
  const result = await getOtelStatus();
@@ -124448,32 +124541,11 @@ function registerPhaseCommand(program) {
124448
124541
  });
124449
124542
  }
124450
124543
 
124451
- // packages/cleo/src/cli/commands/phases.ts
124452
- init_cli();
124453
- function registerPhasesCommand(program) {
124454
- const phases = program.command("phases").description("List phases with progress bars and statistics");
124455
- phases.command("list", { isDefault: true }).description("List all phases with progress (default)").action(async () => {
124456
- await dispatchFromCli("query", "pipeline", "phase.list", {}, { command: "phases" });
124457
- });
124458
- phases.command("show <phase>").description("Show phase details and task counts").action(async (phase) => {
124459
- await dispatchFromCli(
124460
- "query",
124461
- "pipeline",
124462
- "phase.show",
124463
- { phaseId: phase },
124464
- { command: "phases" }
124465
- );
124466
- });
124467
- phases.command("stats").description("Show detailed phase statistics").action(async () => {
124468
- await dispatchFromCli("query", "pipeline", "phase.list", {}, { command: "phases" });
124469
- });
124470
- }
124471
-
124472
124544
  // packages/cleo/src/cli/commands/plan.ts
124473
124545
  init_cli();
124474
124546
  function registerPlanCommand(program) {
124475
124547
  program.command("plan").description(
124476
- "Composite planning view: in-progress epics, ready tasks, blocked tasks, open bugs"
124548
+ "Task prioritization view: in-progress epics, ready tasks, blocked tasks, open bugs with scoring. Use when deciding what to work on next."
124477
124549
  ).action(async () => {
124478
124550
  await dispatchFromCli(
124479
124551
  "query",
@@ -124581,28 +124653,7 @@ function registerProviderCommand(program) {
124581
124653
  // packages/cleo/src/cli/commands/reason.ts
124582
124654
  init_cli();
124583
124655
  function registerReasonCommand(program) {
124584
- const reason = program.command("reason").description("Reasoning and intelligence operations (why, similar, impact, timeline)");
124585
- reason.command("why <taskId>").description("Explain why a task exists via causal trace through dependency chains").option("--json", "Output raw JSON envelope").action(async (taskId) => {
124586
- await dispatchFromCli(
124587
- "query",
124588
- "memory",
124589
- "reason.why",
124590
- { taskId },
124591
- { command: "reason", operation: "memory.reason.why" }
124592
- );
124593
- });
124594
- reason.command("similar <taskId>").description("Find BRAIN entries semantically similar to a task or observation ID").option("--limit <n>", "Maximum number of results to return", parseInt).option("--json", "Output raw JSON envelope").action(async (taskId, opts) => {
124595
- await dispatchFromCli(
124596
- "query",
124597
- "memory",
124598
- "reason.similar",
124599
- {
124600
- entryId: taskId,
124601
- limit: opts["limit"]
124602
- },
124603
- { command: "reason", operation: "memory.reason.similar" }
124604
- );
124605
- });
124656
+ const reason = program.command("reason").description("Reasoning and intelligence operations (impact, timeline)");
124606
124657
  reason.command("impact [taskId]").description(
124607
124658
  "Predict impact of a change. Use --change for free-text prediction, or pass a taskId for graph-based analysis."
124608
124659
  ).option("--change <description>", "Free-text description of the proposed change (T043)").option("--limit <n>", "Maximum seed tasks to match when using --change (default: 5)", "5").option("--depth <n>", "Maximum traversal depth when using taskId (default: 10)", "10").option("--json", "Output raw JSON envelope").action(async (taskId, opts) => {
@@ -124682,7 +124733,9 @@ function registerRelatesCommand(program) {
124682
124733
  handleRawError(response, { command: "relates", operation: "relates" });
124683
124734
  cliOutput(response.data ?? {}, { command: "relates" });
124684
124735
  });
124685
- relates.command("add <from> <to> <type> <reason>").description("Add a relates entry to a task").action(async (from, to2, type, reason) => {
124736
+ relates.command("add <from> <to> <type> <reason>").description(
124737
+ "Add a relates entry to a task. Valid types: blocks|related|duplicates|absorbs|fixes|extends|supersedes"
124738
+ ).action(async (from, to2, type, reason) => {
124686
124739
  await dispatchFromCli(
124687
124740
  "mutate",
124688
124741
  "tasks",
@@ -124736,15 +124789,6 @@ function registerReleaseCommand(program) {
124736
124789
  { command: "release" }
124737
124790
  );
124738
124791
  });
124739
- release2.command("changelog <version>").description("Generate changelog for a release").action(async (version2) => {
124740
- await dispatchFromCli(
124741
- "mutate",
124742
- "pipeline",
124743
- "release.ship",
124744
- { version: version2, step: "changelog" },
124745
- { command: "release" }
124746
- );
124747
- });
124748
124792
  release2.command("cancel <version>").description("Cancel and remove a release in draft or prepared state").action(async (version2) => {
124749
124793
  await dispatchFromCli(
124750
124794
  "mutate",
@@ -124890,15 +124934,15 @@ function registerRemoteCommand(program) {
124890
124934
  const remoteName = opts["remote"];
124891
124935
  const result = await pull(remoteName);
124892
124936
  if (!result.success) {
124893
- const output = {
124937
+ const details = {
124894
124938
  pulled: false,
124895
124939
  branch: result.branch,
124896
124940
  remote: result.remote
124897
124941
  };
124898
124942
  if (result.hasConflicts) {
124899
- output["conflicts"] = result.conflictFiles;
124943
+ details["conflicts"] = result.conflictFiles;
124900
124944
  }
124901
- cliOutput(output, { command: "pull", message: result.message });
124945
+ cliError(result.message, 1 /* GENERAL_ERROR */, { details });
124902
124946
  process.exit(1 /* GENERAL_ERROR */);
124903
124947
  }
124904
124948
  cliOutput(
@@ -124956,9 +125000,20 @@ function registerRemoteCommand(program) {
124956
125000
 
124957
125001
  // packages/cleo/src/cli/commands/reorder.ts
124958
125002
  init_cli();
125003
+ var BOTTOM_POSITION = 999999;
124959
125004
  function registerReorderCommand(program) {
124960
- program.command("reorder <task-id>").description("Change task position within sibling group").option("--position <n>", "Move to specific position", parseInt).option("--before <id>", "Move before specified task").option("--after <id>", "Move after specified task").option("--top", "Move to first position").option("--bottom", "Move to last position").action(async (taskId, opts) => {
124961
- const position = opts["position"];
125005
+ program.command("reorder <task-id>").description("Change task position within sibling group").option("--position <n>", "Move to specific zero-based position among siblings", parseInt).option("--top", "Move to the top (position 0)").option("--bottom", "Move to the bottom").action(async (taskId, opts) => {
125006
+ let position = opts["position"];
125007
+ if (opts["top"]) {
125008
+ position = 0;
125009
+ } else if (opts["bottom"]) {
125010
+ position = BOTTOM_POSITION;
125011
+ }
125012
+ if (position === void 0) {
125013
+ console.error("Error: Must specify --position <n>, --top, or --bottom.");
125014
+ process.exitCode = 2;
125015
+ return;
125016
+ }
124962
125017
  await dispatchFromCli(
124963
125018
  "mutate",
124964
125019
  "tasks",
@@ -124986,22 +125041,36 @@ function registerReparentCommand(program) {
124986
125041
 
124987
125042
  // packages/cleo/src/cli/commands/research.ts
124988
125043
  init_cli();
125044
+ function generateResearchId() {
125045
+ return `res_${Date.now()}`;
125046
+ }
124989
125047
  function registerResearchCommand(program) {
124990
125048
  const research = program.command("research").description("Research commands and manifest operations");
124991
- research.command("add").description("Add a research entry").requiredOption("-t, --task <taskId>", "Task ID to attach research to").requiredOption("--topic <topic>", "Research topic").option("--findings <findings>", "Comma-separated findings").option("--sources <sources>", "Comma-separated sources").action(async (opts) => {
125049
+ research.command("add").description("Add a research entry").requiredOption("-t, --task <taskId>", "Task ID to attach research to").requiredOption("--topic <topic>", "Research topic").option("--findings <findings>", "Comma-separated findings").option("--sources <sources>", "Comma-separated sources").option("--agent-type <agentType>", "Agent type that produced this entry", "researcher").action(async (opts) => {
125050
+ const topic = opts["topic"];
125051
+ const findings = opts["findings"] ? opts["findings"].split(",").map((s3) => s3.trim()) : [];
125052
+ const taskId = opts["task"];
125053
+ const agentType = opts["agentType"] ?? "researcher";
124992
125054
  await dispatchFromCli(
124993
125055
  "mutate",
124994
125056
  "pipeline",
124995
125057
  "manifest.append",
124996
125058
  {
124997
125059
  entry: {
124998
- taskId: opts["task"],
124999
- topic: opts["topic"],
125000
- findings: opts["findings"] ? opts["findings"].split(",").map((s3) => s3.trim()) : void 0,
125001
- sources: opts["sources"] ? opts["sources"].split(",").map((s3) => s3.trim()) : void 0
125060
+ id: generateResearchId(),
125061
+ file: "",
125062
+ title: topic,
125063
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
125064
+ status: "partial",
125065
+ agent_type: agentType,
125066
+ topics: [topic],
125067
+ key_findings: findings,
125068
+ actionable: findings.length > 0,
125069
+ needs_followup: [],
125070
+ linked_tasks: [taskId]
125002
125071
  }
125003
125072
  },
125004
- { command: "research" }
125073
+ { command: "research", operation: "pipeline.manifest.append" }
125005
125074
  );
125006
125075
  });
125007
125076
  research.command("show <id>").description("Show a research entry").action(async (id) => {
@@ -125042,29 +125111,46 @@ function registerResearchCommand(program) {
125042
125111
  "manifest.append",
125043
125112
  {
125044
125113
  entry: {
125045
- type: "link",
125046
- entryId: researchId,
125047
- taskId
125048
- }
125049
- },
125050
- { command: "research" }
125051
- );
125052
- });
125053
- research.command("update <id>").description("Update research findings").option("--findings <findings>", "Comma-separated findings").option("--sources <sources>", "Comma-separated sources").option("-s, --status <status>", "Set status").action(async (id, opts) => {
125114
+ id: researchId,
125115
+ file: "",
125116
+ title: `Link: ${researchId} -> ${taskId}`,
125117
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
125118
+ status: "partial",
125119
+ agent_type: "researcher",
125120
+ topics: [],
125121
+ key_findings: [],
125122
+ actionable: false,
125123
+ needs_followup: [],
125124
+ linked_tasks: [taskId]
125125
+ }
125126
+ },
125127
+ { command: "research", operation: "pipeline.manifest.append" }
125128
+ );
125129
+ });
125130
+ research.command("update <id>").description("Update research findings").option("--findings <findings>", "Comma-separated findings").option("--sources <sources>", "Comma-separated sources").option("-s, --status <status>", "Set status (completed, partial, blocked)").option("--topic <topic>", "Research topic (used as title)").action(async (id, opts) => {
125131
+ const findings = opts["findings"] ? opts["findings"].split(",").map((s3) => s3.trim()) : [];
125132
+ const status = opts["status"] ?? "partial";
125133
+ const topic = opts["topic"] ?? `Updated research: ${id}`;
125054
125134
  await dispatchFromCli(
125055
125135
  "mutate",
125056
125136
  "pipeline",
125057
125137
  "manifest.append",
125058
125138
  {
125059
125139
  entry: {
125060
- type: "update",
125061
- entryId: id,
125062
- findings: opts["findings"] ? opts["findings"].split(",").map((s3) => s3.trim()) : void 0,
125063
- sources: opts["sources"] ? opts["sources"].split(",").map((s3) => s3.trim()) : void 0,
125064
- status: opts["status"]
125140
+ id,
125141
+ file: "",
125142
+ title: topic,
125143
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
125144
+ status,
125145
+ agent_type: "researcher",
125146
+ topics: topic !== `Updated research: ${id}` ? [topic] : [],
125147
+ key_findings: findings,
125148
+ actionable: findings.length > 0,
125149
+ needs_followup: [],
125150
+ linked_tasks: []
125065
125151
  }
125066
125152
  },
125067
- { command: "research" }
125153
+ { command: "research", operation: "pipeline.manifest.append" }
125068
125154
  );
125069
125155
  });
125070
125156
  research.command("stats").description("Show research statistics").action(async () => {
@@ -125305,7 +125391,7 @@ function registerRestoreCommand(program) {
125305
125391
  const fileName = opts["file"] || "tasks.db";
125306
125392
  const scope = opts["scope"] || "project";
125307
125393
  const response = await dispatchRaw("mutate", "admin", "backup", {
125308
- action: "restore",
125394
+ action: "restore.file",
125309
125395
  file: fileName,
125310
125396
  dryRun: opts["dryRun"],
125311
125397
  scope
@@ -125667,7 +125753,7 @@ init_src();
125667
125753
  init_internal();
125668
125754
  import { execFile as execFile8 } from "node:child_process";
125669
125755
  import { readFile as readFile22 } from "node:fs/promises";
125670
- import { join as join128 } from "node:path";
125756
+ import { join as join129 } from "node:path";
125671
125757
  import * as readline2 from "node:readline";
125672
125758
  import { promisify as promisify8 } from "node:util";
125673
125759
  init_renderers();
@@ -125676,7 +125762,7 @@ var GITHUB_REPO = BUILD_CONFIG.repository.fullName;
125676
125762
  async function getCurrentVersion() {
125677
125763
  const cleoHome = getCleoHome();
125678
125764
  try {
125679
- const content = await readFile22(join128(cleoHome, "VERSION"), "utf-8");
125765
+ const content = await readFile22(join129(cleoHome, "VERSION"), "utf-8");
125680
125766
  return (content.split("\n")[0] ?? "unknown").trim();
125681
125767
  } catch {
125682
125768
  return "unknown";
@@ -125730,7 +125816,7 @@ async function writeRuntimeVersionMetadata(mode, source, version2) {
125730
125816
  ];
125731
125817
  await import("node:fs/promises").then(
125732
125818
  ({ writeFile: writeFile15, mkdir: mkdir20 }) => mkdir20(cleoHome, { recursive: true }).then(
125733
- () => writeFile15(join128(cleoHome, "VERSION"), `${lines.join("\n")}
125819
+ () => writeFile15(join129(cleoHome, "VERSION"), `${lines.join("\n")}
125734
125820
  `, "utf-8")
125735
125821
  )
125736
125822
  );
@@ -126043,7 +126129,7 @@ function registerSessionCommand(program) {
126043
126129
  { command: "session", operation: "session.start" }
126044
126130
  );
126045
126131
  });
126046
- session.command("stop").alias("end").description("Stop the current session").option("--session <id>", "Specific session ID to stop").option("--note <note>", "Stop note").option("--next-action <action>", "Suggested next action").action(async (opts) => {
126132
+ session.command("end").alias("stop").description("End the current session").option("--session <id>", "Specific session ID to stop").option("--note <note>", "Stop note").option("--next-action <action>", "Suggested next action").action(async (opts) => {
126047
126133
  await dispatchFromCli(
126048
126134
  "mutate",
126049
126135
  "session",
@@ -126064,7 +126150,7 @@ function registerSessionCommand(program) {
126064
126150
  handleRawError(response, { command: "session handoff", operation: "session.handoff.show" });
126065
126151
  }
126066
126152
  const data = response.data;
126067
- if (!data || !data.handoff) {
126153
+ if (!data?.handoff) {
126068
126154
  cliOutput(
126069
126155
  { handoff: null },
126070
126156
  {
@@ -126208,7 +126294,7 @@ function registerSessionCommand(program) {
126208
126294
  { command: "session", operation: "session.record.assumption" }
126209
126295
  );
126210
126296
  });
126211
- session.command("record-decision").description("Record a decision made during the current session").requiredOption("--session-id <sessionId>", "Session ID").requiredOption("--task-id <taskId>", "Task ID the decision relates to").requiredOption("--decision <decision>", "Decision text").requiredOption("--rationale <rationale>", "Rationale for the decision").option("--alternatives <alternatives>", "Alternatives considered").action(async (opts) => {
126297
+ session.command("record-decision").description("Record a decision made during the current session").option("--session-id <sessionId>", "Session ID (defaults to active session)").requiredOption("--task-id <taskId>", "Task ID the decision relates to").requiredOption("--decision <decision>", "Decision text").requiredOption("--rationale <rationale>", "Rationale for the decision").option("--alternatives <alternatives>", "Alternatives considered").action(async (opts) => {
126212
126298
  await dispatchFromCli(
126213
126299
  "mutate",
126214
126300
  "session",
@@ -126249,7 +126335,13 @@ var SHOW_PARAMS = [
126249
126335
  }
126250
126336
  ];
126251
126337
  function registerShowCommand(program) {
126252
- const cmd = program.command("show").description(buildOperationHelp("tasks.show", "Show full task details by ID", SHOW_PARAMS));
126338
+ const cmd = program.command("show").description(
126339
+ buildOperationHelp(
126340
+ "tasks.show",
126341
+ "Show full task details by ID (returns complete task record with metadata, verification, lifecycle)",
126342
+ SHOW_PARAMS
126343
+ )
126344
+ );
126253
126345
  applyParamDefsToCommand(cmd, SHOW_PARAMS, "tasks.show");
126254
126346
  cmd.action(async (taskId) => {
126255
126347
  await dispatchFromCli("query", "tasks", "show", { taskId }, { command: "show" });
@@ -126478,46 +126570,10 @@ function registerSnapshotCommand(program) {
126478
126570
  });
126479
126571
  }
126480
126572
 
126481
- // packages/cleo/src/cli/commands/specification.ts
126482
- init_cli();
126483
- function registerSpecificationCommand(program) {
126484
- const specification = program.command("specification").description("Validate specification protocol compliance");
126485
- specification.command("validate <taskId>").description("Validate specification protocol compliance for task").option("--strict", "Exit with error code on violations").option("--spec-file <file>", "Path to specification file").action(async (taskId, opts) => {
126486
- await dispatchFromCli(
126487
- "query",
126488
- "check",
126489
- "protocol",
126490
- {
126491
- protocolType: "specification",
126492
- mode: "task",
126493
- taskId,
126494
- strict: opts["strict"],
126495
- specFile: opts["specFile"]
126496
- },
126497
- { command: "specification" }
126498
- );
126499
- });
126500
- specification.command("check <manifestFile>").description("Validate manifest entry directly").option("--strict", "Exit with error code on violations").option("--spec-file <file>", "Path to specification file").action(async (manifestFile, opts) => {
126501
- await dispatchFromCli(
126502
- "query",
126503
- "check",
126504
- "protocol",
126505
- {
126506
- protocolType: "specification",
126507
- mode: "manifest",
126508
- manifestFile,
126509
- strict: opts["strict"],
126510
- specFile: opts["specFile"]
126511
- },
126512
- { command: "specification" }
126513
- );
126514
- });
126515
- }
126516
-
126517
126573
  // packages/cleo/src/cli/commands/start.ts
126518
126574
  init_cli();
126519
126575
  function registerStartCommand(program) {
126520
- program.command("start <taskId>").description("Start working on a task").action(async (taskId) => {
126576
+ program.command("start <taskId>").description("Start working on a task (sets it as the current task in the active session)").action(async (taskId) => {
126521
126577
  await dispatchFromCli("mutate", "tasks", "start", { taskId }, { command: "start" });
126522
126578
  });
126523
126579
  }
@@ -126531,7 +126587,7 @@ function registerStatsCommand(program) {
126531
126587
  "admin",
126532
126588
  "stats",
126533
126589
  {
126534
- period: opts["period"] ? Number(opts["period"]) : 30
126590
+ period: opts["period"] ?? 30
126535
126591
  },
126536
126592
  { command: "stats", operation: "admin.stats" }
126537
126593
  );
@@ -126557,15 +126613,17 @@ init_cli();
126557
126613
  init_renderers();
126558
126614
  function registerStickyCommand(program) {
126559
126615
  const sticky = program.command("sticky").description("Manage sticky notes - quick project-wide ephemeral captures");
126560
- sticky.command("add <content>").alias("jot").description("Create a new sticky note").option("--tag <tag>", "Add a tag (can be used multiple times)", collect, []).option("--color <color>", "Sticky color: yellow|blue|green|red|purple", "yellow").option("--priority <priority>", "Priority: low|medium|high", "medium").action(async (content, opts) => {
126616
+ sticky.command("add <content>").alias("jot").description("Create a new sticky note").option("--tag <tags>", 'Comma-separated tags (e.g. "bug,urgent")').option("--color <color>", "Sticky color: yellow|blue|green|red|purple", "yellow").option("--priority <priority>", "Priority: low|medium|high", "medium").action(async (content, opts) => {
126561
126617
  try {
126618
+ const rawTag = opts["tag"];
126619
+ const tags = rawTag ? rawTag.split(",").map((t) => t.trim()).filter(Boolean) : [];
126562
126620
  await dispatchFromCli(
126563
126621
  "mutate",
126564
126622
  "sticky",
126565
126623
  "add",
126566
126624
  {
126567
126625
  content,
126568
- tags: opts["tag"],
126626
+ tags,
126569
126627
  color: opts["color"],
126570
126628
  priority: opts["priority"]
126571
126629
  },
@@ -126579,10 +126637,12 @@ function registerStickyCommand(program) {
126579
126637
  throw err;
126580
126638
  }
126581
126639
  });
126582
- sticky.command("list").alias("ls").description("List active sticky notes").option("--tag <tag>", "Filter by tag").option("--color <color>", "Filter by color").option("--status <status>", "Filter by status: active|converted|archived", "active").option("--limit <n>", "Max results", parseInt, 50).action(async (opts) => {
126640
+ sticky.command("list").alias("ls").description("List active sticky notes").option("--tag <tags>", 'Filter by tags (comma-separated, e.g. "bug,urgent")').option("--color <color>", "Filter by color").option("--status <status>", "Filter by status: active|converted|archived", "active").option("--limit <n>", "Max results", parseInt, 50).action(async (opts) => {
126583
126641
  try {
126642
+ const rawTag = opts["tag"];
126643
+ const tags = rawTag ? rawTag.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
126584
126644
  const response = await dispatchRaw("query", "sticky", "list", {
126585
- tag: opts["tag"],
126645
+ tags,
126586
126646
  color: opts["color"],
126587
126647
  status: opts["status"],
126588
126648
  limit: opts["limit"]
@@ -126721,32 +126781,37 @@ function registerStickyCommand(program) {
126721
126781
  }
126722
126782
  });
126723
126783
  }
126724
- function collect(value, previous) {
126725
- return previous.concat([value]);
126726
- }
126727
126784
 
126728
126785
  // packages/cleo/src/cli/commands/stop.ts
126729
126786
  init_cli();
126730
126787
  function registerStopCommand(program) {
126731
- program.command("stop").description("Stop working on the current task").action(async () => {
126788
+ program.command("stop").description(
126789
+ "Stop working on the current task (clears the active task, returns {cleared: boolean, previousTask: string|null})"
126790
+ ).action(async () => {
126732
126791
  await dispatchFromCli("mutate", "tasks", "stop", {}, { command: "stop" });
126733
126792
  });
126734
126793
  }
126735
126794
 
126736
126795
  // packages/cleo/src/cli/commands/sync.ts
126796
+ init_src();
126737
126797
  init_cli();
126738
126798
  function registerSyncCommand(program) {
126739
126799
  const sync = program.command("sync").description("External task synchronisation management");
126740
126800
  const links = sync.command("links").description("List external task links");
126741
126801
  links.command("list").description("List external task links (filter by provider or task)").option("--provider <providerId>", "Filter links by provider (e.g. linear, jira, github)").option("--task <taskId>", "Filter links by CLEO task ID").action(async (opts) => {
126802
+ const providerId = opts["provider"];
126803
+ const taskId = opts["task"];
126804
+ if (!providerId && !taskId) {
126805
+ console.error(
126806
+ "Error: at least one of --provider or --task is required for sync links list"
126807
+ );
126808
+ process.exit(2 /* INVALID_INPUT */);
126809
+ }
126742
126810
  await dispatchFromCli(
126743
126811
  "query",
126744
126812
  "tasks",
126745
126813
  "sync.links",
126746
- {
126747
- providerId: opts["provider"],
126748
- taskId: opts["task"]
126749
- },
126814
+ { providerId, taskId },
126750
126815
  { command: "sync", operation: "tasks.sync.links" }
126751
126816
  );
126752
126817
  });
@@ -126880,7 +126945,9 @@ function readPayload(opts, textKey, fileKey) {
126880
126945
  return text3;
126881
126946
  }
126882
126947
  function registerTokenCommand(program) {
126883
- const token = program.command("token").description("Provider-aware token telemetry and estimation");
126948
+ const token = program.command("token").description(
126949
+ "Provider-aware token telemetry from tasks.db (historical, per-operation tracking)"
126950
+ );
126884
126951
  token.command("summary").description("Summarize recorded token telemetry").option("--provider <provider>", "Filter by provider").option("--transport <transport>", "Filter by transport").option("--domain <domain>", "Filter by domain").option("--operation <name>", "Filter by operation name").option("--session <id>", "Filter by session ID").option("--task <id>", "Filter by task ID").action(async (opts) => {
126885
126952
  await dispatchFromCli(
126886
126953
  "query",
@@ -126976,7 +127043,7 @@ function registerTokenCommand(program) {
126976
127043
  // packages/cleo/src/cli/commands/update.ts
126977
127044
  init_cli();
126978
127045
  function registerUpdateCommand(program) {
126979
- program.command("update <taskId>").description("Update a task").option("--title <title>", "New title").option("-s, --status <status>", "New status").option("-p, --priority <priority>", "New priority").option("-t, --type <type>", "New type").option("--size <size>", "New size").option("-P, --phase <phase>", "New phase").option("-d, --description <desc>", "New description").option("-l, --labels <labels>", "Set labels (comma-separated)").option("--add-labels <labels>", "Add labels (comma-separated)").option("--remove-labels <labels>", "Remove labels (comma-separated)").option("-D, --depends <ids>", "Set dependencies (comma-separated)").option("--add-depends <ids>", "Add dependencies (comma-separated)").option("--remove-depends <ids>", "Remove dependencies (comma-separated)").option("--notes <note>", "Add a note").option(
127046
+ program.command("update <taskId>").description("Update a task").option("--title <title>", "New title").option("-s, --status <status>", "New status (pending|active|blocked|done|cancelled)").option("-p, --priority <priority>", "New priority (critical|high|medium|low)").option("-t, --type <type>", "New type (task|epic|subtask|bug)").option("--size <size>", "New size").option("-P, --phase <phase>", "New phase").option("-d, --description <desc>", "New description").option("-l, --labels <labels>", "Set labels (comma-separated)").option("--add-labels <labels>", "Add labels (comma-separated)").option("--remove-labels <labels>", "Remove labels (comma-separated)").option("-D, --depends <ids>", "Set dependencies (comma-separated)").option("--add-depends <ids>", "Add dependencies (comma-separated)").option("--remove-depends <ids>", "Remove dependencies (comma-separated)").option("--notes <note>", "Add a note").option(
126980
127047
  "--acceptance <criteria>",
126981
127048
  'Set acceptance criteria (pipe-separated, e.g. "AC1|AC2|AC3")'
126982
127049
  ).option("--files <files>", "Set files (comma-separated)").option("--blocked-by <reason>", "Set blocked-by reason").option("--parent <id>", "Set parent ID").option("--no-auto-complete", "Disable auto-complete for epic").option(
@@ -127096,23 +127163,6 @@ function registerUpgradeCommand(program) {
127096
127163
  });
127097
127164
  }
127098
127165
 
127099
- // packages/cleo/src/cli/commands/validate.ts
127100
- init_cli();
127101
- function registerValidateCommand(program) {
127102
- program.command("validate").description("Validate task data against schema and business rules").option("--strict", "Treat warnings as errors").action(async (opts) => {
127103
- await dispatchFromCli(
127104
- "query",
127105
- "check",
127106
- "schema",
127107
- {
127108
- type: "todo",
127109
- strict: opts["strict"]
127110
- },
127111
- { command: "validate", operation: "check.schema" }
127112
- );
127113
- });
127114
- }
127115
-
127116
127166
  // packages/cleo/src/cli/commands/verify.ts
127117
127167
  init_cli();
127118
127168
  function registerVerifyCommand(program) {
@@ -127141,15 +127191,15 @@ init_src2();
127141
127191
  init_renderers();
127142
127192
  import { execFileSync as execFileSync18, spawn as spawn2 } from "node:child_process";
127143
127193
  import { mkdir as mkdir19, readFile as readFile23, rm as rm3, stat as stat3, writeFile as writeFile14 } from "node:fs/promises";
127144
- import { join as join129 } from "node:path";
127194
+ import { join as join130 } from "node:path";
127145
127195
  var DEFAULT_PORT = 3456;
127146
127196
  var DEFAULT_HOST = "127.0.0.1";
127147
127197
  function getWebPaths() {
127148
127198
  const cleoHome = getCleoHome();
127149
127199
  return {
127150
- pidFile: join129(cleoHome, "web-server.pid"),
127151
- configFile: join129(cleoHome, "web-server.json"),
127152
- logFile: join129(cleoHome, "logs", "web-server.log")
127200
+ pidFile: join130(cleoHome, "web-server.pid"),
127201
+ configFile: join130(cleoHome, "web-server.json"),
127202
+ logFile: join130(cleoHome, "logs", "web-server.log")
127153
127203
  };
127154
127204
  }
127155
127205
  function isProcessRunning(pid) {
@@ -127196,8 +127246,8 @@ function registerWebCommand(program) {
127196
127246
  );
127197
127247
  }
127198
127248
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
127199
- const distServerDir = join129(projectRoot, "dist", "cli");
127200
- await mkdir19(join129(getCleoHome(), "logs"), { recursive: true });
127249
+ const distServerDir = join130(projectRoot, "dist", "cli");
127250
+ await mkdir19(join130(getCleoHome(), "logs"), { recursive: true });
127201
127251
  await writeFile14(
127202
127252
  configFile,
127203
127253
  JSON.stringify({
@@ -127206,7 +127256,7 @@ function registerWebCommand(program) {
127206
127256
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
127207
127257
  })
127208
127258
  );
127209
- const webIndexPath = join129(distServerDir, "index.js");
127259
+ const webIndexPath = join130(distServerDir, "index.js");
127210
127260
  try {
127211
127261
  await stat3(webIndexPath);
127212
127262
  } catch {
@@ -127372,9 +127422,9 @@ var codeCommand = defineCommand({
127372
127422
  async run({ args }) {
127373
127423
  await requireTreeSitter();
127374
127424
  const { smartOutline: smartOutline2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
127375
- const { join: join131 } = await import("node:path");
127425
+ const { join: join132 } = await import("node:path");
127376
127426
  const root = process.cwd();
127377
- const absPath = args.file.startsWith("/") ? args.file : join131(root, args.file);
127427
+ const absPath = args.file.startsWith("/") ? args.file : join132(root, args.file);
127378
127428
  const result = smartOutline2(absPath, root);
127379
127429
  if (result.errors.length > 0 && result.symbols.length === 0) {
127380
127430
  console.error(`Error: ${result.errors.join(", ")}`);
@@ -127440,9 +127490,9 @@ var codeCommand = defineCommand({
127440
127490
  async run({ args }) {
127441
127491
  await requireTreeSitter();
127442
127492
  const { smartUnfold: smartUnfold2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
127443
- const { join: join131 } = await import("node:path");
127493
+ const { join: join132 } = await import("node:path");
127444
127494
  const root = process.cwd();
127445
- const absPath = args.file.startsWith("/") ? args.file : join131(root, args.file);
127495
+ const absPath = args.file.startsWith("/") ? args.file : join132(root, args.file);
127446
127496
  const result = smartUnfold2(absPath, args.symbol, root);
127447
127497
  if (!result.found) {
127448
127498
  console.error(`Symbol "${args.symbol}" not found in ${args.file}`);
@@ -127461,14 +127511,13 @@ var codeCommand = defineCommand({
127461
127511
 
127462
127512
  // packages/cleo/src/cli/index.ts
127463
127513
  function getPackageVersion() {
127464
- const pkgPath = join130(dirname28(fileURLToPath5(import.meta.url)), "../../package.json");
127514
+ const pkgPath = join131(dirname29(fileURLToPath6(import.meta.url)), "../../package.json");
127465
127515
  const pkg = JSON.parse(readFileSync101(pkgPath, "utf-8"));
127466
127516
  return pkg.version;
127467
127517
  }
127468
127518
  var CLI_VERSION = getPackageVersion();
127469
127519
  var rootShim = new ShimCommand();
127470
127520
  registerAgentCommand(rootShim);
127471
- registerAgentsCommand(rootShim);
127472
127521
  registerAddCommand(rootShim);
127473
127522
  registerAddBatchCommand(rootShim);
127474
127523
  registerListCommand(rootShim);
@@ -127492,7 +127541,6 @@ registerChainCommand(rootShim);
127492
127541
  registerLifecycleCommand(rootShim);
127493
127542
  registerReleaseCommand(rootShim);
127494
127543
  registerCheckpointCommand(rootShim);
127495
- registerCommandsCommand(rootShim);
127496
127544
  registerDocsCommand(rootShim);
127497
127545
  registerExportTasksCommand(rootShim);
127498
127546
  registerImportTasksCommand(rootShim);
@@ -127520,15 +127568,11 @@ registerBlockersCommand(rootShim);
127520
127568
  registerCheckCommand(rootShim);
127521
127569
  registerComplianceCommand(rootShim);
127522
127570
  registerConfigCommand(rootShim);
127523
- registerConsensusCommand(rootShim);
127524
127571
  registerContextCommand(rootShim);
127525
- registerContributionCommand(rootShim);
127526
127572
  registerDashCommand(rootShim);
127527
- registerDecompositionCommand(rootShim);
127528
127573
  registerDoctorCommand(rootShim);
127529
127574
  registerExportCommand(rootShim);
127530
127575
  registerHistoryCommand(rootShim);
127531
- registerImplementationCommand(rootShim);
127532
127576
  registerImportCommand(rootShim);
127533
127577
  registerInitCommand(rootShim);
127534
127578
  registerInjectCommand(rootShim);
@@ -127538,7 +127582,6 @@ registerNextCommand(rootShim);
127538
127582
  registerPlanCommand(rootShim);
127539
127583
  registerOtelCommand(rootShim);
127540
127584
  registerTokenCommand(rootShim);
127541
- registerPhasesCommand(rootShim);
127542
127585
  registerPromoteCommand(rootShim);
127543
127586
  registerRelatesCommand(rootShim);
127544
127587
  registerReorderCommand(rootShim);
@@ -127547,10 +127590,8 @@ registerRestoreCommand(rootShim);
127547
127590
  registerRoadmapCommand(rootShim);
127548
127591
  registerSelfUpdateCommand(rootShim);
127549
127592
  registerSequenceCommand(rootShim);
127550
- registerSpecificationCommand(rootShim);
127551
127593
  registerStatsCommand(rootShim);
127552
127594
  registerUpgradeCommand(rootShim);
127553
- registerValidateCommand(rootShim);
127554
127595
  registerVerifyCommand(rootShim);
127555
127596
  registerDetectCommand(rootShim);
127556
127597
  registerDetectDriftCommand(rootShim);
@@ -127568,7 +127609,6 @@ registerMigrateClaudeMemCommand(rootShim);
127568
127609
  registerStickyCommand(rootShim);
127569
127610
  registerReasonCommand(rootShim);
127570
127611
  registerRefreshMemoryCommand(rootShim);
127571
- registerObserveCommand(rootShim);
127572
127612
  registerSchemaCommand(rootShim);
127573
127613
  function shimToCitty(shim) {
127574
127614
  const cittyArgs = {};