@cleocode/cleo 2026.3.60 → 2026.3.61

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
@@ -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
 
@@ -74633,6 +74665,7 @@ var init_migration_sqlite = __esm({
74633
74665
  // packages/core/src/repair.ts
74634
74666
  var repair_exports = {};
74635
74667
  __export(repair_exports, {
74668
+ repairMissingColumns: () => repairMissingColumns,
74636
74669
  repairMissingCompletedAt: () => repairMissingCompletedAt,
74637
74670
  repairMissingSizes: () => repairMissingSizes,
74638
74671
  runAllRepairs: () => runAllRepairs
@@ -74696,12 +74729,43 @@ async function repairMissingCompletedAt(cwd, dryRun) {
74696
74729
  details: `Set completedAt for ${affected.length} done/cancelled task(s)`
74697
74730
  };
74698
74731
  }
74732
+ async function repairMissingColumns(cwd, dryRun) {
74733
+ const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
74734
+ const db = await getDb4(cwd);
74735
+ const { sql: sql12 } = await import("drizzle-orm");
74736
+ const columns = db.all(sql12`PRAGMA table_info(tasks)`);
74737
+ const existingCols = new Set(columns.map((c) => c.name));
74738
+ const missingCols = ["pipeline_stage"].filter((c) => !existingCols.has(c));
74739
+ if (missingCols.length === 0) {
74740
+ return {
74741
+ action: "fix_missing_columns",
74742
+ status: "skipped",
74743
+ details: "All required columns present on tasks table"
74744
+ };
74745
+ }
74746
+ if (dryRun) {
74747
+ return {
74748
+ action: "fix_missing_columns",
74749
+ status: "preview",
74750
+ details: `Would add missing column(s): ${missingCols.join(", ")}`
74751
+ };
74752
+ }
74753
+ for (const col of missingCols) {
74754
+ db.run(sql12.raw(`ALTER TABLE tasks ADD COLUMN ${col} text`));
74755
+ }
74756
+ return {
74757
+ action: "fix_missing_columns",
74758
+ status: "applied",
74759
+ details: `Added missing column(s): ${missingCols.join(", ")}`
74760
+ };
74761
+ }
74699
74762
  async function runAllRepairs(cwd, dryRun) {
74700
- const [sizes, completedAt] = await Promise.all([
74763
+ const [sizes, completedAt, columns] = await Promise.all([
74701
74764
  repairMissingSizes(cwd, dryRun),
74702
- repairMissingCompletedAt(cwd, dryRun)
74765
+ repairMissingCompletedAt(cwd, dryRun),
74766
+ repairMissingColumns(cwd, dryRun)
74703
74767
  ]);
74704
- return [sizes, completedAt];
74768
+ return [sizes, completedAt, columns];
74705
74769
  }
74706
74770
  var init_repair = __esm({
74707
74771
  "packages/core/src/repair.ts"() {
@@ -78317,6 +78381,7 @@ __export(internal_exports, {
78317
78381
  WorkflowGateTracker: () => WorkflowGateTracker,
78318
78382
  adapters: () => adapters_exports,
78319
78383
  addChain: () => addChain,
78384
+ addIssue: () => addIssue,
78320
78385
  addRemote: () => addRemote,
78321
78386
  addSticky: () => addSticky,
78322
78387
  addTask: () => addTask,
@@ -78957,6 +79022,7 @@ var init_internal = __esm({
78957
79022
  init_impact();
78958
79023
  init_patterns2();
78959
79024
  init_prediction();
79025
+ init_create();
78960
79026
  init_diagnostics();
78961
79027
  init_retry2();
78962
79028
  init_chain_store();
@@ -95527,23 +95593,23 @@ function registerIssueCommand(program) {
95527
95593
  });
95528
95594
  }
95529
95595
  async function handleIssueType(issueType, opts) {
95530
- const params = {
95531
- issueType,
95532
- title: opts["title"],
95533
- body: opts["body"],
95534
- dryRun: !!opts["dryRun"]
95535
- };
95536
- if (opts["severity"]) params["severity"] = opts["severity"];
95537
- if (opts["area"]) params["area"] = opts["area"];
95538
- const opName = `issue.add.${issueType}`;
95539
- const response = await dispatchRaw("mutate", "tools", opName, params);
95540
- if (!response.success) {
95541
- handleRawError(response, { command: "issue", operation: `tools.${opName}` });
95596
+ let result;
95597
+ try {
95598
+ result = addIssue({
95599
+ issueType,
95600
+ title: opts["title"],
95601
+ body: opts["body"],
95602
+ severity: opts["severity"],
95603
+ area: opts["area"],
95604
+ dryRun: !!opts["dryRun"]
95605
+ });
95606
+ } catch (err) {
95607
+ console.error(`Failed to create issue: ${err instanceof Error ? err.message : String(err)}`);
95608
+ process.exitCode = 1;
95542
95609
  return;
95543
95610
  }
95544
- const result = response.data;
95545
- if (opts["open"] && typeof result["url"] === "string" && result["url"].startsWith("https://")) {
95546
- const issueNumber = result["url"].match(/(\d+)$/)?.[1] ?? "unknown";
95611
+ if (opts["open"] && typeof result.url === "string" && result.url.startsWith("https://")) {
95612
+ const issueNumber = result.url.match(/(\d+)$/)?.[1] ?? "unknown";
95547
95613
  try {
95548
95614
  execFileSync15("gh", ["issue", "view", issueNumber, "--repo", CLEO_REPO2, "--web"], {
95549
95615
  stdio: ["pipe", "pipe", "pipe"]
@@ -95551,7 +95617,7 @@ async function handleIssueType(issueType, opts) {
95551
95617
  } catch {
95552
95618
  }
95553
95619
  }
95554
- cliOutput(result, { command: "issue", operation: `tools.${opName}` });
95620
+ cliOutput(result, { command: "issue", operation: `tools.issue.add.${issueType}` });
95555
95621
  }
95556
95622
 
95557
95623
  // packages/cleo/src/cli/commands/labels.ts