@cleocode/cleo 2026.3.60 → 2026.3.62

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/mcp/index.js CHANGED
@@ -11229,16 +11229,33 @@ function runMigrations(nativeDb, db) {
11229
11229
  );
11230
11230
  }
11231
11231
  }
11232
- let lastError;
11232
+ if (tableExists3(nativeDb, "__drizzle_migrations") && tableExists3(nativeDb, "tasks")) {
11233
+ const localMigrations = readMigrationFiles({ migrationsFolder });
11234
+ const localHashes = new Set(localMigrations.map((m) => m.hash));
11235
+ const dbEntries = nativeDb.prepare('SELECT hash FROM "__drizzle_migrations"').all();
11236
+ const hasOrphanedEntries = dbEntries.some((e) => !localHashes.has(e.hash));
11237
+ if (hasOrphanedEntries) {
11238
+ const log11 = getLogger("sqlite");
11239
+ log11.warn(
11240
+ { orphaned: dbEntries.filter((e) => !localHashes.has(e.hash)).length },
11241
+ "Detected stale migration journal entries from a previous CLEO version. Reconciling."
11242
+ );
11243
+ nativeDb.exec('DELETE FROM "__drizzle_migrations"');
11244
+ for (const m of localMigrations) {
11245
+ nativeDb.exec(
11246
+ `INSERT INTO "__drizzle_migrations" ("hash", "created_at") VALUES ('${m.hash}', ${m.folderMillis})`
11247
+ );
11248
+ }
11249
+ }
11250
+ }
11233
11251
  for (let attempt = 1; attempt <= MAX_MIGRATION_RETRIES; attempt++) {
11234
11252
  try {
11235
11253
  migrate(db, { migrationsFolder });
11236
- return;
11254
+ break;
11237
11255
  } catch (err) {
11238
11256
  if (!isSqliteBusy(err) || attempt === MAX_MIGRATION_RETRIES) {
11239
11257
  throw err;
11240
11258
  }
11241
- lastError = err;
11242
11259
  const delay = Math.min(
11243
11260
  MIGRATION_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1) * (1 + Math.random() * 0.5),
11244
11261
  MIGRATION_RETRY_MAX_DELAY_MS
@@ -11246,7 +11263,19 @@ function runMigrations(nativeDb, db) {
11246
11263
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, Math.round(delay));
11247
11264
  }
11248
11265
  }
11249
- throw lastError;
11266
+ ensureRequiredColumns(nativeDb);
11267
+ }
11268
+ function ensureRequiredColumns(nativeDb) {
11269
+ if (!tableExists3(nativeDb, "tasks")) return;
11270
+ const columns = nativeDb.prepare("PRAGMA table_info(tasks)").all();
11271
+ const existingCols = new Set(columns.map((c) => c.name));
11272
+ for (const req of REQUIRED_TASK_COLUMNS) {
11273
+ if (!existingCols.has(req.name)) {
11274
+ const log11 = getLogger("sqlite");
11275
+ log11.warn({ column: req.name }, `Adding missing column tasks.${req.name} via ALTER TABLE`);
11276
+ nativeDb.exec(`ALTER TABLE tasks ADD COLUMN ${req.name} ${req.ddl}`);
11277
+ }
11278
+ }
11250
11279
  }
