@cleocode/core 2026.4.45 → 2026.4.46
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/index.js +65 -57
- package/dist/index.js.map +3 -3
- package/dist/internal.js +97 -89
- package/dist/internal.js.map +3 -3
- package/dist/store/db-helpers.d.ts +8 -3
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/store/__tests__/db-helpers.test.ts +46 -6
- package/src/store/db-helpers.ts +25 -4
- package/src/store/sqlite-data-accessor.ts +2 -1
- package/src/tasks/__tests__/epic-auto-complete.test.ts +331 -0
- package/src/tasks/complete.ts +7 -4
package/dist/internal.js
CHANGED
|
@@ -11471,14 +11471,14 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
|
|
|
11471
11471
|
const dbHashes = new Set(dbEntries.map((e) => e.hash));
|
|
11472
11472
|
const allLocalHashesPresentInDb = localMigrations.every((m2) => dbHashes.has(m2.hash));
|
|
11473
11473
|
if (allLocalHashesPresentInDb) {
|
|
11474
|
-
const
|
|
11475
|
-
|
|
11474
|
+
const log12 = getLogger(logSubsystem);
|
|
11475
|
+
log12.debug(
|
|
11476
11476
|
{ extra: orphanedEntries.length },
|
|
11477
11477
|
`Migration journal has ${orphanedEntries.length} entries for migrations not known to this install (DB is ahead). Skipping reconciliation.`
|
|
11478
11478
|
);
|
|
11479
11479
|
} else {
|
|
11480
|
-
const
|
|
11481
|
-
|
|
11480
|
+
const log12 = getLogger(logSubsystem);
|
|
11481
|
+
log12.warn(
|
|
11482
11482
|
{ orphaned: orphanedEntries.length },
|
|
11483
11483
|
`Detected stale migration journal entries from a previous CLEO version. Reconciling.`
|
|
11484
11484
|
);
|
|
@@ -11509,8 +11509,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
|
|
|
11509
11509
|
return cols.some((c) => c.name === column);
|
|
11510
11510
|
});
|
|
11511
11511
|
if (allColumnsExist) {
|
|
11512
|
-
const
|
|
11513
|
-
|
|
11512
|
+
const log12 = getLogger(logSubsystem);
|
|
11513
|
+
log12.warn(
|
|
11514
11514
|
{ migration: migration.name, columns: alterMatches },
|
|
11515
11515
|
`Detected partially-applied migration ${migration.name} \u2014 columns exist but journal entry missing. Auto-reconciling.`
|
|
11516
11516
|
);
|
|
@@ -11528,8 +11528,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
|
|
|
11528
11528
|
for (const entry of unnamedEntries) {
|
|
11529
11529
|
const migrationName = hashToName.get(entry.hash);
|
|
11530
11530
|
if (!migrationName) continue;
|
|
11531
|
-
const
|
|
11532
|
-
|
|
11531
|
+
const log12 = getLogger(logSubsystem);
|
|
11532
|
+
log12.warn(
|
|
11533
11533
|
{ id: entry.id, hash: entry.hash, name: migrationName },
|
|
11534
11534
|
`Backfilling missing name on journal entry id=${entry.id} \u2014 Drizzle v1 beta requires name for applied-migration detection.`
|
|
11535
11535
|
);
|
|
@@ -11573,8 +11573,8 @@ function ensureColumns(nativeDb, tableName, requiredColumns, logSubsystem) {
|
|
|
11573
11573
|
const existingCols = new Set(columns.map((c) => c.name));
|
|
11574
11574
|
for (const req of requiredColumns) {
|
|
11575
11575
|
if (!existingCols.has(req.name)) {
|
|
11576
|
-
const
|
|
11577
|
-
|
|
11576
|
+
const log12 = getLogger(logSubsystem);
|
|
11577
|
+
log12.warn(
|
|
11578
11578
|
{ column: req.name },
|
|
11579
11579
|
`Adding missing column ${tableName}.${req.name} via ALTER TABLE`
|
|
11580
11580
|
);
|
|
@@ -13972,7 +13972,7 @@ function getDbPath(cwd) {
|
|
|
13972
13972
|
return join10(getCleoDirAbsolute(cwd), DB_FILENAME2);
|
|
13973
13973
|
}
|
|
13974
13974
|
async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
13975
|
-
const
|
|
13975
|
+
const log12 = getLogger("sqlite");
|
|
13976
13976
|
try {
|
|
13977
13977
|
const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks").get();
|
|
13978
13978
|
const taskCount = countResult?.cnt ?? 0;
|
|
@@ -13993,7 +13993,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
13993
13993
|
if (backupTaskCount < MIN_BACKUP_TASK_COUNT) {
|
|
13994
13994
|
return;
|
|
13995
13995
|
}
|
|
13996
|
-
|
|
13996
|
+
log12.warn(
|
|
13997
13997
|
{ dbPath, backupPath: newestBackup.path, backupTasks: backupTaskCount },
|
|
13998
13998
|
`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).`
|
|
13999
13999
|
);
|
|
@@ -14011,7 +14011,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
14011
14011
|
const tempPath = dbPath + ".recovery-tmp";
|
|
14012
14012
|
copyFileSync4(newestBackup.path, tempPath);
|
|
14013
14013
|
renameSync(tempPath, dbPath);
|
|
14014
|
-
|
|
14014
|
+
log12.info(
|
|
14015
14015
|
{ dbPath, backupPath: newestBackup.path, restoredTasks: backupTaskCount },
|
|
14016
14016
|
"Database auto-recovered from backup successfully."
|
|
14017
14017
|
);
|
|
@@ -14021,7 +14021,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
|
|
|
14021
14021
|
runMigrations(restoredNativeDb, restoredDb);
|
|
14022
14022
|
_db = restoredDb;
|
|
14023
14023
|
} catch (err) {
|
|
14024
|
-
|
|
14024
|
+
log12.error({ err, dbPath }, "Auto-recovery from backup failed. Continuing with empty database.");
|
|
14025
14025
|
}
|
|
14026
14026
|
}
|
|
14027
14027
|
async function getDb(cwd) {
|
|
@@ -14055,7 +14055,7 @@ async function getDb(cwd) {
|
|
|
14055
14055
|
const { execFileSync: execFileSync14 } = await import("node:child_process");
|
|
14056
14056
|
const gitCwd = resolve3(dbPath, "..", "..");
|
|
14057
14057
|
const filesToCheck = [dbPath, dbPath + "-wal", dbPath + "-shm"];
|
|
14058
|
-
const
|
|
14058
|
+
const log12 = getLogger("sqlite");
|
|
14059
14059
|
for (const fileToCheck of filesToCheck) {
|
|
14060
14060
|
try {
|
|
14061
14061
|
execFileSync14("git", ["ls-files", "--error-unmatch", fileToCheck], {
|
|
@@ -14064,7 +14064,7 @@ async function getDb(cwd) {
|
|
|
14064
14064
|
});
|
|
14065
14065
|
const basename18 = fileToCheck.split(/[\\/]/).pop();
|
|
14066
14066
|
const relPath = fileToCheck.replace(gitCwd + sep, "");
|
|
14067
|
-
|
|
14067
|
+
log12.warn(
|
|
14068
14068
|
{ path: fileToCheck },
|
|
14069
14069
|
`${basename18} 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.`
|
|
14070
14070
|
);
|
|
@@ -15258,11 +15258,18 @@ var init_cross_db_cleanup = __esm({
|
|
|
15258
15258
|
|
|
15259
15259
|
// packages/core/src/store/db-helpers.ts
|
|
15260
15260
|
import { eq as eq4, inArray as inArray2 } from "drizzle-orm";
|
|
15261
|
-
async function upsertTask(db, row, archiveFields) {
|
|
15261
|
+
async function upsertTask(db, row, archiveFields, allowOrphanParent = false) {
|
|
15262
15262
|
if (row.parentId) {
|
|
15263
15263
|
const parent = await db.select({ id: tasks.id }).from(tasks).where(eq4(tasks.id, row.parentId)).limit(1).all();
|
|
15264
15264
|
if (parent.length === 0) {
|
|
15265
|
-
|
|
15265
|
+
if (allowOrphanParent) {
|
|
15266
|
+
row = { ...row, parentId: null };
|
|
15267
|
+
} else {
|
|
15268
|
+
log2.warn(
|
|
15269
|
+
{ taskId: row.id, parentId: row.parentId },
|
|
15270
|
+
"upsertTask: parentId references a non-existent task \u2014 parent relationship may be lost"
|
|
15271
|
+
);
|
|
15272
|
+
}
|
|
15266
15273
|
}
|
|
15267
15274
|
}
|
|
15268
15275
|
const values = archiveFields ? { ...row, ...archiveFields, status: "archived" } : row;
|
|
@@ -15406,10 +15413,13 @@ async function loadRelationsForTasks(db, tasks2) {
|
|
|
15406
15413
|
}
|
|
15407
15414
|
}
|
|
15408
15415
|
}
|
|
15416
|
+
var log2;
|
|
15409
15417
|
var init_db_helpers = __esm({
|
|
15410
15418
|
"packages/core/src/store/db-helpers.ts"() {
|
|
15411
15419
|
"use strict";
|
|
15420
|
+
init_logger();
|
|
15412
15421
|
init_tasks_schema();
|
|
15422
|
+
log2 = getLogger("db-helpers");
|
|
15413
15423
|
}
|
|
15414
15424
|
});
|
|
15415
15425
|
|
|
@@ -15743,7 +15753,7 @@ async function createSqliteDataAccessor(cwd) {
|
|
|
15743
15753
|
archiveReason: taskAny.archiveReason ?? "completed",
|
|
15744
15754
|
cycleTimeDays: taskAny.cycleTimeDays ?? null
|
|
15745
15755
|
};
|
|
15746
|
-
await upsertTask(db, row, archiveFields);
|
|
15756
|
+
await upsertTask(db, row, archiveFields, true);
|
|
15747
15757
|
depBatch.push({ taskId: task.id, deps: task.depends ?? [] });
|
|
15748
15758
|
}
|
|
15749
15759
|
await batchUpdateDependencies(db, depBatch, validDepIds);
|
|
@@ -16756,7 +16766,7 @@ async function ensureSequenceValid(cwd, options) {
|
|
|
16756
16766
|
if (!options?.validateSequence) return;
|
|
16757
16767
|
const check2 = await checkSequence(cwd);
|
|
16758
16768
|
if (!check2.valid) {
|
|
16759
|
-
|
|
16769
|
+
log3.warn({ counter: check2.counter, maxId: check2.maxIdInData }, "Sequence behind, repairing");
|
|
16760
16770
|
const repair = await repairSequence(cwd);
|
|
16761
16771
|
if (!repair.repaired && options.strict) {
|
|
16762
16772
|
throw new DataSafetyError(`Sequence repair failed: ${repair.message}`, "SEQUENCE_INVALID", {
|
|
@@ -16773,7 +16783,7 @@ async function checkpoint(context, cwd, options) {
|
|
|
16773
16783
|
stats.checkpoints++;
|
|
16774
16784
|
stats.lastCheckpoint = /* @__PURE__ */ new Date();
|
|
16775
16785
|
} catch (err) {
|
|
16776
|
-
|
|
16786
|
+
log3.warn({ err }, "Checkpoint failed (non-fatal)");
|
|
16777
16787
|
}
|
|
16778
16788
|
vacuumIntoBackup({ cwd }).catch(() => {
|
|
16779
16789
|
});
|
|
@@ -16835,7 +16845,7 @@ async function safeAppendLog(accessor, entry, cwd, options) {
|
|
|
16835
16845
|
stats.writes++;
|
|
16836
16846
|
await checkpoint("log entry", cwd, opts);
|
|
16837
16847
|
}
|
|
16838
|
-
var
|
|
16848
|
+
var log3, DataSafetyError, DEFAULT_SAFETY, stats;
|
|
16839
16849
|
var init_data_safety_central = __esm({
|
|
16840
16850
|
"packages/core/src/store/data-safety-central.ts"() {
|
|
16841
16851
|
"use strict";
|
|
@@ -16843,7 +16853,7 @@ var init_data_safety_central = __esm({
|
|
|
16843
16853
|
init_sequence();
|
|
16844
16854
|
init_git_checkpoint();
|
|
16845
16855
|
init_sqlite_backup();
|
|
16846
|
-
|
|
16856
|
+
log3 = getLogger("data-safety");
|
|
16847
16857
|
DataSafetyError = class extends Error {
|
|
16848
16858
|
constructor(message, code, context) {
|
|
16849
16859
|
super(message);
|
|
@@ -16883,7 +16893,7 @@ function isSafetyDisabled() {
|
|
|
16883
16893
|
}
|
|
16884
16894
|
function wrapWithSafety(accessor, cwd) {
|
|
16885
16895
|
if (isSafetyDisabled()) {
|
|
16886
|
-
|
|
16896
|
+
log4.warn(
|
|
16887
16897
|
"Safety disabled - emergency mode (CLEO_DISABLE_SAFETY=true). Data integrity checks bypassed."
|
|
16888
16898
|
);
|
|
16889
16899
|
return accessor;
|
|
@@ -16904,13 +16914,13 @@ function getSafetyStatus() {
|
|
|
16904
16914
|
enabled: true
|
|
16905
16915
|
};
|
|
16906
16916
|
}
|
|
16907
|
-
var
|
|
16917
|
+
var log4, SafetyDataAccessor;
|
|
16908
16918
|
var init_safety_data_accessor = __esm({
|
|
16909
16919
|
"packages/core/src/store/safety-data-accessor.ts"() {
|
|
16910
16920
|
"use strict";
|
|
16911
16921
|
init_logger();
|
|
16912
16922
|
init_data_safety_central();
|
|
16913
|
-
|
|
16923
|
+
log4 = getLogger("data-safety");
|
|
16914
16924
|
SafetyDataAccessor = class {
|
|
16915
16925
|
/** The underlying accessor being wrapped. */
|
|
16916
16926
|
inner;
|
|
@@ -16934,7 +16944,7 @@ var init_safety_data_accessor = __esm({
|
|
|
16934
16944
|
...config2
|
|
16935
16945
|
};
|
|
16936
16946
|
if (this.config.verbose) {
|
|
16937
|
-
|
|
16947
|
+
log4.debug({ engine: inner.engine }, "SafetyDataAccessor initialized");
|
|
16938
16948
|
}
|
|
16939
16949
|
}
|
|
16940
16950
|
/** The storage engine backing this accessor. */
|
|
@@ -16946,7 +16956,7 @@ var init_safety_data_accessor = __esm({
|
|
|
16946
16956
|
*/
|
|
16947
16957
|
logVerbose(message) {
|
|
16948
16958
|
if (this.config.verbose) {
|
|
16949
|
-
|
|
16959
|
+
log4.debug(message);
|
|
16950
16960
|
}
|
|
16951
16961
|
}
|
|
16952
16962
|
/**
|
|
@@ -21347,16 +21357,16 @@ async function queryAudit(options) {
|
|
|
21347
21357
|
error: row.errorMessage ?? void 0
|
|
21348
21358
|
}));
|
|
21349
21359
|
} catch (err) {
|
|
21350
|
-
|
|
21360
|
+
log5.warn({ err }, "Failed to query audit entries from SQLite");
|
|
21351
21361
|
return [];
|
|
21352
21362
|
}
|
|
21353
21363
|
}
|
|
21354
|
-
var
|
|
21364
|
+
var log5;
|
|
21355
21365
|
var init_audit = __esm({
|
|
21356
21366
|
"packages/core/src/audit.ts"() {
|
|
21357
21367
|
"use strict";
|
|
21358
21368
|
init_logger();
|
|
21359
|
-
|
|
21369
|
+
log5 = getLogger("audit");
|
|
21360
21370
|
}
|
|
21361
21371
|
});
|
|
21362
21372
|
|
|
@@ -54112,9 +54122,7 @@ async function completeTask(options, cwd, accessor) {
|
|
|
54112
54122
|
const parent = await acc.loadSingleTask(task.parentId);
|
|
54113
54123
|
if (parent && parent.type === "epic" && !parent.noAutoComplete) {
|
|
54114
54124
|
const siblings = await acc.getChildren(parent.id);
|
|
54115
|
-
const allDone = siblings.every(
|
|
54116
|
-
(c) => c.id === task.id || c.status === "done" || c.status === "cancelled"
|
|
54117
|
-
);
|
|
54125
|
+
const allDone = siblings.length > 0 && siblings.every((c) => c.id === task.id || c.status === "done" || c.status === "cancelled");
|
|
54118
54126
|
if (allDone) {
|
|
54119
54127
|
parent.status = "done";
|
|
54120
54128
|
parent.completedAt = now2;
|
|
@@ -58253,7 +58261,7 @@ async function validateAndRepairSequence(cwd, config2 = {}) {
|
|
|
58253
58261
|
}
|
|
58254
58262
|
const repair = await repairSequence(cwd);
|
|
58255
58263
|
if (repair.repaired) {
|
|
58256
|
-
|
|
58264
|
+
log11.warn(
|
|
58257
58265
|
{ oldCounter: repair.oldCounter, newCounter: repair.newCounter },
|
|
58258
58266
|
"Sequence repaired"
|
|
58259
58267
|
);
|
|
@@ -58282,7 +58290,7 @@ async function triggerCheckpoint(context, cwd, config2 = {}) {
|
|
|
58282
58290
|
try {
|
|
58283
58291
|
await gitCheckpoint("auto", context, cwd);
|
|
58284
58292
|
} catch (err) {
|
|
58285
|
-
|
|
58293
|
+
log11.warn({ err }, "Checkpoint failed (non-fatal)");
|
|
58286
58294
|
}
|
|
58287
58295
|
vacuumIntoBackup({ cwd }).catch(() => {
|
|
58288
58296
|
});
|
|
@@ -58320,16 +58328,16 @@ async function safeDeleteTask(deleteFn, taskId, cwd, config2 = {}) {
|
|
|
58320
58328
|
return result;
|
|
58321
58329
|
}
|
|
58322
58330
|
async function forceCheckpointBeforeOperation(operation, cwd) {
|
|
58323
|
-
|
|
58331
|
+
log11.info({ operation }, "Forcing checkpoint before operation");
|
|
58324
58332
|
try {
|
|
58325
58333
|
await gitCheckpoint("manual", `pre-${operation}`, cwd);
|
|
58326
58334
|
} catch (err) {
|
|
58327
|
-
|
|
58335
|
+
log11.error({ err }, "Failed to create pre-operation checkpoint");
|
|
58328
58336
|
}
|
|
58329
58337
|
vacuumIntoBackup({ cwd, force: true }).catch(() => {
|
|
58330
58338
|
});
|
|
58331
58339
|
}
|
|
58332
|
-
var
|
|
58340
|
+
var log11, DEFAULT_CONFIG2, SafetyError;
|
|
58333
58341
|
var init_data_safety = __esm({
|
|
58334
58342
|
"packages/core/src/store/data-safety.ts"() {
|
|
58335
58343
|
"use strict";
|
|
@@ -58339,7 +58347,7 @@ var init_data_safety = __esm({
|
|
|
58339
58347
|
init_sqlite2();
|
|
58340
58348
|
init_sqlite_backup();
|
|
58341
58349
|
init_tasks_schema();
|
|
58342
|
-
|
|
58350
|
+
log11 = getLogger("data-safety");
|
|
58343
58351
|
DEFAULT_CONFIG2 = {
|
|
58344
58352
|
verifyWrites: true,
|
|
58345
58353
|
detectCollisions: true,
|
|
@@ -63649,11 +63657,11 @@ var require_core = __commonJS({
|
|
|
63649
63657
|
Ajv4.ValidationError = validation_error_1.default;
|
|
63650
63658
|
Ajv4.MissingRefError = ref_error_1.default;
|
|
63651
63659
|
exports.default = Ajv4;
|
|
63652
|
-
function checkOptions(checkOpts, options, msg,
|
|
63660
|
+
function checkOptions(checkOpts, options, msg, log12 = "error") {
|
|
63653
63661
|
for (const key in checkOpts) {
|
|
63654
63662
|
const opt = key;
|
|
63655
63663
|
if (opt in options)
|
|
63656
|
-
this.logger[
|
|
63664
|
+
this.logger[log12](`${msg}: option ${key}. ${checkOpts[opt]}`);
|
|
63657
63665
|
}
|
|
63658
63666
|
}
|
|
63659
63667
|
function getSchEnv(keyRef) {
|
|
@@ -71017,7 +71025,7 @@ init_logger();
|
|
|
71017
71025
|
init_paths();
|
|
71018
71026
|
init_tasks_schema();
|
|
71019
71027
|
import { basename as basename6, relative as relative2 } from "node:path";
|
|
71020
|
-
var
|
|
71028
|
+
var log6 = getLogger("lifecycle:evidence");
|
|
71021
71029
|
async function recordEvidence(epicId, stage, uri, type, options) {
|
|
71022
71030
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
71023
71031
|
const stageId = `stage-${epicId}-${stage}`;
|
|
@@ -71044,7 +71052,7 @@ async function recordEvidence(epicId, stage, uri, type, options) {
|
|
|
71044
71052
|
description: options?.description ?? null
|
|
71045
71053
|
}).run();
|
|
71046
71054
|
} catch (err) {
|
|
71047
|
-
|
|
71055
|
+
log6.warn({ err }, "Failed to write evidence to SQLite");
|
|
71048
71056
|
}
|
|
71049
71057
|
return record2;
|
|
71050
71058
|
}
|
|
@@ -76782,7 +76790,7 @@ init_sqlite2();
|
|
|
76782
76790
|
init_tasks_schema();
|
|
76783
76791
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
76784
76792
|
import { and as and8, eq as eq11, sql as sql11 } from "drizzle-orm";
|
|
76785
|
-
var
|
|
76793
|
+
var log7 = getLogger("link-store");
|
|
76786
76794
|
async function getLinksByProvider(providerId, cwd) {
|
|
76787
76795
|
const db = await getDb(cwd);
|
|
76788
76796
|
const rows = await db.select().from(externalTaskLinks).where(eq11(externalTaskLinks.providerId, providerId));
|
|
@@ -76837,7 +76845,7 @@ async function ensureExternalTaskLinksTable(cwd) {
|
|
|
76837
76845
|
)
|
|
76838
76846
|
);
|
|
76839
76847
|
} catch (err) {
|
|
76840
|
-
|
|
76848
|
+
log7.warn({ err }, "Failed to ensure external_task_links table exists");
|
|
76841
76849
|
throw err;
|
|
76842
76850
|
}
|
|
76843
76851
|
}
|
|
@@ -76911,7 +76919,7 @@ init_brain_accessor();
|
|
|
76911
76919
|
init_brain_sqlite();
|
|
76912
76920
|
init_data_accessor();
|
|
76913
76921
|
init_registry3();
|
|
76914
|
-
var
|
|
76922
|
+
var log8 = getLogger("nexus:transfer");
|
|
76915
76923
|
async function previewTransfer(params) {
|
|
76916
76924
|
return executeTransferInternal({ ...params, dryRun: true });
|
|
76917
76925
|
}
|
|
@@ -77052,7 +77060,7 @@ async function executeTransferInternal(params) {
|
|
|
77052
77060
|
}
|
|
77053
77061
|
}
|
|
77054
77062
|
} catch (err) {
|
|
77055
|
-
|
|
77063
|
+
log8.warn(
|
|
77056
77064
|
{ err, linksCreated },
|
|
77057
77065
|
"Failed to create external_task_links during transfer \u2014 tasks were transferred successfully but provenance links could not be written"
|
|
77058
77066
|
);
|
|
@@ -77080,7 +77088,7 @@ async function executeTransferInternal(params) {
|
|
|
77080
77088
|
})
|
|
77081
77089
|
});
|
|
77082
77090
|
} catch (err) {
|
|
77083
|
-
|
|
77091
|
+
log8.warn({ err }, "nexus transfer audit write failed");
|
|
77084
77092
|
}
|
|
77085
77093
|
if (mode === "move") {
|
|
77086
77094
|
let archived = 0;
|
|
@@ -77093,7 +77101,7 @@ async function executeTransferInternal(params) {
|
|
|
77093
77101
|
});
|
|
77094
77102
|
archived++;
|
|
77095
77103
|
} catch (err) {
|
|
77096
|
-
|
|
77104
|
+
log8.warn({ err, taskId: entry.sourceId }, "failed to archive source task after transfer");
|
|
77097
77105
|
}
|
|
77098
77106
|
}
|
|
77099
77107
|
}
|
|
@@ -77131,7 +77139,7 @@ async function executeTransferInternal(params) {
|
|
|
77131
77139
|
}
|
|
77132
77140
|
}
|
|
77133
77141
|
} catch (err) {
|
|
77134
|
-
|
|
77142
|
+
log8.warn({ err }, "brain observation transfer failed");
|
|
77135
77143
|
}
|
|
77136
77144
|
result.brainObservationsTransferred = brainTransferred;
|
|
77137
77145
|
result.manifest.brainObservationsTransferred = brainTransferred;
|
|
@@ -77179,8 +77187,8 @@ async function loadProjectACL(projectPath) {
|
|
|
77179
77187
|
async function logAclFailure(projectPath) {
|
|
77180
77188
|
try {
|
|
77181
77189
|
const { getLogger: getLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
77182
|
-
const
|
|
77183
|
-
|
|
77190
|
+
const log12 = getLogger2("nexus.acl");
|
|
77191
|
+
log12.warn({ projectPath }, "Failed to load ACL configuration, defaulting to deny-all");
|
|
77184
77192
|
} catch {
|
|
77185
77193
|
}
|
|
77186
77194
|
}
|
|
@@ -77335,9 +77343,9 @@ async function executeOperation(operation, taskId, projectPath, accessor, direct
|
|
|
77335
77343
|
async function logRouteAudit(directive, projectName, taskId, operation, success2, error48) {
|
|
77336
77344
|
try {
|
|
77337
77345
|
const { getLogger: getLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
77338
|
-
const
|
|
77346
|
+
const log12 = getLogger2("nexus.route");
|
|
77339
77347
|
const level = success2 ? "info" : "warn";
|
|
77340
|
-
|
|
77348
|
+
log12[level](
|
|
77341
77349
|
{
|
|
77342
77350
|
directive: directive.verb,
|
|
77343
77351
|
agentId: directive.agentId,
|
|
@@ -85909,7 +85917,7 @@ init_data_accessor();
|
|
|
85909
85917
|
|
|
85910
85918
|
// packages/core/src/stats/workflow-telemetry.ts
|
|
85911
85919
|
init_logger();
|
|
85912
|
-
var
|
|
85920
|
+
var log9 = getLogger("workflow-telemetry");
|
|
85913
85921
|
async function queryTasks(cwd, since) {
|
|
85914
85922
|
try {
|
|
85915
85923
|
const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
@@ -85931,7 +85939,7 @@ async function queryTasks(cwd, since) {
|
|
|
85931
85939
|
}).from(tasks2).where(conditions.length > 0 ? and13(...conditions) : void 0).all();
|
|
85932
85940
|
return rows;
|
|
85933
85941
|
} catch (err) {
|
|
85934
|
-
|
|
85942
|
+
log9.warn({ err }, "Failed to query tasks for workflow telemetry");
|
|
85935
85943
|
return [];
|
|
85936
85944
|
}
|
|
85937
85945
|
}
|
|
@@ -85965,7 +85973,7 @@ async function queryCompletionAuditRows(cwd, since) {
|
|
|
85965
85973
|
return isComplete;
|
|
85966
85974
|
});
|
|
85967
85975
|
} catch (err) {
|
|
85968
|
-
|
|
85976
|
+
log9.warn({ err }, "Failed to query audit log for workflow telemetry");
|
|
85969
85977
|
return [];
|
|
85970
85978
|
}
|
|
85971
85979
|
}
|
|
@@ -87451,11 +87459,11 @@ import { join as join88 } from "node:path";
|
|
|
87451
87459
|
import { Readable } from "node:stream";
|
|
87452
87460
|
import { pipeline } from "node:stream/promises";
|
|
87453
87461
|
import { createGzip } from "node:zlib";
|
|
87454
|
-
var
|
|
87462
|
+
var log10 = getLogger("prune");
|
|
87455
87463
|
async function pruneAuditLog(cleoDir, config2) {
|
|
87456
87464
|
try {
|
|
87457
87465
|
if (!config2.auditRetentionDays || config2.auditRetentionDays <= 0) {
|
|
87458
|
-
|
|
87466
|
+
log10.debug("auditRetentionDays is 0 or unset; skipping audit prune");
|
|
87459
87467
|
return { rowsArchived: 0, rowsDeleted: 0 };
|
|
87460
87468
|
}
|
|
87461
87469
|
const cutoff = new Date(Date.now() - config2.auditRetentionDays * 864e5).toISOString();
|
|
@@ -87466,7 +87474,7 @@ async function pruneAuditLog(cleoDir, config2) {
|
|
|
87466
87474
|
const db = await getDb4(projectRoot);
|
|
87467
87475
|
const oldRows = await db.select().from(auditLog2).where(lt4(auditLog2.timestamp, cutoff));
|
|
87468
87476
|
if (oldRows.length === 0) {
|
|
87469
|
-
|
|
87477
|
+
log10.debug("No audit_log rows older than cutoff; nothing to prune");
|
|
87470
87478
|
return { rowsArchived: 0, rowsDeleted: 0 };
|
|
87471
87479
|
}
|
|
87472
87480
|
let archivePath;
|
|
@@ -87484,17 +87492,17 @@ async function pruneAuditLog(cleoDir, config2) {
|
|
|
87484
87492
|
const inStream = Readable.from([jsonlContent]);
|
|
87485
87493
|
await pipeline(inStream, gzip, outStream);
|
|
87486
87494
|
rowsArchived = oldRows.length;
|
|
87487
|
-
|
|
87495
|
+
log10.info(
|
|
87488
87496
|
{ archivePath, rowsArchived },
|
|
87489
87497
|
`Archived ${rowsArchived} audit rows to ${archivePath}`
|
|
87490
87498
|
);
|
|
87491
87499
|
} catch (archiveErr) {
|
|
87492
|
-
|
|
87500
|
+
log10.warn({ err: archiveErr }, "Failed to archive audit rows; continuing with deletion");
|
|
87493
87501
|
archivePath = void 0;
|
|
87494
87502
|
}
|
|
87495
87503
|
}
|
|
87496
87504
|
await db.delete(auditLog2).where(lt4(auditLog2.timestamp, cutoff)).run();
|
|
87497
|
-
|
|
87505
|
+
log10.info(
|
|
87498
87506
|
{ rowsDeleted: oldRows.length, cutoff },
|
|
87499
87507
|
`Pruned ${oldRows.length} audit_log rows older than ${cutoff}`
|
|
87500
87508
|
);
|
|
@@ -87504,7 +87512,7 @@ async function pruneAuditLog(cleoDir, config2) {
|
|
|
87504
87512
|
archivePath
|
|
87505
87513
|
};
|
|
87506
87514
|
} catch (err) {
|
|
87507
|
-
|
|
87515
|
+
log10.warn({ err }, "audit log pruning failed");
|
|
87508
87516
|
return { rowsArchived: 0, rowsDeleted: 0 };
|
|
87509
87517
|
}
|
|
87510
87518
|
}
|
|
@@ -102838,7 +102846,7 @@ var LEGACY_FILES = [
|
|
|
102838
102846
|
"nexus-pre-cleo.db.bak"
|
|
102839
102847
|
];
|
|
102840
102848
|
function detectAndRemoveLegacyGlobalFiles(cleoHomeOverride) {
|
|
102841
|
-
const
|
|
102849
|
+
const log12 = getLogger("cleanup-legacy");
|
|
102842
102850
|
const cleoHome = cleoHomeOverride ?? getCleoHome();
|
|
102843
102851
|
const removed = [];
|
|
102844
102852
|
const errors = [];
|
|
@@ -102848,30 +102856,30 @@ function detectAndRemoveLegacyGlobalFiles(cleoHomeOverride) {
|
|
|
102848
102856
|
if (fs5.existsSync(fullPath)) {
|
|
102849
102857
|
fs5.unlinkSync(fullPath);
|
|
102850
102858
|
removed.push(fileName);
|
|
102851
|
-
|
|
102859
|
+
log12.info({ file: fullPath }, "Removed legacy global file");
|
|
102852
102860
|
}
|
|
102853
102861
|
} catch (err) {
|
|
102854
102862
|
const message = err instanceof Error ? err.message : String(err);
|
|
102855
102863
|
errors.push({ file: fileName, error: message });
|
|
102856
|
-
|
|
102864
|
+
log12.warn({ file: fullPath, error: message }, "Failed to remove legacy global file");
|
|
102857
102865
|
}
|
|
102858
102866
|
}
|
|
102859
102867
|
return { removed, errors };
|
|
102860
102868
|
}
|
|
102861
102869
|
function detectAndRemoveStrayProjectNexus(projectRoot) {
|
|
102862
|
-
const
|
|
102870
|
+
const log12 = getLogger("cleanup-legacy");
|
|
102863
102871
|
const strayPath = path5.join(projectRoot, ".cleo", "nexus.db");
|
|
102864
102872
|
if (fs5.existsSync(strayPath)) {
|
|
102865
102873
|
try {
|
|
102866
102874
|
fs5.unlinkSync(strayPath);
|
|
102867
|
-
|
|
102875
|
+
log12.warn(
|
|
102868
102876
|
{ path: strayPath },
|
|
102869
102877
|
"Removed stray project-tier nexus.db (violates ADR-036 global-only contract)"
|
|
102870
102878
|
);
|
|
102871
102879
|
return { removed: true, path: strayPath };
|
|
102872
102880
|
} catch (err) {
|
|
102873
102881
|
const message = err instanceof Error ? err.message : String(err);
|
|
102874
|
-
|
|
102882
|
+
log12.warn(
|
|
102875
102883
|
{ path: strayPath, error: message },
|
|
102876
102884
|
"Failed to remove stray project-tier nexus.db \u2014 manual deletion may be required"
|
|
102877
102885
|
);
|
|
@@ -102964,7 +102972,7 @@ function brokenTimestamp() {
|
|
|
102964
102972
|
return `${now2.getFullYear()}${pad2(now2.getMonth() + 1)}${pad2(now2.getDate())}-${pad2(now2.getHours())}${pad2(now2.getMinutes())}${pad2(now2.getSeconds())}-${pad3(now2.getMilliseconds())}`;
|
|
102965
102973
|
}
|
|
102966
102974
|
function migrateSignaldockToConduit(projectRoot) {
|
|
102967
|
-
const
|
|
102975
|
+
const log12 = getLogger("migrate-signaldock-to-conduit");
|
|
102968
102976
|
const legacyPath = join112(projectRoot, ".cleo", "signaldock.db");
|
|
102969
102977
|
const conduitPath = join112(projectRoot, ".cleo", "conduit.db");
|
|
102970
102978
|
const globalSignaldockPath = join112(getCleoHome(), "signaldock.db");
|
|
@@ -102981,13 +102989,13 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
102981
102989
|
if (!needsSignaldockToConduitMigration(projectRoot)) {
|
|
102982
102990
|
return result;
|
|
102983
102991
|
}
|
|
102984
|
-
|
|
102992
|
+
log12.info({ projectRoot, legacyPath }, "T310 migration: starting signaldock.db \u2192 conduit.db");
|
|
102985
102993
|
let legacy = null;
|
|
102986
102994
|
try {
|
|
102987
102995
|
legacy = new DatabaseSync7(legacyPath, { readOnly: true });
|
|
102988
102996
|
} catch (err) {
|
|
102989
102997
|
const message = err instanceof Error ? err.message : String(err);
|
|
102990
|
-
|
|
102998
|
+
log12.error({ legacyPath, error: message }, "T310 migration: cannot open legacy signaldock.db");
|
|
102991
102999
|
result.errors.push({ step: "step-2-open-legacy", error: message });
|
|
102992
103000
|
result.status = "failed";
|
|
102993
103001
|
return result;
|
|
@@ -102995,7 +103003,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
102995
103003
|
try {
|
|
102996
103004
|
if (!integrityCheckPasses(legacy)) {
|
|
102997
103005
|
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.";
|
|
102998
|
-
|
|
103006
|
+
log12.error({ legacyPath }, msg);
|
|
102999
103007
|
result.errors.push({ step: "step-3-legacy-integrity", error: msg });
|
|
103000
103008
|
result.status = "failed";
|
|
103001
103009
|
legacy.close();
|
|
@@ -103003,7 +103011,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103003
103011
|
}
|
|
103004
103012
|
} catch (err) {
|
|
103005
103013
|
const message = err instanceof Error ? err.message : String(err);
|
|
103006
|
-
|
|
103014
|
+
log12.error({ legacyPath, error: message }, "T310 migration: integrity_check threw on legacy DB");
|
|
103007
103015
|
result.errors.push({ step: "step-3-legacy-integrity", error: message });
|
|
103008
103016
|
result.status = "failed";
|
|
103009
103017
|
legacy.close();
|
|
@@ -103021,7 +103029,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103021
103029
|
getGlobalSalt();
|
|
103022
103030
|
} catch (err) {
|
|
103023
103031
|
const message = err instanceof Error ? err.message : String(err);
|
|
103024
|
-
|
|
103032
|
+
log12.error({ error: message }, "T310 migration: getGlobalSalt failed \u2014 migration aborted");
|
|
103025
103033
|
result.errors.push({ step: "step-6-global-salt", error: message });
|
|
103026
103034
|
result.status = "failed";
|
|
103027
103035
|
legacy.close();
|
|
@@ -103035,7 +103043,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103035
103043
|
conduit.exec("PRAGMA foreign_keys = OFF");
|
|
103036
103044
|
} catch (err) {
|
|
103037
103045
|
const message = err instanceof Error ? err.message : String(err);
|
|
103038
|
-
|
|
103046
|
+
log12.error({ conduitPath, error: message }, "T310 migration: failed to create conduit.db");
|
|
103039
103047
|
result.errors.push({ step: "step-7-create-conduit", error: message });
|
|
103040
103048
|
result.status = "failed";
|
|
103041
103049
|
legacy.close();
|
|
@@ -103081,7 +103089,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103081
103089
|
result.agentsCopied = agentsCountForConduit;
|
|
103082
103090
|
} catch (err) {
|
|
103083
103091
|
const message = err instanceof Error ? err.message : String(err);
|
|
103084
|
-
|
|
103092
|
+
log12.error({ error: message }, "T310 migration: conduit.db write failed \u2014 rolling back");
|
|
103085
103093
|
result.errors.push({ step: "step-8-conduit-write", error: message });
|
|
103086
103094
|
result.status = "failed";
|
|
103087
103095
|
try {
|
|
@@ -103102,7 +103110,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103102
103110
|
try {
|
|
103103
103111
|
if (!integrityCheckPasses(conduit)) {
|
|
103104
103112
|
const msg = "conduit.db failed PRAGMA integrity_check after write";
|
|
103105
|
-
|
|
103113
|
+
log12.error({ conduitPath }, msg);
|
|
103106
103114
|
result.errors.push({ step: "step-10-conduit-integrity", error: msg });
|
|
103107
103115
|
result.status = "failed";
|
|
103108
103116
|
conduit.close();
|
|
@@ -103117,7 +103125,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103117
103125
|
}
|
|
103118
103126
|
} catch (err) {
|
|
103119
103127
|
const message = err instanceof Error ? err.message : String(err);
|
|
103120
|
-
|
|
103128
|
+
log12.error({ error: message }, "T310 migration: conduit.db integrity_check threw");
|
|
103121
103129
|
result.errors.push({ step: "step-10-conduit-integrity", error: message });
|
|
103122
103130
|
result.status = "failed";
|
|
103123
103131
|
if (conduit) {
|
|
@@ -103139,7 +103147,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103139
103147
|
globalDb.exec("PRAGMA foreign_keys = OFF");
|
|
103140
103148
|
} catch (err) {
|
|
103141
103149
|
const message = err instanceof Error ? err.message : String(err);
|
|
103142
|
-
|
|
103150
|
+
log12.error(
|
|
103143
103151
|
{ globalSignaldockPath, error: message },
|
|
103144
103152
|
"T310 migration: cannot open global signaldock.db"
|
|
103145
103153
|
);
|
|
@@ -103178,7 +103186,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103178
103186
|
result.agentsCopied = agentsCopiedToGlobal;
|
|
103179
103187
|
} catch (err) {
|
|
103180
103188
|
const message = err instanceof Error ? err.message : String(err);
|
|
103181
|
-
|
|
103189
|
+
log12.error(
|
|
103182
103190
|
{ error: message },
|
|
103183
103191
|
"T310 migration: global signaldock.db write failed \u2014 rolling back"
|
|
103184
103192
|
);
|
|
@@ -103196,7 +103204,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103196
103204
|
try {
|
|
103197
103205
|
if (!integrityCheckPasses(globalDb)) {
|
|
103198
103206
|
const msg = "Global signaldock.db failed PRAGMA integrity_check after write";
|
|
103199
|
-
|
|
103207
|
+
log12.error({ globalSignaldockPath }, msg);
|
|
103200
103208
|
result.errors.push({ step: "step-14-global-integrity", error: msg });
|
|
103201
103209
|
result.status = "failed";
|
|
103202
103210
|
globalDb.close();
|
|
@@ -103211,7 +103219,7 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103211
103219
|
}
|
|
103212
103220
|
} catch (err) {
|
|
103213
103221
|
const message = err instanceof Error ? err.message : String(err);
|
|
103214
|
-
|
|
103222
|
+
log12.error({ error: message }, "T310 migration: global signaldock.db integrity_check threw");
|
|
103215
103223
|
result.errors.push({ step: "step-14-global-integrity", error: message });
|
|
103216
103224
|
result.status = "failed";
|
|
103217
103225
|
if (globalDb) {
|
|
@@ -103230,21 +103238,21 @@ function migrateSignaldockToConduit(projectRoot) {
|
|
|
103230
103238
|
result.bakPath = bakPath;
|
|
103231
103239
|
} catch (err) {
|
|
103232
103240
|
const message = err instanceof Error ? err.message : String(err);
|
|
103233
|
-
|
|
103241
|
+
log12.error(
|
|
103234
103242
|
{ legacyPath, bakPath, error: message },
|
|
103235
103243
|
"T310 migration: rename to .pre-t310.bak failed \u2014 legacy file left in place (harmless)"
|
|
103236
103244
|
);
|
|
103237
103245
|
result.errors.push({ step: "step-16-rename-bak", error: message });
|
|
103238
103246
|
}
|
|
103239
|
-
|
|
103247
|
+
log12.info(
|
|
103240
103248
|
{ projectRoot, agentsCopied: result.agentsCopied, conduitPath, bakPath: result.bakPath },
|
|
103241
103249
|
`T310 migration complete: ${result.agentsCopied} agents migrated to global, conduit.db created`
|
|
103242
103250
|
);
|
|
103243
|
-
|
|
103251
|
+
log12.warn(
|
|
103244
103252
|
{},
|
|
103245
103253
|
"T310 migration: API keys have been re-keyed. External systems holding old API keys (CI env vars, remote agent configs) must be updated."
|
|
103246
103254
|
);
|
|
103247
|
-
|
|
103255
|
+
log12.info(
|
|
103248
103256
|
{ legacyPath, bakPath: result.bakPath, conduitPath },
|
|
103249
103257
|
"T310 migration recovery: if problems occur, rename .pre-t310.bak to signaldock.db and delete conduit.db to re-run migration."
|
|
103250
103258
|
);
|