@cleocode/cleo 2026.3.17 → 2026.3.19
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 +671 -358
- package/dist/cli/index.js.map +4 -4
- package/dist/mcp/index.js +473 -164
- package/dist/mcp/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1803,6 +1803,16 @@ var init_registry = __esm({
|
|
|
1803
1803
|
sessionRequired: false,
|
|
1804
1804
|
requiredParams: ["version"]
|
|
1805
1805
|
},
|
|
1806
|
+
{
|
|
1807
|
+
gateway: "query",
|
|
1808
|
+
domain: "pipeline",
|
|
1809
|
+
operation: "release.channel.show",
|
|
1810
|
+
description: "Show the current release channel based on git branch (latest/beta/alpha)",
|
|
1811
|
+
tier: 0,
|
|
1812
|
+
idempotent: true,
|
|
1813
|
+
sessionRequired: false,
|
|
1814
|
+
requiredParams: []
|
|
1815
|
+
},
|
|
1806
1816
|
{
|
|
1807
1817
|
gateway: "mutate",
|
|
1808
1818
|
domain: "pipeline",
|
|
@@ -1863,6 +1873,16 @@ var init_registry = __esm({
|
|
|
1863
1873
|
sessionRequired: false,
|
|
1864
1874
|
requiredParams: []
|
|
1865
1875
|
},
|
|
1876
|
+
{
|
|
1877
|
+
gateway: "mutate",
|
|
1878
|
+
domain: "pipeline",
|
|
1879
|
+
operation: "release.cancel",
|
|
1880
|
+
description: "pipeline.release.cancel (mutate)",
|
|
1881
|
+
tier: 0,
|
|
1882
|
+
idempotent: false,
|
|
1883
|
+
sessionRequired: false,
|
|
1884
|
+
requiredParams: ["version"]
|
|
1885
|
+
},
|
|
1866
1886
|
{
|
|
1867
1887
|
gateway: "mutate",
|
|
1868
1888
|
domain: "pipeline",
|
|
@@ -19690,10 +19710,10 @@ async function systemLog(projectRoot, filters) {
|
|
|
19690
19710
|
}
|
|
19691
19711
|
async function queryAuditLogSqlite(projectRoot, filters) {
|
|
19692
19712
|
try {
|
|
19693
|
-
const { join:
|
|
19694
|
-
const { existsSync:
|
|
19695
|
-
const dbPath =
|
|
19696
|
-
if (!
|
|
19713
|
+
const { join: join78 } = await import("node:path");
|
|
19714
|
+
const { existsSync: existsSync73 } = await import("node:fs");
|
|
19715
|
+
const dbPath = join78(projectRoot, ".cleo", "tasks.db");
|
|
19716
|
+
if (!existsSync73(dbPath)) {
|
|
19697
19717
|
const offset = filters?.offset ?? 0;
|
|
19698
19718
|
const limit = filters?.limit ?? 20;
|
|
19699
19719
|
return {
|
|
@@ -20549,10 +20569,10 @@ async function readProjectMeta(projectPath) {
|
|
|
20549
20569
|
}
|
|
20550
20570
|
async function readProjectId(projectPath) {
|
|
20551
20571
|
try {
|
|
20552
|
-
const { readFileSync:
|
|
20572
|
+
const { readFileSync: readFileSync54, existsSync: existsSync73 } = await import("node:fs");
|
|
20553
20573
|
const infoPath = join33(projectPath, ".cleo", "project-info.json");
|
|
20554
|
-
if (!
|
|
20555
|
-
const data = JSON.parse(
|
|
20574
|
+
if (!existsSync73(infoPath)) return "";
|
|
20575
|
+
const data = JSON.parse(readFileSync54(infoPath, "utf-8"));
|
|
20556
20576
|
return typeof data.projectId === "string" ? data.projectId : "";
|
|
20557
20577
|
} catch {
|
|
20558
20578
|
return "";
|
|
@@ -28477,7 +28497,8 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
28477
28497
|
}
|
|
28478
28498
|
function buildEntry(task) {
|
|
28479
28499
|
const cleanTitle = capitalize(stripConventionalPrefix(task.title));
|
|
28480
|
-
const
|
|
28500
|
+
const safeDesc = task.description?.replace(/\r?\n/g, " ").replace(/\s{2,}/g, " ").trim();
|
|
28501
|
+
const desc6 = safeDesc;
|
|
28481
28502
|
const shouldIncludeDesc = (() => {
|
|
28482
28503
|
if (!desc6 || desc6.length === 0) return false;
|
|
28483
28504
|
const titleNorm = cleanTitle.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim();
|
|
@@ -28494,23 +28515,29 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
28494
28515
|
}
|
|
28495
28516
|
function categorizeTask(task) {
|
|
28496
28517
|
if (task.type === "epic") return "changes";
|
|
28497
|
-
const
|
|
28498
|
-
|
|
28499
|
-
|
|
28518
|
+
const taskType = (task.type ?? "").toLowerCase();
|
|
28519
|
+
if (taskType === "test") return "tests";
|
|
28520
|
+
if (taskType === "fix" || taskType === "bugfix") return "fixes";
|
|
28521
|
+
if (taskType === "feat" || taskType === "feature") return "features";
|
|
28522
|
+
if (taskType === "docs" || taskType === "doc") return "docs";
|
|
28523
|
+
if (taskType === "chore" || taskType === "refactor") return "chores";
|
|
28500
28524
|
if (/^feat(\([^)]+\))?:/.test(task.title.toLowerCase())) return "features";
|
|
28501
28525
|
if (/^fix(\([^)]+\))?:/.test(task.title.toLowerCase())) return "fixes";
|
|
28502
28526
|
if (/^docs?(\([^)]+\))?:/.test(task.title.toLowerCase())) return "docs";
|
|
28503
28527
|
if (/^test(\([^)]+\))?:/.test(task.title.toLowerCase())) return "tests";
|
|
28504
28528
|
if (/^(chore|refactor|style|ci|build|perf)(\([^)]+\))?:/.test(task.title.toLowerCase())) return "chores";
|
|
28505
|
-
|
|
28529
|
+
const labels = task.labels ?? [];
|
|
28530
|
+
if (labels.some((l) => ["test", "testing"].includes(l.toLowerCase()))) return "tests";
|
|
28506
28531
|
if (labels.some((l) => ["fix", "bug", "bugfix", "regression"].includes(l.toLowerCase()))) return "fixes";
|
|
28532
|
+
if (labels.some((l) => ["feat", "feature", "enhancement", "add"].includes(l.toLowerCase()))) return "features";
|
|
28507
28533
|
if (labels.some((l) => ["docs", "documentation"].includes(l.toLowerCase()))) return "docs";
|
|
28508
|
-
if (labels.some((l) => ["test", "testing"].includes(l.toLowerCase()))) return "tests";
|
|
28509
28534
|
if (labels.some((l) => ["chore", "refactor", "cleanup", "maintenance"].includes(l.toLowerCase()))) return "chores";
|
|
28510
|
-
|
|
28535
|
+
const titleLower = stripConventionalPrefix(task.title).toLowerCase();
|
|
28536
|
+
const rawTitleLower = task.title.toLowerCase();
|
|
28537
|
+
if (titleLower.startsWith("test") || titleLower.includes("test") && titleLower.includes("add")) return "tests";
|
|
28511
28538
|
if (titleLower.includes("bug") || titleLower.startsWith("fix") || titleLower.includes("regression") || titleLower.includes("broken")) return "fixes";
|
|
28539
|
+
if (titleLower.startsWith("add ") || titleLower.includes("implement") || titleLower.startsWith("create ") || titleLower.startsWith("introduce ")) return "features";
|
|
28512
28540
|
if (titleLower.startsWith("doc") || titleLower.includes("documentation") || titleLower.includes("readme") || titleLower.includes("changelog")) return "docs";
|
|
28513
|
-
if (titleLower.startsWith("test") || titleLower.includes("test") && titleLower.includes("add")) return "tests";
|
|
28514
28541
|
if (titleLower.startsWith("chore") || titleLower.includes("refactor") || titleLower.includes("cleanup") || titleLower.includes("migrate") || titleLower.includes("upgrade") || titleLower.includes("remove ") || titleLower.startsWith("audit")) return "chores";
|
|
28515
28542
|
if (rawTitleLower.startsWith("feat")) return "features";
|
|
28516
28543
|
return "changes";
|
|
@@ -28521,6 +28548,10 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
28521
28548
|
if (task.type === "epic") continue;
|
|
28522
28549
|
if (task.labels?.some((l) => l.toLowerCase() === "epic")) continue;
|
|
28523
28550
|
if (/^epic:/i.test(task.title.trim())) continue;
|
|
28551
|
+
const labelsLower = (task.labels ?? []).map((l) => l.toLowerCase());
|
|
28552
|
+
if (labelsLower.some((l) => ["research", "internal", "spike", "audit"].includes(l))) continue;
|
|
28553
|
+
if (["spike", "research"].includes((task.type ?? "").toLowerCase())) continue;
|
|
28554
|
+
if (/^(research|investigate|audit|spike)\s/i.test(task.title.trim())) continue;
|
|
28524
28555
|
const category = categorizeTask(task);
|
|
28525
28556
|
const entry = buildEntry(task);
|
|
28526
28557
|
if (category === "features") features.push(entry);
|
|
@@ -28578,7 +28609,7 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
28578
28609
|
}
|
|
28579
28610
|
const { customBlocks } = parseChangelogBlocks(existingChangelogContent);
|
|
28580
28611
|
const changelogBody = sections.slice(2).join("\n");
|
|
28581
|
-
await writeChangelogSection(normalizedVersion, changelogBody, customBlocks, changelogPath);
|
|
28612
|
+
await writeChangelogSection(normalizedVersion.replace(/^v/, ""), changelogBody, customBlocks, changelogPath);
|
|
28582
28613
|
return {
|
|
28583
28614
|
version: normalizedVersion,
|
|
28584
28615
|
changelog,
|
|
@@ -28651,7 +28682,7 @@ async function tagRelease(version, cwd) {
|
|
|
28651
28682
|
await db.update(releaseManifests).set({ status: "tagged", taggedAt }).where(eq14(releaseManifests.version, normalizedVersion)).run();
|
|
28652
28683
|
return { version: normalizedVersion, status: "tagged", taggedAt };
|
|
28653
28684
|
}
|
|
28654
|
-
async function runReleaseGates(version, loadTasksFn, cwd) {
|
|
28685
|
+
async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
28655
28686
|
if (!version) {
|
|
28656
28687
|
throw new Error("version is required");
|
|
28657
28688
|
}
|
|
@@ -28699,23 +28730,31 @@ async function runReleaseGates(version, loadTasksFn, cwd) {
|
|
|
28699
28730
|
message: existsSync49(distPath) ? "dist/cli/index.js present" : "dist/ not built \u2014 run: npm run build"
|
|
28700
28731
|
});
|
|
28701
28732
|
}
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28733
|
+
if (opts?.dryRun) {
|
|
28734
|
+
gates.push({
|
|
28735
|
+
name: "clean_working_tree",
|
|
28736
|
+
status: "passed",
|
|
28737
|
+
message: "Skipped in dry-run mode"
|
|
28738
|
+
});
|
|
28739
|
+
} else {
|
|
28740
|
+
let workingTreeClean = true;
|
|
28741
|
+
let dirtyFiles = [];
|
|
28742
|
+
try {
|
|
28743
|
+
const porcelain = execFileSync7("git", ["status", "--porcelain"], {
|
|
28744
|
+
cwd: projectRoot,
|
|
28745
|
+
encoding: "utf-8",
|
|
28746
|
+
stdio: "pipe"
|
|
28747
|
+
});
|
|
28748
|
+
dirtyFiles = porcelain.split("\n").filter((l) => l.trim()).filter((l) => !l.startsWith("?? ")).map((l) => l.slice(3).trim()).filter((f) => f !== "CHANGELOG.md" && f !== "VERSION" && f !== "package.json");
|
|
28749
|
+
workingTreeClean = dirtyFiles.length === 0;
|
|
28750
|
+
} catch {
|
|
28751
|
+
}
|
|
28752
|
+
gates.push({
|
|
28753
|
+
name: "clean_working_tree",
|
|
28754
|
+
status: workingTreeClean ? "passed" : "failed",
|
|
28755
|
+
message: workingTreeClean ? "Working tree clean (excluding CHANGELOG.md, VERSION, package.json)" : `Uncommitted changes in: ${dirtyFiles.slice(0, 5).join(", ")}${dirtyFiles.length > 5 ? ` (+${dirtyFiles.length - 5} more)` : ""}`
|
|
28709
28756
|
});
|
|
28710
|
-
dirtyFiles = porcelain.split("\n").filter((l) => l.trim()).map((l) => l.slice(3).trim()).filter((f) => f !== "CHANGELOG.md" && f !== "VERSION" && f !== "package.json");
|
|
28711
|
-
workingTreeClean = dirtyFiles.length === 0;
|
|
28712
|
-
} catch {
|
|
28713
28757
|
}
|
|
28714
|
-
gates.push({
|
|
28715
|
-
name: "clean_working_tree",
|
|
28716
|
-
status: workingTreeClean ? "passed" : "failed",
|
|
28717
|
-
message: workingTreeClean ? "Working tree clean (excluding CHANGELOG.md, VERSION, package.json)" : `Uncommitted changes in: ${dirtyFiles.slice(0, 5).join(", ")}${dirtyFiles.length > 5 ? ` (+${dirtyFiles.length - 5} more)` : ""}`
|
|
28718
|
-
});
|
|
28719
28758
|
const isPreRelease = normalizedVersion.includes("-");
|
|
28720
28759
|
let currentBranch = "";
|
|
28721
28760
|
try {
|
|
@@ -28775,6 +28814,28 @@ async function runReleaseGates(version, loadTasksFn, cwd) {
|
|
|
28775
28814
|
metadata
|
|
28776
28815
|
};
|
|
28777
28816
|
}
|
|
28817
|
+
async function cancelRelease(version, projectRoot) {
|
|
28818
|
+
if (!version) {
|
|
28819
|
+
throw new Error("version is required");
|
|
28820
|
+
}
|
|
28821
|
+
const normalizedVersion = normalizeVersion(version);
|
|
28822
|
+
const db = await getDb(projectRoot);
|
|
28823
|
+
const rows = await db.select().from(releaseManifests).where(eq14(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
28824
|
+
if (rows.length === 0) {
|
|
28825
|
+
return { success: false, message: `Release ${normalizedVersion} not found`, version: normalizedVersion };
|
|
28826
|
+
}
|
|
28827
|
+
const status = rows[0].status;
|
|
28828
|
+
const cancellableStates = ["draft", "prepared"];
|
|
28829
|
+
if (!cancellableStates.includes(status)) {
|
|
28830
|
+
return {
|
|
28831
|
+
success: false,
|
|
28832
|
+
message: `Cannot cancel a release in '${status}' state. Use 'release rollback' instead.`,
|
|
28833
|
+
version: normalizedVersion
|
|
28834
|
+
};
|
|
28835
|
+
}
|
|
28836
|
+
await db.delete(releaseManifests).where(eq14(releaseManifests.version, normalizedVersion)).run();
|
|
28837
|
+
return { success: true, message: `Release ${normalizedVersion} cancelled and removed`, version: normalizedVersion };
|
|
28838
|
+
}
|
|
28778
28839
|
async function rollbackRelease(version, reason, cwd) {
|
|
28779
28840
|
if (!version) {
|
|
28780
28841
|
throw new Error("version is required");
|
|
@@ -28849,7 +28910,8 @@ async function pushRelease(version, remote, cwd, opts) {
|
|
|
28849
28910
|
encoding: "utf-8",
|
|
28850
28911
|
stdio: ["pipe", "pipe", "pipe"]
|
|
28851
28912
|
});
|
|
28852
|
-
|
|
28913
|
+
const trackedDirty = statusOutput.split("\n").filter((l) => l.trim() && !l.startsWith("?? ")).join("\n");
|
|
28914
|
+
if (trackedDirty.trim().length > 0) {
|
|
28853
28915
|
throw new Error(
|
|
28854
28916
|
"Git working tree is not clean. Commit or stash changes before pushing (config: release.push.requireCleanTree=true)."
|
|
28855
28917
|
);
|
|
@@ -28981,6 +29043,179 @@ var init_guards = __esm({
|
|
|
28981
29043
|
}
|
|
28982
29044
|
});
|
|
28983
29045
|
|
|
29046
|
+
// src/core/release/version-bump.ts
|
|
29047
|
+
import { existsSync as existsSync50, readFileSync as readFileSync39, writeFileSync as writeFileSync8 } from "node:fs";
|
|
29048
|
+
import { join as join48 } from "node:path";
|
|
29049
|
+
function readConfigValueSync2(path, defaultValue, cwd) {
|
|
29050
|
+
try {
|
|
29051
|
+
const configPath = join48(getCleoDir(cwd), "config.json");
|
|
29052
|
+
if (!existsSync50(configPath)) return defaultValue;
|
|
29053
|
+
const config = JSON.parse(readFileSync39(configPath, "utf-8"));
|
|
29054
|
+
const keys = path.split(".");
|
|
29055
|
+
let value = config;
|
|
29056
|
+
for (const key of keys) {
|
|
29057
|
+
if (value == null || typeof value !== "object") return defaultValue;
|
|
29058
|
+
value = value[key];
|
|
29059
|
+
}
|
|
29060
|
+
return value ?? defaultValue;
|
|
29061
|
+
} catch {
|
|
29062
|
+
return defaultValue;
|
|
29063
|
+
}
|
|
29064
|
+
}
|
|
29065
|
+
function validateVersionFormat(version) {
|
|
29066
|
+
return VERSION_WITH_PRERELEASE.test(version);
|
|
29067
|
+
}
|
|
29068
|
+
function getVersionBumpConfig(cwd) {
|
|
29069
|
+
try {
|
|
29070
|
+
const raw = readConfigValueSync2("release.versionBump.files", [], cwd);
|
|
29071
|
+
return raw.map((entry) => ({
|
|
29072
|
+
file: entry.path ?? entry.file ?? "",
|
|
29073
|
+
strategy: entry.strategy,
|
|
29074
|
+
field: entry.jsonPath?.replace(/^\./, "") ?? entry.field,
|
|
29075
|
+
key: entry.key,
|
|
29076
|
+
section: entry.section,
|
|
29077
|
+
pattern: entry.sedPattern ?? entry.pattern
|
|
29078
|
+
})).filter((t) => t.file !== "");
|
|
29079
|
+
} catch {
|
|
29080
|
+
return [];
|
|
29081
|
+
}
|
|
29082
|
+
}
|
|
29083
|
+
function bumpFile(target, newVersion, projectRoot) {
|
|
29084
|
+
const filePath = join48(projectRoot, target.file);
|
|
29085
|
+
if (!existsSync50(filePath)) {
|
|
29086
|
+
return {
|
|
29087
|
+
file: target.file,
|
|
29088
|
+
strategy: target.strategy,
|
|
29089
|
+
success: false,
|
|
29090
|
+
error: `File not found: ${target.file}`
|
|
29091
|
+
};
|
|
29092
|
+
}
|
|
29093
|
+
try {
|
|
29094
|
+
const content = readFileSync39(filePath, "utf-8");
|
|
29095
|
+
let previousVersion;
|
|
29096
|
+
let newContent;
|
|
29097
|
+
switch (target.strategy) {
|
|
29098
|
+
case "plain": {
|
|
29099
|
+
previousVersion = content.trim();
|
|
29100
|
+
newContent = newVersion + "\n";
|
|
29101
|
+
break;
|
|
29102
|
+
}
|
|
29103
|
+
case "json": {
|
|
29104
|
+
const field = target.field ?? "version";
|
|
29105
|
+
const json = JSON.parse(content);
|
|
29106
|
+
previousVersion = getNestedField(json, field);
|
|
29107
|
+
setNestedField(json, field, newVersion);
|
|
29108
|
+
newContent = JSON.stringify(json, null, 2) + "\n";
|
|
29109
|
+
break;
|
|
29110
|
+
}
|
|
29111
|
+
case "toml": {
|
|
29112
|
+
const key = target.key ?? "version";
|
|
29113
|
+
const versionRegex = new RegExp(`^(${key}\\s*=\\s*")([^"]+)(")`, "m");
|
|
29114
|
+
const match = content.match(versionRegex);
|
|
29115
|
+
previousVersion = match?.[2];
|
|
29116
|
+
newContent = content.replace(versionRegex, `$1${newVersion}$3`);
|
|
29117
|
+
break;
|
|
29118
|
+
}
|
|
29119
|
+
case "sed": {
|
|
29120
|
+
const pattern = target.pattern ?? "";
|
|
29121
|
+
if (!pattern.includes("{{VERSION}}")) {
|
|
29122
|
+
return {
|
|
29123
|
+
file: target.file,
|
|
29124
|
+
strategy: target.strategy,
|
|
29125
|
+
success: false,
|
|
29126
|
+
error: "sed strategy requires {{VERSION}} placeholder in pattern"
|
|
29127
|
+
};
|
|
29128
|
+
}
|
|
29129
|
+
const regex = new RegExp(pattern.replace("{{VERSION}}", "([\\d.]+)"));
|
|
29130
|
+
const match = content.match(regex);
|
|
29131
|
+
previousVersion = match?.[1];
|
|
29132
|
+
newContent = content.replace(
|
|
29133
|
+
regex,
|
|
29134
|
+
pattern.replace("{{VERSION}}", newVersion)
|
|
29135
|
+
);
|
|
29136
|
+
break;
|
|
29137
|
+
}
|
|
29138
|
+
default:
|
|
29139
|
+
return {
|
|
29140
|
+
file: target.file,
|
|
29141
|
+
strategy: target.strategy,
|
|
29142
|
+
success: false,
|
|
29143
|
+
error: `Unknown strategy: ${target.strategy}`
|
|
29144
|
+
};
|
|
29145
|
+
}
|
|
29146
|
+
writeFileSync8(filePath, newContent, "utf-8");
|
|
29147
|
+
return {
|
|
29148
|
+
file: target.file,
|
|
29149
|
+
strategy: target.strategy,
|
|
29150
|
+
success: true,
|
|
29151
|
+
previousVersion,
|
|
29152
|
+
newVersion
|
|
29153
|
+
};
|
|
29154
|
+
} catch (err) {
|
|
29155
|
+
return {
|
|
29156
|
+
file: target.file,
|
|
29157
|
+
strategy: target.strategy,
|
|
29158
|
+
success: false,
|
|
29159
|
+
error: String(err)
|
|
29160
|
+
};
|
|
29161
|
+
}
|
|
29162
|
+
}
|
|
29163
|
+
function bumpVersionFromConfig(newVersion, options = {}, cwd) {
|
|
29164
|
+
if (!validateVersionFormat(newVersion)) {
|
|
29165
|
+
throw new CleoError(
|
|
29166
|
+
6 /* VALIDATION_ERROR */,
|
|
29167
|
+
`Invalid version: '${newVersion}' (expected X.Y.Z or YYYY.M.patch)`
|
|
29168
|
+
);
|
|
29169
|
+
}
|
|
29170
|
+
const targets = getVersionBumpConfig(cwd);
|
|
29171
|
+
if (targets.length === 0) {
|
|
29172
|
+
throw new CleoError(
|
|
29173
|
+
1 /* GENERAL_ERROR */,
|
|
29174
|
+
"No version bump targets configured. Add release.versionBump.files to .cleo/config.json"
|
|
29175
|
+
);
|
|
29176
|
+
}
|
|
29177
|
+
const projectRoot = getProjectRoot(cwd);
|
|
29178
|
+
const results = [];
|
|
29179
|
+
if (options.dryRun) {
|
|
29180
|
+
for (const target of targets) {
|
|
29181
|
+
results.push({
|
|
29182
|
+
file: target.file,
|
|
29183
|
+
strategy: target.strategy,
|
|
29184
|
+
success: true,
|
|
29185
|
+
newVersion
|
|
29186
|
+
});
|
|
29187
|
+
}
|
|
29188
|
+
return { results, allSuccess: true };
|
|
29189
|
+
}
|
|
29190
|
+
for (const target of targets) {
|
|
29191
|
+
results.push(bumpFile(target, newVersion, projectRoot));
|
|
29192
|
+
}
|
|
29193
|
+
const allSuccess = results.every((r) => r.success);
|
|
29194
|
+
return { results, allSuccess };
|
|
29195
|
+
}
|
|
29196
|
+
function getNestedField(obj, path) {
|
|
29197
|
+
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
29198
|
+
}
|
|
29199
|
+
function setNestedField(obj, path, value) {
|
|
29200
|
+
const parts = path.split(".");
|
|
29201
|
+
let current = obj;
|
|
29202
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
29203
|
+
if (typeof current[parts[i]] !== "object") current[parts[i]] = {};
|
|
29204
|
+
current = current[parts[i]];
|
|
29205
|
+
}
|
|
29206
|
+
current[parts[parts.length - 1]] = value;
|
|
29207
|
+
}
|
|
29208
|
+
var VERSION_WITH_PRERELEASE;
|
|
29209
|
+
var init_version_bump = __esm({
|
|
29210
|
+
"src/core/release/version-bump.ts"() {
|
|
29211
|
+
"use strict";
|
|
29212
|
+
init_paths();
|
|
29213
|
+
init_errors();
|
|
29214
|
+
init_exit_codes();
|
|
29215
|
+
VERSION_WITH_PRERELEASE = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/;
|
|
29216
|
+
}
|
|
29217
|
+
});
|
|
29218
|
+
|
|
28984
29219
|
// src/dispatch/engines/release-engine.ts
|
|
28985
29220
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
28986
29221
|
function isAgentContext() {
|
|
@@ -29103,6 +29338,23 @@ async function releaseRollback(version, reason, projectRoot) {
|
|
|
29103
29338
|
return engineError(code, message);
|
|
29104
29339
|
}
|
|
29105
29340
|
}
|
|
29341
|
+
async function releaseCancel(version, projectRoot) {
|
|
29342
|
+
if (!version) {
|
|
29343
|
+
return engineError("E_INVALID_INPUT", "version is required");
|
|
29344
|
+
}
|
|
29345
|
+
try {
|
|
29346
|
+
const result = await cancelRelease(version, projectRoot);
|
|
29347
|
+
if (!result.success) {
|
|
29348
|
+
const code = result.message.includes("not found") ? "E_NOT_FOUND" : "E_INVALID_STATE";
|
|
29349
|
+
return engineError(code, result.message);
|
|
29350
|
+
}
|
|
29351
|
+
return { success: true, data: result };
|
|
29352
|
+
} catch (err) {
|
|
29353
|
+
const message = err.message;
|
|
29354
|
+
const code = message.includes("not found") ? "E_NOT_FOUND" : "E_CANCEL_FAILED";
|
|
29355
|
+
return engineError(code, message);
|
|
29356
|
+
}
|
|
29357
|
+
}
|
|
29106
29358
|
async function releasePush(version, remote, projectRoot, opts) {
|
|
29107
29359
|
if (isAgentContext()) {
|
|
29108
29360
|
const hasEntry = await hasManifestEntry(version, projectRoot);
|
|
@@ -29146,7 +29398,7 @@ async function releasePush(version, remote, projectRoot, opts) {
|
|
|
29146
29398
|
}
|
|
29147
29399
|
}
|
|
29148
29400
|
async function releaseShip(params, projectRoot) {
|
|
29149
|
-
const { version, epicId, remote, dryRun = false } = params;
|
|
29401
|
+
const { version, epicId, remote, dryRun = false, bump = true } = params;
|
|
29150
29402
|
if (!version) {
|
|
29151
29403
|
return engineError("E_INVALID_INPUT", "version is required");
|
|
29152
29404
|
}
|
|
@@ -29154,30 +29406,51 @@ async function releaseShip(params, projectRoot) {
|
|
|
29154
29406
|
return engineError("E_INVALID_INPUT", "epicId is required");
|
|
29155
29407
|
}
|
|
29156
29408
|
const cwd = projectRoot ?? resolveProjectRoot();
|
|
29409
|
+
const steps = [];
|
|
29157
29410
|
const logStep = (n, total, label, done, error) => {
|
|
29411
|
+
let msg;
|
|
29158
29412
|
if (done === void 0) {
|
|
29159
|
-
|
|
29413
|
+
msg = `[Step ${n}/${total}] ${label}...`;
|
|
29160
29414
|
} else if (done) {
|
|
29161
|
-
|
|
29415
|
+
msg = ` \u2713 ${label}`;
|
|
29162
29416
|
} else {
|
|
29163
|
-
|
|
29417
|
+
msg = ` \u2717 ${label}: ${error ?? "failed"}`;
|
|
29164
29418
|
}
|
|
29419
|
+
steps.push(msg);
|
|
29420
|
+
console.log(msg);
|
|
29165
29421
|
};
|
|
29422
|
+
const bumpTargets = getVersionBumpConfig(cwd);
|
|
29423
|
+
const shouldBump = bump && bumpTargets.length > 0;
|
|
29166
29424
|
try {
|
|
29167
|
-
|
|
29425
|
+
if (shouldBump) {
|
|
29426
|
+
logStep(0, 8, "Bump version files");
|
|
29427
|
+
if (!dryRun) {
|
|
29428
|
+
const bumpResults = bumpVersionFromConfig(version, { dryRun: false }, cwd);
|
|
29429
|
+
if (!bumpResults.allSuccess) {
|
|
29430
|
+
const failed = bumpResults.results.filter((r) => !r.success).map((r) => r.file);
|
|
29431
|
+
steps.push(` ! Version bump partial: failed for ${failed.join(", ")}`);
|
|
29432
|
+
} else {
|
|
29433
|
+
logStep(0, 8, "Bump version files", true);
|
|
29434
|
+
}
|
|
29435
|
+
} else {
|
|
29436
|
+
logStep(0, 8, "Bump version files", true);
|
|
29437
|
+
}
|
|
29438
|
+
}
|
|
29439
|
+
logStep(1, 8, "Validate release gates");
|
|
29168
29440
|
const gatesResult = await runReleaseGates(
|
|
29169
29441
|
version,
|
|
29170
29442
|
() => loadTasks2(projectRoot),
|
|
29171
|
-
projectRoot
|
|
29443
|
+
projectRoot,
|
|
29444
|
+
{ dryRun }
|
|
29172
29445
|
);
|
|
29173
29446
|
if (gatesResult && !gatesResult.allPassed) {
|
|
29174
29447
|
const failedGates = gatesResult.gates.filter((g) => g.status === "failed");
|
|
29175
|
-
logStep(1,
|
|
29448
|
+
logStep(1, 8, "Validate release gates", false, failedGates.map((g) => g.name).join(", "));
|
|
29176
29449
|
return engineError("E_LIFECYCLE_GATE_FAILED", `Release gates failed for ${version}: ${failedGates.map((g) => g.name).join(", ")}`, {
|
|
29177
29450
|
details: { gates: gatesResult.gates, failedCount: gatesResult.failedCount }
|
|
29178
29451
|
});
|
|
29179
29452
|
}
|
|
29180
|
-
logStep(1,
|
|
29453
|
+
logStep(1, 8, "Validate release gates", true);
|
|
29181
29454
|
let resolvedChannel = "latest";
|
|
29182
29455
|
let currentBranchForPR = "HEAD";
|
|
29183
29456
|
try {
|
|
@@ -29197,7 +29470,7 @@ async function releaseShip(params, projectRoot) {
|
|
|
29197
29470
|
if (gateMetadata?.currentBranch) {
|
|
29198
29471
|
currentBranchForPR = gateMetadata.currentBranch;
|
|
29199
29472
|
}
|
|
29200
|
-
logStep(2,
|
|
29473
|
+
logStep(2, 8, "Check epic completeness");
|
|
29201
29474
|
let releaseTaskIds = [];
|
|
29202
29475
|
try {
|
|
29203
29476
|
const manifest = await showManifestRelease(version, projectRoot);
|
|
@@ -29208,13 +29481,13 @@ async function releaseShip(params, projectRoot) {
|
|
|
29208
29481
|
const epicCheck = await checkEpicCompleteness(releaseTaskIds, projectRoot, epicAccessor);
|
|
29209
29482
|
if (epicCheck.hasIncomplete) {
|
|
29210
29483
|
const incomplete = epicCheck.epics.filter((e) => e.missingChildren.length > 0).map((e) => `${e.epicId}: missing ${e.missingChildren.map((c) => c.id).join(", ")}`).join("; ");
|
|
29211
|
-
logStep(2,
|
|
29484
|
+
logStep(2, 8, "Check epic completeness", false, incomplete);
|
|
29212
29485
|
return engineError("E_LIFECYCLE_GATE_FAILED", `Epic completeness check failed: ${incomplete}`, {
|
|
29213
29486
|
details: { epics: epicCheck.epics }
|
|
29214
29487
|
});
|
|
29215
29488
|
}
|
|
29216
|
-
logStep(2,
|
|
29217
|
-
logStep(3,
|
|
29489
|
+
logStep(2, 8, "Check epic completeness", true);
|
|
29490
|
+
logStep(3, 8, "Check task double-listing");
|
|
29218
29491
|
const allReleases = await listManifestReleases(projectRoot);
|
|
29219
29492
|
const existingReleases = (allReleases.releases ?? []).filter((r) => r.version !== version);
|
|
29220
29493
|
const doubleCheck = checkDoubleListing(
|
|
@@ -29223,39 +29496,38 @@ async function releaseShip(params, projectRoot) {
|
|
|
29223
29496
|
);
|
|
29224
29497
|
if (doubleCheck.hasDoubleListing) {
|
|
29225
29498
|
const dupes = doubleCheck.duplicates.map((d) => `${d.taskId} (in ${d.releases.join(", ")})`).join("; ");
|
|
29226
|
-
logStep(3,
|
|
29499
|
+
logStep(3, 8, "Check task double-listing", false, dupes);
|
|
29227
29500
|
return engineError("E_VALIDATION", `Double-listing detected: ${dupes}`, {
|
|
29228
29501
|
details: { duplicates: doubleCheck.duplicates }
|
|
29229
29502
|
});
|
|
29230
29503
|
}
|
|
29231
|
-
logStep(3,
|
|
29232
|
-
logStep(4, 7, "Generate CHANGELOG");
|
|
29233
|
-
const changelogResult = await generateReleaseChangelog(
|
|
29234
|
-
version,
|
|
29235
|
-
() => loadTasks2(projectRoot),
|
|
29236
|
-
projectRoot
|
|
29237
|
-
);
|
|
29238
|
-
const changelogPath = `${cwd}/CHANGELOG.md`;
|
|
29239
|
-
const generatedContent = changelogResult.changelog ?? "";
|
|
29240
|
-
logStep(4, 7, "Generate CHANGELOG", true);
|
|
29504
|
+
logStep(3, 8, "Check task double-listing", true);
|
|
29241
29505
|
const loadedConfig = loadReleaseConfig(cwd);
|
|
29242
29506
|
const pushMode = getPushMode(loadedConfig);
|
|
29243
29507
|
const gitflowCfg = getGitFlowConfig(loadedConfig);
|
|
29244
29508
|
const targetBranch = targetBranchFromGates ?? gitflowCfg.branches.main;
|
|
29245
29509
|
if (dryRun) {
|
|
29510
|
+
logStep(4, 8, "Generate CHANGELOG");
|
|
29511
|
+
logStep(4, 8, "Generate CHANGELOG", true);
|
|
29246
29512
|
const wouldCreatePR = requiresPRFromGates || pushMode === "pr";
|
|
29513
|
+
const filesToStagePreview = ["CHANGELOG.md", ...shouldBump ? bumpTargets.map((t) => t.file) : []];
|
|
29514
|
+
const wouldDo = [];
|
|
29515
|
+
if (shouldBump) {
|
|
29516
|
+
wouldDo.push(`bump version files: ${bumpTargets.map((t) => t.file).join(", ")} \u2192 ${version}`);
|
|
29517
|
+
}
|
|
29518
|
+
wouldDo.push(
|
|
29519
|
+
`write CHANGELOG.md: ## [${version}] - ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]} (preview only, not written in dry-run)`,
|
|
29520
|
+
`git add ${filesToStagePreview.join(" ")}`,
|
|
29521
|
+
`git commit -m "release: ship v${version} (${epicId})"`,
|
|
29522
|
+
`git tag -a v${version} -m "Release v${version}"`
|
|
29523
|
+
);
|
|
29247
29524
|
const dryRunOutput = {
|
|
29248
29525
|
version,
|
|
29249
29526
|
epicId,
|
|
29250
29527
|
dryRun: true,
|
|
29251
29528
|
channel: resolvedChannel,
|
|
29252
29529
|
pushMode,
|
|
29253
|
-
wouldDo
|
|
29254
|
-
`write CHANGELOG section for ${version} (${generatedContent.length} chars)`,
|
|
29255
|
-
"git add CHANGELOG.md",
|
|
29256
|
-
`git commit -m "release: ship v${version} (${epicId})"`,
|
|
29257
|
-
`git tag -a v${version} -m "Release v${version}"`
|
|
29258
|
-
]
|
|
29530
|
+
wouldDo
|
|
29259
29531
|
};
|
|
29260
29532
|
if (wouldCreatePR) {
|
|
29261
29533
|
const ghAvailable = isGhCliAvailable();
|
|
@@ -29272,15 +29544,24 @@ async function releaseShip(params, projectRoot) {
|
|
|
29272
29544
|
dryRunOutput["wouldCreatePR"] = false;
|
|
29273
29545
|
}
|
|
29274
29546
|
dryRunOutput["wouldDo"].push("markReleasePushed(...)");
|
|
29275
|
-
return { success: true, data: dryRunOutput };
|
|
29547
|
+
return { success: true, data: { ...dryRunOutput, steps } };
|
|
29276
29548
|
}
|
|
29277
|
-
logStep(
|
|
29549
|
+
logStep(4, 8, "Generate CHANGELOG");
|
|
29550
|
+
await generateReleaseChangelog(
|
|
29551
|
+
version,
|
|
29552
|
+
() => loadTasks2(projectRoot),
|
|
29553
|
+
projectRoot
|
|
29554
|
+
);
|
|
29555
|
+
const changelogPath = `${cwd}/CHANGELOG.md`;
|
|
29556
|
+
logStep(4, 8, "Generate CHANGELOG", true);
|
|
29557
|
+
logStep(5, 8, "Commit release");
|
|
29278
29558
|
const gitCwd = { cwd, encoding: "utf-8", stdio: "pipe" };
|
|
29559
|
+
const filesToStage = ["CHANGELOG.md", ...shouldBump ? bumpTargets.map((t) => t.file) : []];
|
|
29279
29560
|
try {
|
|
29280
|
-
execFileSync8("git", ["add",
|
|
29561
|
+
execFileSync8("git", ["add", ...filesToStage], gitCwd);
|
|
29281
29562
|
} catch (err) {
|
|
29282
29563
|
const msg = err.message ?? String(err);
|
|
29283
|
-
logStep(5,
|
|
29564
|
+
logStep(5, 8, "Commit release", false, `git add failed: ${msg}`);
|
|
29284
29565
|
return engineError("E_GENERAL", `git add failed: ${msg}`);
|
|
29285
29566
|
}
|
|
29286
29567
|
try {
|
|
@@ -29291,26 +29572,26 @@ async function releaseShip(params, projectRoot) {
|
|
|
29291
29572
|
);
|
|
29292
29573
|
} catch (err) {
|
|
29293
29574
|
const msg = err.stderr ?? err.message ?? String(err);
|
|
29294
|
-
logStep(5,
|
|
29575
|
+
logStep(5, 8, "Commit release", false, `git commit failed: ${msg}`);
|
|
29295
29576
|
return engineError("E_GENERAL", `git commit failed: ${msg}`);
|
|
29296
29577
|
}
|
|
29297
|
-
logStep(5,
|
|
29578
|
+
logStep(5, 8, "Commit release", true);
|
|
29298
29579
|
let commitSha;
|
|
29299
29580
|
try {
|
|
29300
29581
|
commitSha = execFileSync8("git", ["rev-parse", "HEAD"], gitCwd).toString().trim();
|
|
29301
29582
|
} catch {
|
|
29302
29583
|
}
|
|
29303
|
-
logStep(6,
|
|
29584
|
+
logStep(6, 8, "Tag release");
|
|
29304
29585
|
const gitTag = `v${version.replace(/^v/, "")}`;
|
|
29305
29586
|
try {
|
|
29306
29587
|
execFileSync8("git", ["tag", "-a", gitTag, "-m", `Release ${gitTag}`], gitCwd);
|
|
29307
29588
|
} catch (err) {
|
|
29308
29589
|
const msg = err.stderr ?? err.message ?? String(err);
|
|
29309
|
-
logStep(6,
|
|
29590
|
+
logStep(6, 8, "Tag release", false, `git tag failed: ${msg}`);
|
|
29310
29591
|
return engineError("E_GENERAL", `git tag failed: ${msg}`);
|
|
29311
29592
|
}
|
|
29312
|
-
logStep(6,
|
|
29313
|
-
logStep(7,
|
|
29593
|
+
logStep(6, 8, "Tag release", true);
|
|
29594
|
+
logStep(7, 8, "Push / create PR");
|
|
29314
29595
|
let prResult = null;
|
|
29315
29596
|
const pushResult = await pushRelease(version, remote, projectRoot, {
|
|
29316
29597
|
explicitPush: true,
|
|
@@ -29337,24 +29618,34 @@ async function releaseShip(params, projectRoot) {
|
|
|
29337
29618
|
projectRoot: cwd
|
|
29338
29619
|
});
|
|
29339
29620
|
if (prResult.mode === "created") {
|
|
29340
|
-
|
|
29341
|
-
|
|
29342
|
-
|
|
29621
|
+
const m1 = ` \u2713 Push / create PR`;
|
|
29622
|
+
const m2 = ` PR created: ${prResult.prUrl}`;
|
|
29623
|
+
const m3 = ` \u2192 Next: merge the PR, then CI will publish to npm @${resolvedChannel}`;
|
|
29624
|
+
steps.push(m1, m2, m3);
|
|
29625
|
+
console.log(m1);
|
|
29626
|
+
console.log(m2);
|
|
29627
|
+
console.log(m3);
|
|
29343
29628
|
} else if (prResult.mode === "skipped") {
|
|
29344
|
-
|
|
29345
|
-
|
|
29629
|
+
const m1 = ` \u2713 Push / create PR`;
|
|
29630
|
+
const m2 = ` PR already exists: ${prResult.prUrl}`;
|
|
29631
|
+
steps.push(m1, m2);
|
|
29632
|
+
console.log(m1);
|
|
29633
|
+
console.log(m2);
|
|
29346
29634
|
} else {
|
|
29347
|
-
|
|
29348
|
-
|
|
29635
|
+
const m1 = ` ! Push / create PR \u2014 manual PR required:`;
|
|
29636
|
+
const m2 = prResult.instructions ?? "";
|
|
29637
|
+
steps.push(m1, m2);
|
|
29638
|
+
console.log(m1);
|
|
29639
|
+
console.log(m2);
|
|
29349
29640
|
}
|
|
29350
29641
|
} else {
|
|
29351
29642
|
try {
|
|
29352
29643
|
execFileSync8("git", ["push", remote ?? "origin", "--follow-tags"], gitCwd);
|
|
29353
|
-
logStep(7,
|
|
29644
|
+
logStep(7, 8, "Push / create PR", true);
|
|
29354
29645
|
} catch (err) {
|
|
29355
29646
|
const execError = err;
|
|
29356
29647
|
const msg = (execError.stderr ?? execError.message ?? "").slice(0, 500);
|
|
29357
|
-
logStep(7,
|
|
29648
|
+
logStep(7, 8, "Push / create PR", false, `git push failed: ${msg}`);
|
|
29358
29649
|
return engineError("E_GENERAL", `git push failed: ${msg}`, {
|
|
29359
29650
|
details: { exitCode: execError.status }
|
|
29360
29651
|
});
|
|
@@ -29372,6 +29663,7 @@ async function releaseShip(params, projectRoot) {
|
|
|
29372
29663
|
pushedAt,
|
|
29373
29664
|
changelog: changelogPath,
|
|
29374
29665
|
channel: resolvedChannel,
|
|
29666
|
+
steps,
|
|
29375
29667
|
...prResult ? {
|
|
29376
29668
|
pr: {
|
|
29377
29669
|
mode: prResult.mode,
|
|
@@ -29396,13 +29688,14 @@ var init_release_engine = __esm({
|
|
|
29396
29688
|
init_github_pr();
|
|
29397
29689
|
init_channel();
|
|
29398
29690
|
init_release_config();
|
|
29691
|
+
init_version_bump();
|
|
29399
29692
|
init_error();
|
|
29400
29693
|
}
|
|
29401
29694
|
});
|
|
29402
29695
|
|
|
29403
29696
|
// src/dispatch/engines/template-parser.ts
|
|
29404
|
-
import { readFileSync as
|
|
29405
|
-
import { join as
|
|
29697
|
+
import { readFileSync as readFileSync40, readdirSync as readdirSync12, existsSync as existsSync51 } from "fs";
|
|
29698
|
+
import { join as join49 } from "path";
|
|
29406
29699
|
import { parse as parseYaml } from "yaml";
|
|
29407
29700
|
function deriveSubcommand(filename) {
|
|
29408
29701
|
let stem = filename.replace(/\.ya?ml$/i, "");
|
|
@@ -29416,8 +29709,8 @@ function deriveSubcommand(filename) {
|
|
|
29416
29709
|
return firstWord.toLowerCase();
|
|
29417
29710
|
}
|
|
29418
29711
|
function parseTemplateFile(templateDir, filename) {
|
|
29419
|
-
const filePath =
|
|
29420
|
-
const raw =
|
|
29712
|
+
const filePath = join49(templateDir, filename);
|
|
29713
|
+
const raw = readFileSync40(filePath, "utf-8");
|
|
29421
29714
|
const parsed = parseYaml(raw);
|
|
29422
29715
|
const name = typeof parsed.name === "string" ? parsed.name : filename;
|
|
29423
29716
|
const titlePrefix = typeof parsed.title === "string" ? parsed.title : "";
|
|
@@ -29466,8 +29759,8 @@ function parseTemplateFile(templateDir, filename) {
|
|
|
29466
29759
|
};
|
|
29467
29760
|
}
|
|
29468
29761
|
function parseIssueTemplates(projectRoot) {
|
|
29469
|
-
const templateDir =
|
|
29470
|
-
if (!
|
|
29762
|
+
const templateDir = join49(projectRoot, ".github", "ISSUE_TEMPLATE");
|
|
29763
|
+
if (!existsSync51(templateDir)) {
|
|
29471
29764
|
return engineError("E_NOT_FOUND", `Issue template directory not found: ${templateDir}`);
|
|
29472
29765
|
}
|
|
29473
29766
|
let files;
|
|
@@ -31146,26 +31439,26 @@ var init_check = __esm({
|
|
|
31146
31439
|
});
|
|
31147
31440
|
|
|
31148
31441
|
// src/core/adrs/validate.ts
|
|
31149
|
-
import { readFileSync as
|
|
31150
|
-
import { join as
|
|
31442
|
+
import { readFileSync as readFileSync41, readdirSync as readdirSync13, existsSync as existsSync52 } from "node:fs";
|
|
31443
|
+
import { join as join50 } from "node:path";
|
|
31151
31444
|
import AjvModule3 from "ajv";
|
|
31152
31445
|
async function validateAllAdrs(projectRoot) {
|
|
31153
|
-
const adrsDir =
|
|
31154
|
-
const schemaPath =
|
|
31155
|
-
if (!
|
|
31446
|
+
const adrsDir = join50(projectRoot, ".cleo", "adrs");
|
|
31447
|
+
const schemaPath = join50(projectRoot, "schemas", "adr-frontmatter.schema.json");
|
|
31448
|
+
if (!existsSync52(schemaPath)) {
|
|
31156
31449
|
return {
|
|
31157
31450
|
valid: false,
|
|
31158
31451
|
errors: [{ file: "schemas/adr-frontmatter.schema.json", field: "schema", message: "Schema file not found" }],
|
|
31159
31452
|
checked: 0
|
|
31160
31453
|
};
|
|
31161
31454
|
}
|
|
31162
|
-
if (!
|
|
31455
|
+
if (!existsSync52(adrsDir)) {
|
|
31163
31456
|
return { valid: true, errors: [], checked: 0 };
|
|
31164
31457
|
}
|
|
31165
|
-
const schema = JSON.parse(
|
|
31458
|
+
const schema = JSON.parse(readFileSync41(schemaPath, "utf-8"));
|
|
31166
31459
|
const ajv = new Ajv3({ allErrors: true });
|
|
31167
31460
|
const validate = ajv.compile(schema);
|
|
31168
|
-
const files = readdirSync13(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).map((f) =>
|
|
31461
|
+
const files = readdirSync13(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).map((f) => join50(adrsDir, f));
|
|
31169
31462
|
const errors = [];
|
|
31170
31463
|
for (const filePath of files) {
|
|
31171
31464
|
const record = parseAdrFile(filePath, projectRoot);
|
|
@@ -31192,15 +31485,15 @@ var init_validate = __esm({
|
|
|
31192
31485
|
});
|
|
31193
31486
|
|
|
31194
31487
|
// src/core/adrs/list.ts
|
|
31195
|
-
import { readdirSync as readdirSync14, existsSync as
|
|
31196
|
-
import { join as
|
|
31488
|
+
import { readdirSync as readdirSync14, existsSync as existsSync53 } from "node:fs";
|
|
31489
|
+
import { join as join51 } from "node:path";
|
|
31197
31490
|
async function listAdrs(projectRoot, opts) {
|
|
31198
|
-
const adrsDir =
|
|
31199
|
-
if (!
|
|
31491
|
+
const adrsDir = join51(projectRoot, ".cleo", "adrs");
|
|
31492
|
+
if (!existsSync53(adrsDir)) {
|
|
31200
31493
|
return { adrs: [], total: 0 };
|
|
31201
31494
|
}
|
|
31202
31495
|
const files = readdirSync14(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).sort();
|
|
31203
|
-
const records = files.map((f) => parseAdrFile(
|
|
31496
|
+
const records = files.map((f) => parseAdrFile(join51(adrsDir, f), projectRoot));
|
|
31204
31497
|
const filtered = records.filter((r) => {
|
|
31205
31498
|
if (opts?.status && r.frontmatter.Status !== opts.status) return false;
|
|
31206
31499
|
if (opts?.since && r.frontmatter.Date < opts.since) return false;
|
|
@@ -31225,14 +31518,14 @@ var init_list2 = __esm({
|
|
|
31225
31518
|
});
|
|
31226
31519
|
|
|
31227
31520
|
// src/core/adrs/show.ts
|
|
31228
|
-
import { existsSync as
|
|
31229
|
-
import { join as
|
|
31521
|
+
import { existsSync as existsSync54, readdirSync as readdirSync15 } from "node:fs";
|
|
31522
|
+
import { join as join52 } from "node:path";
|
|
31230
31523
|
async function showAdr(projectRoot, adrId) {
|
|
31231
|
-
const adrsDir =
|
|
31232
|
-
if (!
|
|
31524
|
+
const adrsDir = join52(projectRoot, ".cleo", "adrs");
|
|
31525
|
+
if (!existsSync54(adrsDir)) return null;
|
|
31233
31526
|
const files = readdirSync15(adrsDir).filter((f) => f.startsWith(adrId) && f.endsWith(".md"));
|
|
31234
31527
|
if (files.length === 0) return null;
|
|
31235
|
-
const filePath =
|
|
31528
|
+
const filePath = join52(adrsDir, files[0]);
|
|
31236
31529
|
return parseAdrFile(filePath, projectRoot);
|
|
31237
31530
|
}
|
|
31238
31531
|
var init_show2 = __esm({
|
|
@@ -31243,8 +31536,8 @@ var init_show2 = __esm({
|
|
|
31243
31536
|
});
|
|
31244
31537
|
|
|
31245
31538
|
// src/core/adrs/find.ts
|
|
31246
|
-
import { readdirSync as readdirSync16, existsSync as
|
|
31247
|
-
import { join as
|
|
31539
|
+
import { readdirSync as readdirSync16, existsSync as existsSync55 } from "node:fs";
|
|
31540
|
+
import { join as join53 } from "node:path";
|
|
31248
31541
|
function normalise(s) {
|
|
31249
31542
|
return s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
31250
31543
|
}
|
|
@@ -31261,8 +31554,8 @@ function matchedTerms(target, terms) {
|
|
|
31261
31554
|
return terms.filter((term) => t.includes(term));
|
|
31262
31555
|
}
|
|
31263
31556
|
async function findAdrs(projectRoot, query, opts) {
|
|
31264
|
-
const adrsDir =
|
|
31265
|
-
if (!
|
|
31557
|
+
const adrsDir = join53(projectRoot, ".cleo", "adrs");
|
|
31558
|
+
if (!existsSync55(adrsDir)) {
|
|
31266
31559
|
return { adrs: [], query, total: 0 };
|
|
31267
31560
|
}
|
|
31268
31561
|
const files = readdirSync16(adrsDir).filter((f) => f.endsWith(".md") && f.startsWith("ADR-")).sort();
|
|
@@ -31271,7 +31564,7 @@ async function findAdrs(projectRoot, query, opts) {
|
|
|
31271
31564
|
const filterKeywords = opts?.keywords ? parseTags(opts.keywords) : null;
|
|
31272
31565
|
const results = [];
|
|
31273
31566
|
for (const file of files) {
|
|
31274
|
-
const record = parseAdrFile(
|
|
31567
|
+
const record = parseAdrFile(join53(adrsDir, file), projectRoot);
|
|
31275
31568
|
const fm = record.frontmatter;
|
|
31276
31569
|
if (opts?.status && fm.Status !== opts.status) continue;
|
|
31277
31570
|
if (filterTopics && filterTopics.length > 0) {
|
|
@@ -31349,12 +31642,12 @@ var init_adrs = __esm({
|
|
|
31349
31642
|
});
|
|
31350
31643
|
|
|
31351
31644
|
// src/core/admin/sync.ts
|
|
31352
|
-
import { join as
|
|
31645
|
+
import { join as join54 } from "node:path";
|
|
31353
31646
|
import { rm as rm2, rmdir, stat as stat2 } from "node:fs/promises";
|
|
31354
31647
|
async function getSyncStatus(projectRoot) {
|
|
31355
31648
|
try {
|
|
31356
31649
|
const cleoDir = getCleoDir(projectRoot);
|
|
31357
|
-
const stateFile =
|
|
31650
|
+
const stateFile = join54(cleoDir, "sync", "todowrite-session.json");
|
|
31358
31651
|
const sessionState = await readJson(stateFile);
|
|
31359
31652
|
if (!sessionState) {
|
|
31360
31653
|
return {
|
|
@@ -31398,8 +31691,8 @@ async function getSyncStatus(projectRoot) {
|
|
|
31398
31691
|
async function clearSyncState(projectRoot, dryRun) {
|
|
31399
31692
|
try {
|
|
31400
31693
|
const cleoDir = getCleoDir(projectRoot);
|
|
31401
|
-
const syncDir =
|
|
31402
|
-
const stateFile =
|
|
31694
|
+
const syncDir = join54(cleoDir, "sync");
|
|
31695
|
+
const stateFile = join54(syncDir, "todowrite-session.json");
|
|
31403
31696
|
let exists = false;
|
|
31404
31697
|
try {
|
|
31405
31698
|
await stat2(stateFile);
|
|
@@ -32166,8 +32459,8 @@ var init_import_tasks = __esm({
|
|
|
32166
32459
|
// src/core/snapshot/index.ts
|
|
32167
32460
|
import { createHash as createHash6 } from "node:crypto";
|
|
32168
32461
|
import { readFile as readFile13, writeFile as writeFile10, mkdir as mkdir10 } from "node:fs/promises";
|
|
32169
|
-
import { existsSync as
|
|
32170
|
-
import { join as
|
|
32462
|
+
import { existsSync as existsSync56 } from "node:fs";
|
|
32463
|
+
import { join as join55, dirname as dirname14 } from "node:path";
|
|
32171
32464
|
function toSnapshotTask(task) {
|
|
32172
32465
|
return {
|
|
32173
32466
|
id: task.id,
|
|
@@ -32220,7 +32513,7 @@ async function exportSnapshot(cwd) {
|
|
|
32220
32513
|
}
|
|
32221
32514
|
async function writeSnapshot(snapshot, outputPath) {
|
|
32222
32515
|
const dir = dirname14(outputPath);
|
|
32223
|
-
if (!
|
|
32516
|
+
if (!existsSync56(dir)) {
|
|
32224
32517
|
await mkdir10(dir, { recursive: true });
|
|
32225
32518
|
}
|
|
32226
32519
|
await writeFile10(outputPath, JSON.stringify(snapshot, null, 2) + "\n");
|
|
@@ -32236,7 +32529,7 @@ async function readSnapshot(inputPath) {
|
|
|
32236
32529
|
function getDefaultSnapshotPath(cwd) {
|
|
32237
32530
|
const cleoDir = getCleoDirAbsolute(cwd);
|
|
32238
32531
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
32239
|
-
return
|
|
32532
|
+
return join55(cleoDir, "snapshots", `snapshot-${timestamp}.json`);
|
|
32240
32533
|
}
|
|
32241
32534
|
async function importSnapshot(snapshot, cwd) {
|
|
32242
32535
|
const accessor = await getAccessor(cwd);
|
|
@@ -32534,15 +32827,15 @@ var init_archive_stats2 = __esm({
|
|
|
32534
32827
|
});
|
|
32535
32828
|
|
|
32536
32829
|
// src/core/project-info.ts
|
|
32537
|
-
import { readFileSync as
|
|
32538
|
-
import { join as
|
|
32830
|
+
import { readFileSync as readFileSync42, existsSync as existsSync57 } from "node:fs";
|
|
32831
|
+
import { join as join56 } from "node:path";
|
|
32539
32832
|
function getProjectInfoSync(cwd) {
|
|
32540
32833
|
const projectRoot = cwd ?? process.cwd();
|
|
32541
32834
|
const cleoDir = getCleoDirAbsolute(projectRoot);
|
|
32542
|
-
const infoPath =
|
|
32543
|
-
if (!
|
|
32835
|
+
const infoPath = join56(cleoDir, "project-info.json");
|
|
32836
|
+
if (!existsSync57(infoPath)) return null;
|
|
32544
32837
|
try {
|
|
32545
|
-
const raw =
|
|
32838
|
+
const raw = readFileSync42(infoPath, "utf-8");
|
|
32546
32839
|
const data = JSON.parse(raw);
|
|
32547
32840
|
if (typeof data.projectHash !== "string" || data.projectHash.length === 0) {
|
|
32548
32841
|
return null;
|
|
@@ -32629,8 +32922,8 @@ var init_defaults = __esm({
|
|
|
32629
32922
|
});
|
|
32630
32923
|
|
|
32631
32924
|
// src/mcp/lib/config.ts
|
|
32632
|
-
import { readFileSync as
|
|
32633
|
-
import { join as
|
|
32925
|
+
import { readFileSync as readFileSync43, existsSync as existsSync58 } from "fs";
|
|
32926
|
+
import { join as join57 } from "path";
|
|
32634
32927
|
function loadFromEnv(key) {
|
|
32635
32928
|
const envKey = `${ENV_PREFIX}${key.toUpperCase()}`;
|
|
32636
32929
|
return process.env[envKey];
|
|
@@ -32651,12 +32944,12 @@ function parseEnvValue2(key, value) {
|
|
|
32651
32944
|
}
|
|
32652
32945
|
function loadFromFile(projectRoot) {
|
|
32653
32946
|
const root = projectRoot || process.cwd();
|
|
32654
|
-
const configPath =
|
|
32655
|
-
if (!
|
|
32947
|
+
const configPath = join57(root, ".cleo", "config.json");
|
|
32948
|
+
if (!existsSync58(configPath)) {
|
|
32656
32949
|
return {};
|
|
32657
32950
|
}
|
|
32658
32951
|
try {
|
|
32659
|
-
const content =
|
|
32952
|
+
const content = readFileSync43(configPath, "utf-8");
|
|
32660
32953
|
const config = JSON.parse(content);
|
|
32661
32954
|
const result = {};
|
|
32662
32955
|
if (config.mcp) {
|
|
@@ -32996,8 +33289,8 @@ __export(session_grade_exports, {
|
|
|
32996
33289
|
gradeSession: () => gradeSession,
|
|
32997
33290
|
readGrades: () => readGrades
|
|
32998
33291
|
});
|
|
32999
|
-
import { join as
|
|
33000
|
-
import { existsSync as
|
|
33292
|
+
import { join as join58 } from "node:path";
|
|
33293
|
+
import { existsSync as existsSync59 } from "node:fs";
|
|
33001
33294
|
import { readFile as readFile14, appendFile, mkdir as mkdir11 } from "node:fs/promises";
|
|
33002
33295
|
async function gradeSession(sessionId, cwd) {
|
|
33003
33296
|
const sessionEntries = await queryAudit({ sessionId });
|
|
@@ -33177,9 +33470,9 @@ function detectDuplicateCreates(entries) {
|
|
|
33177
33470
|
async function appendGradeResult(result, cwd) {
|
|
33178
33471
|
try {
|
|
33179
33472
|
const cleoDir = getCleoDirAbsolute(cwd);
|
|
33180
|
-
const metricsDir =
|
|
33473
|
+
const metricsDir = join58(cleoDir, "metrics");
|
|
33181
33474
|
await mkdir11(metricsDir, { recursive: true });
|
|
33182
|
-
const gradesPath =
|
|
33475
|
+
const gradesPath = join58(metricsDir, "GRADES.jsonl");
|
|
33183
33476
|
const line = JSON.stringify({ ...result, evaluator: "auto" }) + "\n";
|
|
33184
33477
|
await appendFile(gradesPath, line, "utf8");
|
|
33185
33478
|
} catch {
|
|
@@ -33188,8 +33481,8 @@ async function appendGradeResult(result, cwd) {
|
|
|
33188
33481
|
async function readGrades(sessionId, cwd) {
|
|
33189
33482
|
try {
|
|
33190
33483
|
const cleoDir = getCleoDirAbsolute(cwd);
|
|
33191
|
-
const gradesPath =
|
|
33192
|
-
if (!
|
|
33484
|
+
const gradesPath = join58(cleoDir, "metrics", "GRADES.jsonl");
|
|
33485
|
+
if (!existsSync59(gradesPath)) return [];
|
|
33193
33486
|
const content = await readFile14(gradesPath, "utf8");
|
|
33194
33487
|
const results = content.split("\n").filter((l) => l.trim()).map((l) => JSON.parse(l));
|
|
33195
33488
|
return sessionId ? results.filter((r) => r.sessionId === sessionId) : results;
|
|
@@ -35543,6 +35836,7 @@ var init_pipeline2 = __esm({
|
|
|
35543
35836
|
"release.push",
|
|
35544
35837
|
"release.gates.run",
|
|
35545
35838
|
"release.rollback",
|
|
35839
|
+
"release.cancel",
|
|
35546
35840
|
"release.ship",
|
|
35547
35841
|
"manifest.append",
|
|
35548
35842
|
"manifest.archive",
|
|
@@ -35907,6 +36201,20 @@ var init_pipeline2 = __esm({
|
|
|
35907
36201
|
const result = await releaseRollback(version, reason, this.projectRoot);
|
|
35908
36202
|
return this.wrapEngineResult(result, "mutate", "release.rollback", startTime);
|
|
35909
36203
|
}
|
|
36204
|
+
case "cancel": {
|
|
36205
|
+
const version = params?.version;
|
|
36206
|
+
if (!version) {
|
|
36207
|
+
return this.errorResponse(
|
|
36208
|
+
"mutate",
|
|
36209
|
+
"release.cancel",
|
|
36210
|
+
"E_INVALID_INPUT",
|
|
36211
|
+
"version is required",
|
|
36212
|
+
startTime
|
|
36213
|
+
);
|
|
36214
|
+
}
|
|
36215
|
+
const result = await releaseCancel(version, this.projectRoot);
|
|
36216
|
+
return this.wrapEngineResult(result, "mutate", "release.cancel", startTime);
|
|
36217
|
+
}
|
|
35910
36218
|
case "ship": {
|
|
35911
36219
|
const version = params?.version;
|
|
35912
36220
|
const epicId = params?.epicId;
|
|
@@ -35921,8 +36229,9 @@ var init_pipeline2 = __esm({
|
|
|
35921
36229
|
}
|
|
35922
36230
|
const remote = params?.remote;
|
|
35923
36231
|
const dryRun = params?.dryRun;
|
|
36232
|
+
const bump = params?.bump;
|
|
35924
36233
|
const result = await releaseShip(
|
|
35925
|
-
{ version, epicId, remote, dryRun },
|
|
36234
|
+
{ version, epicId, remote, dryRun, bump },
|
|
35926
36235
|
this.projectRoot
|
|
35927
36236
|
);
|
|
35928
36237
|
return this.wrapEngineResult(result, "mutate", "release.ship", startTime);
|
|
@@ -36448,7 +36757,7 @@ var init_build_config = __esm({
|
|
|
36448
36757
|
"use strict";
|
|
36449
36758
|
BUILD_CONFIG = {
|
|
36450
36759
|
"name": "@cleocode/cleo",
|
|
36451
|
-
"version": "2026.3.
|
|
36760
|
+
"version": "2026.3.19",
|
|
36452
36761
|
"description": "CLEO V2 - TypeScript task management CLI for AI coding agents",
|
|
36453
36762
|
"repository": {
|
|
36454
36763
|
"owner": "kryptobaseddev",
|
|
@@ -36457,7 +36766,7 @@ var init_build_config = __esm({
|
|
|
36457
36766
|
"url": "https://github.com/kryptobaseddev/cleo.git",
|
|
36458
36767
|
"issuesUrl": "https://github.com/kryptobaseddev/cleo/issues"
|
|
36459
36768
|
},
|
|
36460
|
-
"buildDate": "2026-03-
|
|
36769
|
+
"buildDate": "2026-03-07T20:22:23.104Z",
|
|
36461
36770
|
"templates": {
|
|
36462
36771
|
"issueTemplatesDir": "templates/issue-templates"
|
|
36463
36772
|
}
|
|
@@ -36466,8 +36775,8 @@ var init_build_config = __esm({
|
|
|
36466
36775
|
});
|
|
36467
36776
|
|
|
36468
36777
|
// src/core/issue/template-parser.ts
|
|
36469
|
-
import { existsSync as
|
|
36470
|
-
import { join as
|
|
36778
|
+
import { existsSync as existsSync60, readFileSync as readFileSync44, readdirSync as readdirSync17, writeFileSync as writeFileSync9 } from "node:fs";
|
|
36779
|
+
import { join as join59, basename as basename10 } from "node:path";
|
|
36471
36780
|
function extractYamlField(content, field) {
|
|
36472
36781
|
const regex = new RegExp(`^${field}:\\s*["']?(.+?)["']?\\s*$`, "m");
|
|
36473
36782
|
const match = content.match(regex);
|
|
@@ -36499,9 +36808,9 @@ function extractYamlArray(content, field) {
|
|
|
36499
36808
|
return items;
|
|
36500
36809
|
}
|
|
36501
36810
|
function parseTemplateFile2(filePath) {
|
|
36502
|
-
if (!
|
|
36811
|
+
if (!existsSync60(filePath)) return null;
|
|
36503
36812
|
try {
|
|
36504
|
-
const content =
|
|
36813
|
+
const content = readFileSync44(filePath, "utf-8");
|
|
36505
36814
|
const fileName = basename10(filePath);
|
|
36506
36815
|
const stem = fileName.replace(/\.ya?ml$/, "");
|
|
36507
36816
|
const name = extractYamlField(content, "name");
|
|
@@ -36518,12 +36827,12 @@ function parseTemplateFile2(filePath) {
|
|
|
36518
36827
|
function parseIssueTemplates2(projectDir) {
|
|
36519
36828
|
try {
|
|
36520
36829
|
const packageRoot = getPackageRoot();
|
|
36521
|
-
const packagedTemplateDir =
|
|
36522
|
-
if (
|
|
36830
|
+
const packagedTemplateDir = join59(packageRoot, PACKAGED_TEMPLATE_DIR);
|
|
36831
|
+
if (existsSync60(packagedTemplateDir)) {
|
|
36523
36832
|
const templates3 = [];
|
|
36524
36833
|
for (const file of readdirSync17(packagedTemplateDir)) {
|
|
36525
36834
|
if (!file.endsWith(".yml") && !file.endsWith(".yaml")) continue;
|
|
36526
|
-
const template = parseTemplateFile2(
|
|
36835
|
+
const template = parseTemplateFile2(join59(packagedTemplateDir, file));
|
|
36527
36836
|
if (template) templates3.push(template);
|
|
36528
36837
|
}
|
|
36529
36838
|
if (templates3.length > 0) return templates3;
|
|
@@ -36531,12 +36840,12 @@ function parseIssueTemplates2(projectDir) {
|
|
|
36531
36840
|
} catch {
|
|
36532
36841
|
}
|
|
36533
36842
|
const dir = projectDir ?? getProjectRoot();
|
|
36534
|
-
const templateDir =
|
|
36535
|
-
if (!
|
|
36843
|
+
const templateDir = join59(dir, TEMPLATE_DIR);
|
|
36844
|
+
if (!existsSync60(templateDir)) return [];
|
|
36536
36845
|
const templates2 = [];
|
|
36537
36846
|
for (const file of readdirSync17(templateDir)) {
|
|
36538
36847
|
if (!file.endsWith(".yml") && !file.endsWith(".yaml")) continue;
|
|
36539
|
-
const template = parseTemplateFile2(
|
|
36848
|
+
const template = parseTemplateFile2(join59(templateDir, file));
|
|
36540
36849
|
if (template) templates2.push(template);
|
|
36541
36850
|
}
|
|
36542
36851
|
return templates2;
|
|
@@ -36545,10 +36854,10 @@ function getTemplateConfig(cwd) {
|
|
|
36545
36854
|
const projectDir = cwd ?? getProjectRoot();
|
|
36546
36855
|
const liveTemplates = parseIssueTemplates2(projectDir);
|
|
36547
36856
|
if (liveTemplates.length > 0) return liveTemplates;
|
|
36548
|
-
const cachePath =
|
|
36549
|
-
if (
|
|
36857
|
+
const cachePath = join59(getCleoDir(cwd), CACHE_FILE);
|
|
36858
|
+
if (existsSync60(cachePath)) {
|
|
36550
36859
|
try {
|
|
36551
|
-
const cached = JSON.parse(
|
|
36860
|
+
const cached = JSON.parse(readFileSync44(cachePath, "utf-8"));
|
|
36552
36861
|
if (cached.templates?.length > 0) return cached.templates;
|
|
36553
36862
|
} catch {
|
|
36554
36863
|
}
|
|
@@ -37607,8 +37916,8 @@ var init_tools = __esm({
|
|
|
37607
37916
|
});
|
|
37608
37917
|
|
|
37609
37918
|
// src/core/nexus/query.ts
|
|
37610
|
-
import { join as
|
|
37611
|
-
import { existsSync as
|
|
37919
|
+
import { join as join60, basename as basename11 } from "node:path";
|
|
37920
|
+
import { existsSync as existsSync61, readFileSync as readFileSync45 } from "node:fs";
|
|
37612
37921
|
import { z as z3 } from "zod";
|
|
37613
37922
|
function validateSyntax(query) {
|
|
37614
37923
|
if (!query) return false;
|
|
@@ -37644,9 +37953,9 @@ function getCurrentProject() {
|
|
|
37644
37953
|
return process.env["NEXUS_CURRENT_PROJECT"];
|
|
37645
37954
|
}
|
|
37646
37955
|
try {
|
|
37647
|
-
const infoPath =
|
|
37648
|
-
if (
|
|
37649
|
-
const data = JSON.parse(
|
|
37956
|
+
const infoPath = join60(process.cwd(), ".cleo", "project-info.json");
|
|
37957
|
+
if (existsSync61(infoPath)) {
|
|
37958
|
+
const data = JSON.parse(readFileSync45(infoPath, "utf-8"));
|
|
37650
37959
|
if (typeof data.name === "string" && data.name.length > 0) {
|
|
37651
37960
|
return data.name;
|
|
37652
37961
|
}
|
|
@@ -37682,7 +37991,7 @@ async function resolveProjectPath2(projectName) {
|
|
|
37682
37991
|
return project.path;
|
|
37683
37992
|
}
|
|
37684
37993
|
async function readProjectTasks(projectPath) {
|
|
37685
|
-
const tasksDbPath =
|
|
37994
|
+
const tasksDbPath = join60(projectPath, ".cleo", "tasks.db");
|
|
37686
37995
|
try {
|
|
37687
37996
|
const accessor = await getAccessor(projectPath);
|
|
37688
37997
|
const taskFile = await accessor.loadTaskFile();
|
|
@@ -38096,8 +38405,8 @@ var init_deps2 = __esm({
|
|
|
38096
38405
|
|
|
38097
38406
|
// src/core/nexus/sharing/index.ts
|
|
38098
38407
|
import { readFile as readFile15, writeFile as writeFile11 } from "node:fs/promises";
|
|
38099
|
-
import { existsSync as
|
|
38100
|
-
import { join as
|
|
38408
|
+
import { existsSync as existsSync62, readdirSync as readdirSync18, statSync as statSync8 } from "node:fs";
|
|
38409
|
+
import { join as join61, relative as relative4 } from "node:path";
|
|
38101
38410
|
function matchesPattern(filePath, pattern) {
|
|
38102
38411
|
const normalizedPath = filePath.replace(/^\/+|\/+$/g, "");
|
|
38103
38412
|
const normalizedPattern = pattern.replace(/^\/+|\/+$/g, "");
|
|
@@ -38122,7 +38431,7 @@ function collectCleoFiles(cleoDir) {
|
|
|
38122
38431
|
const entries = readdirSync18(dir);
|
|
38123
38432
|
for (const entry of entries) {
|
|
38124
38433
|
if (entry === ".git") continue;
|
|
38125
|
-
const fullPath =
|
|
38434
|
+
const fullPath = join61(dir, entry);
|
|
38126
38435
|
const relPath = relative4(cleoDir, fullPath);
|
|
38127
38436
|
try {
|
|
38128
38437
|
const stat5 = statSync8(fullPath);
|
|
@@ -38182,7 +38491,7 @@ function generateGitignoreEntries(sharing) {
|
|
|
38182
38491
|
async function syncGitignore(cwd) {
|
|
38183
38492
|
const config = await loadConfig(cwd);
|
|
38184
38493
|
const projectRoot = getProjectRoot(cwd);
|
|
38185
|
-
const gitignorePath =
|
|
38494
|
+
const gitignorePath = join61(projectRoot, ".gitignore");
|
|
38186
38495
|
const entries = generateGitignoreEntries(config.sharing);
|
|
38187
38496
|
const managedSection = [
|
|
38188
38497
|
"",
|
|
@@ -38192,7 +38501,7 @@ async function syncGitignore(cwd) {
|
|
|
38192
38501
|
""
|
|
38193
38502
|
].join("\n");
|
|
38194
38503
|
let content = "";
|
|
38195
|
-
if (
|
|
38504
|
+
if (existsSync62(gitignorePath)) {
|
|
38196
38505
|
content = await readFile15(gitignorePath, "utf-8");
|
|
38197
38506
|
}
|
|
38198
38507
|
const startIdx = content.indexOf(GITIGNORE_START);
|
|
@@ -40114,13 +40423,13 @@ var init_field_context = __esm({
|
|
|
40114
40423
|
});
|
|
40115
40424
|
|
|
40116
40425
|
// src/core/sessions/context-alert.ts
|
|
40117
|
-
import { existsSync as
|
|
40118
|
-
import { join as
|
|
40426
|
+
import { existsSync as existsSync63, readFileSync as readFileSync46, writeFileSync as writeFileSync10 } from "node:fs";
|
|
40427
|
+
import { join as join62 } from "node:path";
|
|
40119
40428
|
function getCurrentSessionId(cwd) {
|
|
40120
40429
|
if (process.env.CLEO_SESSION) return process.env.CLEO_SESSION;
|
|
40121
|
-
const sessionFile =
|
|
40122
|
-
if (
|
|
40123
|
-
return
|
|
40430
|
+
const sessionFile = join62(getCleoDir(cwd), ".current-session");
|
|
40431
|
+
if (existsSync63(sessionFile)) {
|
|
40432
|
+
return readFileSync46(sessionFile, "utf-8").trim() || null;
|
|
40124
40433
|
}
|
|
40125
40434
|
return null;
|
|
40126
40435
|
}
|
|
@@ -41183,7 +41492,7 @@ async function stopTask2(sessionId, cwd) {
|
|
|
41183
41492
|
}
|
|
41184
41493
|
async function workHistory(sessionId, limit = 50, cwd) {
|
|
41185
41494
|
const db = await getDb(cwd);
|
|
41186
|
-
const rows = await db.select().from(taskWorkHistory).where(eq16(taskWorkHistory.sessionId, sessionId)).orderBy(desc5(taskWorkHistory.setAt)).limit(limit).all();
|
|
41495
|
+
const rows = await db.select().from(taskWorkHistory).where(eq16(taskWorkHistory.sessionId, sessionId)).orderBy(desc5(taskWorkHistory.setAt), desc5(taskWorkHistory.id)).limit(limit).all();
|
|
41187
41496
|
return rows.map((r) => ({
|
|
41188
41497
|
taskId: r.taskId,
|
|
41189
41498
|
setAt: r.setAt,
|
|
@@ -41367,14 +41676,14 @@ __export(logger_exports, {
|
|
|
41367
41676
|
logFileExists: () => logFileExists,
|
|
41368
41677
|
readMigrationLog: () => readMigrationLog
|
|
41369
41678
|
});
|
|
41370
|
-
import { existsSync as
|
|
41371
|
-
import { join as
|
|
41679
|
+
import { existsSync as existsSync66, mkdirSync as mkdirSync16, statSync as statSync9, appendFileSync as appendFileSync4 } from "node:fs";
|
|
41680
|
+
import { join as join69, dirname as dirname16, relative as relative6 } from "node:path";
|
|
41372
41681
|
function createMigrationLogger(cleoDir, config) {
|
|
41373
41682
|
return new MigrationLogger(cleoDir, config);
|
|
41374
41683
|
}
|
|
41375
41684
|
function readMigrationLog(logPath) {
|
|
41376
|
-
const { readFileSync:
|
|
41377
|
-
const content =
|
|
41685
|
+
const { readFileSync: readFileSync54 } = __require("node:fs");
|
|
41686
|
+
const content = readFileSync54(logPath, "utf-8");
|
|
41378
41687
|
return content.split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
41379
41688
|
}
|
|
41380
41689
|
function logFileExists(logPath) {
|
|
@@ -41389,14 +41698,14 @@ function logFileExists(logPath) {
|
|
|
41389
41698
|
function getLatestMigrationLog(cleoDir) {
|
|
41390
41699
|
try {
|
|
41391
41700
|
const { readdirSync: readdirSync21, statSync: statSync10 } = __require("node:fs");
|
|
41392
|
-
const logsDir =
|
|
41393
|
-
if (!
|
|
41701
|
+
const logsDir = join69(cleoDir, "logs");
|
|
41702
|
+
if (!existsSync66(logsDir)) {
|
|
41394
41703
|
return null;
|
|
41395
41704
|
}
|
|
41396
41705
|
const files = readdirSync21(logsDir).filter((f) => f.startsWith("migration-") && f.endsWith(".jsonl")).map((f) => ({
|
|
41397
41706
|
name: f,
|
|
41398
|
-
path:
|
|
41399
|
-
mtime: statSync10(
|
|
41707
|
+
path: join69(logsDir, f),
|
|
41708
|
+
mtime: statSync10(join69(logsDir, f)).mtime.getTime()
|
|
41400
41709
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
41401
41710
|
return files.length > 0 ? files[0].path : null;
|
|
41402
41711
|
} catch {
|
|
@@ -41426,9 +41735,9 @@ var init_logger2 = __esm({
|
|
|
41426
41735
|
consoleOutput: config.consoleOutput ?? false
|
|
41427
41736
|
};
|
|
41428
41737
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
41429
|
-
this.logPath =
|
|
41738
|
+
this.logPath = join69(cleoDir, "logs", `migration-${timestamp}.jsonl`);
|
|
41430
41739
|
const logsDir = dirname16(this.logPath);
|
|
41431
|
-
if (!
|
|
41740
|
+
if (!existsSync66(logsDir)) {
|
|
41432
41741
|
mkdirSync16(logsDir, { recursive: true });
|
|
41433
41742
|
}
|
|
41434
41743
|
this.startTime = Date.now();
|
|
@@ -41517,7 +41826,7 @@ var init_logger2 = __esm({
|
|
|
41517
41826
|
sourcePath: relative6(this.cleoDir, sourcePath),
|
|
41518
41827
|
...additionalData
|
|
41519
41828
|
};
|
|
41520
|
-
if (
|
|
41829
|
+
if (existsSync66(sourcePath)) {
|
|
41521
41830
|
try {
|
|
41522
41831
|
const stats2 = statSync9(sourcePath);
|
|
41523
41832
|
data.sourceSize = stats2.size;
|
|
@@ -41527,7 +41836,7 @@ var init_logger2 = __esm({
|
|
|
41527
41836
|
}
|
|
41528
41837
|
if (targetPath) {
|
|
41529
41838
|
data.targetPath = relative6(this.cleoDir, targetPath);
|
|
41530
|
-
if (
|
|
41839
|
+
if (existsSync66(targetPath)) {
|
|
41531
41840
|
try {
|
|
41532
41841
|
const stats2 = statSync9(targetPath);
|
|
41533
41842
|
data.targetSize = stats2.size;
|
|
@@ -41596,15 +41905,15 @@ var init_logger2 = __esm({
|
|
|
41596
41905
|
*/
|
|
41597
41906
|
cleanupOldLogs() {
|
|
41598
41907
|
try {
|
|
41599
|
-
const logsDir =
|
|
41600
|
-
if (!
|
|
41908
|
+
const logsDir = join69(this.cleoDir, "logs");
|
|
41909
|
+
if (!existsSync66(logsDir)) {
|
|
41601
41910
|
return;
|
|
41602
41911
|
}
|
|
41603
41912
|
const { readdirSync: readdirSync21, unlinkSync: unlinkSync5 } = __require("node:fs");
|
|
41604
41913
|
const files = readdirSync21(logsDir).filter((f) => f.startsWith("migration-") && f.endsWith(".jsonl")).map((f) => ({
|
|
41605
41914
|
name: f,
|
|
41606
|
-
path:
|
|
41607
|
-
mtime: statSync9(
|
|
41915
|
+
path: join69(logsDir, f),
|
|
41916
|
+
mtime: statSync9(join69(logsDir, f)).mtime.getTime()
|
|
41608
41917
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
41609
41918
|
const filesToRemove = files.slice(this.config.maxLogFiles);
|
|
41610
41919
|
for (const file of filesToRemove) {
|
|
@@ -41700,8 +42009,8 @@ __export(state_exports, {
|
|
|
41700
42009
|
verifySourceIntegrity: () => verifySourceIntegrity
|
|
41701
42010
|
});
|
|
41702
42011
|
import { readFile as readFile19, writeFile as writeFile13, unlink as unlink5 } from "node:fs/promises";
|
|
41703
|
-
import { join as
|
|
41704
|
-
import { existsSync as
|
|
42012
|
+
import { join as join70 } from "node:path";
|
|
42013
|
+
import { existsSync as existsSync67 } from "node:fs";
|
|
41705
42014
|
import { createHash as createHash8 } from "node:crypto";
|
|
41706
42015
|
async function computeFileChecksum(filePath) {
|
|
41707
42016
|
try {
|
|
@@ -41723,8 +42032,8 @@ async function countRecords(filePath, key) {
|
|
|
41723
42032
|
async function createMigrationState(cleoDir, sourceFiles) {
|
|
41724
42033
|
const files = sourceFiles ?? {};
|
|
41725
42034
|
if (!files.todoJson) {
|
|
41726
|
-
const todoPath =
|
|
41727
|
-
if (
|
|
42035
|
+
const todoPath = join70(cleoDir, "todo.json");
|
|
42036
|
+
if (existsSync67(todoPath)) {
|
|
41728
42037
|
files.todoJson = {
|
|
41729
42038
|
path: todoPath,
|
|
41730
42039
|
checksum: await computeFileChecksum(todoPath),
|
|
@@ -41733,8 +42042,8 @@ async function createMigrationState(cleoDir, sourceFiles) {
|
|
|
41733
42042
|
}
|
|
41734
42043
|
}
|
|
41735
42044
|
if (!files.sessionsJson) {
|
|
41736
|
-
const sessionsPath =
|
|
41737
|
-
if (
|
|
42045
|
+
const sessionsPath = join70(cleoDir, "sessions.json");
|
|
42046
|
+
if (existsSync67(sessionsPath)) {
|
|
41738
42047
|
files.sessionsJson = {
|
|
41739
42048
|
path: sessionsPath,
|
|
41740
42049
|
checksum: await computeFileChecksum(sessionsPath),
|
|
@@ -41743,8 +42052,8 @@ async function createMigrationState(cleoDir, sourceFiles) {
|
|
|
41743
42052
|
}
|
|
41744
42053
|
}
|
|
41745
42054
|
if (!files.archiveJson) {
|
|
41746
|
-
const archivePath =
|
|
41747
|
-
if (
|
|
42055
|
+
const archivePath = join70(cleoDir, "todo-archive.json");
|
|
42056
|
+
if (existsSync67(archivePath)) {
|
|
41748
42057
|
files.archiveJson = {
|
|
41749
42058
|
path: archivePath,
|
|
41750
42059
|
checksum: await computeFileChecksum(archivePath),
|
|
@@ -41772,7 +42081,7 @@ async function createMigrationState(cleoDir, sourceFiles) {
|
|
|
41772
42081
|
return state;
|
|
41773
42082
|
}
|
|
41774
42083
|
async function writeMigrationState(cleoDir, state) {
|
|
41775
|
-
const statePath =
|
|
42084
|
+
const statePath = join70(cleoDir, STATE_FILENAME);
|
|
41776
42085
|
const tempPath = `${statePath}.tmp`;
|
|
41777
42086
|
await writeFile13(tempPath, JSON.stringify(state, null, 2));
|
|
41778
42087
|
await writeFile13(statePath, await readFile19(tempPath));
|
|
@@ -41847,7 +42156,7 @@ async function addMigrationWarning(cleoDir, warning) {
|
|
|
41847
42156
|
}
|
|
41848
42157
|
async function loadMigrationState(cleoDir) {
|
|
41849
42158
|
try {
|
|
41850
|
-
const statePath =
|
|
42159
|
+
const statePath = join70(cleoDir, STATE_FILENAME);
|
|
41851
42160
|
const content = await readFile19(statePath, "utf-8");
|
|
41852
42161
|
return JSON.parse(content);
|
|
41853
42162
|
} catch {
|
|
@@ -41889,7 +42198,7 @@ async function failMigration(cleoDir, error) {
|
|
|
41889
42198
|
}
|
|
41890
42199
|
async function clearMigrationState(cleoDir) {
|
|
41891
42200
|
try {
|
|
41892
|
-
const statePath =
|
|
42201
|
+
const statePath = join70(cleoDir, STATE_FILENAME);
|
|
41893
42202
|
await unlink5(statePath);
|
|
41894
42203
|
} catch {
|
|
41895
42204
|
}
|
|
@@ -41929,7 +42238,7 @@ async function verifySourceIntegrity(cleoDir) {
|
|
|
41929
42238
|
const missing = [];
|
|
41930
42239
|
for (const [key, fileInfo] of Object.entries(state.sourceFiles)) {
|
|
41931
42240
|
if (!fileInfo) continue;
|
|
41932
|
-
if (!
|
|
42241
|
+
if (!existsSync67(fileInfo.path)) {
|
|
41933
42242
|
missing.push(key);
|
|
41934
42243
|
continue;
|
|
41935
42244
|
}
|
|
@@ -41960,8 +42269,8 @@ __export(migration_sqlite_exports, {
|
|
|
41960
42269
|
migrateJsonToSqlite: () => migrateJsonToSqlite2,
|
|
41961
42270
|
migrateJsonToSqliteAtomic: () => migrateJsonToSqliteAtomic
|
|
41962
42271
|
});
|
|
41963
|
-
import { existsSync as
|
|
41964
|
-
import { join as
|
|
42272
|
+
import { existsSync as existsSync68, readFileSync as readFileSync49 } from "node:fs";
|
|
42273
|
+
import { join as join71, dirname as dirname17 } from "node:path";
|
|
41965
42274
|
import { mkdirSync as mkdirSync17 } from "node:fs";
|
|
41966
42275
|
import { drizzle as drizzle4 } from "drizzle-orm/sqlite-proxy";
|
|
41967
42276
|
import { migrate as migrate4 } from "drizzle-orm/sqlite-proxy/migrator";
|
|
@@ -41999,26 +42308,26 @@ function countJsonRecords(cleoDir) {
|
|
|
41999
42308
|
let tasks2 = 0;
|
|
42000
42309
|
let archived = 0;
|
|
42001
42310
|
let sessions2 = 0;
|
|
42002
|
-
const todoPath =
|
|
42003
|
-
if (
|
|
42311
|
+
const todoPath = join71(cleoDir, "todo.json");
|
|
42312
|
+
if (existsSync68(todoPath)) {
|
|
42004
42313
|
try {
|
|
42005
|
-
const data = JSON.parse(
|
|
42314
|
+
const data = JSON.parse(readFileSync49(todoPath, "utf-8"));
|
|
42006
42315
|
tasks2 = (data.tasks ?? []).length;
|
|
42007
42316
|
} catch {
|
|
42008
42317
|
}
|
|
42009
42318
|
}
|
|
42010
|
-
const archivePath =
|
|
42011
|
-
if (
|
|
42319
|
+
const archivePath = join71(cleoDir, "todo-archive.json");
|
|
42320
|
+
if (existsSync68(archivePath)) {
|
|
42012
42321
|
try {
|
|
42013
|
-
const data = JSON.parse(
|
|
42322
|
+
const data = JSON.parse(readFileSync49(archivePath, "utf-8"));
|
|
42014
42323
|
archived = (data.tasks ?? data.archivedTasks ?? []).length;
|
|
42015
42324
|
} catch {
|
|
42016
42325
|
}
|
|
42017
42326
|
}
|
|
42018
|
-
const sessionsPath =
|
|
42019
|
-
if (
|
|
42327
|
+
const sessionsPath = join71(cleoDir, "sessions.json");
|
|
42328
|
+
if (existsSync68(sessionsPath)) {
|
|
42020
42329
|
try {
|
|
42021
|
-
const data = JSON.parse(
|
|
42330
|
+
const data = JSON.parse(readFileSync49(sessionsPath, "utf-8"));
|
|
42022
42331
|
sessions2 = (data.sessions ?? []).length;
|
|
42023
42332
|
} catch {
|
|
42024
42333
|
}
|
|
@@ -42095,13 +42404,13 @@ async function migrateJsonToSqliteAtomic(cwd, tempDbPath, logger) {
|
|
|
42095
42404
|
}
|
|
42096
42405
|
}
|
|
42097
42406
|
async function runMigrationDataImport(db, cleoDir, result, logger) {
|
|
42098
|
-
const todoPath =
|
|
42099
|
-
if (
|
|
42407
|
+
const todoPath = join71(cleoDir, "todo.json");
|
|
42408
|
+
if (existsSync68(todoPath)) {
|
|
42100
42409
|
try {
|
|
42101
42410
|
logger?.info("import", "read-todo", "Reading todo.json", {
|
|
42102
42411
|
path: todoPath.replace(cleoDir, ".")
|
|
42103
42412
|
});
|
|
42104
|
-
const todoData = JSON.parse(
|
|
42413
|
+
const todoData = JSON.parse(readFileSync49(todoPath, "utf-8"));
|
|
42105
42414
|
const tasks2 = topoSortTasks(todoData.tasks ?? []);
|
|
42106
42415
|
const totalTasks = tasks2.length;
|
|
42107
42416
|
logger?.info("import", "tasks-start", `Starting import of ${totalTasks} tasks`, {
|
|
@@ -42170,13 +42479,13 @@ async function runMigrationDataImport(db, cleoDir, result, logger) {
|
|
|
42170
42479
|
result.warnings.push("todo.json not found, skipping task import");
|
|
42171
42480
|
logger?.warn("import", "todo-missing", "todo.json not found, skipping task import");
|
|
42172
42481
|
}
|
|
42173
|
-
const archivePath =
|
|
42174
|
-
if (
|
|
42482
|
+
const archivePath = join71(cleoDir, "todo-archive.json");
|
|
42483
|
+
if (existsSync68(archivePath)) {
|
|
42175
42484
|
try {
|
|
42176
42485
|
logger?.info("import", "read-archive", "Reading todo-archive.json", {
|
|
42177
42486
|
path: archivePath.replace(cleoDir, ".")
|
|
42178
42487
|
});
|
|
42179
|
-
const archiveData = JSON.parse(
|
|
42488
|
+
const archiveData = JSON.parse(readFileSync49(archivePath, "utf-8"));
|
|
42180
42489
|
const archivedTasks = topoSortTasks(archiveData.tasks ?? archiveData.archivedTasks ?? []);
|
|
42181
42490
|
const totalArchived = archivedTasks.length;
|
|
42182
42491
|
logger?.info("import", "archive-start", `Starting import of ${totalArchived} archived tasks`, {
|
|
@@ -42229,13 +42538,13 @@ async function runMigrationDataImport(db, cleoDir, result, logger) {
|
|
|
42229
42538
|
logger?.error("import", "parse-archive", errorMsg);
|
|
42230
42539
|
}
|
|
42231
42540
|
}
|
|
42232
|
-
const sessionsPath =
|
|
42233
|
-
if (
|
|
42541
|
+
const sessionsPath = join71(cleoDir, "sessions.json");
|
|
42542
|
+
if (existsSync68(sessionsPath)) {
|
|
42234
42543
|
try {
|
|
42235
42544
|
logger?.info("import", "read-sessions", "Reading sessions.json", {
|
|
42236
42545
|
path: sessionsPath.replace(cleoDir, ".")
|
|
42237
42546
|
});
|
|
42238
|
-
const sessionsData = JSON.parse(
|
|
42547
|
+
const sessionsData = JSON.parse(readFileSync49(sessionsPath, "utf-8"));
|
|
42239
42548
|
const sessions2 = sessionsData.sessions ?? [];
|
|
42240
42549
|
const totalSessions = sessions2.length;
|
|
42241
42550
|
logger?.info("import", "sessions-start", `Starting import of ${totalSessions} sessions`, {
|
|
@@ -42367,10 +42676,10 @@ async function migrateJsonToSqlite2(cwd, options) {
|
|
|
42367
42676
|
return result;
|
|
42368
42677
|
}
|
|
42369
42678
|
const db = await getDb(cwd);
|
|
42370
|
-
const todoPath =
|
|
42371
|
-
if (
|
|
42679
|
+
const todoPath = join71(cleoDir, "todo.json");
|
|
42680
|
+
if (existsSync68(todoPath)) {
|
|
42372
42681
|
try {
|
|
42373
|
-
const todoData = JSON.parse(
|
|
42682
|
+
const todoData = JSON.parse(readFileSync49(todoPath, "utf-8"));
|
|
42374
42683
|
const tasks2 = topoSortTasks(todoData.tasks ?? []);
|
|
42375
42684
|
for (const task of tasks2) {
|
|
42376
42685
|
try {
|
|
@@ -42419,10 +42728,10 @@ async function migrateJsonToSqlite2(cwd, options) {
|
|
|
42419
42728
|
} else {
|
|
42420
42729
|
result.warnings.push("todo.json not found, skipping task import");
|
|
42421
42730
|
}
|
|
42422
|
-
const archivePath =
|
|
42423
|
-
if (
|
|
42731
|
+
const archivePath = join71(cleoDir, "todo-archive.json");
|
|
42732
|
+
if (existsSync68(archivePath)) {
|
|
42424
42733
|
try {
|
|
42425
|
-
const archiveData = JSON.parse(
|
|
42734
|
+
const archiveData = JSON.parse(readFileSync49(archivePath, "utf-8"));
|
|
42426
42735
|
const archivedTasks = topoSortTasks(archiveData.tasks ?? archiveData.archivedTasks ?? []);
|
|
42427
42736
|
for (const task of archivedTasks) {
|
|
42428
42737
|
try {
|
|
@@ -42459,11 +42768,11 @@ async function migrateJsonToSqlite2(cwd, options) {
|
|
|
42459
42768
|
result.errors.push(`Failed to parse todo-archive.json: ${String(err)}`);
|
|
42460
42769
|
}
|
|
42461
42770
|
}
|
|
42462
|
-
const sessionsPath =
|
|
42463
|
-
if (
|
|
42771
|
+
const sessionsPath = join71(cleoDir, "sessions.json");
|
|
42772
|
+
if (existsSync68(sessionsPath)) {
|
|
42464
42773
|
try {
|
|
42465
42774
|
const sessionsData = JSON.parse(
|
|
42466
|
-
|
|
42775
|
+
readFileSync49(sessionsPath, "utf-8")
|
|
42467
42776
|
);
|
|
42468
42777
|
const sessions2 = sessionsData.sessions ?? [];
|
|
42469
42778
|
for (const session of sessions2) {
|
|
@@ -42531,8 +42840,8 @@ var init_migration_sqlite = __esm({
|
|
|
42531
42840
|
|
|
42532
42841
|
// src/cli/index.ts
|
|
42533
42842
|
import { Command, Help } from "commander";
|
|
42534
|
-
import { readFileSync as
|
|
42535
|
-
import { join as
|
|
42843
|
+
import { readFileSync as readFileSync53 } from "node:fs";
|
|
42844
|
+
import { join as join77 } from "node:path";
|
|
42536
42845
|
|
|
42537
42846
|
// src/cli/commands/add.ts
|
|
42538
42847
|
init_cli();
|
|
@@ -43147,12 +43456,13 @@ function registerReleaseCommand(program2) {
|
|
|
43147
43456
|
notes: opts["notes"]
|
|
43148
43457
|
}, { command: "release" });
|
|
43149
43458
|
});
|
|
43150
|
-
release2.command("ship <version>").description("Ship a release: gates \u2192 changelog \u2192 commit \u2192 tag \u2192 push").requiredOption("--epic <id>", "Epic task ID for commit message (e.g. T5576)").option("--dry-run", "Preview all actions without writing anything").option("--no-push", "Commit and tag but skip git push").option("--remote <remote>", "Git remote to push to (default: origin)").action(async (version, opts) => {
|
|
43459
|
+
release2.command("ship <version>").description("Ship a release: gates \u2192 changelog \u2192 commit \u2192 tag \u2192 push").requiredOption("--epic <id>", "Epic task ID for commit message (e.g. T5576)").option("--dry-run", "Preview all actions without writing anything").option("--no-push", "Commit and tag but skip git push").option("--no-bump", "Skip version file bumping (default: bump if configured)").option("--remote <remote>", "Git remote to push to (default: origin)").action(async (version, opts) => {
|
|
43151
43460
|
await dispatchFromCli("mutate", "pipeline", "release.ship", {
|
|
43152
43461
|
version,
|
|
43153
43462
|
epicId: opts["epic"],
|
|
43154
43463
|
dryRun: opts["dryRun"],
|
|
43155
43464
|
push: opts["push"] !== false,
|
|
43465
|
+
bump: opts["bump"] !== false,
|
|
43156
43466
|
remote: opts["remote"]
|
|
43157
43467
|
}, { command: "release" });
|
|
43158
43468
|
});
|
|
@@ -43165,6 +43475,9 @@ function registerReleaseCommand(program2) {
|
|
|
43165
43475
|
release2.command("changelog <version>").description("Generate changelog for a release").action(async (version) => {
|
|
43166
43476
|
await dispatchFromCli("mutate", "pipeline", "release.changelog", { version }, { command: "release" });
|
|
43167
43477
|
});
|
|
43478
|
+
release2.command("cancel <version>").description("Cancel and remove a release in draft or prepared state").action(async (version) => {
|
|
43479
|
+
await dispatchFromCli("mutate", "pipeline", "release.cancel", { version }, { command: "release" });
|
|
43480
|
+
});
|
|
43168
43481
|
}
|
|
43169
43482
|
|
|
43170
43483
|
// src/cli/commands/env.ts
|
|
@@ -43382,14 +43695,14 @@ init_errors();
|
|
|
43382
43695
|
init_exit_codes();
|
|
43383
43696
|
init_paths();
|
|
43384
43697
|
init_json();
|
|
43385
|
-
import { join as
|
|
43698
|
+
import { join as join63 } from "node:path";
|
|
43386
43699
|
var VALID_CATEGORIES = ["write", "read", "sync", "maintenance"];
|
|
43387
43700
|
var VALID_RELEVANCE = ["critical", "high", "medium", "low"];
|
|
43388
43701
|
async function locateCommandsIndex() {
|
|
43389
43702
|
const cleoHome = getCleoHome();
|
|
43390
43703
|
const paths = [
|
|
43391
|
-
|
|
43392
|
-
|
|
43704
|
+
join63(cleoHome, "docs", "commands", "COMMANDS-INDEX.json"),
|
|
43705
|
+
join63(process.cwd(), "docs", "commands", "COMMANDS-INDEX.json")
|
|
43393
43706
|
];
|
|
43394
43707
|
for (const p of paths) {
|
|
43395
43708
|
const data = await readJson(p);
|
|
@@ -43470,9 +43783,9 @@ init_errors();
|
|
|
43470
43783
|
init_json();
|
|
43471
43784
|
init_paths();
|
|
43472
43785
|
import { readdir as readdir2, readFile as readFile16 } from "node:fs/promises";
|
|
43473
|
-
import { join as
|
|
43786
|
+
import { join as join64 } from "node:path";
|
|
43474
43787
|
async function getScriptNames(projectRoot) {
|
|
43475
|
-
const scriptsDir =
|
|
43788
|
+
const scriptsDir = join64(projectRoot, "scripts");
|
|
43476
43789
|
try {
|
|
43477
43790
|
const files = await readdir2(scriptsDir);
|
|
43478
43791
|
return files.filter((f) => f.endsWith(".sh")).map((f) => f.replace(".sh", "")).sort();
|
|
@@ -43481,7 +43794,7 @@ async function getScriptNames(projectRoot) {
|
|
|
43481
43794
|
}
|
|
43482
43795
|
}
|
|
43483
43796
|
async function getIndexedCommands(projectRoot) {
|
|
43484
|
-
const indexPath =
|
|
43797
|
+
const indexPath = join64(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
|
|
43485
43798
|
const index5 = await readJson(indexPath);
|
|
43486
43799
|
if (!index5) return [];
|
|
43487
43800
|
return index5.commands.map((c) => c.name).sort();
|
|
@@ -43514,7 +43827,7 @@ async function runGapCheck(_projectRoot, filterId) {
|
|
|
43514
43827
|
const reviewFiles = files.filter((f) => f.endsWith(".md"));
|
|
43515
43828
|
for (const file of reviewFiles) {
|
|
43516
43829
|
if (filterId && !file.includes(filterId)) continue;
|
|
43517
|
-
const filePath =
|
|
43830
|
+
const filePath = join64(reviewDir, file);
|
|
43518
43831
|
const content = await readFile16(filePath, "utf-8");
|
|
43519
43832
|
const taskMatch = file.match(/^(T\d+)/);
|
|
43520
43833
|
const taskId = taskMatch ? taskMatch[1] : "UNKNOWN";
|
|
@@ -43618,7 +43931,7 @@ init_paths();
|
|
|
43618
43931
|
init_json();
|
|
43619
43932
|
init_data_accessor();
|
|
43620
43933
|
import { readFile as readFile17, rm as rm3, stat as stat3 } from "node:fs/promises";
|
|
43621
|
-
import { join as
|
|
43934
|
+
import { join as join65 } from "node:path";
|
|
43622
43935
|
function parseTaskId(content) {
|
|
43623
43936
|
const match = content.match(/^\[T(\d+)\]/);
|
|
43624
43937
|
return match ? `T${match[1]}` : null;
|
|
@@ -43674,7 +43987,7 @@ function registerExtractCommand(program2) {
|
|
|
43674
43987
|
const accessor = await getAccessor();
|
|
43675
43988
|
const taskData = await accessor.loadTaskFile();
|
|
43676
43989
|
const cleoDir = getCleoDir();
|
|
43677
|
-
const stateFile =
|
|
43990
|
+
const stateFile = join65(cleoDir, "sync", "todowrite-session.json");
|
|
43678
43991
|
let sessionState = null;
|
|
43679
43992
|
try {
|
|
43680
43993
|
sessionState = await readJson(stateFile);
|
|
@@ -43862,15 +44175,15 @@ init_exit_codes();
|
|
|
43862
44175
|
init_paths();
|
|
43863
44176
|
import { spawn as spawn2, execFileSync as execFileSync12 } from "node:child_process";
|
|
43864
44177
|
import { readFile as readFile18, writeFile as writeFile12, mkdir as mkdir12, rm as rm4, stat as stat4 } from "node:fs/promises";
|
|
43865
|
-
import { join as
|
|
44178
|
+
import { join as join66 } from "node:path";
|
|
43866
44179
|
var DEFAULT_PORT = 3456;
|
|
43867
44180
|
var DEFAULT_HOST = "127.0.0.1";
|
|
43868
44181
|
function getWebPaths() {
|
|
43869
44182
|
const cleoHome = getCleoHome();
|
|
43870
44183
|
return {
|
|
43871
|
-
pidFile:
|
|
43872
|
-
configFile:
|
|
43873
|
-
logFile:
|
|
44184
|
+
pidFile: join66(cleoHome, "web-server.pid"),
|
|
44185
|
+
configFile: join66(cleoHome, "web-server.json"),
|
|
44186
|
+
logFile: join66(cleoHome, "logs", "web-server.log")
|
|
43874
44187
|
};
|
|
43875
44188
|
}
|
|
43876
44189
|
function isProcessRunning(pid) {
|
|
@@ -43914,14 +44227,14 @@ function registerWebCommand(program2) {
|
|
|
43914
44227
|
throw new CleoError(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
|
|
43915
44228
|
}
|
|
43916
44229
|
const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
|
|
43917
|
-
const distMcpDir =
|
|
43918
|
-
await mkdir12(
|
|
44230
|
+
const distMcpDir = join66(projectRoot, "dist", "mcp");
|
|
44231
|
+
await mkdir12(join66(getCleoHome(), "logs"), { recursive: true });
|
|
43919
44232
|
await writeFile12(configFile, JSON.stringify({
|
|
43920
44233
|
port,
|
|
43921
44234
|
host,
|
|
43922
44235
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43923
44236
|
}));
|
|
43924
|
-
const webIndexPath =
|
|
44237
|
+
const webIndexPath = join66(distMcpDir, "index.js");
|
|
43925
44238
|
try {
|
|
43926
44239
|
await stat4(webIndexPath);
|
|
43927
44240
|
} catch {
|
|
@@ -44145,13 +44458,13 @@ init_renderers();
|
|
|
44145
44458
|
init_errors();
|
|
44146
44459
|
init_exit_codes();
|
|
44147
44460
|
init_paths();
|
|
44148
|
-
import { existsSync as
|
|
44461
|
+
import { existsSync as existsSync64, readFileSync as readFileSync47, writeFileSync as writeFileSync11, mkdirSync as mkdirSync15 } from "node:fs";
|
|
44149
44462
|
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
44150
|
-
import { join as
|
|
44463
|
+
import { join as join67, dirname as dirname15 } from "node:path";
|
|
44151
44464
|
function getChangelogSource(cwd) {
|
|
44152
44465
|
const configPath = getConfigPath(cwd);
|
|
44153
44466
|
try {
|
|
44154
|
-
const config = JSON.parse(
|
|
44467
|
+
const config = JSON.parse(readFileSync47(configPath, "utf-8"));
|
|
44155
44468
|
return config?.release?.changelog?.source ?? "CHANGELOG.md";
|
|
44156
44469
|
} catch {
|
|
44157
44470
|
return "CHANGELOG.md";
|
|
@@ -44160,7 +44473,7 @@ function getChangelogSource(cwd) {
|
|
|
44160
44473
|
function getEnabledPlatforms(cwd) {
|
|
44161
44474
|
const configPath = getConfigPath(cwd);
|
|
44162
44475
|
try {
|
|
44163
|
-
const config = JSON.parse(
|
|
44476
|
+
const config = JSON.parse(readFileSync47(configPath, "utf-8"));
|
|
44164
44477
|
const outputs = config?.release?.changelog?.outputs ?? [];
|
|
44165
44478
|
return outputs.filter((o) => o.enabled);
|
|
44166
44479
|
} catch {
|
|
@@ -44287,11 +44600,11 @@ function registerGenerateChangelogCommand(program2) {
|
|
|
44287
44600
|
const targetPlatform = opts["platform"];
|
|
44288
44601
|
const dryRun = !!opts["dryRun"];
|
|
44289
44602
|
const sourceFile = getChangelogSource();
|
|
44290
|
-
const sourcePath =
|
|
44291
|
-
if (!
|
|
44603
|
+
const sourcePath = join67(getProjectRoot(), sourceFile);
|
|
44604
|
+
if (!existsSync64(sourcePath)) {
|
|
44292
44605
|
throw new CleoError(4 /* NOT_FOUND */, `Changelog source not found: ${sourcePath}`);
|
|
44293
44606
|
}
|
|
44294
|
-
const sourceContent =
|
|
44607
|
+
const sourceContent = readFileSync47(sourcePath, "utf-8");
|
|
44295
44608
|
const repoSlug = getGitHubRepoSlug();
|
|
44296
44609
|
const results = [];
|
|
44297
44610
|
if (targetPlatform) {
|
|
@@ -44300,9 +44613,9 @@ function registerGenerateChangelogCommand(program2) {
|
|
|
44300
44613
|
const outputPath = platformConfig?.path ?? getDefaultOutputPath(targetPlatform);
|
|
44301
44614
|
const content = generateForPlatform(targetPlatform, sourceContent, repoSlug, limit);
|
|
44302
44615
|
if (!dryRun) {
|
|
44303
|
-
const fullPath =
|
|
44616
|
+
const fullPath = join67(getProjectRoot(), outputPath);
|
|
44304
44617
|
mkdirSync15(dirname15(fullPath), { recursive: true });
|
|
44305
|
-
|
|
44618
|
+
writeFileSync11(fullPath, content, "utf-8");
|
|
44306
44619
|
}
|
|
44307
44620
|
results.push({ platform: targetPlatform, path: outputPath, written: !dryRun });
|
|
44308
44621
|
} else {
|
|
@@ -44321,9 +44634,9 @@ function registerGenerateChangelogCommand(program2) {
|
|
|
44321
44634
|
limit
|
|
44322
44635
|
);
|
|
44323
44636
|
if (!dryRun) {
|
|
44324
|
-
const fullPath =
|
|
44637
|
+
const fullPath = join67(getProjectRoot(), platformConfig.path);
|
|
44325
44638
|
mkdirSync15(dirname15(fullPath), { recursive: true });
|
|
44326
|
-
|
|
44639
|
+
writeFileSync11(fullPath, content, "utf-8");
|
|
44327
44640
|
}
|
|
44328
44641
|
results.push({
|
|
44329
44642
|
platform: platformConfig.platform,
|
|
@@ -45076,22 +45389,22 @@ function registerPlanCommand(program2) {
|
|
|
45076
45389
|
}
|
|
45077
45390
|
|
|
45078
45391
|
// src/core/otel/index.ts
|
|
45079
|
-
import { readFileSync as
|
|
45080
|
-
import { join as
|
|
45392
|
+
import { readFileSync as readFileSync48, existsSync as existsSync65, writeFileSync as writeFileSync12, copyFileSync as copyFileSync4 } from "node:fs";
|
|
45393
|
+
import { join as join68 } from "node:path";
|
|
45081
45394
|
function getProjectRoot2() {
|
|
45082
45395
|
let dir = process.cwd();
|
|
45083
45396
|
while (dir !== "/") {
|
|
45084
|
-
if (
|
|
45085
|
-
dir =
|
|
45397
|
+
if (existsSync65(join68(dir, ".cleo", "config.json"))) return dir;
|
|
45398
|
+
dir = join68(dir, "..");
|
|
45086
45399
|
}
|
|
45087
45400
|
return process.cwd();
|
|
45088
45401
|
}
|
|
45089
45402
|
function getTokenFilePath() {
|
|
45090
|
-
return
|
|
45403
|
+
return join68(getProjectRoot2(), ".cleo", "metrics", "TOKEN_USAGE.jsonl");
|
|
45091
45404
|
}
|
|
45092
45405
|
function readJsonlFile(filePath) {
|
|
45093
|
-
if (!
|
|
45094
|
-
const content =
|
|
45406
|
+
if (!existsSync65(filePath)) return [];
|
|
45407
|
+
const content = readFileSync48(filePath, "utf-8").trim();
|
|
45095
45408
|
if (!content) return [];
|
|
45096
45409
|
return content.split("\n").map((line) => JSON.parse(line));
|
|
45097
45410
|
}
|
|
@@ -45173,10 +45486,10 @@ async function getRealTokenUsage(_opts) {
|
|
|
45173
45486
|
}
|
|
45174
45487
|
async function clearOtelData() {
|
|
45175
45488
|
const tokenFile = getTokenFilePath();
|
|
45176
|
-
if (
|
|
45489
|
+
if (existsSync65(tokenFile)) {
|
|
45177
45490
|
const backup = `${tokenFile}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
45178
45491
|
copyFileSync4(tokenFile, backup);
|
|
45179
|
-
|
|
45492
|
+
writeFileSync12(tokenFile, "");
|
|
45180
45493
|
return { message: "Token tracking cleared", backup };
|
|
45181
45494
|
}
|
|
45182
45495
|
return { message: "No token file to clear" };
|
|
@@ -45538,8 +45851,8 @@ init_storage_preflight();
|
|
|
45538
45851
|
init_paths();
|
|
45539
45852
|
init_storage_preflight();
|
|
45540
45853
|
init_agent_outputs();
|
|
45541
|
-
import { existsSync as
|
|
45542
|
-
import { join as
|
|
45854
|
+
import { existsSync as existsSync69, readFileSync as readFileSync50, writeFileSync as writeFileSync13, mkdirSync as mkdirSync18, readdirSync as readdirSync19, copyFileSync as copyFileSync5 } from "node:fs";
|
|
45855
|
+
import { join as join72 } from "node:path";
|
|
45543
45856
|
|
|
45544
45857
|
// src/store/index.ts
|
|
45545
45858
|
init_atomic();
|
|
@@ -45575,8 +45888,8 @@ async function runUpgrade(options = {}) {
|
|
|
45575
45888
|
return { success: false, upToDate: false, dryRun: isDryRun, actions, applied: 0, errors: [String(err)] };
|
|
45576
45889
|
}
|
|
45577
45890
|
const cleoDir = getCleoDirAbsolute(options.cwd);
|
|
45578
|
-
const dbPath =
|
|
45579
|
-
const dbExists2 =
|
|
45891
|
+
const dbPath = join72(cleoDir, "tasks.db");
|
|
45892
|
+
const dbExists2 = existsSync69(dbPath);
|
|
45580
45893
|
const legacyRecordCount = preflight.details.todoJsonTaskCount + preflight.details.archiveJsonTaskCount + preflight.details.sessionsJsonCount;
|
|
45581
45894
|
const needsMigration = !dbExists2 && legacyRecordCount > 0;
|
|
45582
45895
|
const needsCleanup = dbExists2 && preflight.migrationNeeded;
|
|
@@ -45592,7 +45905,7 @@ async function runUpgrade(options = {}) {
|
|
|
45592
45905
|
let migrationLock = null;
|
|
45593
45906
|
try {
|
|
45594
45907
|
const cleoDir2 = getCleoDirAbsolute(options.cwd);
|
|
45595
|
-
const dbPath2 =
|
|
45908
|
+
const dbPath2 = join72(cleoDir2, "tasks.db");
|
|
45596
45909
|
try {
|
|
45597
45910
|
migrationLock = await acquireLock(dbPath2, { stale: 3e4, retries: 0 });
|
|
45598
45911
|
} catch {
|
|
@@ -45617,23 +45930,23 @@ async function runUpgrade(options = {}) {
|
|
|
45617
45930
|
} = await Promise.resolve().then(() => (init_state(), state_exports));
|
|
45618
45931
|
const logger = new MigrationLogger2(cleoDir2);
|
|
45619
45932
|
await createMigrationState2(cleoDir2, {
|
|
45620
|
-
todoJson: { path:
|
|
45621
|
-
sessionsJson: { path:
|
|
45622
|
-
archiveJson: { path:
|
|
45933
|
+
todoJson: { path: join72(cleoDir2, "todo.json"), checksum: "" },
|
|
45934
|
+
sessionsJson: { path: join72(cleoDir2, "sessions.json"), checksum: "" },
|
|
45935
|
+
archiveJson: { path: join72(cleoDir2, "todo-archive.json"), checksum: "" }
|
|
45623
45936
|
});
|
|
45624
45937
|
await updateMigrationPhase2(cleoDir2, "backup");
|
|
45625
45938
|
logger.info("init", "start", "Migration state initialized");
|
|
45626
|
-
const dbBackupPath =
|
|
45627
|
-
const dbTempPath =
|
|
45628
|
-
if (
|
|
45629
|
-
const backupDir =
|
|
45630
|
-
if (!
|
|
45939
|
+
const dbBackupPath = join72(cleoDir2, "backups", "safety", `tasks.db.pre-migration.${Date.now()}`);
|
|
45940
|
+
const dbTempPath = join72(cleoDir2, "tasks.db.migrating");
|
|
45941
|
+
if (existsSync69(dbPath2)) {
|
|
45942
|
+
const backupDir = join72(cleoDir2, "backups", "safety");
|
|
45943
|
+
if (!existsSync69(backupDir)) {
|
|
45631
45944
|
mkdirSync18(backupDir, { recursive: true });
|
|
45632
45945
|
}
|
|
45633
45946
|
copyFileSync5(dbPath2, dbBackupPath);
|
|
45634
45947
|
const { createHash: createHash9 } = await import("node:crypto");
|
|
45635
|
-
const origChecksum = createHash9("sha256").update(
|
|
45636
|
-
const backupChecksum = createHash9("sha256").update(
|
|
45948
|
+
const origChecksum = createHash9("sha256").update(readFileSync50(dbPath2)).digest("hex");
|
|
45949
|
+
const backupChecksum = createHash9("sha256").update(readFileSync50(dbBackupPath)).digest("hex");
|
|
45637
45950
|
if (origChecksum !== backupChecksum) {
|
|
45638
45951
|
throw new Error(
|
|
45639
45952
|
`Backup verification failed: checksum mismatch. Aborting migration to prevent data loss.`
|
|
@@ -45648,14 +45961,14 @@ async function runUpgrade(options = {}) {
|
|
|
45648
45961
|
}
|
|
45649
45962
|
logger.info("backup", "verified", "Backup integrity verified", { checksum: origChecksum });
|
|
45650
45963
|
}
|
|
45651
|
-
if (
|
|
45964
|
+
if (existsSync69(dbTempPath)) {
|
|
45652
45965
|
const { unlinkSync: unlinkSync5 } = await import("node:fs");
|
|
45653
45966
|
unlinkSync5(dbTempPath);
|
|
45654
45967
|
}
|
|
45655
|
-
const configPath =
|
|
45968
|
+
const configPath = join72(cleoDir2, "config.json");
|
|
45656
45969
|
let configBackup = null;
|
|
45657
|
-
if (
|
|
45658
|
-
configBackup =
|
|
45970
|
+
if (existsSync69(configPath)) {
|
|
45971
|
+
configBackup = readFileSync50(configPath, "utf-8");
|
|
45659
45972
|
}
|
|
45660
45973
|
const { resetDbState: resetDbState2 } = await Promise.resolve().then(() => (init_sqlite(), sqlite_exports));
|
|
45661
45974
|
resetDbState2();
|
|
@@ -45681,10 +45994,10 @@ async function runUpgrade(options = {}) {
|
|
|
45681
45994
|
resetDbState2();
|
|
45682
45995
|
if (result.success) {
|
|
45683
45996
|
const totalImported = result.tasksImported + result.archivedImported;
|
|
45684
|
-
if (totalImported === 0 &&
|
|
45997
|
+
if (totalImported === 0 && existsSync69(dbBackupPath)) {
|
|
45685
45998
|
copyFileSync5(dbBackupPath, dbPath2);
|
|
45686
45999
|
if (configBackup) {
|
|
45687
|
-
|
|
46000
|
+
writeFileSync13(configPath, configBackup);
|
|
45688
46001
|
}
|
|
45689
46002
|
actions.push({
|
|
45690
46003
|
action: "storage_migration",
|
|
@@ -45695,9 +46008,9 @@ async function runUpgrade(options = {}) {
|
|
|
45695
46008
|
errors.push("Migration imported 0 tasks \u2014 restored from backup to prevent data loss");
|
|
45696
46009
|
} else {
|
|
45697
46010
|
let config = {};
|
|
45698
|
-
if (
|
|
46011
|
+
if (existsSync69(configPath)) {
|
|
45699
46012
|
try {
|
|
45700
|
-
config = JSON.parse(
|
|
46013
|
+
config = JSON.parse(readFileSync50(configPath, "utf-8"));
|
|
45701
46014
|
} catch {
|
|
45702
46015
|
}
|
|
45703
46016
|
}
|
|
@@ -45705,7 +46018,7 @@ async function runUpgrade(options = {}) {
|
|
|
45705
46018
|
config.storage = {};
|
|
45706
46019
|
}
|
|
45707
46020
|
config.storage.engine = "sqlite";
|
|
45708
|
-
|
|
46021
|
+
writeFileSync13(configPath, JSON.stringify(config, null, 2));
|
|
45709
46022
|
actions.push({
|
|
45710
46023
|
action: "storage_migration",
|
|
45711
46024
|
status: "applied",
|
|
@@ -45723,11 +46036,11 @@ async function runUpgrade(options = {}) {
|
|
|
45723
46036
|
logger.info("complete", "finish", "Migration completed successfully");
|
|
45724
46037
|
}
|
|
45725
46038
|
} else {
|
|
45726
|
-
if (
|
|
46039
|
+
if (existsSync69(dbBackupPath)) {
|
|
45727
46040
|
copyFileSync5(dbBackupPath, dbPath2);
|
|
45728
46041
|
}
|
|
45729
46042
|
if (configBackup) {
|
|
45730
|
-
|
|
46043
|
+
writeFileSync13(configPath, configBackup);
|
|
45731
46044
|
}
|
|
45732
46045
|
await updateMigrationPhase2(cleoDir2, "failed");
|
|
45733
46046
|
for (const error of result.errors) {
|
|
@@ -45746,12 +46059,12 @@ async function runUpgrade(options = {}) {
|
|
|
45746
46059
|
} catch (err) {
|
|
45747
46060
|
try {
|
|
45748
46061
|
const cleoDir2 = getCleoDirAbsolute(options.cwd);
|
|
45749
|
-
const dbPath2 =
|
|
45750
|
-
const safetyDir =
|
|
45751
|
-
if (
|
|
46062
|
+
const dbPath2 = join72(cleoDir2, "tasks.db");
|
|
46063
|
+
const safetyDir = join72(cleoDir2, "backups", "safety");
|
|
46064
|
+
if (existsSync69(safetyDir)) {
|
|
45752
46065
|
const backups = readdirSync19(safetyDir).filter((f) => f.startsWith("tasks.db.pre-migration.")).sort().reverse();
|
|
45753
|
-
if (backups.length > 0 && !
|
|
45754
|
-
copyFileSync5(
|
|
46066
|
+
if (backups.length > 0 && !existsSync69(dbPath2)) {
|
|
46067
|
+
copyFileSync5(join72(safetyDir, backups[0]), dbPath2);
|
|
45755
46068
|
}
|
|
45756
46069
|
}
|
|
45757
46070
|
} catch {
|
|
@@ -45786,7 +46099,7 @@ async function runUpgrade(options = {}) {
|
|
|
45786
46099
|
details: preflight.summary
|
|
45787
46100
|
});
|
|
45788
46101
|
}
|
|
45789
|
-
if (
|
|
46102
|
+
if (existsSync69(dbPath)) {
|
|
45790
46103
|
try {
|
|
45791
46104
|
const { runAllRepairs: runAllRepairs2 } = await Promise.resolve().then(() => (init_repair(), repair_exports));
|
|
45792
46105
|
const repairActions = await runAllRepairs2(options.cwd, isDryRun);
|
|
@@ -45796,8 +46109,8 @@ async function runUpgrade(options = {}) {
|
|
|
45796
46109
|
} catch {
|
|
45797
46110
|
}
|
|
45798
46111
|
}
|
|
45799
|
-
if (
|
|
45800
|
-
const legacySequenceFiles = [".sequence", ".sequence.json"].filter((f) =>
|
|
46112
|
+
if (existsSync69(dbPath)) {
|
|
46113
|
+
const legacySequenceFiles = [".sequence", ".sequence.json"].filter((f) => existsSync69(join72(cleoDir, f)));
|
|
45801
46114
|
if (legacySequenceFiles.length > 0) {
|
|
45802
46115
|
if (isDryRun) {
|
|
45803
46116
|
actions.push({
|
|
@@ -45826,7 +46139,7 @@ async function runUpgrade(options = {}) {
|
|
|
45826
46139
|
}
|
|
45827
46140
|
if (needsCleanup) {
|
|
45828
46141
|
const staleJsonFiles = ["todo.json", "sessions.json", "todo-archive.json", ".sequence", ".sequence.json"];
|
|
45829
|
-
const foundStale = staleJsonFiles.filter((f) =>
|
|
46142
|
+
const foundStale = staleJsonFiles.filter((f) => existsSync69(join72(cleoDir, f)));
|
|
45830
46143
|
if (foundStale.length > 0) {
|
|
45831
46144
|
if (isDryRun) {
|
|
45832
46145
|
actions.push({
|
|
@@ -45836,15 +46149,15 @@ async function runUpgrade(options = {}) {
|
|
|
45836
46149
|
});
|
|
45837
46150
|
} else {
|
|
45838
46151
|
try {
|
|
45839
|
-
const backupDir =
|
|
46152
|
+
const backupDir = join72(cleoDir, ".backups", `legacy-json-${Date.now()}`);
|
|
45840
46153
|
mkdirSync18(backupDir, { recursive: true });
|
|
45841
46154
|
for (const f of foundStale) {
|
|
45842
|
-
const src =
|
|
45843
|
-
copyFileSync5(src,
|
|
46155
|
+
const src = join72(cleoDir, f);
|
|
46156
|
+
copyFileSync5(src, join72(backupDir, f));
|
|
45844
46157
|
}
|
|
45845
46158
|
const { unlinkSync: unlinkSync5 } = await import("node:fs");
|
|
45846
46159
|
for (const f of foundStale) {
|
|
45847
|
-
unlinkSync5(
|
|
46160
|
+
unlinkSync5(join72(cleoDir, f));
|
|
45848
46161
|
}
|
|
45849
46162
|
actions.push({
|
|
45850
46163
|
action: "stale_json_cleanup",
|
|
@@ -45864,7 +46177,7 @@ async function runUpgrade(options = {}) {
|
|
|
45864
46177
|
if (options.includeGlobal) {
|
|
45865
46178
|
try {
|
|
45866
46179
|
const globalDir = getCleoHome();
|
|
45867
|
-
const globalPreflight = checkStorageMigration(
|
|
46180
|
+
const globalPreflight = checkStorageMigration(join72(globalDir, ".."));
|
|
45868
46181
|
if (globalPreflight.migrationNeeded) {
|
|
45869
46182
|
actions.push({
|
|
45870
46183
|
action: "global_storage_check",
|
|
@@ -45885,8 +46198,8 @@ async function runUpgrade(options = {}) {
|
|
|
45885
46198
|
try {
|
|
45886
46199
|
const projectRoot = getProjectRoot(options.cwd);
|
|
45887
46200
|
if (isDryRun) {
|
|
45888
|
-
const gitignorePath =
|
|
45889
|
-
if (!
|
|
46201
|
+
const gitignorePath = join72(cleoDir, ".gitignore");
|
|
46202
|
+
if (!existsSync69(gitignorePath)) {
|
|
45890
46203
|
actions.push({ action: "gitignore_integrity", status: "preview", details: "Would create .cleo/.gitignore from template" });
|
|
45891
46204
|
} else {
|
|
45892
46205
|
actions.push({ action: "gitignore_integrity", status: "preview", details: "Would verify .cleo/.gitignore matches template" });
|
|
@@ -45929,12 +46242,12 @@ async function runUpgrade(options = {}) {
|
|
|
45929
46242
|
try {
|
|
45930
46243
|
const projectRootForContext = getProjectRoot(options.cwd);
|
|
45931
46244
|
if (isDryRun) {
|
|
45932
|
-
const contextPath =
|
|
45933
|
-
if (!
|
|
46245
|
+
const contextPath = join72(cleoDir, "project-context.json");
|
|
46246
|
+
if (!existsSync69(contextPath)) {
|
|
45934
46247
|
actions.push({ action: "project_context_detection", status: "preview", details: "Would detect and create project-context.json" });
|
|
45935
46248
|
} else {
|
|
45936
46249
|
try {
|
|
45937
|
-
const context = JSON.parse(
|
|
46250
|
+
const context = JSON.parse(readFileSync50(contextPath, "utf-8"));
|
|
45938
46251
|
if (context.detectedAt) {
|
|
45939
46252
|
const daysSince = (Date.now() - new Date(context.detectedAt).getTime()) / (1e3 * 60 * 60 * 24);
|
|
45940
46253
|
if (daysSince > 30) {
|
|
@@ -46095,7 +46408,7 @@ async function runUpgrade(options = {}) {
|
|
|
46095
46408
|
init_runtime();
|
|
46096
46409
|
import { readFile as readFile20 } from "node:fs/promises";
|
|
46097
46410
|
import * as readline from "node:readline";
|
|
46098
|
-
import { join as
|
|
46411
|
+
import { join as join73 } from "node:path";
|
|
46099
46412
|
import { execFile as execFile7 } from "node:child_process";
|
|
46100
46413
|
import { promisify as promisify9 } from "node:util";
|
|
46101
46414
|
init_build_config();
|
|
@@ -46104,7 +46417,7 @@ var GITHUB_REPO = BUILD_CONFIG.repository.fullName;
|
|
|
46104
46417
|
async function getCurrentVersion() {
|
|
46105
46418
|
const cleoHome = getCleoHome();
|
|
46106
46419
|
try {
|
|
46107
|
-
const content = await readFile20(
|
|
46420
|
+
const content = await readFile20(join73(cleoHome, "VERSION"), "utf-8");
|
|
46108
46421
|
return (content.split("\n")[0] ?? "unknown").trim();
|
|
46109
46422
|
} catch {
|
|
46110
46423
|
return "unknown";
|
|
@@ -46151,7 +46464,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
|
|
|
46151
46464
|
`installed=${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
46152
46465
|
];
|
|
46153
46466
|
await import("node:fs/promises").then(
|
|
46154
|
-
({ writeFile: writeFile15, mkdir: mkdir14 }) => mkdir14(cleoHome, { recursive: true }).then(() => writeFile15(
|
|
46467
|
+
({ writeFile: writeFile15, mkdir: mkdir14 }) => mkdir14(cleoHome, { recursive: true }).then(() => writeFile15(join73(cleoHome, "VERSION"), `${lines.join("\n")}
|
|
46155
46468
|
`, "utf-8"))
|
|
46156
46469
|
);
|
|
46157
46470
|
}
|
|
@@ -46510,14 +46823,14 @@ function registerVerifyCommand(program2) {
|
|
|
46510
46823
|
|
|
46511
46824
|
// src/cli/commands/detect-drift.ts
|
|
46512
46825
|
init_renderers();
|
|
46513
|
-
import { readFileSync as
|
|
46514
|
-
import { join as
|
|
46826
|
+
import { readFileSync as readFileSync51, existsSync as existsSync70, readdirSync as readdirSync20 } from "node:fs";
|
|
46827
|
+
import { join as join74, dirname as dirname18 } from "node:path";
|
|
46515
46828
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
46516
46829
|
function findProjectRoot() {
|
|
46517
46830
|
const currentFile = fileURLToPath5(import.meta.url);
|
|
46518
46831
|
let currentDir = dirname18(currentFile);
|
|
46519
46832
|
while (currentDir !== "/") {
|
|
46520
|
-
if (
|
|
46833
|
+
if (existsSync70(join74(currentDir, "package.json"))) {
|
|
46521
46834
|
return currentDir;
|
|
46522
46835
|
}
|
|
46523
46836
|
const parent = dirname18(currentDir);
|
|
@@ -46555,16 +46868,16 @@ function registerDetectDriftCommand(program2) {
|
|
|
46555
46868
|
};
|
|
46556
46869
|
const safeRead = (path) => {
|
|
46557
46870
|
try {
|
|
46558
|
-
return
|
|
46871
|
+
return readFileSync51(path, "utf-8");
|
|
46559
46872
|
} catch {
|
|
46560
46873
|
return "";
|
|
46561
46874
|
}
|
|
46562
46875
|
};
|
|
46563
46876
|
try {
|
|
46564
|
-
const specPath =
|
|
46565
|
-
const queryPath =
|
|
46566
|
-
const mutatePath =
|
|
46567
|
-
if (!
|
|
46877
|
+
const specPath = join74(projectRoot, "docs", "specs", "CLEO-OPERATIONS-REFERENCE.md");
|
|
46878
|
+
const queryPath = join74(projectRoot, "src", "mcp", "gateways", "query.ts");
|
|
46879
|
+
const mutatePath = join74(projectRoot, "src", "mcp", "gateways", "mutate.ts");
|
|
46880
|
+
if (!existsSync70(specPath)) {
|
|
46568
46881
|
addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATIONS-REFERENCE.md missing", [{
|
|
46569
46882
|
severity: "error",
|
|
46570
46883
|
category: "spec",
|
|
@@ -46572,7 +46885,7 @@ function registerDetectDriftCommand(program2) {
|
|
|
46572
46885
|
file: specPath,
|
|
46573
46886
|
recommendation: "Create docs/specs/CLEO-OPERATIONS-REFERENCE.md with canonical operation definitions"
|
|
46574
46887
|
}]);
|
|
46575
|
-
} else if (!
|
|
46888
|
+
} else if (!existsSync70(queryPath) || !existsSync70(mutatePath)) {
|
|
46576
46889
|
addCheck("Gateway-to-spec sync", "fail", "MCP gateway files missing", [{
|
|
46577
46890
|
severity: "error",
|
|
46578
46891
|
category: "implementation",
|
|
@@ -46626,16 +46939,16 @@ function registerDetectDriftCommand(program2) {
|
|
|
46626
46939
|
}]);
|
|
46627
46940
|
}
|
|
46628
46941
|
try {
|
|
46629
|
-
const cliDir =
|
|
46630
|
-
const coreDir =
|
|
46631
|
-
if (!
|
|
46942
|
+
const cliDir = join74(projectRoot, "src", "cli", "commands");
|
|
46943
|
+
const coreDir = join74(projectRoot, "src", "core");
|
|
46944
|
+
if (!existsSync70(cliDir)) {
|
|
46632
46945
|
addCheck("CLI-to-core sync", "fail", "CLI commands directory missing", [{
|
|
46633
46946
|
severity: "error",
|
|
46634
46947
|
category: "structure",
|
|
46635
46948
|
message: "src/cli/commands/ directory not found",
|
|
46636
46949
|
recommendation: "Verify TypeScript source structure is intact"
|
|
46637
46950
|
}]);
|
|
46638
|
-
} else if (!
|
|
46951
|
+
} else if (!existsSync70(coreDir)) {
|
|
46639
46952
|
addCheck("CLI-to-core sync", "fail", "Core directory missing", [{
|
|
46640
46953
|
severity: "error",
|
|
46641
46954
|
category: "structure",
|
|
@@ -46650,8 +46963,8 @@ function registerDetectDriftCommand(program2) {
|
|
|
46650
46963
|
addCheck("CLI-to-core sync", "fail", `Error: ${e.message}`);
|
|
46651
46964
|
}
|
|
46652
46965
|
try {
|
|
46653
|
-
const domainsDir =
|
|
46654
|
-
if (!
|
|
46966
|
+
const domainsDir = join74(projectRoot, "src", "mcp", "domains");
|
|
46967
|
+
if (!existsSync70(domainsDir)) {
|
|
46655
46968
|
addCheck("Domain handler coverage", "fail", "MCP domains directory missing", [{
|
|
46656
46969
|
severity: "error",
|
|
46657
46970
|
category: "structure",
|
|
@@ -46666,8 +46979,8 @@ function registerDetectDriftCommand(program2) {
|
|
|
46666
46979
|
addCheck("Domain handler coverage", "fail", `Error: ${e.message}`);
|
|
46667
46980
|
}
|
|
46668
46981
|
try {
|
|
46669
|
-
const matrixPath =
|
|
46670
|
-
if (!
|
|
46982
|
+
const matrixPath = join74(projectRoot, "src", "dispatch", "lib", "capability-matrix.ts");
|
|
46983
|
+
if (!existsSync70(matrixPath)) {
|
|
46671
46984
|
addCheck("Capability matrix", "fail", "Capability matrix missing", [{
|
|
46672
46985
|
severity: "error",
|
|
46673
46986
|
category: "configuration",
|
|
@@ -46681,8 +46994,8 @@ function registerDetectDriftCommand(program2) {
|
|
|
46681
46994
|
addCheck("Capability matrix", "fail", `Error: ${e.message}`);
|
|
46682
46995
|
}
|
|
46683
46996
|
try {
|
|
46684
|
-
const schemaPath =
|
|
46685
|
-
if (!
|
|
46997
|
+
const schemaPath = join74(projectRoot, "src", "store", "schema.ts");
|
|
46998
|
+
if (!existsSync70(schemaPath)) {
|
|
46686
46999
|
addCheck("Schema validation", "fail", "Schema definition missing", [{
|
|
46687
47000
|
severity: "error",
|
|
46688
47001
|
category: "data-model",
|
|
@@ -46707,10 +47020,10 @@ function registerDetectDriftCommand(program2) {
|
|
|
46707
47020
|
addCheck("Schema validation", "fail", `Error: ${e.message}`);
|
|
46708
47021
|
}
|
|
46709
47022
|
try {
|
|
46710
|
-
const visionPath =
|
|
46711
|
-
const specPath =
|
|
47023
|
+
const visionPath = join74(projectRoot, "docs", "concepts", "CLEO-VISION.md");
|
|
47024
|
+
const specPath = join74(projectRoot, "docs", "specs", "PORTABLE-BRAIN-SPEC.md");
|
|
46712
47025
|
const issues = [];
|
|
46713
|
-
if (!
|
|
47026
|
+
if (!existsSync70(visionPath)) {
|
|
46714
47027
|
issues.push({
|
|
46715
47028
|
severity: "error",
|
|
46716
47029
|
category: "vision",
|
|
@@ -46719,7 +47032,7 @@ function registerDetectDriftCommand(program2) {
|
|
|
46719
47032
|
recommendation: "Create docs/concepts/CLEO-VISION.md with project vision"
|
|
46720
47033
|
});
|
|
46721
47034
|
}
|
|
46722
|
-
if (!
|
|
47035
|
+
if (!existsSync70(specPath)) {
|
|
46723
47036
|
issues.push({
|
|
46724
47037
|
severity: "error",
|
|
46725
47038
|
category: "spec",
|
|
@@ -46756,8 +47069,8 @@ function registerDetectDriftCommand(program2) {
|
|
|
46756
47069
|
addCheck("Canonical identity", "fail", `Error: ${e.message}`);
|
|
46757
47070
|
}
|
|
46758
47071
|
try {
|
|
46759
|
-
const injectionPath =
|
|
46760
|
-
if (!
|
|
47072
|
+
const injectionPath = join74(projectRoot, ".cleo", "templates", "CLEO-INJECTION.md");
|
|
47073
|
+
if (!existsSync70(injectionPath)) {
|
|
46761
47074
|
addCheck("Agent injection", "fail", "Agent injection template missing", [{
|
|
46762
47075
|
severity: "error",
|
|
46763
47076
|
category: "agent-support",
|
|
@@ -46782,8 +47095,8 @@ function registerDetectDriftCommand(program2) {
|
|
|
46782
47095
|
addCheck("Agent injection", "fail", `Error: ${e.message}`);
|
|
46783
47096
|
}
|
|
46784
47097
|
try {
|
|
46785
|
-
const exitCodesPath =
|
|
46786
|
-
if (!
|
|
47098
|
+
const exitCodesPath = join74(projectRoot, "src", "types", "exit-codes.ts");
|
|
47099
|
+
if (!existsSync70(exitCodesPath)) {
|
|
46787
47100
|
addCheck("Exit codes", "fail", "Exit codes definition missing", [{
|
|
46788
47101
|
severity: "error",
|
|
46789
47102
|
category: "protocol",
|
|
@@ -47022,8 +47335,8 @@ function registerRemoteCommand(program2) {
|
|
|
47022
47335
|
init_renderers();
|
|
47023
47336
|
init_paths();
|
|
47024
47337
|
import { mkdir as mkdir13, writeFile as writeFile14, readFile as readFile21 } from "node:fs/promises";
|
|
47025
|
-
import { existsSync as
|
|
47026
|
-
import { join as
|
|
47338
|
+
import { existsSync as existsSync71, readFileSync as readFileSync52 } from "node:fs";
|
|
47339
|
+
import { join as join75, resolve as resolve10, dirname as dirname19 } from "node:path";
|
|
47027
47340
|
import { homedir as homedir4 } from "node:os";
|
|
47028
47341
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
47029
47342
|
function registerInstallGlobalCommand(program2) {
|
|
@@ -47033,17 +47346,17 @@ function registerInstallGlobalCommand(program2) {
|
|
|
47033
47346
|
const warnings = [];
|
|
47034
47347
|
try {
|
|
47035
47348
|
const cleoHome = getCleoHome();
|
|
47036
|
-
const globalTemplatesDir =
|
|
47349
|
+
const globalTemplatesDir = join75(cleoHome, "templates");
|
|
47037
47350
|
if (!isDryRun) {
|
|
47038
47351
|
await mkdir13(globalTemplatesDir, { recursive: true });
|
|
47039
47352
|
}
|
|
47040
47353
|
try {
|
|
47041
47354
|
const thisFile = fileURLToPath6(import.meta.url);
|
|
47042
47355
|
const packageRoot = resolve10(dirname19(thisFile), "..", "..", "..");
|
|
47043
|
-
const templatePath =
|
|
47044
|
-
if (
|
|
47045
|
-
const content =
|
|
47046
|
-
const globalPath =
|
|
47356
|
+
const templatePath = join75(packageRoot, "templates", "CLEO-INJECTION.md");
|
|
47357
|
+
if (existsSync71(templatePath)) {
|
|
47358
|
+
const content = readFileSync52(templatePath, "utf-8");
|
|
47359
|
+
const globalPath = join75(globalTemplatesDir, "CLEO-INJECTION.md");
|
|
47047
47360
|
if (!isDryRun) {
|
|
47048
47361
|
await writeFile14(globalPath, content);
|
|
47049
47362
|
}
|
|
@@ -47053,12 +47366,12 @@ function registerInstallGlobalCommand(program2) {
|
|
|
47053
47366
|
warnings.push("Could not refresh CLEO-INJECTION.md template");
|
|
47054
47367
|
}
|
|
47055
47368
|
const globalAgentsDir = getAgentsHome();
|
|
47056
|
-
const globalAgentsMd =
|
|
47369
|
+
const globalAgentsMd = join75(globalAgentsDir, "AGENTS.md");
|
|
47057
47370
|
try {
|
|
47058
47371
|
const { inject, getInstalledProviders: getInstalledProviders3, injectAll: injectAll2, buildInjectionContent: buildInjectionContent2 } = await import("@cleocode/caamp");
|
|
47059
47372
|
if (!isDryRun) {
|
|
47060
47373
|
await mkdir13(globalAgentsDir, { recursive: true });
|
|
47061
|
-
if (
|
|
47374
|
+
if (existsSync71(globalAgentsMd)) {
|
|
47062
47375
|
const content = await readFile21(globalAgentsMd, "utf8");
|
|
47063
47376
|
const stripped = content.replace(/\n?<!-- CLEO:START -->[\s\S]*?<!-- CLEO:END -->\n?/g, "");
|
|
47064
47377
|
if (stripped !== content) {
|
|
@@ -47077,8 +47390,8 @@ function registerInstallGlobalCommand(program2) {
|
|
|
47077
47390
|
const injectionContent = buildInjectionContent2({ references: ["@~/.agents/AGENTS.md"] });
|
|
47078
47391
|
if (!isDryRun) {
|
|
47079
47392
|
for (const provider of providers) {
|
|
47080
|
-
const instructFilePath =
|
|
47081
|
-
if (
|
|
47393
|
+
const instructFilePath = join75(provider.pathGlobal, provider.instructFile);
|
|
47394
|
+
if (existsSync71(instructFilePath)) {
|
|
47082
47395
|
const fileContent = await readFile21(instructFilePath, "utf8");
|
|
47083
47396
|
const stripped = fileContent.replace(/\n?<!-- CLEO:START -->[\s\S]*?<!-- CLEO:END -->\n?/g, "");
|
|
47084
47397
|
if (stripped !== fileContent) {
|
|
@@ -47093,7 +47406,7 @@ function registerInstallGlobalCommand(program2) {
|
|
|
47093
47406
|
}
|
|
47094
47407
|
} else {
|
|
47095
47408
|
for (const p of providers) {
|
|
47096
|
-
const displayPath =
|
|
47409
|
+
const displayPath = join75(p.pathGlobal, p.instructFile).replace(homedir4(), "~");
|
|
47097
47410
|
created.push(`${displayPath} (would update CAAMP block)`);
|
|
47098
47411
|
}
|
|
47099
47412
|
}
|
|
@@ -47299,7 +47612,7 @@ init_paths();
|
|
|
47299
47612
|
init_paths();
|
|
47300
47613
|
init_brain_sqlite();
|
|
47301
47614
|
init_brain_search();
|
|
47302
|
-
import { existsSync as
|
|
47615
|
+
import { existsSync as existsSync72 } from "node:fs";
|
|
47303
47616
|
import { createRequire as createRequire5 } from "node:module";
|
|
47304
47617
|
var _require5 = createRequire5(import.meta.url);
|
|
47305
47618
|
var { DatabaseSync: DatabaseSync3 } = _require5("node:sqlite");
|
|
@@ -47343,7 +47656,7 @@ async function migrateClaudeMem(projectRoot, options = {}) {
|
|
|
47343
47656
|
errors: [],
|
|
47344
47657
|
dryRun
|
|
47345
47658
|
};
|
|
47346
|
-
if (!
|
|
47659
|
+
if (!existsSync72(sourcePath)) {
|
|
47347
47660
|
throw new Error(
|
|
47348
47661
|
`claude-mem database not found at: ${sourcePath}
|
|
47349
47662
|
Expected location: ~/.claude-mem/claude-mem.db
|
|
@@ -47745,10 +48058,10 @@ init_config();
|
|
|
47745
48058
|
// src/cli/logger-bootstrap.ts
|
|
47746
48059
|
init_logger();
|
|
47747
48060
|
init_project_info();
|
|
47748
|
-
import { join as
|
|
48061
|
+
import { join as join76 } from "node:path";
|
|
47749
48062
|
function initCliLogger(cwd, loggingConfig) {
|
|
47750
48063
|
const projectInfo = getProjectInfoSync(cwd);
|
|
47751
|
-
initLogger(
|
|
48064
|
+
initLogger(join76(cwd, ".cleo"), loggingConfig, projectInfo?.projectHash);
|
|
47752
48065
|
}
|
|
47753
48066
|
|
|
47754
48067
|
// src/cli/index.ts
|
|
@@ -47981,8 +48294,8 @@ Upgrade options:
|
|
|
47981
48294
|
}
|
|
47982
48295
|
function getPackageVersion() {
|
|
47983
48296
|
try {
|
|
47984
|
-
const moduleRoot =
|
|
47985
|
-
const pkg = JSON.parse(
|
|
48297
|
+
const moduleRoot = join77(import.meta.dirname ?? "", "..", "..");
|
|
48298
|
+
const pkg = JSON.parse(readFileSync53(join77(moduleRoot, "package.json"), "utf-8"));
|
|
47986
48299
|
return pkg.version ?? "0.0.0";
|
|
47987
48300
|
} catch {
|
|
47988
48301
|
return "0.0.0";
|
|
@@ -48093,7 +48406,7 @@ program.hook("preAction", async () => {
|
|
|
48093
48406
|
const config = await loadConfig();
|
|
48094
48407
|
initCliLogger(process.cwd(), config.logging);
|
|
48095
48408
|
const { pruneAuditLog: pruneAuditLog2 } = await Promise.resolve().then(() => (init_audit_prune(), audit_prune_exports));
|
|
48096
|
-
pruneAuditLog2(
|
|
48409
|
+
pruneAuditLog2(join77(process.cwd(), ".cleo"), config.logging).catch(() => {
|
|
48097
48410
|
});
|
|
48098
48411
|
} catch {
|
|
48099
48412
|
}
|
|
@@ -48133,7 +48446,7 @@ program.hook("preAction", (thisCommand) => {
|
|
|
48133
48446
|
}
|
|
48134
48447
|
});
|
|
48135
48448
|
if (process.argv[2] === "mcp") {
|
|
48136
|
-
const mcpPath =
|
|
48449
|
+
const mcpPath = join77(import.meta.dirname ?? "", "..", "mcp", "index.js");
|
|
48137
48450
|
const { spawn: spawn3 } = await import("node:child_process");
|
|
48138
48451
|
const child = spawn3(
|
|
48139
48452
|
process.execPath,
|