11251
11280
  function closeDb() {
11252
11281
  if (_nativeDb2) {
@@ -11303,7 +11332,7 @@ async function closeAllDatabases() {
11303
11332
  } catch {
11304
11333
  }
11305
11334
  }
11306
- var _require2, DatabaseSync2, DB_FILENAME3, SQLITE_SCHEMA_VERSION, SCHEMA_VERSION, _db2, _nativeDb2, _dbPath2, _initPromise2, _gitTrackingChecked, MIN_BACKUP_TASK_COUNT, MAX_MIGRATION_RETRIES, MIGRATION_RETRY_BASE_DELAY_MS, MIGRATION_RETRY_MAX_DELAY_MS;
11335
+ var _require2, DatabaseSync2, DB_FILENAME3, SQLITE_SCHEMA_VERSION, SCHEMA_VERSION, _db2, _nativeDb2, _dbPath2, _initPromise2, _gitTrackingChecked, MIN_BACKUP_TASK_COUNT, MAX_MIGRATION_RETRIES, MIGRATION_RETRY_BASE_DELAY_MS, MIGRATION_RETRY_MAX_DELAY_MS, REQUIRED_TASK_COLUMNS;
11307
11336
  var init_sqlite2 = __esm({
11308
11337
  "packages/core/src/store/sqlite.ts"() {
11309
11338
  "use strict";
@@ -11328,6 +11357,9 @@ var init_sqlite2 = __esm({
11328
11357
  MAX_MIGRATION_RETRIES = 5;
11329
11358
  MIGRATION_RETRY_BASE_DELAY_MS = 100;
11330
11359
  MIGRATION_RETRY_MAX_DELAY_MS = 2e3;
11360
+ REQUIRED_TASK_COLUMNS = [
11361
+ { name: "pipeline_stage", ddl: "text" }
11362
+ ];
11331
11363
  }
11332
11364
  });
11333
11365
 
@@ -13227,7 +13259,7 @@ async function showSequence(cwd) {
13227
13259
  counter: seq.counter,
13228
13260
  lastId: seq.lastId,
13229
13261
  checksum: seq.checksum,
13230
- nextId: `T${seq.counter + 1}`
13262
+ nextId: `T${String(seq.counter + 1).padStart(3, "0")}`
13231
13263
  };
13232
13264
  }
13233
13265
  async function loadAllTasks(cwd, accessor) {
@@ -41780,6 +41812,58 @@ async function addTask(options, cwd, accessor) {
41780
41812
  if (duplicate) {
41781
41813
  return { task: duplicate, duplicate: true };
41782
41814
  }
41815
+ if (options.dryRun) {
41816
+ const previewNow = (/* @__PURE__ */ new Date()).toISOString();
41817
+ let previewParentForStage = null;
41818
+ if (parentId) {
41819
+ const previewParentTask = await dataAccessor.loadSingleTask(parentId);
41820
+ previewParentForStage = previewParentTask ? { pipelineStage: previewParentTask.pipelineStage, type: previewParentTask.type } : null;
41821
+ }
41822
+ const previewPipelineStage = resolveDefaultPipelineStage({
41823
+ explicitStage: options.pipelineStage,
41824
+ taskType: taskType ?? null,
41825
+ parentTask: previewParentForStage
41826
+ });
41827
+ const previewPosition = options.position !== void 0 ? options.position : await dataAccessor.getNextPosition(parentId);
41828
+ const previewTask = {
41829
+ id: "T???",
41830
+ title: options.title,
41831
+ description: options.description,
41832
+ status,
41833
+ priority,
41834
+ type: taskType,
41835
+ parentId: parentId || null,
41836
+ position: previewPosition,
41837
+ positionVersion: 0,
41838
+ size,
41839
+ pipelineStage: previewPipelineStage,
41840
+ createdAt: previewNow,
41841
+ updatedAt: previewNow
41842
+ };
41843
+ if (phase) previewTask.phase = phase;
41844
+ if (options.labels?.length) previewTask.labels = options.labels.map((l) => l.trim());
41845
+ if (options.files?.length) previewTask.files = options.files.map((f) => f.trim());
41846
+ if (options.acceptance?.length)
41847
+ previewTask.acceptance = options.acceptance.map((a) => a.trim());
41848
+ if (options.depends?.length) previewTask.depends = options.depends.map((d) => d.trim());
41849
+ if (options.notes) {
41850
+ const previewNote = `${(/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}: ${options.notes}`;
41851
+ previewTask.notes = [previewNote];
41852
+ }
41853
+ if (status === "blocked" && options.description) {
41854
+ previewTask.blockedBy = options.description;
41855
+ }
41856
+ if (status === "done") {
41857
+ previewTask.completedAt = previewNow;
41858
+ }
41859
+ if (taskType !== "epic") {
41860
+ const verificationEnabledRaw = await getRawConfigValue("verification.enabled", cwd);
41861
+ if (verificationEnabledRaw === true) {
41862
+ previewTask.verification = buildDefaultVerification(previewNow);
41863
+ }
41864
+ }
41865
+ return { task: previewTask, dryRun: true };
41866
+ }
41783
41867
  const taskId = await allocateNextTaskId(cwd);
41784
41868
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
41785
41869
  let resolvedParentForStage = null;
@@ -41849,9 +41933,6 @@ async function addTask(options, cwd, accessor) {
41849
41933
  task.verification = buildDefaultVerification(now2);
41850
41934
  }
41851
41935
  }
41852
- if (options.dryRun) {
41853
- return { task, dryRun: true };
41854
- }
41855
41936
  await dataAccessor.transaction(async (tx) => {
41856
41937
  if (options.position !== void 0) {
41857
41938
  await dataAccessor.shiftPositions(parentId, options.position, 1);
@@ -47763,8 +47844,9 @@ var init_observability = __esm({
47763
47844
  });
47764
47845
 
47765
47846
  // packages/core/src/phases/deps.ts
47766
- async function loadAllTasks3(_cwd, accessor) {
47767
- const { tasks: tasks2 } = await accessor.queryTasks({});
47847
+ async function loadAllTasks3(cwd, accessor) {
47848
+ const acc = accessor ?? await getAccessor(cwd);
47849
+ const { tasks: tasks2 } = await acc.queryTasks({});
47768
47850
  return tasks2;
47769
47851
  }
47770
47852
  function buildGraph(tasks2) {
@@ -47840,11 +47922,45 @@ async function getExecutionWaves(epicId, cwd, accessor) {
47840
47922
  }
47841
47923
  return waves;
47842
47924
  }
47925
+ async function getCriticalPath2(taskId, cwd, accessor) {
47926
+ const allTasks = await loadAllTasks3(cwd, accessor);
47927
+ const task = allTasks.find((t) => t.id === taskId);
47928
+ if (!task) {
47929
+ throw new CleoError(4 /* NOT_FOUND */, `Task not found: ${taskId}`);
47930
+ }
47931
+ const graph = buildGraph(allTasks);
47932
+ const taskMap = new Map(allTasks.map((t) => [t.id, t]));
47933
+ function findLongestPath(id, visited) {
47934
+ if (visited.has(id)) return [];
47935
+ visited.add(id);
47936
+ const node = graph.get(id);
47937
+ if (!node || node.dependents.length === 0) {
47938
+ return [id];
47939
+ }
47940
+ let longest = [];
47941
+ for (const depId of node.dependents) {
47942
+ const path3 = findLongestPath(depId, new Set(visited));
47943
+ if (path3.length > longest.length) {
47944
+ longest = path3;
47945
+ }
47946
+ }
47947
+ return [id, ...longest];
47948
+ }
47949
+ const path2 = findLongestPath(taskId, /* @__PURE__ */ new Set());
47950
+ return {
47951
+ path: path2.map((id) => {
47952
+ const t = taskMap.get(id);
47953
+ return t ? { id: t.id, title: t.title, status: t.status } : { id, title: "Unknown", status: "unknown" };
47954
+ }),
47955
+ length: path2.length
47956
+ };
47957
+ }
47843
47958
  var init_deps2 = __esm({
47844
47959
  "packages/core/src/phases/deps.ts"() {
47845
47960
  "use strict";
47846
47961
  init_src();
47847
47962
  init_errors3();
47963
+ init_data_accessor();
47848
47964
  }
47849
47965
  });
47850
47966
 
@@ -52646,6 +52762,13 @@ var init_capability_matrix = __esm({
52646
52762
  mode: "native",
52647
52763
  preferredChannel: "either"
52648
52764
  },
52765
+ {
52766
+ domain: "admin",
52767
+ operation: "backup",
52768
+ gateway: "query",
52769
+ mode: "native",
52770
+ preferredChannel: "either"
52771
+ },
52649
52772
  {
52650
52773
  domain: "admin",
52651
52774
  operation: "backup",
@@ -57895,7 +58018,7 @@ async function getProjectStats(opts, accessor) {
57895
58018
  dbAnd(dbEq(tasksTable.status, "archived"), dbEq(tasksTable.archiveReason, "completed"))
57896
58019
  ).get();
57897
58020
  archivedCompleted = archivedDoneRow?.c ?? 0;
57898
- totalCompleted = (statusMap["done"] ?? 0) + archivedCompleted;
58021
+ totalCompleted = entries.filter(isComplete).length;
57899
58022
  } catch {
57900
58023
  totalCreated = entries.filter(isCreate).length;
57901
58024
  totalCompleted = entries.filter(isComplete).length;
@@ -58901,7 +59024,7 @@ var init_audit2 = __esm({
58901
59024
  });
58902
59025
 
58903
59026
  // packages/core/src/system/backup.ts
58904
- import { existsSync as existsSync82, mkdirSync as mkdirSync18, readFileSync as readFileSync59, writeFileSync as writeFileSync11 } from "node:fs";
59027
+ import { existsSync as existsSync82, mkdirSync as mkdirSync18, readdirSync as readdirSync27, readFileSync as readFileSync59, writeFileSync as writeFileSync11 } from "node:fs";
58905
59028
  import { join as join84 } from "node:path";
58906
59029
  function createBackup2(projectRoot, opts) {
58907
59030
  const cleoDir = join84(projectRoot, ".cleo");
@@ -58947,6 +59070,36 @@ function createBackup2(projectRoot, opts) {
58947
59070
  }
58948
59071
  return { backupId, path: backupDir, timestamp: timestamp2, type: btype, files: backedUp };
58949
59072
  }
59073
+ function listSystemBackups(projectRoot) {
59074
+ const cleoDir = join84(projectRoot, ".cleo");
59075
+ const backupTypes = ["snapshot", "safety", "migration"];
59076
+ const entries = [];
59077
+ for (const btype of backupTypes) {
59078
+ const backupDir = join84(cleoDir, "backups", btype);
59079
+ if (!existsSync82(backupDir)) continue;
59080
+ try {
59081
+ const files = readdirSync27(backupDir).filter((f) => f.endsWith(".meta.json"));
59082
+ for (const metaFile of files) {
59083
+ try {
59084
+ const raw = readFileSync59(join84(backupDir, metaFile), "utf-8");
59085
+ const meta = JSON.parse(raw);
59086
+ if (meta.backupId && meta.timestamp) {
59087
+ entries.push({
59088
+ backupId: meta.backupId,
59089
+ type: meta.type ?? btype,
59090
+ timestamp: meta.timestamp,
59091
+ note: meta.note,
59092
+ files: meta.files ?? []
59093
+ });
59094
+ }
59095
+ } catch {
59096
+ }
59097
+ }
59098
+ } catch {
59099
+ }
59100
+ }
59101
+ return entries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
59102
+ }
58950
59103
  function restoreBackup(projectRoot, params) {
58951
59104
  if (!params.backupId) {
58952
59105
  throw new CleoError(2 /* INVALID_INPUT */, "backupId is required");
@@ -59071,7 +59224,7 @@ var init_audit_prune = __esm({
59071
59224
  });
59072
59225
 
59073
59226
  // packages/core/src/system/cleanup.ts
59074
- import { existsSync as existsSync83, readdirSync as readdirSync27, readFileSync as readFileSync60, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
59227
+ import { existsSync as existsSync83, readdirSync as readdirSync28, readFileSync as readFileSync60, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
59075
59228
  import { join as join86 } from "node:path";
59076
59229
  async function cleanupSystem(projectRoot, params) {
59077
59230
  if (!params.target) {
@@ -59119,10 +59272,10 @@ async function cleanupSystem(projectRoot, params) {
59119
59272
  case "backups": {
59120
59273
  const backupBaseDir = join86(cleoDir, "backups");
59121
59274
  if (existsSync83(backupBaseDir)) {
59122
- for (const typeDir of readdirSync27(backupBaseDir)) {
59275
+ for (const typeDir of readdirSync28(backupBaseDir)) {
59123
59276
  const fullDir = join86(backupBaseDir, typeDir);
59124
59277
  try {
59125
- for (const file2 of readdirSync27(fullDir)) {
59278
+ for (const file2 of readdirSync28(fullDir)) {
59126
59279
  if (file2.endsWith(".meta.json")) {
59127
59280
  const metaFilePath = join86(fullDir, file2);
59128
59281
  try {
@@ -59131,7 +59284,7 @@ async function cleanupSystem(projectRoot, params) {
59131
59284
  items.push(file2.replace(".meta.json", ""));
59132
59285
  if (!dryRun) {
59133
59286
  unlinkSync5(metaFilePath);
59134
- for (const bf of readdirSync27(fullDir)) {
59287
+ for (const bf of readdirSync28(fullDir)) {
59135
59288
  if (bf.includes(meta.backupId)) {
59136
59289
  try {
59137
59290
  unlinkSync5(join86(fullDir, bf));
@@ -59161,7 +59314,7 @@ async function cleanupSystem(projectRoot, params) {
59161
59314
  }
59162
59315
  const auditPattern = /^audit-log-.*\.json$/;
59163
59316
  if (existsSync83(cleoDir)) {
59164
- for (const file2 of readdirSync27(cleoDir)) {
59317
+ for (const file2 of readdirSync28(cleoDir)) {
59165
59318
  if (auditPattern.test(file2)) {
59166
59319
  items.push(file2);
59167
59320
  if (!dryRun) {
@@ -59321,7 +59474,7 @@ import { randomBytes as randomBytes12 } from "node:crypto";
59321
59474
  import {
59322
59475
  existsSync as existsSync85,
59323
59476
  mkdirSync as mkdirSync20,
59324
- readdirSync as readdirSync28,
59477
+ readdirSync as readdirSync29,
59325
59478
  readFileSync as readFileSync61,
59326
59479
  renameSync as renameSync6,
59327
59480
  unlinkSync as unlinkSync6,
@@ -62360,7 +62513,7 @@ var init_tasks2 = __esm({
62360
62513
  });
62361
62514
 
62362
62515
  // packages/core/src/templates/parser.ts
62363
- import { existsSync as existsSync93, readdirSync as readdirSync29, readFileSync as readFileSync67 } from "fs";
62516
+ import { existsSync as existsSync93, readdirSync as readdirSync30, readFileSync as readFileSync67 } from "fs";
62364
62517
  import { join as join96 } from "path";
62365
62518
  import { parse as parseYaml } from "yaml";
62366
62519
  function deriveSubcommand(filename) {
@@ -62434,7 +62587,7 @@ function parseIssueTemplates2(projectRoot) {
62434
62587
  }
62435
62588
  let files;
62436
62589
  try {
62437
- files = readdirSync29(templateDir).filter((f) => /\.ya?ml$/i.test(f) && f !== "config.yml");
62590
+ files = readdirSync30(templateDir).filter((f) => /\.ya?ml$/i.test(f) && f !== "config.yml");
62438
62591
  } catch (error40) {
62439
62592
  return {
62440
62593
  success: false,
@@ -62847,7 +63000,7 @@ var init_changelog = __esm({
62847
63000
  });
62848
63001
 
62849
63002
  // packages/core/src/ui/command-registry.ts
62850
- import { existsSync as existsSync96, readdirSync as readdirSync30, readFileSync as readFileSync70 } from "node:fs";
63003
+ import { existsSync as existsSync96, readdirSync as readdirSync31, readFileSync as readFileSync70 } from "node:fs";
62851
63004
  import { basename as basename16, join as join98 } from "node:path";
62852
63005
  function parseCommandHeader(scriptPath) {
62853
63006
  if (!existsSync96(scriptPath)) return null;
@@ -62930,7 +63083,7 @@ function parseCommandHeader(scriptPath) {
62930
63083
  function scanAllCommands(scriptsDir) {
62931
63084
  const registry2 = /* @__PURE__ */ new Map();
62932
63085
  if (!existsSync96(scriptsDir)) return registry2;
62933
- for (const file2 of readdirSync30(scriptsDir)) {
63086
+ for (const file2 of readdirSync31(scriptsDir)) {
62934
63087
  if (!file2.endsWith(".sh") && !file2.endsWith(".ts")) continue;
62935
63088
  const meta = parseCommandHeader(join98(scriptsDir, file2));
62936
63089
  if (meta) {
@@ -63858,12 +64011,12 @@ var init_compliance2 = __esm({
63858
64011
  });
63859
64012
 
63860
64013
  // packages/core/src/validation/docs-sync.ts
63861
- import { existsSync as existsSync97, readdirSync as readdirSync31, readFileSync as readFileSync71 } from "node:fs";
64014
+ import { existsSync as existsSync97, readdirSync as readdirSync32, readFileSync as readFileSync71 } from "node:fs";
63862
64015
  import { join as join99 } from "node:path";
63863
64016
  function getScriptCommands(scriptsDir) {
63864
64017
  if (!existsSync97(scriptsDir)) return [];
63865
64018
  try {
63866
- return readdirSync31(scriptsDir).filter((f) => f.endsWith(".sh")).map((f) => f.replace(/\.sh$/, "")).sort();
64019
+ return readdirSync32(scriptsDir).filter((f) => f.endsWith(".sh")).map((f) => f.replace(/\.sh$/, "")).sort();
63867
64020
  } catch {
63868
64021
  return [];
63869
64022
  }
@@ -65285,12 +65438,12 @@ var init_manifest = __esm({
65285
65438
  });
65286
65439
 
65287
65440
  // packages/core/src/validation/protocol-common.ts
65288
- import { existsSync as existsSync100, readdirSync as readdirSync32, readFileSync as readFileSync73 } from "node:fs";
65441
+ import { existsSync as existsSync100, readdirSync as readdirSync33, readFileSync as readFileSync73 } from "node:fs";
65289
65442
  function checkOutputFileExists(taskId, expectedDir, pattern) {
65290
65443
  if (!existsSync100(expectedDir)) return false;
65291
65444
  const filePattern = pattern ?? `${taskId}`;
65292
65445
  try {
65293
- const files = readdirSync32(expectedDir);
65446
+ const files = readdirSync33(expectedDir);
65294
65447
  return files.some((f) => f.includes(filePattern) && f.endsWith(".md"));
65295
65448
  } catch {
65296
65449
  return false;
@@ -66269,7 +66422,7 @@ __export(init_exports, {
66269
66422
  isAutoInitEnabled: () => isAutoInitEnabled,
66270
66423
  updateDocs: () => updateDocs
66271
66424
  });
66272
- import { existsSync as existsSync101, readdirSync as readdirSync33, readFileSync as readFileSync74 } from "node:fs";
66425
+ import { existsSync as existsSync101, readdirSync as readdirSync34, readFileSync as readFileSync74 } from "node:fs";
66273
66426
  import { copyFile as copyFile3, lstat, mkdir as mkdir16, readFile as readFile17, symlink, unlink as unlink4, writeFile as writeFile11 } from "node:fs/promises";
66274
66427
  import { platform as platform4 } from "node:os";
66275
66428
  import { basename as basename17, dirname as dirname19, join as join101 } from "node:path";
@@ -66319,7 +66472,7 @@ async function initAgentDefinition(created, warnings) {
66319
66472
  } catch (_err) {
66320
66473
  try {
66321
66474
  await mkdir16(globalAgentsDir, { recursive: true });
66322
- const files = readdirSync33(agentSourceDir);
66475
+ const files = readdirSync34(agentSourceDir);
66323
66476
  for (const file2 of files) {
66324
66477
  await copyFile3(join101(agentSourceDir, file2), join101(globalAgentsDir, file2));
66325
66478
  }
@@ -66468,7 +66621,7 @@ async function installGitHubTemplates(projectRoot, created, skipped) {
66468
66621
  await mkdir16(issueTemplateDir, { recursive: true });
66469
66622
  const issueSrcDir = join101(templateSrcDir, "ISSUE_TEMPLATE");
66470
66623
  if (existsSync101(issueSrcDir)) {
66471
- const issueFiles = readdirSync33(issueSrcDir);
66624
+ const issueFiles = readdirSync34(issueSrcDir);
66472
66625
  for (const file2 of issueFiles) {
66473
66626
  const dest = join101(issueTemplateDir, file2);
66474
66627
  if (existsSync101(dest)) {
@@ -71274,7 +71427,7 @@ var init_model_provider_registry = __esm({
71274
71427
 
71275
71428
  // packages/core/src/metrics/token-service.ts
71276
71429
  import { createHash as createHash13, randomUUID as randomUUID8 } from "node:crypto";
71277
- import { existsSync as existsSync107, readdirSync as readdirSync34, readFileSync as readFileSync79 } from "node:fs";
71430
+ import { existsSync as existsSync107, readdirSync as readdirSync35, readFileSync as readFileSync79 } from "node:fs";
71278
71431
  import { join as join106 } from "node:path";
71279
71432
  function normalizeProvider(provider, model, runtimeProvider) {
71280
71433
  const value = (provider ?? "").trim().toLowerCase();
@@ -71359,7 +71512,7 @@ function getOtelDir2() {
71359
71512
  function readOtelJsonl(dir) {
71360
71513
  if (!existsSync107(dir)) return [];
71361
71514
  const entries = [];
71362
- for (const file2 of readdirSync34(dir)) {
71515
+ for (const file2 of readdirSync35(dir)) {
71363
71516
  if (!file2.endsWith(".json") && !file2.endsWith(".jsonl")) continue;
71364
71517
  const filePath = join106(dir, file2);
71365
71518
  const raw = readFileSync79(filePath, "utf-8").trim();
@@ -71751,7 +71904,7 @@ var init_parallel = __esm({
71751
71904
  });
71752
71905
 
71753
71906
  // packages/core/src/orchestration/skill-ops.ts
71754
- import { existsSync as existsSync108, readdirSync as readdirSync35, readFileSync as readFileSync80 } from "node:fs";
71907
+ import { existsSync as existsSync108, readdirSync as readdirSync36, readFileSync as readFileSync80 } from "node:fs";
71755
71908
  import { join as join107 } from "node:path";
71756
71909
  import { getCanonicalSkillsDir as getCanonicalSkillsDir3 } from "@cleocode/caamp";
71757
71910
  function getSkillContent(skillName, projectRoot) {
@@ -71776,7 +71929,7 @@ function getSkillContent(skillName, projectRoot) {
71776
71929
  let references = [];
71777
71930
  if (existsSync108(refsDir)) {
71778
71931
  try {
71779
- references = readdirSync35(refsDir).filter((f) => f.endsWith(".md") || f.endsWith(".txt")).map((f) => ({
71932
+ references = readdirSync36(refsDir).filter((f) => f.endsWith(".md") || f.endsWith(".txt")).map((f) => ({
71780
71933
  name: f,
71781
71934
  path: join107(skillDir, "references", f)
71782
71935
  }));
@@ -74377,6 +74530,7 @@ var init_migration_sqlite = __esm({
74377
74530
  // packages/core/src/repair.ts
74378
74531
  var repair_exports = {};
74379
74532
  __export(repair_exports, {
74533
+ repairMissingColumns: () => repairMissingColumns,
74380
74534
  repairMissingCompletedAt: () => repairMissingCompletedAt,
74381
74535
  repairMissingSizes: () => repairMissingSizes,
74382
74536
  runAllRepairs: () => runAllRepairs
@@ -74440,12 +74594,43 @@ async function repairMissingCompletedAt(cwd, dryRun) {
74440
74594
  details: `Set completedAt for ${affected.length} done/cancelled task(s)`
74441
74595
  };
74442
74596
  }
74597
+ async function repairMissingColumns(cwd, dryRun) {
74598
+ const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
74599
+ const db = await getDb4(cwd);
74600
+ const { sql: sql12 } = await import("drizzle-orm");
74601
+ const columns = db.all(sql12`PRAGMA table_info(tasks)`);
74602
+ const existingCols = new Set(columns.map((c) => c.name));
74603
+ const missingCols = ["pipeline_stage"].filter((c) => !existingCols.has(c));
74604
+ if (missingCols.length === 0) {
74605
+ return {
74606
+ action: "fix_missing_columns",
74607
+ status: "skipped",
74608
+ details: "All required columns present on tasks table"
74609
+ };
74610
+ }
74611
+ if (dryRun) {
74612
+ return {
74613
+ action: "fix_missing_columns",
74614
+ status: "preview",
74615
+ details: `Would add missing column(s): ${missingCols.join(", ")}`
74616
+ };
74617
+ }
74618
+ for (const col of missingCols) {
74619
+ db.run(sql12.raw(`ALTER TABLE tasks ADD COLUMN ${col} text`));
74620
+ }
74621
+ return {
74622
+ action: "fix_missing_columns",
74623
+ status: "applied",
74624
+ details: `Added missing column(s): ${missingCols.join(", ")}`
74625
+ };
74626
+ }
74443
74627
  async function runAllRepairs(cwd, dryRun) {
74444
- const [sizes, completedAt] = await Promise.all([
74628
+ const [sizes, completedAt, columns] = await Promise.all([
74445
74629
  repairMissingSizes(cwd, dryRun),
74446
- repairMissingCompletedAt(cwd, dryRun)
74630
+ repairMissingCompletedAt(cwd, dryRun),
74631
+ repairMissingColumns(cwd, dryRun)
74447
74632
  ]);
74448
- return [sizes, completedAt];
74633
+ return [sizes, completedAt, columns];
74449
74634
  }
74450
74635
  var init_repair = __esm({
74451
74636
  "packages/core/src/repair.ts"() {
@@ -74458,7 +74643,7 @@ import {
74458
74643
  copyFileSync as copyFileSync7,
74459
74644
  existsSync as existsSync111,
74460
74645
  mkdirSync as mkdirSync23,
74461
- readdirSync as readdirSync36,
74646
+ readdirSync as readdirSync37,
74462
74647
  readFileSync as readFileSync83,
74463
74648
  writeFileSync as writeFileSync20
74464
74649
  } from "node:fs";
@@ -74671,7 +74856,7 @@ async function runUpgrade(options = {}) {
74671
74856
  const dbPath2 = join109(cleoDir2, "tasks.db");
74672
74857
  const safetyDir = join109(cleoDir2, "backups", "safety");
74673
74858
  if (existsSync111(safetyDir)) {
74674
- const backups = readdirSync36(safetyDir).filter((f) => f.startsWith("tasks.db.pre-migration.")).sort().reverse();
74859
+ const backups = readdirSync37(safetyDir).filter((f) => f.startsWith("tasks.db.pre-migration.")).sort().reverse();
74675
74860
  if (backups.length > 0 && !existsSync111(dbPath2)) {
74676
74861
  copyFileSync7(join109(safetyDir, backups[0]), dbPath2);
74677
74862
  }
@@ -77598,7 +77783,7 @@ var init_bootstrap2 = __esm({
77598
77783
  });
77599
77784
 
77600
77785
  // packages/core/src/orchestration/critical-path.ts
77601
- async function getCriticalPath2(cwd, accessor) {
77786
+ async function getCriticalPath3(cwd, accessor) {
77602
77787
  const acc = accessor ?? await getAccessor(cwd);
77603
77788
  const { tasks: tasks2 } = await acc.queryTasks({});
77604
77789
  if (tasks2.length === 0) {
@@ -78061,6 +78246,7 @@ __export(internal_exports, {
78061
78246
  WorkflowGateTracker: () => WorkflowGateTracker,
78062
78247
  adapters: () => adapters_exports,
78063
78248
  addChain: () => addChain,
78249
+ addIssue: () => addIssue,
78064
78250
  addRemote: () => addRemote,
78065
78251
  addSticky: () => addSticky,
78066
78252
  addTask: () => addTask,
@@ -78218,6 +78404,7 @@ __export(internal_exports, {
78218
78404
  deletePhase: () => deletePhase,
78219
78405
  deleteTask: () => deleteTask,
78220
78406
  deleteTokenUsage: () => deleteTokenUsage,
78407
+ depsCriticalPath: () => getCriticalPath2,
78221
78408
  deregisterAgent: () => deregisterAgent,
78222
78409
  describeChannel: () => describeChannel,
78223
78410
  detectCrashedAgents: () => detectCrashedAgents,
@@ -78359,6 +78546,7 @@ __export(internal_exports, {
78359
78546
  getSystemInfo: () => getSystemInfo2,
78360
78547
  getSystemMetrics: () => getSystemMetrics,
78361
78548
  getSystemMigrationStatus: () => getMigrationStatus2,
78549
+ getTask: () => getTask,
78362
78550
  getTaskHistory: () => getTaskHistory,
78363
78551
  getTaskPath: () => getTaskPath,
78364
78552
  getTemplateForSubcommand: () => getTemplateForSubcommand2,
@@ -78434,6 +78622,7 @@ __export(internal_exports, {
78434
78622
  listSessions: () => listSessions,
78435
78623
  listStickies: () => listStickies,
78436
78624
  listStrictnessPresets: () => listStrictnessPresets,
78625
+ listSystemBackups: () => listSystemBackups,
78437
78626
  listTasks: () => listTasks,
78438
78627
  listTesseraTemplates: () => listTesseraTemplates,
78439
78628
  listTokenUsage: () => listTokenUsage,
@@ -78494,7 +78683,7 @@ __export(internal_exports, {
78494
78683
  ops: () => operations_exports,
78495
78684
  orchestration: () => orchestration_exports,
78496
78685
  orchestrationAnalyzeDependencies: () => analyzeDependencies,
78497
- orchestrationGetCriticalPath: () => getCriticalPath2,
78686
+ orchestrationGetCriticalPath: () => getCriticalPath3,
78498
78687
  orchestrationGetNextTask: () => getNextTask,
78499
78688
  orchestrationGetReadyTasks: () => getReadyTasks2,
78500
78689
  orphanDetection: () => orphanDetection,
@@ -78701,6 +78890,7 @@ var init_internal = __esm({
78701
78890
  init_impact();
78702
78891
  init_patterns2();
78703
78892
  init_prediction();
78893
+ init_create();
78704
78894
  init_diagnostics();
78705
78895
  init_retry2();
78706
78896
  init_chain_store();
@@ -78727,6 +78917,7 @@ var init_internal = __esm({
78727
78917
  init_waves();
78728
78918
  init_otel();
78729
78919
  init_paths();
78920
+ init_deps2();
78730
78921
  init_phases();
78731
78922
  init_pipeline2();
78732
78923
  init_platform();
@@ -84449,6 +84640,16 @@ var OPERATIONS = [
84449
84640
  }
84450
84641
  ]
84451
84642
  },
84643
+ {
84644
+ gateway: "query",
84645
+ domain: "admin",
84646
+ operation: "backup",
84647
+ description: "admin.backup (query) \u2014 list available backups (read-only)",
84648
+ tier: 1,
84649
+ idempotent: true,
84650
+ sessionRequired: false,
84651
+ requiredParams: []
84652
+ },
84452
84653
  {
84453
84654
  gateway: "mutate",
84454
84655
  domain: "admin",
@@ -86502,7 +86703,7 @@ async function orchestrateCriticalPath(projectRoot) {
86502
86703
  try {
86503
86704
  const root = projectRoot || resolveProjectRoot();
86504
86705
  const accessor = await getAccessor(root);
86505
- const result = await getCriticalPath2(root, accessor);
86706
+ const result = await getCriticalPath3(root, accessor);
86506
86707
  return { success: true, data: result };
86507
86708
  } catch (err) {
86508
86709
  return engineError("E_GENERAL", err.message);
@@ -87258,7 +87459,7 @@ async function releaseShip(params, projectRoot) {
87258
87459
  // packages/cleo/src/dispatch/engines/system-engine.ts
87259
87460
  init_internal();
87260
87461
  init_error();
87261
- import { existsSync as existsSync119, readdirSync as readdirSync37, readFileSync as readFileSync93 } from "node:fs";
87462
+ import { existsSync as existsSync119, readdirSync as readdirSync38, readFileSync as readFileSync93 } from "node:fs";
87262
87463
  import { basename as basename18, join as join112 } from "node:path";
87263
87464
  var HELP_TOPICS = {
87264
87465
  session: {
@@ -87565,7 +87766,7 @@ function systemContext(projectRoot, params) {
87565
87766
  const sessions2 = [];
87566
87767
  const statesDir = join112(cleoDir, "context-states");
87567
87768
  if (existsSync119(statesDir)) {
87568
- for (const file2 of readdirSync37(statesDir)) {
87769
+ for (const file2 of readdirSync38(statesDir)) {
87569
87770
  if (file2.startsWith("context-state-") && file2.endsWith(".json")) {
87570
87771
  try {
87571
87772
  const state = JSON.parse(readFileSync93(join112(statesDir, file2), "utf-8"));
@@ -87702,6 +87903,14 @@ function systemBackup(projectRoot, params) {
87702
87903
  return engineError("E_GENERAL", err.message);
87703
87904
  }
87704
87905
  }
87906
+ function systemListBackups(projectRoot) {
87907
+ try {
87908
+ const result = listSystemBackups(projectRoot);
87909
+ return { success: true, data: result };
87910
+ } catch (err) {
87911
+ return engineError("E_GENERAL", err.message);
87912
+ }
87913
+ }
87705
87914
  function systemRestore(projectRoot, params) {
87706
87915
  try {
87707
87916
  const result = restoreBackup(projectRoot, params);
@@ -89268,6 +89477,16 @@ var AdminHandler = class {
89268
89477
  data: result
89269
89478
  };
89270
89479
  }
89480
+ case "backup": {
89481
+ const result = systemListBackups(projectRoot);
89482
+ return wrapResult(
89483
+ { success: true, data: { backups: result, count: result.length } },
89484
+ "query",
89485
+ "admin",
89486
+ operation,
89487
+ startTime
89488
+ );
89489
+ }
89271
89490
  case "map": {
89272
89491
  const { mapCodebase: mapCodebase3 } = await Promise.resolve().then(() => (init_codebase_map_engine(), codebase_map_engine_exports));
89273
89492
  const result = await mapCodebase3(projectRoot, {
@@ -89757,6 +89976,7 @@ var AdminHandler = class {
89757
89976
  "token",
89758
89977
  "adr.show",
89759
89978
  "adr.find",
89979
+ "backup",
89760
89980
  "export",
89761
89981
  "map"
89762
89982
  ],