@cleocode/cleo 2026.4.91 → 2026.4.92
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 +184 -64
- package/dist/cli/index.js.map +3 -3
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -12424,26 +12424,67 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
|
|
|
12424
12424
|
const journaledHashes = new Set(journalEntries.map((e) => e.hash));
|
|
12425
12425
|
for (const migration of localMigrations) {
|
|
12426
12426
|
if (journaledHashes.has(migration.hash)) continue;
|
|
12427
|
-
const alterColumnRegex = /ALTER\s+TABLE\s+[`"]?(\w+)[`"]?\s+ADD\s+COLUMN\s+[`"]?(\w+)[`"]
|
|
12427
|
+
const alterColumnRegex = /ALTER\s+TABLE\s+[`"]?(\w+)[`"]?\s+ADD\s+COLUMN\s+[`"]?(\w+)[`"]?\s*(.*?)(?:;|$)/gi;
|
|
12428
12428
|
const alterMatches = [];
|
|
12429
12429
|
const sqlStatements = Array.isArray(migration.sql) ? migration.sql : [migration.sql ?? ""];
|
|
12430
12430
|
const fullSql = sqlStatements.join("\n");
|
|
12431
12431
|
for (const m2 of fullSql.matchAll(alterColumnRegex)) {
|
|
12432
|
-
alterMatches.push({
|
|
12432
|
+
alterMatches.push({
|
|
12433
|
+
table: m2[1],
|
|
12434
|
+
column: m2[2],
|
|
12435
|
+
ddl: (m2[3] || "").trim()
|
|
12436
|
+
});
|
|
12433
12437
|
}
|
|
12434
12438
|
if (alterMatches.length === 0) continue;
|
|
12435
|
-
const
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12439
|
+
const existingColumns = [];
|
|
12440
|
+
const missingColumns = [];
|
|
12441
|
+
for (const target of alterMatches) {
|
|
12442
|
+
if (!tableExists(nativeDb, target.table)) {
|
|
12443
|
+
missingColumns.push(target);
|
|
12444
|
+
continue;
|
|
12445
|
+
}
|
|
12446
|
+
const cols = nativeDb.prepare(`PRAGMA table_info(${target.table})`).all();
|
|
12447
|
+
if (cols.some((c) => c.name === target.column)) {
|
|
12448
|
+
existingColumns.push(target);
|
|
12449
|
+
} else {
|
|
12450
|
+
missingColumns.push(target);
|
|
12451
|
+
}
|
|
12452
|
+
}
|
|
12453
|
+
if (missingColumns.length === 0) {
|
|
12441
12454
|
const log15 = getLogger(logSubsystem);
|
|
12442
12455
|
log15.warn(
|
|
12443
12456
|
{ migration: migration.name, columns: alterMatches },
|
|
12444
12457
|
`Detected partially-applied migration ${migration.name} \u2014 columns exist but journal entry missing. Auto-reconciling.`
|
|
12445
12458
|
);
|
|
12446
12459
|
insertJournalEntry(nativeDb, migration.hash, migration.folderMillis, migration.name ?? "");
|
|
12460
|
+
continue;
|
|
12461
|
+
}
|
|
12462
|
+
if (existingColumns.length > 0 && missingColumns.length > 0) {
|
|
12463
|
+
const log15 = getLogger(logSubsystem);
|
|
12464
|
+
log15.warn(
|
|
12465
|
+
{
|
|
12466
|
+
migration: migration.name,
|
|
12467
|
+
existingColumns: existingColumns.map((c) => `${c.table}.${c.column}`),
|
|
12468
|
+
missingColumns: missingColumns.map((c) => `${c.table}.${c.column}`)
|
|
12469
|
+
},
|
|
12470
|
+
`T920: Detected partial migration ${migration.name} \u2014 some ALTER columns exist, some missing. Adding missing columns and marking applied.`
|
|
12471
|
+
);
|
|
12472
|
+
for (const { table, column, ddl } of missingColumns) {
|
|
12473
|
+
if (!tableExists(nativeDb, table)) continue;
|
|
12474
|
+
try {
|
|
12475
|
+
nativeDb.exec(`ALTER TABLE ${table} ADD COLUMN ${column}${ddl ? ` ${ddl}` : ""}`);
|
|
12476
|
+
log15.warn(
|
|
12477
|
+
{ migration: migration.name, table, column },
|
|
12478
|
+
`T920: Added missing column ${table}.${column} to complete partial migration.`
|
|
12479
|
+
);
|
|
12480
|
+
} catch {
|
|
12481
|
+
log15.warn(
|
|
12482
|
+
{ migration: migration.name, table, column },
|
|
12483
|
+
`T920: Could not add missing column ${table}.${column} \u2014 will let Drizzle migrate() handle it.`
|
|
12484
|
+
);
|
|
12485
|
+
}
|
|
12486
|
+
}
|
|
12487
|
+
insertJournalEntry(nativeDb, migration.hash, migration.folderMillis, migration.name ?? "");
|
|
12447
12488
|
}
|
|
12448
12489
|
}
|
|
12449
12490
|
}
|
|
@@ -74223,10 +74264,10 @@ async function execCommand(command, dryRun) {
|
|
|
74223
74264
|
return { success: true, output: `[DRY RUN] Would execute: ${command}`, dryRun: true };
|
|
74224
74265
|
}
|
|
74225
74266
|
try {
|
|
74226
|
-
const { stdout
|
|
74267
|
+
const { stdout, stderr: stderr2 } = await execFileAsync4("sh", ["-c", command], {
|
|
74227
74268
|
timeout: 3e5
|
|
74228
74269
|
});
|
|
74229
|
-
return { success: true, output: (
|
|
74270
|
+
return { success: true, output: (stdout + stderr2).trim(), dryRun: false };
|
|
74230
74271
|
} catch (err) {
|
|
74231
74272
|
const message = err instanceof Error ? err.message : String(err);
|
|
74232
74273
|
return { success: false, output: message, dryRun: false };
|
|
@@ -86020,20 +86061,37 @@ async function pathExists(p2) {
|
|
|
86020
86061
|
return false;
|
|
86021
86062
|
}
|
|
86022
86063
|
}
|
|
86023
|
-
async function probeJsonFile(path12) {
|
|
86064
|
+
async function probeJsonFile(path12, expectedVersion) {
|
|
86024
86065
|
if (!await pathExists(path12)) {
|
|
86025
|
-
|
|
86066
|
+
const base = { exists: false, parseable: false, error: "File not found" };
|
|
86067
|
+
if (expectedVersion !== void 0) {
|
|
86068
|
+
base.expectedVersion = expectedVersion;
|
|
86069
|
+
base.schemaDrift = false;
|
|
86070
|
+
}
|
|
86071
|
+
return base;
|
|
86026
86072
|
}
|
|
86027
86073
|
try {
|
|
86028
86074
|
const raw = await readFile17(path12, "utf-8");
|
|
86029
|
-
JSON.parse(raw);
|
|
86030
|
-
|
|
86075
|
+
const parsed = JSON.parse(raw);
|
|
86076
|
+
const rawVersion = parsed["schemaVersion"] ?? parsed["version"];
|
|
86077
|
+
const schemaVersion = typeof rawVersion === "string" ? rawVersion : void 0;
|
|
86078
|
+
const result = { exists: true, parseable: true, schemaVersion };
|
|
86079
|
+
if (expectedVersion !== void 0) {
|
|
86080
|
+
result.expectedVersion = expectedVersion;
|
|
86081
|
+
result.schemaDrift = schemaVersion !== void 0 && schemaVersion !== expectedVersion;
|
|
86082
|
+
}
|
|
86083
|
+
return result;
|
|
86031
86084
|
} catch (err) {
|
|
86032
|
-
|
|
86085
|
+
const result = {
|
|
86033
86086
|
exists: true,
|
|
86034
86087
|
parseable: false,
|
|
86035
86088
|
error: err instanceof Error ? err.message : String(err)
|
|
86036
86089
|
};
|
|
86090
|
+
if (expectedVersion !== void 0) {
|
|
86091
|
+
result.expectedVersion = expectedVersion;
|
|
86092
|
+
result.schemaDrift = false;
|
|
86093
|
+
}
|
|
86094
|
+
return result;
|
|
86037
86095
|
}
|
|
86038
86096
|
}
|
|
86039
86097
|
async function runWithConcurrency(items, limit, worker) {
|
|
@@ -86061,11 +86119,13 @@ function deriveOverallStatus(reachable, cleoDirExists, dbs, files) {
|
|
|
86061
86119
|
if (!cleoDirExists) return "unknown";
|
|
86062
86120
|
const dbProbes = [dbs.tasks, dbs.brain, dbs.conduit];
|
|
86063
86121
|
const degradedDb = dbProbes.some(
|
|
86064
|
-
(d) => d.exists && (!d.integrityOk || !d.walSidecarClean || !d.sqliteOpenable)
|
|
86122
|
+
(d) => d.exists && (!d.integrityOk || !d.walSidecarClean || !d.sqliteOpenable || d.schemaDrift === true)
|
|
86065
86123
|
);
|
|
86066
86124
|
const configBroken = files.config.exists && !files.config.parseable;
|
|
86067
86125
|
const infoBroken = files.projectInfo.exists && !files.projectInfo.parseable;
|
|
86068
|
-
|
|
86126
|
+
const configDrifted = files.config.schemaDrift === true;
|
|
86127
|
+
const infoDrifted = files.projectInfo.schemaDrift === true;
|
|
86128
|
+
if (degradedDb || configBroken || infoBroken || configDrifted || infoDrifted) return "degraded";
|
|
86069
86129
|
if (!dbs.tasks.exists) return "unknown";
|
|
86070
86130
|
return "healthy";
|
|
86071
86131
|
}
|
|
@@ -86086,13 +86146,25 @@ function collectProjectIssues(report) {
|
|
|
86086
86146
|
issues.push(`${label}: integrity_check failed`);
|
|
86087
86147
|
} else if (probe.exists && !probe.walSidecarClean) {
|
|
86088
86148
|
issues.push(`${label}: WAL sidecar conflict`);
|
|
86149
|
+
} else if (probe.schemaDrift === true) {
|
|
86150
|
+
issues.push(
|
|
86151
|
+
`${label}: schema drift (migrationCount=${probe.migrationCount ?? "?"} < expected=${probe.expectedVersion ?? "?"})`
|
|
86152
|
+
);
|
|
86089
86153
|
}
|
|
86090
86154
|
}
|
|
86091
86155
|
if (report.files.config.exists && !report.files.config.parseable) {
|
|
86092
86156
|
issues.push(`config.json: ${report.files.config.error ?? "parse error"}`);
|
|
86157
|
+
} else if (report.files.config.schemaDrift === true) {
|
|
86158
|
+
issues.push(
|
|
86159
|
+
`config.json: schema drift (version=${report.files.config.schemaVersion ?? "?"} != expected=${report.files.config.expectedVersion ?? "?"})`
|
|
86160
|
+
);
|
|
86093
86161
|
}
|
|
86094
86162
|
if (report.files.projectInfo.exists && !report.files.projectInfo.parseable) {
|
|
86095
86163
|
issues.push(`project-info.json: ${report.files.projectInfo.error ?? "parse error"}`);
|
|
86164
|
+
} else if (report.files.projectInfo.schemaDrift === true) {
|
|
86165
|
+
issues.push(
|
|
86166
|
+
`project-info.json: schema drift (version=${report.files.projectInfo.schemaVersion ?? "?"} != expected=${report.files.projectInfo.expectedVersion ?? "?"})`
|
|
86167
|
+
);
|
|
86096
86168
|
}
|
|
86097
86169
|
return issues;
|
|
86098
86170
|
}
|
|
@@ -86112,6 +86184,10 @@ function collectGlobalIssues(dbs) {
|
|
|
86112
86184
|
issues.push(`${label}: integrity_check failed`);
|
|
86113
86185
|
} else if (!probe.walSidecarClean) {
|
|
86114
86186
|
issues.push(`${label}: WAL sidecar conflict`);
|
|
86187
|
+
} else if (probe.schemaDrift === true) {
|
|
86188
|
+
issues.push(
|
|
86189
|
+
`${label}: schema drift (migrationCount=${probe.migrationCount ?? "?"} < expected=${probe.expectedVersion ?? "?"})`
|
|
86190
|
+
);
|
|
86115
86191
|
}
|
|
86116
86192
|
}
|
|
86117
86193
|
return issues;
|
|
@@ -86120,11 +86196,11 @@ function deriveGlobalStatus(dbs) {
|
|
|
86120
86196
|
const probes = [dbs.nexus, dbs.signaldock];
|
|
86121
86197
|
if (probes.every((p2) => !p2.exists)) return "unknown";
|
|
86122
86198
|
const degraded = probes.some(
|
|
86123
|
-
(p2) => p2.exists && (!p2.integrityOk || !p2.walSidecarClean || !p2.sqliteOpenable)
|
|
86199
|
+
(p2) => p2.exists && (!p2.integrityOk || !p2.walSidecarClean || !p2.sqliteOpenable || p2.schemaDrift === true)
|
|
86124
86200
|
);
|
|
86125
86201
|
return degraded ? "degraded" : "healthy";
|
|
86126
86202
|
}
|
|
86127
|
-
async function probeDb(dbPath) {
|
|
86203
|
+
async function probeDb(dbPath, expectedVersion) {
|
|
86128
86204
|
const result = {
|
|
86129
86205
|
path: dbPath,
|
|
86130
86206
|
exists: false,
|
|
@@ -86134,10 +86210,14 @@ async function probeDb(dbPath) {
|
|
|
86134
86210
|
walSidecarClean: true,
|
|
86135
86211
|
sizeBytes: -1
|
|
86136
86212
|
};
|
|
86213
|
+
if (expectedVersion !== void 0) {
|
|
86214
|
+
result.expectedVersion = expectedVersion;
|
|
86215
|
+
}
|
|
86137
86216
|
const exists3 = await pathExists(dbPath);
|
|
86138
86217
|
result.exists = exists3;
|
|
86139
86218
|
if (!exists3) {
|
|
86140
86219
|
result.error = "File not found";
|
|
86220
|
+
if (expectedVersion !== void 0) result.schemaDrift = false;
|
|
86141
86221
|
return result;
|
|
86142
86222
|
}
|
|
86143
86223
|
try {
|
|
@@ -86145,6 +86225,7 @@ async function probeDb(dbPath) {
|
|
|
86145
86225
|
result.readable = true;
|
|
86146
86226
|
} catch (err) {
|
|
86147
86227
|
result.error = err instanceof Error ? err.message : String(err);
|
|
86228
|
+
if (expectedVersion !== void 0) result.schemaDrift = false;
|
|
86148
86229
|
return result;
|
|
86149
86230
|
}
|
|
86150
86231
|
try {
|
|
@@ -86159,6 +86240,7 @@ async function probeDb(dbPath) {
|
|
|
86159
86240
|
if (!DatabaseSyncCtor) {
|
|
86160
86241
|
result.error = "node:sqlite runtime not available";
|
|
86161
86242
|
result.walSidecarClean = !walExists;
|
|
86243
|
+
if (expectedVersion !== void 0) result.schemaDrift = false;
|
|
86162
86244
|
return result;
|
|
86163
86245
|
}
|
|
86164
86246
|
let db = null;
|
|
@@ -86182,11 +86264,30 @@ async function probeDb(dbPath) {
|
|
|
86182
86264
|
}
|
|
86183
86265
|
} catch {
|
|
86184
86266
|
}
|
|
86267
|
+
try {
|
|
86268
|
+
const tables = db.prepare(
|
|
86269
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name IN ('__drizzle_migrations','_conduit_migrations')"
|
|
86270
|
+
).all();
|
|
86271
|
+
const migrationTable = tables.find(
|
|
86272
|
+
(t) => t.name === "__drizzle_migrations" || t.name === "_conduit_migrations"
|
|
86273
|
+
);
|
|
86274
|
+
if (migrationTable) {
|
|
86275
|
+
const countRow = db.prepare(`SELECT COUNT(*) AS c FROM "${migrationTable.name}"`).get();
|
|
86276
|
+
if (typeof countRow?.c === "number") {
|
|
86277
|
+
result.migrationCount = countRow.c;
|
|
86278
|
+
}
|
|
86279
|
+
}
|
|
86280
|
+
} catch {
|
|
86281
|
+
}
|
|
86282
|
+
if (expectedVersion !== void 0) {
|
|
86283
|
+
result.schemaDrift = result.migrationCount !== void 0 && result.migrationCount < expectedVersion;
|
|
86284
|
+
}
|
|
86185
86285
|
result.walSidecarClean = true;
|
|
86186
86286
|
} catch (err) {
|
|
86187
86287
|
result.sqliteOpenable = false;
|
|
86188
86288
|
result.error = err instanceof Error ? err.message : String(err);
|
|
86189
86289
|
result.walSidecarClean = !walExists;
|
|
86290
|
+
if (expectedVersion !== void 0) result.schemaDrift = false;
|
|
86190
86291
|
} finally {
|
|
86191
86292
|
try {
|
|
86192
86293
|
db?.close();
|
|
@@ -86238,11 +86339,11 @@ async function checkProjectHealth(projectPath, projectHash) {
|
|
|
86238
86339
|
const cleoDir = getCleoDirAbsolute(projectPath);
|
|
86239
86340
|
const cleoDirExists = await pathExists(cleoDir);
|
|
86240
86341
|
const [tasks2, brain, conduit, configProbe, infoProbe] = await Promise.all([
|
|
86241
|
-
probeDb(join103(cleoDir, TASKS_DB)),
|
|
86242
|
-
probeDb(join103(cleoDir, BRAIN_DB)),
|
|
86243
|
-
probeDb(join103(cleoDir, CONDUIT_DB)),
|
|
86244
|
-
probeJsonFile(join103(cleoDir, CONFIG_JSON)),
|
|
86245
|
-
probeJsonFile(join103(cleoDir, PROJECT_INFO_JSON))
|
|
86342
|
+
probeDb(join103(cleoDir, TASKS_DB), DB_EXPECTED_VERSIONS[TASKS_DB]),
|
|
86343
|
+
probeDb(join103(cleoDir, BRAIN_DB), DB_EXPECTED_VERSIONS[BRAIN_DB]),
|
|
86344
|
+
probeDb(join103(cleoDir, CONDUIT_DB), DB_EXPECTED_VERSIONS[CONDUIT_DB]),
|
|
86345
|
+
probeJsonFile(join103(cleoDir, CONFIG_JSON), JSON_EXPECTED_VERSIONS[CONFIG_JSON]),
|
|
86346
|
+
probeJsonFile(join103(cleoDir, PROJECT_INFO_JSON), JSON_EXPECTED_VERSIONS[PROJECT_INFO_JSON])
|
|
86246
86347
|
]);
|
|
86247
86348
|
const base = {
|
|
86248
86349
|
projectHash,
|
|
@@ -86261,8 +86362,8 @@ async function checkProjectHealth(projectPath, projectHash) {
|
|
|
86261
86362
|
async function checkGlobalHealth() {
|
|
86262
86363
|
const cleoHome = getCleoHome();
|
|
86263
86364
|
const [nexus, signaldock] = await Promise.all([
|
|
86264
|
-
probeDb(join103(cleoHome, NEXUS_DB)),
|
|
86265
|
-
probeDb(join103(cleoHome, SIGNALDOCK_DB))
|
|
86365
|
+
probeDb(join103(cleoHome, NEXUS_DB), DB_EXPECTED_VERSIONS[NEXUS_DB]),
|
|
86366
|
+
probeDb(join103(cleoHome, SIGNALDOCK_DB), DB_EXPECTED_VERSIONS[SIGNALDOCK_DB])
|
|
86266
86367
|
]);
|
|
86267
86368
|
const dbs = { nexus, signaldock };
|
|
86268
86369
|
return {
|
|
@@ -86358,7 +86459,7 @@ async function writeHealthBack(reports, log15) {
|
|
|
86358
86459
|
log15.warn({ err }, "project-health: could not open nexus.db for write-back");
|
|
86359
86460
|
}
|
|
86360
86461
|
}
|
|
86361
|
-
var _require14, _databaseSyncCtor, TASKS_DB, BRAIN_DB, CONDUIT_DB, NEXUS_DB, SIGNALDOCK_DB, CONFIG_JSON, PROJECT_INFO_JSON;
|
|
86462
|
+
var _require14, _databaseSyncCtor, TASKS_DB, BRAIN_DB, CONDUIT_DB, NEXUS_DB, SIGNALDOCK_DB, CONFIG_JSON, PROJECT_INFO_JSON, DB_EXPECTED_VERSIONS, JSON_EXPECTED_VERSIONS;
|
|
86362
86463
|
var init_project_health = __esm({
|
|
86363
86464
|
"packages/core/src/system/project-health.ts"() {
|
|
86364
86465
|
"use strict";
|
|
@@ -86372,6 +86473,17 @@ var init_project_health = __esm({
|
|
|
86372
86473
|
SIGNALDOCK_DB = "signaldock.db";
|
|
86373
86474
|
CONFIG_JSON = "config.json";
|
|
86374
86475
|
PROJECT_INFO_JSON = "project-info.json";
|
|
86476
|
+
DB_EXPECTED_VERSIONS = {
|
|
86477
|
+
[TASKS_DB]: 11,
|
|
86478
|
+
[BRAIN_DB]: 14,
|
|
86479
|
+
[NEXUS_DB]: 3,
|
|
86480
|
+
[SIGNALDOCK_DB]: 1,
|
|
86481
|
+
[CONDUIT_DB]: 1
|
|
86482
|
+
};
|
|
86483
|
+
JSON_EXPECTED_VERSIONS = {
|
|
86484
|
+
[CONFIG_JSON]: "2.10.0",
|
|
86485
|
+
[PROJECT_INFO_JSON]: "1.0.0"
|
|
86486
|
+
};
|
|
86375
86487
|
}
|
|
86376
86488
|
});
|
|
86377
86489
|
|
|
@@ -86459,8 +86571,8 @@ async function resolveBinaryPath(name2) {
|
|
|
86459
86571
|
const execFileAsync7 = promisify6(execFile6);
|
|
86460
86572
|
const resolver = process.platform === "win32" ? "where" : "which";
|
|
86461
86573
|
try {
|
|
86462
|
-
const { stdout
|
|
86463
|
-
const first =
|
|
86574
|
+
const { stdout } = await execFileAsync7(resolver, [name2]);
|
|
86575
|
+
const first = stdout.trim().split(/\r?\n/)[0] ?? "";
|
|
86464
86576
|
return first || null;
|
|
86465
86577
|
} catch {
|
|
86466
86578
|
return null;
|
|
@@ -87218,20 +87330,20 @@ async function revalidateEvidence(evidence, projectRoot) {
|
|
|
87218
87330
|
}
|
|
87219
87331
|
function runCommand(cmd, args, cwd) {
|
|
87220
87332
|
return new Promise((resolve20) => {
|
|
87221
|
-
let
|
|
87333
|
+
let stdout = "";
|
|
87222
87334
|
let stderr2 = "";
|
|
87223
87335
|
const child = spawn2(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
87224
87336
|
child.stdout?.on("data", (d) => {
|
|
87225
|
-
|
|
87337
|
+
stdout += d.toString("utf-8");
|
|
87226
87338
|
});
|
|
87227
87339
|
child.stderr?.on("data", (d) => {
|
|
87228
87340
|
stderr2 += d.toString("utf-8");
|
|
87229
87341
|
});
|
|
87230
87342
|
child.on("error", () => {
|
|
87231
|
-
resolve20({ exitCode: null, stdout
|
|
87343
|
+
resolve20({ exitCode: null, stdout, stderr: stderr2 });
|
|
87232
87344
|
});
|
|
87233
87345
|
child.on("close", (code) => {
|
|
87234
|
-
resolve20({ exitCode: code, stdout
|
|
87346
|
+
resolve20({ exitCode: code, stdout, stderr: stderr2 });
|
|
87235
87347
|
});
|
|
87236
87348
|
});
|
|
87237
87349
|
}
|
|
@@ -95622,7 +95734,7 @@ async function runTestGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95622
95734
|
const cwd = resolveCwd(projectRoot, gate.cwd);
|
|
95623
95735
|
const [bin, ...defaultArgs] = gate.command.split(" ");
|
|
95624
95736
|
const args = gate.args ?? defaultArgs;
|
|
95625
|
-
let
|
|
95737
|
+
let stdout = "";
|
|
95626
95738
|
let stderr2 = "";
|
|
95627
95739
|
let exitCode = 0;
|
|
95628
95740
|
let timedOut = false;
|
|
@@ -95632,11 +95744,11 @@ async function runTestGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95632
95744
|
env: { ...process.env, ...gate.env },
|
|
95633
95745
|
timeout: timeoutMs
|
|
95634
95746
|
});
|
|
95635
|
-
|
|
95747
|
+
stdout = out.stdout;
|
|
95636
95748
|
stderr2 = out.stderr;
|
|
95637
95749
|
} catch (err) {
|
|
95638
95750
|
const e = err;
|
|
95639
|
-
|
|
95751
|
+
stdout = e.stdout ?? "";
|
|
95640
95752
|
stderr2 = e.stderr ?? "";
|
|
95641
95753
|
exitCode = typeof e.status === "number" ? e.status : 1;
|
|
95642
95754
|
if (e.killed || e.code === "ETIMEDOUT") {
|
|
@@ -95644,7 +95756,7 @@ async function runTestGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95644
95756
|
}
|
|
95645
95757
|
}
|
|
95646
95758
|
const durationMs = Date.now() - startMs;
|
|
95647
|
-
const combined = truncate(`${
|
|
95759
|
+
const combined = truncate(`${stdout}
|
|
95648
95760
|
${stderr2}`.trim(), MAX_EVIDENCE_BYTES);
|
|
95649
95761
|
if (timedOut) {
|
|
95650
95762
|
return makeResult(
|
|
@@ -95661,7 +95773,7 @@ ${stderr2}`.trim(), MAX_EVIDENCE_BYTES);
|
|
|
95661
95773
|
}
|
|
95662
95774
|
if (gate.expect === "pass") {
|
|
95663
95775
|
const failPattern = /\bFAIL\b|failing|Error:/i;
|
|
95664
|
-
if (failPattern.test(
|
|
95776
|
+
if (failPattern.test(stdout)) {
|
|
95665
95777
|
return makeResult(
|
|
95666
95778
|
index2,
|
|
95667
95779
|
gate,
|
|
@@ -95803,7 +95915,7 @@ async function runCommandGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95803
95915
|
const startMs = Date.now();
|
|
95804
95916
|
const cwd = resolveCwd(projectRoot, gate.cwd);
|
|
95805
95917
|
const expectedExitCode = gate.exitCode ?? 0;
|
|
95806
|
-
let
|
|
95918
|
+
let stdout = "";
|
|
95807
95919
|
let stderr2 = "";
|
|
95808
95920
|
let actualExitCode = 0;
|
|
95809
95921
|
let timedOut = false;
|
|
@@ -95813,11 +95925,11 @@ async function runCommandGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95813
95925
|
env: { ...process.env, ...gate.env },
|
|
95814
95926
|
timeout: timeoutMs
|
|
95815
95927
|
});
|
|
95816
|
-
|
|
95928
|
+
stdout = out.stdout;
|
|
95817
95929
|
stderr2 = out.stderr;
|
|
95818
95930
|
} catch (err) {
|
|
95819
95931
|
const e = err;
|
|
95820
|
-
|
|
95932
|
+
stdout = e.stdout ?? "";
|
|
95821
95933
|
stderr2 = e.stderr ?? "";
|
|
95822
95934
|
actualExitCode = typeof e.status === "number" ? e.status : 1;
|
|
95823
95935
|
if (e.killed || e.code === "ETIMEDOUT") {
|
|
@@ -95825,7 +95937,7 @@ async function runCommandGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95825
95937
|
}
|
|
95826
95938
|
}
|
|
95827
95939
|
const durationMs = Date.now() - startMs;
|
|
95828
|
-
const combined = truncate(`${
|
|
95940
|
+
const combined = truncate(`${stdout}
|
|
95829
95941
|
${stderr2}`.trim(), MAX_EVIDENCE_BYTES);
|
|
95830
95942
|
if (timedOut) {
|
|
95831
95943
|
return makeResult(
|
|
@@ -95849,7 +95961,7 @@ ${stderr2}`.trim(), MAX_EVIDENCE_BYTES);
|
|
|
95849
95961
|
}
|
|
95850
95962
|
if (gate.stdoutMatches) {
|
|
95851
95963
|
const re2 = new RegExp(gate.stdoutMatches);
|
|
95852
|
-
if (!re2.test(
|
|
95964
|
+
if (!re2.test(stdout)) {
|
|
95853
95965
|
return makeResult(
|
|
95854
95966
|
index2,
|
|
95855
95967
|
gate,
|
|
@@ -95880,17 +95992,17 @@ async function runLintGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95880
95992
|
const cwd = resolveCwd(projectRoot, gate.cwd);
|
|
95881
95993
|
const toolDef = LINT_TOOL_DEFAULTS[gate.tool];
|
|
95882
95994
|
const args = gate.args ?? toolDef.defaultArgs;
|
|
95883
|
-
let
|
|
95995
|
+
let stdout = "";
|
|
95884
95996
|
let stderr2 = "";
|
|
95885
95997
|
let exitCode = 0;
|
|
95886
95998
|
let timedOut = false;
|
|
95887
95999
|
try {
|
|
95888
96000
|
const out = await execFileAsync6(toolDef.cmd, args, { cwd, timeout: timeoutMs });
|
|
95889
|
-
|
|
96001
|
+
stdout = out.stdout;
|
|
95890
96002
|
stderr2 = out.stderr;
|
|
95891
96003
|
} catch (err) {
|
|
95892
96004
|
const e = err;
|
|
95893
|
-
|
|
96005
|
+
stdout = e.stdout ?? "";
|
|
95894
96006
|
stderr2 = e.stderr ?? "";
|
|
95895
96007
|
exitCode = typeof e.status === "number" ? e.status : 1;
|
|
95896
96008
|
if (e.killed || e.code === "ETIMEDOUT") {
|
|
@@ -95898,7 +96010,7 @@ async function runLintGate(gate, index2, projectRoot, timeoutMs) {
|
|
|
95898
96010
|
}
|
|
95899
96011
|
}
|
|
95900
96012
|
const durationMs = Date.now() - startMs;
|
|
95901
|
-
const combined = truncate(`${
|
|
96013
|
+
const combined = truncate(`${stdout}
|
|
95902
96014
|
${stderr2}`.trim(), MAX_EVIDENCE_BYTES);
|
|
95903
96015
|
if (timedOut) {
|
|
95904
96016
|
return makeResult(
|
|
@@ -132636,6 +132748,9 @@ Or set CLEO_OWNER_OVERRIDE=1 with CLEO_OWNER_OVERRIDE_REASON=<reason> for emerge
|
|
|
132636
132748
|
result.evidenceStored = evidenceStored;
|
|
132637
132749
|
result.override = override.override;
|
|
132638
132750
|
}
|
|
132751
|
+
if ((action === "set_gate" || action === "set_all") && verification.passed === true && missing.length === 0) {
|
|
132752
|
+
result.hint = `All gates green. Run: cleo complete ${taskId}`;
|
|
132753
|
+
}
|
|
132639
132754
|
return { success: true, data: result };
|
|
132640
132755
|
} catch (err) {
|
|
132641
132756
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -144847,11 +144962,11 @@ var workCommand = defineCommand({
|
|
|
144847
144962
|
}
|
|
144848
144963
|
};
|
|
144849
144964
|
const runCleo = async (cleoArgs, timeoutMs = 15e3) => {
|
|
144850
|
-
const { stdout
|
|
144965
|
+
const { stdout } = await execFileAsync7("cleo", cleoArgs, {
|
|
144851
144966
|
encoding: "utf-8",
|
|
144852
144967
|
timeout: timeoutMs
|
|
144853
144968
|
});
|
|
144854
|
-
return
|
|
144969
|
+
return stdout;
|
|
144855
144970
|
};
|
|
144856
144971
|
const taskInterval = Number.parseInt(args["poll-interval"], 10);
|
|
144857
144972
|
let inFlight = false;
|
|
@@ -150059,8 +150174,8 @@ function checkDiskSpace(directoryPath, dependencies = {
|
|
|
150059
150174
|
pathSep: sep2,
|
|
150060
150175
|
cpExecFile: promisify8(execFile8)
|
|
150061
150176
|
}) {
|
|
150062
|
-
function mapOutput(
|
|
150063
|
-
const parsed =
|
|
150177
|
+
function mapOutput(stdout, filter, mapping, coefficient) {
|
|
150178
|
+
const parsed = stdout.split("\n").map((line2) => line2.trim()).filter((line2) => line2.length !== 0).slice(1).map((line2) => line2.split(/\s+(?=[\d/])/));
|
|
150064
150179
|
const filtered = parsed.filter(filter);
|
|
150065
150180
|
if (filtered.length === 0) {
|
|
150066
150181
|
throw new NoMatchError();
|
|
@@ -150078,8 +150193,8 @@ function checkDiskSpace(directoryPath, dependencies = {
|
|
|
150078
150193
|
return Promise.reject(new Error("cmd must contain at least one item"));
|
|
150079
150194
|
}
|
|
150080
150195
|
try {
|
|
150081
|
-
const { stdout
|
|
150082
|
-
return mapOutput(
|
|
150196
|
+
const { stdout } = await dependencies.cpExecFile(file2, args, { windowsHide: true });
|
|
150197
|
+
return mapOutput(stdout, filter, mapping, coefficient);
|
|
150083
150198
|
} catch (error48) {
|
|
150084
150199
|
return Promise.reject(error48);
|
|
150085
150200
|
}
|
|
@@ -151771,7 +151886,7 @@ var docsCommand = defineCommand({
|
|
|
151771
151886
|
init_cli();
|
|
151772
151887
|
|
|
151773
151888
|
// packages/cleo/src/cli/progress.ts
|
|
151774
|
-
import { stderr
|
|
151889
|
+
import { stderr } from "node:process";
|
|
151775
151890
|
var ProgressTracker = class {
|
|
151776
151891
|
enabled;
|
|
151777
151892
|
prefix;
|
|
@@ -151813,16 +151928,21 @@ ${this.prefix}: Starting...
|
|
|
151813
151928
|
}
|
|
151814
151929
|
/**
|
|
151815
151930
|
* Mark as complete with optional summary.
|
|
151931
|
+
*
|
|
151932
|
+
* @remarks
|
|
151933
|
+
* Writes to stderr (not stdout) so that progress messages never pollute
|
|
151934
|
+
* the machine-readable JSON envelope on stdout. Stdout MUST contain exactly
|
|
151935
|
+
* one JSON object per CLI invocation (ADR-039 / T927).
|
|
151816
151936
|
*/
|
|
151817
151937
|
complete(summary) {
|
|
151818
151938
|
if (!this.enabled) return;
|
|
151819
151939
|
if (summary) {
|
|
151820
|
-
|
|
151940
|
+
stderr.write(`
|
|
151821
151941
|
${this.prefix}: \u2713 ${summary}
|
|
151822
151942
|
|
|
151823
151943
|
`);
|
|
151824
151944
|
} else {
|
|
151825
|
-
|
|
151945
|
+
stderr.write(`
|
|
151826
151946
|
${this.prefix}: \u2713 Complete
|
|
151827
151947
|
|
|
151828
151948
|
`);
|
|
@@ -158495,11 +158615,11 @@ var diffCommand = defineCommand({
|
|
|
158495
158615
|
const execFileAsync7 = promisify10(execFileNode);
|
|
158496
158616
|
const resolveSha = async (ref) => {
|
|
158497
158617
|
try {
|
|
158498
|
-
const { stdout
|
|
158618
|
+
const { stdout } = await execFileAsync7("git", ["rev-parse", "--short", ref], {
|
|
158499
158619
|
timeout: 5e3,
|
|
158500
158620
|
cwd: repoPath
|
|
158501
158621
|
});
|
|
158502
|
-
return
|
|
158622
|
+
return stdout.trim();
|
|
158503
158623
|
} catch {
|
|
158504
158624
|
return ref;
|
|
158505
158625
|
}
|
|
@@ -161830,14 +161950,14 @@ async function getCurrentVersion() {
|
|
|
161830
161950
|
}
|
|
161831
161951
|
async function getNpmInstalledVersion() {
|
|
161832
161952
|
try {
|
|
161833
|
-
const { stdout
|
|
161953
|
+
const { stdout } = await execAsync("npm", [
|
|
161834
161954
|
"ls",
|
|
161835
161955
|
"-g",
|
|
161836
161956
|
"@cleocode/cleo",
|
|
161837
161957
|
"--depth=0",
|
|
161838
161958
|
"--json"
|
|
161839
161959
|
]);
|
|
161840
|
-
const data = JSON.parse(
|
|
161960
|
+
const data = JSON.parse(stdout);
|
|
161841
161961
|
return data.dependencies?.["@cleocode/cleo"]?.version ?? null;
|
|
161842
161962
|
} catch {
|
|
161843
161963
|
return null;
|
|
@@ -161845,19 +161965,19 @@ async function getNpmInstalledVersion() {
|
|
|
161845
161965
|
}
|
|
161846
161966
|
async function getDistTagVersion(tag) {
|
|
161847
161967
|
try {
|
|
161848
|
-
const { stdout
|
|
161849
|
-
const v2 =
|
|
161968
|
+
const { stdout } = await execAsync("npm", ["view", `@cleocode/cleo@${tag}`, "version"]);
|
|
161969
|
+
const v2 = stdout.trim();
|
|
161850
161970
|
return v2 || null;
|
|
161851
161971
|
} catch {
|
|
161852
161972
|
if (tag === "latest") {
|
|
161853
161973
|
try {
|
|
161854
|
-
const { stdout
|
|
161974
|
+
const { stdout } = await execAsync("curl", [
|
|
161855
161975
|
"-sL",
|
|
161856
161976
|
"--max-time",
|
|
161857
161977
|
"10",
|
|
161858
161978
|
`https://api.github.com/repos/${GITHUB_REPO}/releases/latest`
|
|
161859
161979
|
]);
|
|
161860
|
-
const data = JSON.parse(
|
|
161980
|
+
const data = JSON.parse(stdout);
|
|
161861
161981
|
return data.tag_name?.replace(/^v/, "") ?? null;
|
|
161862
161982
|
} catch {
|
|
161863
161983
|
return null;
|