@cleocode/core 2026.3.39 → 2026.3.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +670 -655
- package/dist/index.js.map +4 -4
- package/package.json +2 -2
- package/src/admin/export.ts +2 -17
- package/src/cleo.ts +16 -8
- package/src/inject/index.ts +7 -7
- package/src/internal.ts +14 -23
- package/src/reconciliation/index.ts +11 -2
- package/src/reconciliation/link-store.ts +174 -0
- package/src/reconciliation/reconciliation-engine.ts +136 -83
- package/src/release/release-manifest.ts +55 -1
- package/src/routing/capability-matrix.ts +4 -5
- package/src/store/tasks-schema.ts +52 -0
- package/src/task-work/index.ts +0 -14
- package/src/admin/sync.ts +0 -164
- package/src/reconciliation/sync-state.ts +0 -73
- package/src/task-work/todowrite-merge.ts +0 -289
package/dist/index.js
CHANGED
|
@@ -1774,7 +1774,7 @@ var init_sql = __esm({
|
|
|
1774
1774
|
return new SQL([new StringChunk(str)]);
|
|
1775
1775
|
}
|
|
1776
1776
|
_sql.raw = raw;
|
|
1777
|
-
function
|
|
1777
|
+
function join103(chunks, separator) {
|
|
1778
1778
|
const result = [];
|
|
1779
1779
|
for (const [i, chunk] of chunks.entries()) {
|
|
1780
1780
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -1782,7 +1782,7 @@ var init_sql = __esm({
|
|
|
1782
1782
|
}
|
|
1783
1783
|
return new SQL(result);
|
|
1784
1784
|
}
|
|
1785
|
-
_sql.join =
|
|
1785
|
+
_sql.join = join103;
|
|
1786
1786
|
function identifier(value) {
|
|
1787
1787
|
return new Name(value);
|
|
1788
1788
|
}
|
|
@@ -6469,7 +6469,7 @@ var init_select2 = __esm({
|
|
|
6469
6469
|
const baseTableName = this.tableName;
|
|
6470
6470
|
const tableName = getTableLikeName(table);
|
|
6471
6471
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
6472
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
6472
|
+
if (typeof tableName === "string" && this.config.joins?.some((join103) => join103.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
6473
6473
|
if (!this.isPartialSelect) {
|
|
6474
6474
|
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
|
|
6475
6475
|
if (typeof tableName === "string" && !is(table, SQL)) {
|
|
@@ -7754,7 +7754,7 @@ var init_dialect = __esm({
|
|
|
7754
7754
|
if (!joins2) return;
|
|
7755
7755
|
const withEntries = Object.entries(joins2).filter(([_, v]) => v);
|
|
7756
7756
|
if (!withEntries.length) return;
|
|
7757
|
-
return sql.join(withEntries.map(([k,
|
|
7757
|
+
return sql.join(withEntries.map(([k, join103]) => {
|
|
7758
7758
|
const relation = tableConfig.relations[k];
|
|
7759
7759
|
const isSingle2 = is(relation, One3);
|
|
7760
7760
|
const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
|
|
@@ -7765,7 +7765,7 @@ var init_dialect = __esm({
|
|
|
7765
7765
|
table: targetTable,
|
|
7766
7766
|
mode: isSingle2 ? "first" : "many",
|
|
7767
7767
|
schema,
|
|
7768
|
-
queryConfig:
|
|
7768
|
+
queryConfig: join103,
|
|
7769
7769
|
tableConfig: schema[relation.targetTableName],
|
|
7770
7770
|
relationWhere: filter,
|
|
7771
7771
|
isNested: true,
|
|
@@ -7779,7 +7779,7 @@ var init_dialect = __esm({
|
|
|
7779
7779
|
key: k,
|
|
7780
7780
|
selection: innerQuery.selection,
|
|
7781
7781
|
isArray: !isSingle2,
|
|
7782
|
-
isOptional: (relation.optional ?? false) ||
|
|
7782
|
+
isOptional: (relation.optional ?? false) || join103 !== true && !!join103.where
|
|
7783
7783
|
});
|
|
7784
7784
|
const jsonColumns = sql.join(innerQuery.selection.map((s) => {
|
|
7785
7785
|
return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb2}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
|
|
@@ -8178,7 +8178,7 @@ var init_update = __esm({
|
|
|
8178
8178
|
createJoin(joinType) {
|
|
8179
8179
|
return ((table, on) => {
|
|
8180
8180
|
const tableName = getTableLikeName(table);
|
|
8181
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
8181
|
+
if (typeof tableName === "string" && this.config.joins.some((join103) => join103.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
8182
8182
|
if (typeof on === "function") {
|
|
8183
8183
|
const from = this.config.from ? is(table, SQLiteTable) ? table[Table.Symbol.Columns] : is(table, Subquery) ? table._.selectedFields : is(table, SQLiteViewBase) ? table[ViewBaseConfig].selectedFields : void 0 : void 0;
|
|
8184
8184
|
on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
|
|
@@ -8884,6 +8884,7 @@ __export(tasks_schema_exports, {
|
|
|
8884
8884
|
adrTaskLinks: () => adrTaskLinks,
|
|
8885
8885
|
architectureDecisions: () => architectureDecisions,
|
|
8886
8886
|
auditLog: () => auditLog,
|
|
8887
|
+
externalTaskLinks: () => externalTaskLinks,
|
|
8887
8888
|
isValidStatus: () => isValidStatus,
|
|
8888
8889
|
lifecycleEvidence: () => lifecycleEvidence,
|
|
8889
8890
|
lifecycleGateResults: () => lifecycleGateResults,
|
|
@@ -8905,7 +8906,7 @@ __export(tasks_schema_exports, {
|
|
|
8905
8906
|
warpChains: () => warpChains
|
|
8906
8907
|
});
|
|
8907
8908
|
import { sql as sql3 } from "drizzle-orm";
|
|
8908
|
-
var TASK_PRIORITIES, TASK_TYPES, TASK_SIZES, LIFECYCLE_STAGE_NAMES, LIFECYCLE_GATE_RESULTS, LIFECYCLE_EVIDENCE_TYPES, TOKEN_USAGE_METHODS, TOKEN_USAGE_CONFIDENCE, TOKEN_USAGE_TRANSPORTS, tasks, taskDependencies, taskRelations, sessions, taskWorkHistory, lifecyclePipelines, lifecycleStages, lifecycleGateResults, lifecycleEvidence, lifecycleTransitions, manifestEntries, pipelineManifest, releaseManifests, schemaMeta, auditLog, tokenUsage, architectureDecisions, adrTaskLinks, adrRelations, statusRegistryTable;
|
|
8909
|
+
var TASK_PRIORITIES, TASK_TYPES, TASK_SIZES, LIFECYCLE_STAGE_NAMES, LIFECYCLE_GATE_RESULTS, LIFECYCLE_EVIDENCE_TYPES, TOKEN_USAGE_METHODS, TOKEN_USAGE_CONFIDENCE, TOKEN_USAGE_TRANSPORTS, tasks, taskDependencies, taskRelations, sessions, taskWorkHistory, lifecyclePipelines, lifecycleStages, lifecycleGateResults, lifecycleEvidence, lifecycleTransitions, manifestEntries, pipelineManifest, releaseManifests, schemaMeta, auditLog, tokenUsage, architectureDecisions, adrTaskLinks, adrRelations, externalTaskLinks, statusRegistryTable;
|
|
8909
8910
|
var init_tasks_schema = __esm({
|
|
8910
8911
|
"packages/core/src/store/tasks-schema.ts"() {
|
|
8911
8912
|
"use strict";
|
|
@@ -9360,6 +9361,40 @@ var init_tasks_schema = __esm({
|
|
|
9360
9361
|
},
|
|
9361
9362
|
(table) => [primaryKey({ columns: [table.fromAdrId, table.toAdrId, table.relationType] })]
|
|
9362
9363
|
);
|
|
9364
|
+
externalTaskLinks = sqliteTable(
|
|
9365
|
+
"external_task_links",
|
|
9366
|
+
{
|
|
9367
|
+
id: text("id").primaryKey(),
|
|
9368
|
+
taskId: text("task_id").notNull().references(() => tasks.id, { onDelete: "cascade" }),
|
|
9369
|
+
/** Provider identifier (e.g. 'linear', 'jira', 'github', 'gitlab'). */
|
|
9370
|
+
providerId: text("provider_id").notNull(),
|
|
9371
|
+
/** Provider-assigned identifier for the external task (opaque to CLEO). */
|
|
9372
|
+
externalId: text("external_id").notNull(),
|
|
9373
|
+
/** Optional URL to the external task (for human navigation). */
|
|
9374
|
+
externalUrl: text("external_url"),
|
|
9375
|
+
/** Title of the external task at the time of last sync. */
|
|
9376
|
+
externalTitle: text("external_title"),
|
|
9377
|
+
/** How this link was established. */
|
|
9378
|
+
linkType: text("link_type", {
|
|
9379
|
+
enum: ["created", "matched", "manual"]
|
|
9380
|
+
}).notNull(),
|
|
9381
|
+
/** Direction of the sync that created this link. */
|
|
9382
|
+
syncDirection: text("sync_direction", {
|
|
9383
|
+
enum: ["inbound", "outbound", "bidirectional"]
|
|
9384
|
+
}).notNull().default("inbound"),
|
|
9385
|
+
/** Arbitrary provider-specific metadata (JSON). */
|
|
9386
|
+
metadataJson: text("metadata_json").default("{}"),
|
|
9387
|
+
/** When the link was first established. */
|
|
9388
|
+
linkedAt: text("linked_at").notNull().default(sql3`(datetime('now'))`),
|
|
9389
|
+
/** When the external task was last synchronized. */
|
|
9390
|
+
lastSyncAt: text("last_sync_at")
|
|
9391
|
+
},
|
|
9392
|
+
(table) => [
|
|
9393
|
+
index("idx_ext_links_task_id").on(table.taskId),
|
|
9394
|
+
index("idx_ext_links_provider_external").on(table.providerId, table.externalId),
|
|
9395
|
+
index("idx_ext_links_provider_id").on(table.providerId)
|
|
9396
|
+
]
|
|
9397
|
+
);
|
|
9363
9398
|
statusRegistryTable = sqliteTable(
|
|
9364
9399
|
"status_registry",
|
|
9365
9400
|
{
|
|
@@ -12860,9 +12895,9 @@ async function readSequenceFromDb(cwd, accessor) {
|
|
|
12860
12895
|
return isValidSequenceState(value) ? value : null;
|
|
12861
12896
|
}
|
|
12862
12897
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
12863
|
-
const { eq:
|
|
12898
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
12864
12899
|
const db = await getDb3(cwd);
|
|
12865
|
-
const rows = await db.select().from(schemaMeta).where(
|
|
12900
|
+
const rows = await db.select().from(schemaMeta).where(eq8(schemaMeta.key, SEQUENCE_META_KEY)).all();
|
|
12866
12901
|
const raw = rows[0]?.value;
|
|
12867
12902
|
if (!raw) return null;
|
|
12868
12903
|
try {
|
|
@@ -14298,8 +14333,8 @@ function analyzeArchitecture(projectRoot, _projectContext) {
|
|
|
14298
14333
|
for (const entry of entries) {
|
|
14299
14334
|
const entryPath = join22(srcPath, entry);
|
|
14300
14335
|
try {
|
|
14301
|
-
const
|
|
14302
|
-
if (
|
|
14336
|
+
const stat2 = statSync2(entryPath);
|
|
14337
|
+
if (stat2.isDirectory()) {
|
|
14303
14338
|
const purpose = LAYER_PURPOSE[entry.toLowerCase()] ?? `${entry} layer`;
|
|
14304
14339
|
layers.push({ name: entry, path: `src/${entry}`, purpose });
|
|
14305
14340
|
} else if (ENTRY_POINT_NAMES.has(entry)) {
|
|
@@ -14420,8 +14455,8 @@ function analyzeStructure(projectRoot) {
|
|
|
14420
14455
|
if (EXCLUDED_DIRS.has(entry) || entry.startsWith(".")) continue;
|
|
14421
14456
|
const entryPath = join23(projectRoot, entry);
|
|
14422
14457
|
try {
|
|
14423
|
-
const
|
|
14424
|
-
if (
|
|
14458
|
+
const stat2 = statSync3(entryPath);
|
|
14459
|
+
if (stat2.isDirectory()) {
|
|
14425
14460
|
const fileCount = countFiles(entryPath);
|
|
14426
14461
|
totalFiles += fileCount;
|
|
14427
14462
|
const purpose = DIR_PURPOSE[entry.toLowerCase()] ?? "Project directory";
|
|
@@ -14464,8 +14499,8 @@ function countFiles(dir, depth = 0) {
|
|
|
14464
14499
|
if (EXCLUDED_DIRS.has(entry) || entry.startsWith(".")) continue;
|
|
14465
14500
|
const entryPath = join23(dir, entry);
|
|
14466
14501
|
try {
|
|
14467
|
-
const
|
|
14468
|
-
if (
|
|
14502
|
+
const stat2 = statSync3(entryPath);
|
|
14503
|
+
if (stat2.isDirectory()) {
|
|
14469
14504
|
count2 += countFiles(entryPath, depth + 1);
|
|
14470
14505
|
} else {
|
|
14471
14506
|
count2++;
|
|
@@ -14905,8 +14940,8 @@ function walkSourceFiles(dir, projectRoot, callback, depth = 0) {
|
|
|
14905
14940
|
if (EXCLUDED_DIRS2.has(entry) || entry.startsWith(".")) continue;
|
|
14906
14941
|
const fullPath = join27(dir, entry);
|
|
14907
14942
|
try {
|
|
14908
|
-
const
|
|
14909
|
-
if (
|
|
14943
|
+
const stat2 = statSync5(fullPath);
|
|
14944
|
+
if (stat2.isDirectory()) {
|
|
14910
14945
|
walkSourceFiles(fullPath, projectRoot, callback, depth + 1);
|
|
14911
14946
|
} else {
|
|
14912
14947
|
const ext = entry.slice(entry.lastIndexOf("."));
|
|
@@ -17148,19 +17183,19 @@ async function queryAudit(options) {
|
|
|
17148
17183
|
try {
|
|
17149
17184
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
17150
17185
|
const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
17151
|
-
const { and:
|
|
17186
|
+
const { and: and6, eq: eq8, gte: gte3, or: or4 } = await import("drizzle-orm");
|
|
17152
17187
|
const db = await getDb3(process.cwd());
|
|
17153
17188
|
const conditions = [];
|
|
17154
|
-
if (options?.sessionId) conditions.push(
|
|
17155
|
-
if (options?.domain) conditions.push(
|
|
17189
|
+
if (options?.sessionId) conditions.push(eq8(auditLog2.sessionId, options.sessionId));
|
|
17190
|
+
if (options?.domain) conditions.push(eq8(auditLog2.domain, options.domain));
|
|
17156
17191
|
if (options?.operation)
|
|
17157
17192
|
conditions.push(
|
|
17158
|
-
or4(
|
|
17193
|
+
or4(eq8(auditLog2.operation, options.operation), eq8(auditLog2.action, options.operation))
|
|
17159
17194
|
);
|
|
17160
|
-
if (options?.taskId) conditions.push(
|
|
17195
|
+
if (options?.taskId) conditions.push(eq8(auditLog2.taskId, options.taskId));
|
|
17161
17196
|
if (options?.since) conditions.push(gte3(auditLog2.timestamp, options.since));
|
|
17162
17197
|
const limit = options?.limit ?? 1e3;
|
|
17163
|
-
const rows = await db.select().from(auditLog2).where(conditions.length > 0 ?
|
|
17198
|
+
const rows = await db.select().from(auditLog2).where(conditions.length > 0 ? and6(...conditions) : void 0).orderBy(auditLog2.timestamp).limit(limit);
|
|
17164
17199
|
return rows.map((row) => ({
|
|
17165
17200
|
timestamp: row.timestamp,
|
|
17166
17201
|
sessionId: row.sessionId,
|
|
@@ -17966,8 +18001,8 @@ async function cleanProjectSchemas(projectRoot) {
|
|
|
17966
18001
|
return { cleaned: false };
|
|
17967
18002
|
}
|
|
17968
18003
|
try {
|
|
17969
|
-
const
|
|
17970
|
-
if (!
|
|
18004
|
+
const stat2 = statSync7(projectSchemasDir);
|
|
18005
|
+
if (!stat2.isDirectory()) {
|
|
17971
18006
|
return { cleaned: false };
|
|
17972
18007
|
}
|
|
17973
18008
|
} catch {
|
|
@@ -19013,8 +19048,8 @@ function checkSqliteDb(projectRoot) {
|
|
|
19013
19048
|
fix: "cleo init"
|
|
19014
19049
|
};
|
|
19015
19050
|
}
|
|
19016
|
-
const
|
|
19017
|
-
if (
|
|
19051
|
+
const stat2 = statSync8(dbPath);
|
|
19052
|
+
if (stat2.size === 0) {
|
|
19018
19053
|
return {
|
|
19019
19054
|
id: "sqlite_db",
|
|
19020
19055
|
category: "scaffold",
|
|
@@ -19028,8 +19063,8 @@ function checkSqliteDb(projectRoot) {
|
|
|
19028
19063
|
id: "sqlite_db",
|
|
19029
19064
|
category: "scaffold",
|
|
19030
19065
|
status: "passed",
|
|
19031
|
-
message: `tasks.db exists (${
|
|
19032
|
-
details: { path: dbPath, exists: true, size:
|
|
19066
|
+
message: `tasks.db exists (${stat2.size} bytes)`,
|
|
19067
|
+
details: { path: dbPath, exists: true, size: stat2.size },
|
|
19033
19068
|
fix: null
|
|
19034
19069
|
};
|
|
19035
19070
|
}
|
|
@@ -19081,8 +19116,8 @@ function checkBrainDb(projectRoot) {
|
|
|
19081
19116
|
fix: "cleo init"
|
|
19082
19117
|
};
|
|
19083
19118
|
}
|
|
19084
|
-
const
|
|
19085
|
-
if (
|
|
19119
|
+
const stat2 = statSync8(dbPath);
|
|
19120
|
+
if (stat2.size === 0) {
|
|
19086
19121
|
return {
|
|
19087
19122
|
id: "brain_db",
|
|
19088
19123
|
category: "scaffold",
|
|
@@ -19096,8 +19131,8 @@ function checkBrainDb(projectRoot) {
|
|
|
19096
19131
|
id: "brain_db",
|
|
19097
19132
|
category: "scaffold",
|
|
19098
19133
|
status: "passed",
|
|
19099
|
-
message: `brain.db exists (${
|
|
19100
|
-
details: { path: dbPath, exists: true, size:
|
|
19134
|
+
message: `brain.db exists (${stat2.size} bytes)`,
|
|
19135
|
+
details: { path: dbPath, exists: true, size: stat2.size },
|
|
19101
19136
|
fix: null
|
|
19102
19137
|
};
|
|
19103
19138
|
}
|
|
@@ -19348,8 +19383,8 @@ function detectEnvMode() {
|
|
|
19348
19383
|
const devKv = {};
|
|
19349
19384
|
const devLines = devContent.trim().split("\n");
|
|
19350
19385
|
for (let i = 1; i < devLines.length; i++) {
|
|
19351
|
-
const
|
|
19352
|
-
if (
|
|
19386
|
+
const eq8 = devLines[i].indexOf("=");
|
|
19387
|
+
if (eq8 > 0) devKv[devLines[i].slice(0, eq8).trim()] = devLines[i].slice(eq8 + 1).trim();
|
|
19353
19388
|
}
|
|
19354
19389
|
if (devKv["mode"] === "dev-ts" && devKv["source"]) {
|
|
19355
19390
|
const devSource = devKv["source"].replace(/\\/g, "/");
|
|
@@ -20588,9 +20623,9 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
20588
20623
|
const projectHash = generateProjectHash(projectPath);
|
|
20589
20624
|
await nexusInit();
|
|
20590
20625
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20591
|
-
const { eq:
|
|
20626
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
20592
20627
|
const db = await getNexusDb2();
|
|
20593
|
-
const existingRows = await db.select().from(projectRegistry).where(
|
|
20628
|
+
const existingRows = await db.select().from(projectRegistry).where(eq8(projectRegistry.projectHash, projectHash));
|
|
20594
20629
|
const existing = existingRows[0];
|
|
20595
20630
|
if (existing?.permissions) {
|
|
20596
20631
|
throw new CleoError(
|
|
@@ -20599,7 +20634,7 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
20599
20634
|
);
|
|
20600
20635
|
}
|
|
20601
20636
|
if (!existing) {
|
|
20602
|
-
const nameConflictRows = await db.select().from(projectRegistry).where(
|
|
20637
|
+
const nameConflictRows = await db.select().from(projectRegistry).where(eq8(projectRegistry.name, projectName));
|
|
20603
20638
|
if (nameConflictRows.length > 0) {
|
|
20604
20639
|
throw new CleoError(
|
|
20605
20640
|
6 /* VALIDATION_ERROR */,
|
|
@@ -20617,7 +20652,7 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
20617
20652
|
taskCount: meta.taskCount,
|
|
20618
20653
|
labelsJson: JSON.stringify(meta.labels),
|
|
20619
20654
|
lastSeen: now
|
|
20620
|
-
}).where(
|
|
20655
|
+
}).where(eq8(projectRegistry.projectHash, projectHash));
|
|
20621
20656
|
} else {
|
|
20622
20657
|
if (!projectId) {
|
|
20623
20658
|
projectId = randomUUID3();
|
|
@@ -20655,9 +20690,9 @@ async function nexusUnregister(nameOrHash) {
|
|
|
20655
20690
|
throw new CleoError(4 /* NOT_FOUND */, `Project not found in registry: ${nameOrHash}`);
|
|
20656
20691
|
}
|
|
20657
20692
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20658
|
-
const { eq:
|
|
20693
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
20659
20694
|
const db = await getNexusDb2();
|
|
20660
|
-
await db.delete(projectRegistry).where(
|
|
20695
|
+
await db.delete(projectRegistry).where(eq8(projectRegistry.projectHash, project.hash));
|
|
20661
20696
|
await writeNexusAudit({
|
|
20662
20697
|
action: "unregister",
|
|
20663
20698
|
projectHash: project.hash,
|
|
@@ -20679,9 +20714,9 @@ async function nexusList() {
|
|
|
20679
20714
|
async function nexusGetProject(nameOrHash) {
|
|
20680
20715
|
try {
|
|
20681
20716
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20682
|
-
const { eq:
|
|
20717
|
+
const { eq: eq8, or: or4 } = await import("drizzle-orm");
|
|
20683
20718
|
const db = await getNexusDb2();
|
|
20684
|
-
const rows = await db.select().from(projectRegistry).where(or4(
|
|
20719
|
+
const rows = await db.select().from(projectRegistry).where(or4(eq8(projectRegistry.projectHash, nameOrHash), eq8(projectRegistry.name, nameOrHash)));
|
|
20685
20720
|
const row = rows[0];
|
|
20686
20721
|
if (!row) return null;
|
|
20687
20722
|
return rowToProject(row);
|
|
@@ -20704,14 +20739,14 @@ async function nexusSync(nameOrHash) {
|
|
|
20704
20739
|
const meta = await readProjectMeta(project.path);
|
|
20705
20740
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20706
20741
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20707
|
-
const { eq:
|
|
20742
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
20708
20743
|
const db = await getNexusDb2();
|
|
20709
20744
|
await db.update(projectRegistry).set({
|
|
20710
20745
|
taskCount: meta.taskCount,
|
|
20711
20746
|
labelsJson: JSON.stringify(meta.labels),
|
|
20712
20747
|
lastSync: now,
|
|
20713
20748
|
lastSeen: now
|
|
20714
|
-
}).where(
|
|
20749
|
+
}).where(eq8(projectRegistry.projectHash, project.hash));
|
|
20715
20750
|
await writeNexusAudit({
|
|
20716
20751
|
action: "sync",
|
|
20717
20752
|
projectHash: project.hash,
|
|
@@ -20725,7 +20760,7 @@ async function nexusSyncAll() {
|
|
|
20725
20760
|
let synced = 0;
|
|
20726
20761
|
let failed = 0;
|
|
20727
20762
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20728
|
-
const { eq:
|
|
20763
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
20729
20764
|
const db = await getNexusDb2();
|
|
20730
20765
|
for (const project of projects) {
|
|
20731
20766
|
try {
|
|
@@ -20736,7 +20771,7 @@ async function nexusSyncAll() {
|
|
|
20736
20771
|
labelsJson: JSON.stringify(meta.labels),
|
|
20737
20772
|
lastSync: now,
|
|
20738
20773
|
lastSeen: now
|
|
20739
|
-
}).where(
|
|
20774
|
+
}).where(eq8(projectRegistry.projectHash, project.hash));
|
|
20740
20775
|
synced++;
|
|
20741
20776
|
} catch {
|
|
20742
20777
|
failed++;
|
|
@@ -20756,9 +20791,9 @@ async function nexusSetPermission(nameOrHash, permission) {
|
|
|
20756
20791
|
throw new CleoError(4 /* NOT_FOUND */, `Project not found in registry: ${nameOrHash}`);
|
|
20757
20792
|
}
|
|
20758
20793
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20759
|
-
const { eq:
|
|
20794
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
20760
20795
|
const db = await getNexusDb2();
|
|
20761
|
-
await db.update(projectRegistry).set({ permissions: permission }).where(
|
|
20796
|
+
await db.update(projectRegistry).set({ permissions: permission }).where(eq8(projectRegistry.projectHash, project.hash));
|
|
20762
20797
|
await writeNexusAudit({
|
|
20763
20798
|
action: "set-permission",
|
|
20764
20799
|
projectHash: project.hash,
|
|
@@ -20774,12 +20809,12 @@ async function nexusReconcile(projectRoot) {
|
|
|
20774
20809
|
}
|
|
20775
20810
|
await nexusInit();
|
|
20776
20811
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
20777
|
-
const { eq:
|
|
20812
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
20778
20813
|
const db = await getNexusDb2();
|
|
20779
20814
|
const projectId = await readProjectId(projectRoot);
|
|
20780
20815
|
const currentHash = generateProjectHash(projectRoot);
|
|
20781
20816
|
if (projectId) {
|
|
20782
|
-
const hashRows2 = await db.select().from(projectRegistry).where(
|
|
20817
|
+
const hashRows2 = await db.select().from(projectRegistry).where(eq8(projectRegistry.projectHash, currentHash));
|
|
20783
20818
|
const hashMatch2 = hashRows2[0];
|
|
20784
20819
|
if (hashMatch2 && hashMatch2.projectId !== projectId) {
|
|
20785
20820
|
await writeNexusAudit({
|
|
@@ -20798,12 +20833,12 @@ async function nexusReconcile(projectRoot) {
|
|
|
20798
20833
|
}
|
|
20799
20834
|
}
|
|
20800
20835
|
if (projectId) {
|
|
20801
|
-
const idRows = await db.select().from(projectRegistry).where(
|
|
20836
|
+
const idRows = await db.select().from(projectRegistry).where(eq8(projectRegistry.projectId, projectId));
|
|
20802
20837
|
const existing = idRows[0];
|
|
20803
20838
|
if (existing) {
|
|
20804
20839
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20805
20840
|
if (existing.projectPath === projectRoot) {
|
|
20806
|
-
await db.update(projectRegistry).set({ lastSeen: now }).where(
|
|
20841
|
+
await db.update(projectRegistry).set({ lastSeen: now }).where(eq8(projectRegistry.projectId, projectId));
|
|
20807
20842
|
await writeNexusAudit({
|
|
20808
20843
|
action: "reconcile",
|
|
20809
20844
|
projectHash: currentHash,
|
|
@@ -20819,7 +20854,7 @@ async function nexusReconcile(projectRoot) {
|
|
|
20819
20854
|
projectPath: projectRoot,
|
|
20820
20855
|
projectHash: currentHash,
|
|
20821
20856
|
lastSeen: now
|
|
20822
|
-
}).where(
|
|
20857
|
+
}).where(eq8(projectRegistry.projectId, projectId));
|
|
20823
20858
|
await writeNexusAudit({
|
|
20824
20859
|
action: "reconcile",
|
|
20825
20860
|
projectHash: currentHash,
|
|
@@ -20831,11 +20866,11 @@ async function nexusReconcile(projectRoot) {
|
|
|
20831
20866
|
return { status: "path_updated", oldPath, newPath: projectRoot };
|
|
20832
20867
|
}
|
|
20833
20868
|
}
|
|
20834
|
-
const hashRows = await db.select().from(projectRegistry).where(
|
|
20869
|
+
const hashRows = await db.select().from(projectRegistry).where(eq8(projectRegistry.projectHash, currentHash));
|
|
20835
20870
|
const hashMatch = hashRows[0];
|
|
20836
20871
|
if (hashMatch) {
|
|
20837
20872
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20838
|
-
await db.update(projectRegistry).set({ lastSeen: now }).where(
|
|
20873
|
+
await db.update(projectRegistry).set({ lastSeen: now }).where(eq8(projectRegistry.projectHash, currentHash));
|
|
20839
20874
|
await writeNexusAudit({
|
|
20840
20875
|
action: "reconcile",
|
|
20841
20876
|
projectHash: currentHash,
|
|
@@ -21437,7 +21472,7 @@ var init_update2 = __esm({
|
|
|
21437
21472
|
// packages/core/src/sessions/assumptions.ts
|
|
21438
21473
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
21439
21474
|
import { appendFileSync as appendFileSync7, existsSync as existsSync63, mkdirSync as mkdirSync13 } from "node:fs";
|
|
21440
|
-
import { join as
|
|
21475
|
+
import { join as join67 } from "node:path";
|
|
21441
21476
|
async function recordAssumption(projectRoot, params) {
|
|
21442
21477
|
if (!params?.assumption) {
|
|
21443
21478
|
throw new CleoError(2 /* INVALID_INPUT */, "assumption is required");
|
|
@@ -21459,11 +21494,11 @@ async function recordAssumption(projectRoot, params) {
|
|
|
21459
21494
|
validatedAt: null,
|
|
21460
21495
|
timestamp: now
|
|
21461
21496
|
};
|
|
21462
|
-
const auditDir =
|
|
21497
|
+
const auditDir = join67(projectRoot, ".cleo", "audit");
|
|
21463
21498
|
if (!existsSync63(auditDir)) {
|
|
21464
21499
|
mkdirSync13(auditDir, { recursive: true });
|
|
21465
21500
|
}
|
|
21466
|
-
const assumptionsPath =
|
|
21501
|
+
const assumptionsPath = join67(auditDir, "assumptions.jsonl");
|
|
21467
21502
|
appendFileSync7(assumptionsPath, JSON.stringify(record) + "\n", "utf-8");
|
|
21468
21503
|
return {
|
|
21469
21504
|
id,
|
|
@@ -22915,11 +22950,11 @@ var init_sessions = __esm({
|
|
|
22915
22950
|
|
|
22916
22951
|
// packages/core/src/hooks.ts
|
|
22917
22952
|
import { existsSync as existsSync83 } from "node:fs";
|
|
22918
|
-
import { chmod, copyFile as copyFile2, mkdir as
|
|
22919
|
-
import { join as
|
|
22953
|
+
import { chmod, copyFile as copyFile2, mkdir as mkdir14, readFile as readFile14 } from "node:fs/promises";
|
|
22954
|
+
import { join as join86 } from "node:path";
|
|
22920
22955
|
async function ensureGitHooks(projectRoot, opts) {
|
|
22921
|
-
const gitDir =
|
|
22922
|
-
const gitHooksDir =
|
|
22956
|
+
const gitDir = join86(projectRoot, ".git");
|
|
22957
|
+
const gitHooksDir = join86(gitDir, "hooks");
|
|
22923
22958
|
if (!existsSync83(gitDir)) {
|
|
22924
22959
|
return {
|
|
22925
22960
|
action: "skipped",
|
|
@@ -22928,7 +22963,7 @@ async function ensureGitHooks(projectRoot, opts) {
|
|
|
22928
22963
|
};
|
|
22929
22964
|
}
|
|
22930
22965
|
const packageRoot = getPackageRoot();
|
|
22931
|
-
const sourceDir =
|
|
22966
|
+
const sourceDir = join86(packageRoot, "templates", "git-hooks");
|
|
22932
22967
|
if (!existsSync83(sourceDir)) {
|
|
22933
22968
|
return {
|
|
22934
22969
|
action: "skipped",
|
|
@@ -22936,13 +22971,13 @@ async function ensureGitHooks(projectRoot, opts) {
|
|
|
22936
22971
|
details: "templates/git-hooks/ not found in package root, skipping git hook installation"
|
|
22937
22972
|
};
|
|
22938
22973
|
}
|
|
22939
|
-
await
|
|
22974
|
+
await mkdir14(gitHooksDir, { recursive: true });
|
|
22940
22975
|
const force = opts?.force ?? false;
|
|
22941
22976
|
let installedCount = 0;
|
|
22942
22977
|
const errors = [];
|
|
22943
22978
|
for (const hook of MANAGED_HOOKS) {
|
|
22944
|
-
const sourcePath =
|
|
22945
|
-
const destPath =
|
|
22979
|
+
const sourcePath = join86(sourceDir, hook);
|
|
22980
|
+
const destPath = join86(gitHooksDir, hook);
|
|
22946
22981
|
if (!existsSync83(sourcePath)) {
|
|
22947
22982
|
continue;
|
|
22948
22983
|
}
|
|
@@ -22980,13 +23015,13 @@ async function ensureGitHooks(projectRoot, opts) {
|
|
|
22980
23015
|
};
|
|
22981
23016
|
}
|
|
22982
23017
|
async function checkGitHooks(projectRoot) {
|
|
22983
|
-
const gitHooksDir =
|
|
23018
|
+
const gitHooksDir = join86(projectRoot, ".git", "hooks");
|
|
22984
23019
|
const packageRoot = getPackageRoot();
|
|
22985
|
-
const sourceDir =
|
|
23020
|
+
const sourceDir = join86(packageRoot, "templates", "git-hooks");
|
|
22986
23021
|
const results = [];
|
|
22987
23022
|
for (const hook of MANAGED_HOOKS) {
|
|
22988
|
-
const sourcePath =
|
|
22989
|
-
const installedPath =
|
|
23023
|
+
const sourcePath = join86(sourceDir, hook);
|
|
23024
|
+
const installedPath = join86(gitHooksDir, hook);
|
|
22990
23025
|
const result = {
|
|
22991
23026
|
hook,
|
|
22992
23027
|
installed: false,
|
|
@@ -23069,14 +23104,6 @@ function taskToMarkdown(task) {
|
|
|
23069
23104
|
const priority = task.priority === "critical" ? "!!!" : task.priority === "high" ? "!!" : "";
|
|
23070
23105
|
return `- [${status}] **${task.id}** ${priority} ${task.title}`;
|
|
23071
23106
|
}
|
|
23072
|
-
function taskToTodoWrite(task) {
|
|
23073
|
-
return {
|
|
23074
|
-
id: task.id,
|
|
23075
|
-
content: task.title,
|
|
23076
|
-
status: task.status === "done" ? "completed" : task.status === "active" ? "in_progress" : "pending",
|
|
23077
|
-
priority: task.priority === "critical" ? "high" : task.priority
|
|
23078
|
-
};
|
|
23079
|
-
}
|
|
23080
23107
|
async function exportTasks(params) {
|
|
23081
23108
|
const accessor = await getAccessor(params.cwd);
|
|
23082
23109
|
const queryResult = await accessor.queryTasks({});
|
|
@@ -23140,13 +23167,8 @@ async function exportTasks(params) {
|
|
|
23140
23167
|
content = lines.join("\n");
|
|
23141
23168
|
break;
|
|
23142
23169
|
}
|
|
23143
|
-
case "todowrite": {
|
|
23144
|
-
const items = tasks2.map(taskToTodoWrite);
|
|
23145
|
-
content = JSON.stringify(items, null, 2);
|
|
23146
|
-
break;
|
|
23147
|
-
}
|
|
23148
23170
|
default:
|
|
23149
|
-
throw new Error(`Unknown format: ${format}. Valid: json, csv, tsv, markdown
|
|
23171
|
+
throw new Error(`Unknown format: ${format}. Valid: json, csv, tsv, markdown`);
|
|
23150
23172
|
}
|
|
23151
23173
|
if (params.output) {
|
|
23152
23174
|
await writeFile2(params.output, content);
|
|
@@ -23969,7 +23991,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
23969
23991
|
return result;
|
|
23970
23992
|
}
|
|
23971
23993
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
23972
|
-
const { and:
|
|
23994
|
+
const { and: and6, eq: eq8 } = await import("drizzle-orm");
|
|
23973
23995
|
const db = await getDb3(projectRoot);
|
|
23974
23996
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23975
23997
|
for (const filePath of matchingFiles) {
|
|
@@ -23979,7 +24001,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
23979
24001
|
const fm = record.frontmatter;
|
|
23980
24002
|
const content = readFileSync5(filePath, "utf-8");
|
|
23981
24003
|
const relativePath = `.cleo/adrs/${filename}`;
|
|
23982
|
-
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(
|
|
24004
|
+
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq8(architectureDecisions.id, record.id)).all();
|
|
23983
24005
|
const rowBase = {
|
|
23984
24006
|
id: record.id,
|
|
23985
24007
|
title: record.title,
|
|
@@ -23999,19 +24021,19 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
23999
24021
|
updatedAt: now
|
|
24000
24022
|
};
|
|
24001
24023
|
if (existing.length > 0) {
|
|
24002
|
-
await db.update(architectureDecisions).set(rowBase).where(
|
|
24024
|
+
await db.update(architectureDecisions).set(rowBase).where(eq8(architectureDecisions.id, record.id));
|
|
24003
24025
|
} else {
|
|
24004
24026
|
await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
|
|
24005
24027
|
}
|
|
24006
24028
|
result.synced++;
|
|
24007
|
-
await db.delete(adrTaskLinks).where(
|
|
24029
|
+
await db.delete(adrTaskLinks).where(and6(eq8(adrTaskLinks.adrId, record.id), eq8(adrTaskLinks.taskId, taskId)));
|
|
24008
24030
|
await db.insert(adrTaskLinks).values({ adrId: record.id, taskId, linkType: "implements" });
|
|
24009
24031
|
result.linked.push({ adrId: record.id, taskId });
|
|
24010
24032
|
if (fm["Related ADRs"]) {
|
|
24011
24033
|
const relatedIds = fm["Related ADRs"].split(",").map((r) => r.trim()).filter((r) => /^ADR-\d+$/.test(r));
|
|
24012
24034
|
for (const toId of relatedIds) {
|
|
24013
24035
|
try {
|
|
24014
|
-
const targetExists = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(
|
|
24036
|
+
const targetExists = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq8(architectureDecisions.id, toId)).all();
|
|
24015
24037
|
if (targetExists.length > 0) {
|
|
24016
24038
|
await db.insert(adrRelations).values({ fromAdrId: record.id, toAdrId: toId, relationType: "related" }).onConflictDoNothing();
|
|
24017
24039
|
}
|
|
@@ -24149,7 +24171,7 @@ async function syncAdrsToDb(projectRoot) {
|
|
|
24149
24171
|
return result;
|
|
24150
24172
|
}
|
|
24151
24173
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
24152
|
-
const { eq:
|
|
24174
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
24153
24175
|
const db = await getDb3(projectRoot);
|
|
24154
24176
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24155
24177
|
const allFiles = collectAdrFiles(adrsDir);
|
|
@@ -24183,15 +24205,15 @@ async function syncAdrsToDb(projectRoot) {
|
|
|
24183
24205
|
topics: fm.Topics ?? null,
|
|
24184
24206
|
updatedAt: now
|
|
24185
24207
|
};
|
|
24186
|
-
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(
|
|
24208
|
+
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq8(architectureDecisions.id, record.id)).all();
|
|
24187
24209
|
if (existing.length > 0) {
|
|
24188
|
-
await db.update(architectureDecisions).set(rowBase).where(
|
|
24210
|
+
await db.update(architectureDecisions).set(rowBase).where(eq8(architectureDecisions.id, record.id));
|
|
24189
24211
|
result.updated++;
|
|
24190
24212
|
} else {
|
|
24191
24213
|
await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
|
|
24192
24214
|
result.inserted++;
|
|
24193
24215
|
}
|
|
24194
|
-
await db.delete(adrTaskLinks).where(
|
|
24216
|
+
await db.delete(adrTaskLinks).where(eq8(adrTaskLinks.adrId, record.id));
|
|
24195
24217
|
if (fm["Related Tasks"]) {
|
|
24196
24218
|
for (const taskId of parseTaskIds2(fm["Related Tasks"])) {
|
|
24197
24219
|
await db.insert(adrTaskLinks).values({ adrId: record.id, taskId, linkType: "related" });
|
|
@@ -25124,7 +25146,7 @@ function selectTasksForInjection(data, opts) {
|
|
|
25124
25146
|
});
|
|
25125
25147
|
return tasks2.slice(0, maxTasks);
|
|
25126
25148
|
}
|
|
25127
|
-
function
|
|
25149
|
+
function formatForInjection(tasks2) {
|
|
25128
25150
|
return tasks2.map((t) => {
|
|
25129
25151
|
let prefix = `[${t.id}]`;
|
|
25130
25152
|
if (t.priority === "critical" || t.priority === "high") prefix += " [!]";
|
|
@@ -25143,7 +25165,7 @@ async function injectTasks(opts, accessor) {
|
|
|
25143
25165
|
focus: focusMeta
|
|
25144
25166
|
};
|
|
25145
25167
|
const selectedTasks = selectTasksForInjection(data, opts);
|
|
25146
|
-
const formatted =
|
|
25168
|
+
const formatted = formatForInjection(selectedTasks);
|
|
25147
25169
|
const phase = opts.phase ?? projectMeta?.currentPhase ?? null;
|
|
25148
25170
|
return {
|
|
25149
25171
|
tasks: formatted,
|
|
@@ -26289,12 +26311,12 @@ async function getEnforcementMode(cwd) {
|
|
|
26289
26311
|
}
|
|
26290
26312
|
async function getLifecycleStatus(epicId, cwd) {
|
|
26291
26313
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
26292
|
-
const { eq:
|
|
26314
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26293
26315
|
const db = await getDb3(cwd);
|
|
26294
26316
|
const pipelineResult = await db.select({
|
|
26295
26317
|
pipeline: lifecyclePipelines,
|
|
26296
26318
|
task: tasks
|
|
26297
|
-
}).from(lifecyclePipelines).innerJoin(tasks,
|
|
26319
|
+
}).from(lifecyclePipelines).innerJoin(tasks, eq8(lifecyclePipelines.taskId, tasks.id)).where(eq8(lifecyclePipelines.taskId, epicId)).limit(1);
|
|
26298
26320
|
if (pipelineResult.length === 0) {
|
|
26299
26321
|
return {
|
|
26300
26322
|
epicId,
|
|
@@ -26307,7 +26329,7 @@ async function getLifecycleStatus(epicId, cwd) {
|
|
|
26307
26329
|
}
|
|
26308
26330
|
const task = pipelineResult[0].task;
|
|
26309
26331
|
const pipelineId = `pipeline-${epicId}`;
|
|
26310
|
-
const stageRows = await db.select().from(lifecycleStages).where(
|
|
26332
|
+
const stageRows = await db.select().from(lifecycleStages).where(eq8(lifecycleStages.pipelineId, pipelineId)).orderBy(lifecycleStages.sequence);
|
|
26311
26333
|
const stageDataMap = /* @__PURE__ */ new Map();
|
|
26312
26334
|
for (const row of stageRows) {
|
|
26313
26335
|
let parsedChain;
|
|
@@ -26376,10 +26398,10 @@ async function getLifecycleStatus(epicId, cwd) {
|
|
|
26376
26398
|
}
|
|
26377
26399
|
async function getLifecycleHistory(epicId, cwd) {
|
|
26378
26400
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
26379
|
-
const { eq:
|
|
26401
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26380
26402
|
const db = await getDb3(cwd);
|
|
26381
26403
|
const pipelineId = `pipeline-${epicId}`;
|
|
26382
|
-
const stages = await db.select().from(lifecycleStages).where(
|
|
26404
|
+
const stages = await db.select().from(lifecycleStages).where(eq8(lifecycleStages.pipelineId, pipelineId));
|
|
26383
26405
|
if (stages.length === 0) {
|
|
26384
26406
|
return { epicId, history: [] };
|
|
26385
26407
|
}
|
|
@@ -26409,7 +26431,7 @@ async function getLifecycleHistory(epicId, cwd) {
|
|
|
26409
26431
|
}
|
|
26410
26432
|
const stageIds = stages.map((s) => s.id);
|
|
26411
26433
|
if (stageIds.length > 0) {
|
|
26412
|
-
const gateResults = await db.select().from(lifecycleGateResults).where(
|
|
26434
|
+
const gateResults = await db.select().from(lifecycleGateResults).where(eq8(lifecycleGateResults.stageId, stageIds[0]));
|
|
26413
26435
|
for (const gate of gateResults) {
|
|
26414
26436
|
const stageName = stageIdToName.get(gate.stageId);
|
|
26415
26437
|
if (stageName) {
|
|
@@ -26422,7 +26444,7 @@ async function getLifecycleHistory(epicId, cwd) {
|
|
|
26422
26444
|
}
|
|
26423
26445
|
}
|
|
26424
26446
|
for (let i = 1; i < stageIds.length; i++) {
|
|
26425
|
-
const additionalGates = await db.select().from(lifecycleGateResults).where(
|
|
26447
|
+
const additionalGates = await db.select().from(lifecycleGateResults).where(eq8(lifecycleGateResults.stageId, stageIds[i]));
|
|
26426
26448
|
for (const gate of additionalGates) {
|
|
26427
26449
|
const stageName = stageIdToName.get(gate.stageId);
|
|
26428
26450
|
if (stageName) {
|
|
@@ -26441,16 +26463,16 @@ async function getLifecycleHistory(epicId, cwd) {
|
|
|
26441
26463
|
}
|
|
26442
26464
|
async function getLifecycleGates(epicId, cwd) {
|
|
26443
26465
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
26444
|
-
const { eq:
|
|
26466
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26445
26467
|
const db = await getDb3(cwd);
|
|
26446
26468
|
const pipelineId = `pipeline-${epicId}`;
|
|
26447
|
-
const stages = await db.select().from(lifecycleStages).where(
|
|
26469
|
+
const stages = await db.select().from(lifecycleStages).where(eq8(lifecycleStages.pipelineId, pipelineId));
|
|
26448
26470
|
if (stages.length === 0) {
|
|
26449
26471
|
return {};
|
|
26450
26472
|
}
|
|
26451
26473
|
const gates = {};
|
|
26452
26474
|
for (const stage of stages) {
|
|
26453
|
-
const gateRows = await db.select().from(lifecycleGateResults).where(
|
|
26475
|
+
const gateRows = await db.select().from(lifecycleGateResults).where(eq8(lifecycleGateResults.stageId, stage.id));
|
|
26454
26476
|
if (gateRows.length > 0) {
|
|
26455
26477
|
gates[stage.stageName] = {};
|
|
26456
26478
|
for (const gateRow of gateRows) {
|
|
@@ -26514,7 +26536,7 @@ async function checkStagePrerequisites(epicId, targetStage, cwd) {
|
|
|
26514
26536
|
}
|
|
26515
26537
|
async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
26516
26538
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
26517
|
-
const { eq:
|
|
26539
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26518
26540
|
const db = await getDb3(cwd);
|
|
26519
26541
|
const pipelineId = `pipeline-${epicId}`;
|
|
26520
26542
|
const stageId = `stage-${epicId}-${stageName}`;
|
|
@@ -26522,7 +26544,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
|
26522
26544
|
getNativeDb2().prepare(
|
|
26523
26545
|
`INSERT OR IGNORE INTO tasks (id, title, status, priority, created_at) VALUES (?, ?, 'pending', 'medium', datetime('now'))`
|
|
26524
26546
|
).run(epicId, `Task ${epicId}`);
|
|
26525
|
-
const existingPipeline = await db.select().from(lifecyclePipelines).where(
|
|
26547
|
+
const existingPipeline = await db.select().from(lifecyclePipelines).where(eq8(lifecyclePipelines.id, pipelineId)).limit(1).all();
|
|
26526
26548
|
if (existingPipeline.length === 0) {
|
|
26527
26549
|
await db.insert(lifecyclePipelines).values({
|
|
26528
26550
|
id: pipelineId,
|
|
@@ -26532,7 +26554,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
|
26532
26554
|
startedAt: options.now
|
|
26533
26555
|
}).run();
|
|
26534
26556
|
}
|
|
26535
|
-
const existingStage = await db.select().from(lifecycleStages).where(
|
|
26557
|
+
const existingStage = await db.select().from(lifecycleStages).where(eq8(lifecycleStages.id, stageId)).limit(1).all();
|
|
26536
26558
|
if (existingStage.length === 0) {
|
|
26537
26559
|
const sequence = isValidStage(stageName) ? STAGE_ORDER[stageName] : 0;
|
|
26538
26560
|
await db.insert(lifecycleStages).values({
|
|
@@ -26545,7 +26567,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
|
26545
26567
|
}).run();
|
|
26546
26568
|
}
|
|
26547
26569
|
if (options.updateCurrentStage) {
|
|
26548
|
-
await db.update(lifecyclePipelines).set({ currentStageId: stageId }).where(
|
|
26570
|
+
await db.update(lifecyclePipelines).set({ currentStageId: stageId }).where(eq8(lifecyclePipelines.id, pipelineId)).run();
|
|
26549
26571
|
}
|
|
26550
26572
|
return { db, pipelineId, stageId };
|
|
26551
26573
|
}
|
|
@@ -26560,7 +26582,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
|
|
|
26560
26582
|
`Invalid status: ${status}. Valid: ${validStatuses.join(", ")}`
|
|
26561
26583
|
);
|
|
26562
26584
|
}
|
|
26563
|
-
const { eq:
|
|
26585
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26564
26586
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26565
26587
|
const stageName = stage;
|
|
26566
26588
|
const { db, stageId, pipelineId } = await ensureLifecycleContext(epicId, stage, cwd, {
|
|
@@ -26576,7 +26598,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
|
|
|
26576
26598
|
status,
|
|
26577
26599
|
related: artifact.related
|
|
26578
26600
|
};
|
|
26579
|
-
const existingStage = await db.select().from(lifecycleStages).where(
|
|
26601
|
+
const existingStage = await db.select().from(lifecycleStages).where(eq8(lifecycleStages.id, stageId)).limit(1).all();
|
|
26580
26602
|
const sequence = STAGE_ORDER[stage];
|
|
26581
26603
|
const stageValues = {
|
|
26582
26604
|
status,
|
|
@@ -26603,7 +26625,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
|
|
|
26603
26625
|
provenanceChainJson: JSON.stringify(provenanceChain)
|
|
26604
26626
|
}).run();
|
|
26605
26627
|
} else {
|
|
26606
|
-
await db.update(lifecycleStages).set(stageValues).where(
|
|
26628
|
+
await db.update(lifecycleStages).set(stageValues).where(eq8(lifecycleStages.id, stageId)).run();
|
|
26607
26629
|
}
|
|
26608
26630
|
if (status === "completed") {
|
|
26609
26631
|
await linkProvenance(epicId, stageName, artifact.absolutePath, cwd);
|
|
@@ -26623,7 +26645,7 @@ async function resetStage(epicId, stage, reason, cwd) {
|
|
|
26623
26645
|
if (!PIPELINE_STAGES.includes(stage)) {
|
|
26624
26646
|
throw new CleoError(2 /* INVALID_INPUT */, `Invalid stage: ${stage}`);
|
|
26625
26647
|
}
|
|
26626
|
-
const { eq:
|
|
26648
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26627
26649
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26628
26650
|
const { db, stageId } = await ensureLifecycleContext(epicId, stage, cwd, {
|
|
26629
26651
|
now,
|
|
@@ -26636,11 +26658,11 @@ async function resetStage(epicId, stage, reason, cwd) {
|
|
|
26636
26658
|
skippedAt: null,
|
|
26637
26659
|
skipReason: null,
|
|
26638
26660
|
notesJson: JSON.stringify([`Reset: ${reason}`])
|
|
26639
|
-
}).where(
|
|
26661
|
+
}).where(eq8(lifecycleStages.id, stageId)).run();
|
|
26640
26662
|
return { epicId, stage, reason };
|
|
26641
26663
|
}
|
|
26642
26664
|
async function passGate(epicId, gateName, agent, notes, cwd) {
|
|
26643
|
-
const { eq:
|
|
26665
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26644
26666
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26645
26667
|
const stageName = gateName.split("-")[0];
|
|
26646
26668
|
const gateId = `gate-${epicId}-${stageName}-${gateName}`;
|
|
@@ -26649,7 +26671,7 @@ async function passGate(epicId, gateName, agent, notes, cwd) {
|
|
|
26649
26671
|
stageStatusOnCreate: "in_progress",
|
|
26650
26672
|
updateCurrentStage: true
|
|
26651
26673
|
});
|
|
26652
|
-
const existingGate = await db.select().from(lifecycleGateResults).where(
|
|
26674
|
+
const existingGate = await db.select().from(lifecycleGateResults).where(eq8(lifecycleGateResults.id, gateId)).limit(1).all();
|
|
26653
26675
|
const gateValues = {
|
|
26654
26676
|
id: gateId,
|
|
26655
26677
|
stageId,
|
|
@@ -26661,14 +26683,14 @@ async function passGate(epicId, gateName, agent, notes, cwd) {
|
|
|
26661
26683
|
reason: null
|
|
26662
26684
|
};
|
|
26663
26685
|
if (existingGate.length > 0) {
|
|
26664
|
-
await db.update(lifecycleGateResults).set(gateValues).where(
|
|
26686
|
+
await db.update(lifecycleGateResults).set(gateValues).where(eq8(lifecycleGateResults.id, gateId)).run();
|
|
26665
26687
|
} else {
|
|
26666
26688
|
await db.insert(lifecycleGateResults).values(gateValues).run();
|
|
26667
26689
|
}
|
|
26668
26690
|
return { epicId, gateName, timestamp: now };
|
|
26669
26691
|
}
|
|
26670
26692
|
async function failGate(epicId, gateName, reason, cwd) {
|
|
26671
|
-
const { eq:
|
|
26693
|
+
const { eq: eq8 } = await import("drizzle-orm");
|
|
26672
26694
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26673
26695
|
const stageName = gateName.split("-")[0];
|
|
26674
26696
|
const gateId = `gate-${epicId}-${stageName}-${gateName}`;
|
|
@@ -26677,7 +26699,7 @@ async function failGate(epicId, gateName, reason, cwd) {
|
|
|
26677
26699
|
stageStatusOnCreate: "in_progress",
|
|
26678
26700
|
updateCurrentStage: true
|
|
26679
26701
|
});
|
|
26680
|
-
const existingGate = await db.select().from(lifecycleGateResults).where(
|
|
26702
|
+
const existingGate = await db.select().from(lifecycleGateResults).where(eq8(lifecycleGateResults.id, gateId)).limit(1).all();
|
|
26681
26703
|
const gateValues = {
|
|
26682
26704
|
id: gateId,
|
|
26683
26705
|
stageId,
|
|
@@ -26689,7 +26711,7 @@ async function failGate(epicId, gateName, reason, cwd) {
|
|
|
26689
26711
|
reason: reason ?? null
|
|
26690
26712
|
};
|
|
26691
26713
|
if (existingGate.length > 0) {
|
|
26692
|
-
await db.update(lifecycleGateResults).set(gateValues).where(
|
|
26714
|
+
await db.update(lifecycleGateResults).set(gateValues).where(eq8(lifecycleGateResults.id, gateId)).run();
|
|
26693
26715
|
} else {
|
|
26694
26716
|
await db.insert(lifecycleGateResults).values(gateValues).run();
|
|
26695
26717
|
}
|
|
@@ -27879,8 +27901,8 @@ function parseTokenMetrics(inputFile, cwd) {
|
|
|
27879
27901
|
const raw = JSON.parse(readFileSync28(file, "utf-8"));
|
|
27880
27902
|
if (raw.resourceMetrics) {
|
|
27881
27903
|
const points = [];
|
|
27882
|
-
for (const
|
|
27883
|
-
for (const sm of
|
|
27904
|
+
for (const rm2 of raw.resourceMetrics ?? []) {
|
|
27905
|
+
for (const sm of rm2.scopeMetrics ?? []) {
|
|
27884
27906
|
for (const metric of sm.metrics ?? []) {
|
|
27885
27907
|
if (metric.name !== "claude_code.token.usage") continue;
|
|
27886
27908
|
for (const dp of metric.sum?.dataPoints ?? []) {
|
|
@@ -31064,8 +31086,8 @@ function collectCleoFiles(cleoDir) {
|
|
|
31064
31086
|
const fullPath = join59(dir, entry);
|
|
31065
31087
|
const relPath = relative5(cleoDir, fullPath);
|
|
31066
31088
|
try {
|
|
31067
|
-
const
|
|
31068
|
-
if (
|
|
31089
|
+
const stat2 = statSync15(fullPath);
|
|
31090
|
+
if (stat2.isDirectory()) {
|
|
31069
31091
|
walk(fullPath);
|
|
31070
31092
|
} else {
|
|
31071
31093
|
files.push(relPath.replaceAll("\\", "/"));
|
|
@@ -31301,17 +31323,17 @@ function scanLogDir(dir, includeMigration) {
|
|
|
31301
31323
|
const isMigration = MIGRATION_LOG_PATTERN.test(name2);
|
|
31302
31324
|
if (!cleoMatch && (!isMigration || !includeMigration)) continue;
|
|
31303
31325
|
const filePath = join60(dir, name2);
|
|
31304
|
-
let
|
|
31326
|
+
let stat2;
|
|
31305
31327
|
try {
|
|
31306
|
-
|
|
31328
|
+
stat2 = statSync16(filePath);
|
|
31307
31329
|
} catch {
|
|
31308
31330
|
continue;
|
|
31309
31331
|
}
|
|
31310
31332
|
files.push({
|
|
31311
31333
|
path: filePath,
|
|
31312
31334
|
name: name2,
|
|
31313
|
-
size:
|
|
31314
|
-
mtime:
|
|
31335
|
+
size: stat2.size,
|
|
31336
|
+
mtime: stat2.mtime.toISOString(),
|
|
31315
31337
|
date: cleoMatch ? cleoMatch[1] : null,
|
|
31316
31338
|
isActive: false
|
|
31317
31339
|
// set below
|
|
@@ -32501,53 +32523,109 @@ async function showPhase2(projectRoot, phaseId, accessor) {
|
|
|
32501
32523
|
// packages/core/src/reconciliation/index.ts
|
|
32502
32524
|
var reconciliation_exports = {};
|
|
32503
32525
|
__export(reconciliation_exports, {
|
|
32504
|
-
|
|
32505
|
-
|
|
32526
|
+
createLink: () => createLink,
|
|
32527
|
+
getLinkByExternalId: () => getLinkByExternalId,
|
|
32528
|
+
getLinksByProvider: () => getLinksByProvider,
|
|
32529
|
+
getLinksByTaskId: () => getLinksByTaskId,
|
|
32506
32530
|
reconcile: () => reconcile,
|
|
32507
|
-
|
|
32531
|
+
removeLinksByProvider: () => removeLinksByProvider,
|
|
32532
|
+
touchLink: () => touchLink
|
|
32508
32533
|
});
|
|
32509
32534
|
|
|
32510
|
-
// packages/core/src/reconciliation/
|
|
32511
|
-
|
|
32512
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
32515
|
-
|
|
32516
|
-
|
|
32517
|
-
|
|
32518
|
-
|
|
32519
|
-
init_json2();
|
|
32520
|
-
import { mkdir as mkdir13, rm as rm2 } from "node:fs/promises";
|
|
32521
|
-
import { join as join62 } from "node:path";
|
|
32522
|
-
function getSyncDir(cwd) {
|
|
32523
|
-
return join62(getCleoDir(cwd), "sync");
|
|
32535
|
+
// packages/core/src/reconciliation/link-store.ts
|
|
32536
|
+
init_sqlite2();
|
|
32537
|
+
init_tasks_schema();
|
|
32538
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
32539
|
+
import { and as and4, eq as eq6 } from "drizzle-orm";
|
|
32540
|
+
async function getLinksByProvider(providerId, cwd) {
|
|
32541
|
+
const db = await getDb(cwd);
|
|
32542
|
+
const rows = await db.select().from(externalTaskLinks).where(eq6(externalTaskLinks.providerId, providerId));
|
|
32543
|
+
return rows.map(rowToLink);
|
|
32524
32544
|
}
|
|
32525
|
-
function
|
|
32526
|
-
|
|
32545
|
+
async function getLinkByExternalId(providerId, externalId, cwd) {
|
|
32546
|
+
const db = await getDb(cwd);
|
|
32547
|
+
const rows = await db.select().from(externalTaskLinks).where(
|
|
32548
|
+
and4(
|
|
32549
|
+
eq6(externalTaskLinks.providerId, providerId),
|
|
32550
|
+
eq6(externalTaskLinks.externalId, externalId)
|
|
32551
|
+
)
|
|
32552
|
+
);
|
|
32553
|
+
return rows.length > 0 ? rowToLink(rows[0]) : null;
|
|
32527
32554
|
}
|
|
32528
|
-
async function
|
|
32529
|
-
const
|
|
32530
|
-
|
|
32531
|
-
|
|
32532
|
-
|
|
32533
|
-
|
|
32555
|
+
async function getLinksByTaskId(taskId, cwd) {
|
|
32556
|
+
const db = await getDb(cwd);
|
|
32557
|
+
const rows = await db.select().from(externalTaskLinks).where(eq6(externalTaskLinks.taskId, taskId));
|
|
32558
|
+
return rows.map(rowToLink);
|
|
32559
|
+
}
|
|
32560
|
+
async function createLink(params, cwd) {
|
|
32561
|
+
const db = await getDb(cwd);
|
|
32562
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
32563
|
+
const id = randomUUID4();
|
|
32564
|
+
await db.insert(externalTaskLinks).values({
|
|
32565
|
+
id,
|
|
32566
|
+
taskId: params.taskId,
|
|
32567
|
+
providerId: params.providerId,
|
|
32568
|
+
externalId: params.externalId,
|
|
32569
|
+
externalUrl: params.externalUrl ?? null,
|
|
32570
|
+
externalTitle: params.externalTitle ?? null,
|
|
32571
|
+
linkType: params.linkType,
|
|
32572
|
+
syncDirection: params.syncDirection ?? "inbound",
|
|
32573
|
+
metadataJson: params.metadata ? JSON.stringify(params.metadata) : "{}",
|
|
32574
|
+
linkedAt: now,
|
|
32575
|
+
lastSyncAt: now
|
|
32576
|
+
});
|
|
32577
|
+
return {
|
|
32578
|
+
id,
|
|
32579
|
+
taskId: params.taskId,
|
|
32580
|
+
providerId: params.providerId,
|
|
32581
|
+
externalId: params.externalId,
|
|
32582
|
+
externalUrl: params.externalUrl ?? null,
|
|
32583
|
+
externalTitle: params.externalTitle ?? null,
|
|
32584
|
+
linkType: params.linkType,
|
|
32585
|
+
syncDirection: params.syncDirection ?? "inbound",
|
|
32586
|
+
metadata: params.metadata,
|
|
32587
|
+
linkedAt: now,
|
|
32588
|
+
lastSyncAt: now
|
|
32589
|
+
};
|
|
32590
|
+
}
|
|
32591
|
+
async function touchLink(linkId, updates, cwd) {
|
|
32592
|
+
const db = await getDb(cwd);
|
|
32593
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
32594
|
+
const values = { lastSyncAt: now };
|
|
32595
|
+
if (updates?.externalTitle !== void 0) {
|
|
32596
|
+
values.externalTitle = updates.externalTitle;
|
|
32597
|
+
}
|
|
32598
|
+
if (updates?.metadata !== void 0) {
|
|
32599
|
+
values.metadataJson = JSON.stringify(updates.metadata);
|
|
32534
32600
|
}
|
|
32601
|
+
await db.update(externalTaskLinks).set(values).where(eq6(externalTaskLinks.id, linkId));
|
|
32535
32602
|
}
|
|
32536
|
-
async function
|
|
32537
|
-
const
|
|
32538
|
-
await
|
|
32539
|
-
|
|
32540
|
-
await atomicWriteJson(filePath, state);
|
|
32603
|
+
async function removeLinksByProvider(providerId, cwd) {
|
|
32604
|
+
const db = await getDb(cwd);
|
|
32605
|
+
const result = await db.delete(externalTaskLinks).where(eq6(externalTaskLinks.providerId, providerId));
|
|
32606
|
+
return Number(result.changes);
|
|
32541
32607
|
}
|
|
32542
|
-
|
|
32543
|
-
|
|
32544
|
-
|
|
32545
|
-
|
|
32546
|
-
|
|
32547
|
-
|
|
32608
|
+
function rowToLink(row) {
|
|
32609
|
+
return {
|
|
32610
|
+
id: row.id,
|
|
32611
|
+
taskId: row.taskId,
|
|
32612
|
+
providerId: row.providerId,
|
|
32613
|
+
externalId: row.externalId,
|
|
32614
|
+
externalUrl: row.externalUrl,
|
|
32615
|
+
externalTitle: row.externalTitle,
|
|
32616
|
+
linkType: row.linkType,
|
|
32617
|
+
syncDirection: row.syncDirection,
|
|
32618
|
+
metadata: row.metadataJson ? JSON.parse(row.metadataJson) : void 0,
|
|
32619
|
+
linkedAt: row.linkedAt,
|
|
32620
|
+
lastSyncAt: row.lastSyncAt
|
|
32621
|
+
};
|
|
32548
32622
|
}
|
|
32549
32623
|
|
|
32550
32624
|
// packages/core/src/reconciliation/reconciliation-engine.ts
|
|
32625
|
+
init_data_accessor();
|
|
32626
|
+
init_add();
|
|
32627
|
+
init_complete();
|
|
32628
|
+
init_update2();
|
|
32551
32629
|
function buildTaskMap(tasks2) {
|
|
32552
32630
|
const map = /* @__PURE__ */ new Map();
|
|
32553
32631
|
for (const t of tasks2) {
|
|
@@ -32555,19 +32633,25 @@ function buildTaskMap(tasks2) {
|
|
|
32555
32633
|
}
|
|
32556
32634
|
return map;
|
|
32557
32635
|
}
|
|
32558
|
-
function
|
|
32636
|
+
function buildLinkMap(links) {
|
|
32637
|
+
const map = /* @__PURE__ */ new Map();
|
|
32638
|
+
for (const link of links) {
|
|
32639
|
+
map.set(link.externalId, link);
|
|
32640
|
+
}
|
|
32641
|
+
return map;
|
|
32642
|
+
}
|
|
32643
|
+
function computeActions(externalTasks, taskMap, linkMap) {
|
|
32559
32644
|
const actions = [];
|
|
32560
|
-
const seenCleoIds = /* @__PURE__ */ new Set();
|
|
32561
32645
|
for (const ext of externalTasks) {
|
|
32562
|
-
|
|
32563
|
-
|
|
32564
|
-
const cleoTask = taskMap.get(
|
|
32646
|
+
const existingLink = linkMap.get(ext.externalId);
|
|
32647
|
+
if (existingLink) {
|
|
32648
|
+
const cleoTask = taskMap.get(existingLink.taskId);
|
|
32565
32649
|
if (!cleoTask) {
|
|
32566
32650
|
actions.push({
|
|
32567
32651
|
type: "skip",
|
|
32568
|
-
cleoTaskId:
|
|
32652
|
+
cleoTaskId: existingLink.taskId,
|
|
32569
32653
|
externalId: ext.externalId,
|
|
32570
|
-
summary: `CLEO task ${
|
|
32654
|
+
summary: `Linked CLEO task ${existingLink.taskId} no longer exists \u2014 skipping`,
|
|
32571
32655
|
applied: false
|
|
32572
32656
|
});
|
|
32573
32657
|
continue;
|
|
@@ -32575,9 +32659,9 @@ function computeActions(externalTasks, taskMap, injectedIds) {
|
|
|
32575
32659
|
if (cleoTask.status === "done" || cleoTask.status === "cancelled") {
|
|
32576
32660
|
actions.push({
|
|
32577
32661
|
type: "skip",
|
|
32578
|
-
cleoTaskId:
|
|
32662
|
+
cleoTaskId: cleoTask.id,
|
|
32579
32663
|
externalId: ext.externalId,
|
|
32580
|
-
summary: `CLEO task ${
|
|
32664
|
+
summary: `CLEO task ${cleoTask.id} already ${cleoTask.status}`,
|
|
32581
32665
|
applied: false
|
|
32582
32666
|
});
|
|
32583
32667
|
continue;
|
|
@@ -32585,61 +32669,54 @@ function computeActions(externalTasks, taskMap, injectedIds) {
|
|
|
32585
32669
|
if (ext.status === "completed") {
|
|
32586
32670
|
actions.push({
|
|
32587
32671
|
type: "complete",
|
|
32588
|
-
cleoTaskId:
|
|
32672
|
+
cleoTaskId: cleoTask.id,
|
|
32589
32673
|
externalId: ext.externalId,
|
|
32590
|
-
summary: `Complete ${
|
|
32591
|
-
applied: false
|
|
32674
|
+
summary: `Complete ${cleoTask.id} (${cleoTask.title})`,
|
|
32675
|
+
applied: false,
|
|
32676
|
+
linkId: existingLink.id
|
|
32592
32677
|
});
|
|
32593
32678
|
continue;
|
|
32594
32679
|
}
|
|
32595
32680
|
if (ext.status === "active" && (cleoTask.status === "pending" || cleoTask.status === "blocked")) {
|
|
32596
32681
|
actions.push({
|
|
32597
32682
|
type: "activate",
|
|
32598
|
-
cleoTaskId:
|
|
32683
|
+
cleoTaskId: cleoTask.id,
|
|
32599
32684
|
externalId: ext.externalId,
|
|
32600
|
-
summary: `Activate ${
|
|
32601
|
-
applied: false
|
|
32685
|
+
summary: `Activate ${cleoTask.id} (${cleoTask.title})`,
|
|
32686
|
+
applied: false,
|
|
32687
|
+
linkId: existingLink.id
|
|
32602
32688
|
});
|
|
32603
32689
|
continue;
|
|
32604
32690
|
}
|
|
32605
|
-
if (ext.
|
|
32691
|
+
if (ext.title !== cleoTask.title) {
|
|
32606
32692
|
actions.push({
|
|
32607
|
-
type: "
|
|
32608
|
-
cleoTaskId:
|
|
32693
|
+
type: "update",
|
|
32694
|
+
cleoTaskId: cleoTask.id,
|
|
32609
32695
|
externalId: ext.externalId,
|
|
32610
|
-
summary: `
|
|
32611
|
-
applied: false
|
|
32696
|
+
summary: `Update ${cleoTask.id} title: "${cleoTask.title}" \u2192 "${ext.title}"`,
|
|
32697
|
+
applied: false,
|
|
32698
|
+
linkId: existingLink.id
|
|
32612
32699
|
});
|
|
32613
32700
|
continue;
|
|
32614
32701
|
}
|
|
32615
32702
|
actions.push({
|
|
32616
32703
|
type: "skip",
|
|
32617
|
-
cleoTaskId:
|
|
32704
|
+
cleoTaskId: cleoTask.id,
|
|
32618
32705
|
externalId: ext.externalId,
|
|
32619
|
-
summary: `No change needed for ${
|
|
32620
|
-
applied: false
|
|
32621
|
-
|
|
32622
|
-
continue;
|
|
32623
|
-
}
|
|
32624
|
-
if (ext.status !== "removed") {
|
|
32625
|
-
actions.push({
|
|
32626
|
-
type: "create",
|
|
32627
|
-
cleoTaskId: null,
|
|
32628
|
-
externalId: ext.externalId,
|
|
32629
|
-
summary: `Create new task: ${ext.title}`,
|
|
32630
|
-
applied: false
|
|
32631
|
-
});
|
|
32632
|
-
}
|
|
32633
|
-
}
|
|
32634
|
-
for (const injectedId of injectedIds) {
|
|
32635
|
-
if (!seenCleoIds.has(injectedId)) {
|
|
32636
|
-
actions.push({
|
|
32637
|
-
type: "remove",
|
|
32638
|
-
cleoTaskId: injectedId,
|
|
32639
|
-
externalId: `injected:${injectedId}`,
|
|
32640
|
-
summary: `Injected task ${injectedId} no longer in provider`,
|
|
32641
|
-
applied: false
|
|
32706
|
+
summary: `No change needed for ${cleoTask.id}`,
|
|
32707
|
+
applied: false,
|
|
32708
|
+
linkId: existingLink.id
|
|
32642
32709
|
});
|
|
32710
|
+
} else {
|
|
32711
|
+
if (ext.status !== "removed") {
|
|
32712
|
+
actions.push({
|
|
32713
|
+
type: "create",
|
|
32714
|
+
cleoTaskId: null,
|
|
32715
|
+
externalId: ext.externalId,
|
|
32716
|
+
summary: `Create new task: ${ext.title}`,
|
|
32717
|
+
applied: false
|
|
32718
|
+
});
|
|
32719
|
+
}
|
|
32643
32720
|
}
|
|
32644
32721
|
}
|
|
32645
32722
|
return actions;
|
|
@@ -32649,32 +32726,33 @@ async function reconcile(externalTasks, options, accessor) {
|
|
|
32649
32726
|
const acc = accessor ?? await getAccessor(cwd);
|
|
32650
32727
|
const { tasks: allTasks } = await acc.queryTasks({});
|
|
32651
32728
|
const taskMap = buildTaskMap(allTasks);
|
|
32652
|
-
const
|
|
32653
|
-
const
|
|
32654
|
-
const actions = computeActions(externalTasks, taskMap,
|
|
32729
|
+
const existingLinks = await getLinksByProvider(providerId, cwd);
|
|
32730
|
+
const linkMap = buildLinkMap(existingLinks);
|
|
32731
|
+
const actions = computeActions(externalTasks, taskMap, linkMap);
|
|
32655
32732
|
const summary = {
|
|
32733
|
+
created: 0,
|
|
32734
|
+
updated: 0,
|
|
32656
32735
|
completed: 0,
|
|
32657
32736
|
activated: 0,
|
|
32658
|
-
created: 0,
|
|
32659
|
-
removed: 0,
|
|
32660
32737
|
skipped: 0,
|
|
32661
32738
|
conflicts: 0,
|
|
32739
|
+
total: actions.length,
|
|
32662
32740
|
applied: 0
|
|
32663
32741
|
};
|
|
32664
32742
|
for (const action of actions) {
|
|
32665
32743
|
switch (action.type) {
|
|
32744
|
+
case "create":
|
|
32745
|
+
summary.created++;
|
|
32746
|
+
break;
|
|
32747
|
+
case "update":
|
|
32748
|
+
summary.updated++;
|
|
32749
|
+
break;
|
|
32666
32750
|
case "complete":
|
|
32667
32751
|
summary.completed++;
|
|
32668
32752
|
break;
|
|
32669
32753
|
case "activate":
|
|
32670
32754
|
summary.activated++;
|
|
32671
32755
|
break;
|
|
32672
|
-
case "create":
|
|
32673
|
-
summary.created++;
|
|
32674
|
-
break;
|
|
32675
|
-
case "remove":
|
|
32676
|
-
summary.removed++;
|
|
32677
|
-
break;
|
|
32678
32756
|
case "skip":
|
|
32679
32757
|
summary.skipped++;
|
|
32680
32758
|
break;
|
|
@@ -32683,9 +32761,14 @@ async function reconcile(externalTasks, options, accessor) {
|
|
|
32683
32761
|
break;
|
|
32684
32762
|
}
|
|
32685
32763
|
}
|
|
32764
|
+
let linksAffected = 0;
|
|
32686
32765
|
if (!dryRun) {
|
|
32687
32766
|
for (const action of actions) {
|
|
32688
32767
|
if (action.type === "skip" || action.type === "conflict") {
|
|
32768
|
+
if (action.linkId) {
|
|
32769
|
+
const ext = externalTasks.find((e) => e.externalId === action.externalId);
|
|
32770
|
+
await touchLink(action.linkId, { externalTitle: ext?.title }, cwd);
|
|
32771
|
+
}
|
|
32689
32772
|
continue;
|
|
32690
32773
|
}
|
|
32691
32774
|
try {
|
|
@@ -32694,11 +32777,15 @@ async function reconcile(externalTasks, options, accessor) {
|
|
|
32694
32777
|
await completeTask(
|
|
32695
32778
|
{
|
|
32696
32779
|
taskId: action.cleoTaskId,
|
|
32697
|
-
notes: `Completed via ${providerId}
|
|
32780
|
+
notes: `Completed via ${providerId} sync`
|
|
32698
32781
|
},
|
|
32699
32782
|
cwd,
|
|
32700
32783
|
acc
|
|
32701
32784
|
);
|
|
32785
|
+
if (action.linkId) {
|
|
32786
|
+
await touchLink(action.linkId, void 0, cwd);
|
|
32787
|
+
linksAffected++;
|
|
32788
|
+
}
|
|
32702
32789
|
action.applied = true;
|
|
32703
32790
|
summary.applied++;
|
|
32704
32791
|
break;
|
|
@@ -32708,33 +32795,73 @@ async function reconcile(externalTasks, options, accessor) {
|
|
|
32708
32795
|
{
|
|
32709
32796
|
taskId: action.cleoTaskId,
|
|
32710
32797
|
status: "active",
|
|
32711
|
-
notes: `Activated
|
|
32798
|
+
notes: `Activated via ${providerId} sync`
|
|
32712
32799
|
},
|
|
32713
32800
|
cwd,
|
|
32714
32801
|
acc
|
|
32715
32802
|
);
|
|
32803
|
+
if (action.linkId) {
|
|
32804
|
+
await touchLink(action.linkId, void 0, cwd);
|
|
32805
|
+
linksAffected++;
|
|
32806
|
+
}
|
|
32716
32807
|
action.applied = true;
|
|
32717
32808
|
summary.applied++;
|
|
32718
32809
|
break;
|
|
32719
32810
|
}
|
|
32720
|
-
case "
|
|
32811
|
+
case "update": {
|
|
32721
32812
|
const ext = externalTasks.find((e) => e.externalId === action.externalId);
|
|
32722
32813
|
if (!ext) break;
|
|
32723
|
-
await
|
|
32814
|
+
await updateTask(
|
|
32724
32815
|
{
|
|
32816
|
+
taskId: action.cleoTaskId,
|
|
32725
32817
|
title: ext.title,
|
|
32726
|
-
|
|
32727
|
-
labels: [...defaultLabels ?? [], ...ext.labels ?? [], "sync-created"],
|
|
32728
|
-
...defaultPhase ? { phase: defaultPhase, addPhase: true } : {}
|
|
32818
|
+
notes: `Updated via ${providerId} sync`
|
|
32729
32819
|
},
|
|
32730
32820
|
cwd,
|
|
32731
32821
|
acc
|
|
32732
32822
|
);
|
|
32823
|
+
if (action.linkId) {
|
|
32824
|
+
await touchLink(action.linkId, { externalTitle: ext.title }, cwd);
|
|
32825
|
+
linksAffected++;
|
|
32826
|
+
}
|
|
32733
32827
|
action.applied = true;
|
|
32734
32828
|
summary.applied++;
|
|
32735
32829
|
break;
|
|
32736
32830
|
}
|
|
32737
|
-
case "
|
|
32831
|
+
case "create": {
|
|
32832
|
+
const ext = externalTasks.find((e) => e.externalId === action.externalId);
|
|
32833
|
+
if (!ext) break;
|
|
32834
|
+
const result = await addTask(
|
|
32835
|
+
{
|
|
32836
|
+
title: ext.title,
|
|
32837
|
+
description: ext.description ?? `Synced from ${providerId}`,
|
|
32838
|
+
priority: ext.priority,
|
|
32839
|
+
type: ext.type,
|
|
32840
|
+
labels: [...defaultLabels ?? [], ...ext.labels ?? [], `sync:${providerId}`],
|
|
32841
|
+
...defaultPhase ? { phase: defaultPhase, addPhase: true } : {}
|
|
32842
|
+
},
|
|
32843
|
+
cwd,
|
|
32844
|
+
acc
|
|
32845
|
+
);
|
|
32846
|
+
const newTaskId = result.task.id;
|
|
32847
|
+
if (newTaskId) {
|
|
32848
|
+
const link = await createLink(
|
|
32849
|
+
{
|
|
32850
|
+
taskId: newTaskId,
|
|
32851
|
+
providerId,
|
|
32852
|
+
externalId: ext.externalId,
|
|
32853
|
+
externalUrl: ext.url,
|
|
32854
|
+
externalTitle: ext.title,
|
|
32855
|
+
linkType: "created",
|
|
32856
|
+
syncDirection: "inbound",
|
|
32857
|
+
metadata: ext.providerMeta
|
|
32858
|
+
},
|
|
32859
|
+
cwd
|
|
32860
|
+
);
|
|
32861
|
+
action.cleoTaskId = newTaskId;
|
|
32862
|
+
action.linkId = link.id;
|
|
32863
|
+
linksAffected++;
|
|
32864
|
+
}
|
|
32738
32865
|
action.applied = true;
|
|
32739
32866
|
summary.applied++;
|
|
32740
32867
|
break;
|
|
@@ -32744,14 +32871,13 @@ async function reconcile(externalTasks, options, accessor) {
|
|
|
32744
32871
|
action.error = err instanceof Error ? err.message : String(err);
|
|
32745
32872
|
}
|
|
32746
32873
|
}
|
|
32747
|
-
await clearSyncState(providerId, cwd);
|
|
32748
32874
|
}
|
|
32749
32875
|
return {
|
|
32750
32876
|
dryRun,
|
|
32751
32877
|
providerId,
|
|
32752
32878
|
actions,
|
|
32753
32879
|
summary,
|
|
32754
|
-
|
|
32880
|
+
linksAffected
|
|
32755
32881
|
};
|
|
32756
32882
|
}
|
|
32757
32883
|
|
|
@@ -33358,15 +33484,15 @@ function describeChannel(channel) {
|
|
|
33358
33484
|
|
|
33359
33485
|
// packages/core/src/release/ci.ts
|
|
33360
33486
|
import { existsSync as existsSync59, mkdirSync as mkdirSync12, readFileSync as readFileSync42, writeFileSync as writeFileSync6 } from "node:fs";
|
|
33361
|
-
import { dirname as dirname13, join as
|
|
33487
|
+
import { dirname as dirname13, join as join63 } from "node:path";
|
|
33362
33488
|
|
|
33363
33489
|
// packages/core/src/release/release-config.ts
|
|
33364
33490
|
init_paths();
|
|
33365
33491
|
import { existsSync as existsSync58, readFileSync as readFileSync41 } from "node:fs";
|
|
33366
|
-
import { join as
|
|
33492
|
+
import { join as join62 } from "node:path";
|
|
33367
33493
|
function readConfigValueSync(path2, defaultValue, cwd) {
|
|
33368
33494
|
try {
|
|
33369
|
-
const configPath =
|
|
33495
|
+
const configPath = join62(getCleoDir(cwd), "config.json");
|
|
33370
33496
|
if (!existsSync58(configPath)) return defaultValue;
|
|
33371
33497
|
const config = JSON.parse(readFileSync41(configPath, "utf-8"));
|
|
33372
33498
|
const keys = path2.split(".");
|
|
@@ -33530,9 +33656,9 @@ function getPlatformPath(platform3) {
|
|
|
33530
33656
|
}
|
|
33531
33657
|
function detectCIPlatform(projectDir) {
|
|
33532
33658
|
const dir = projectDir ?? process.cwd();
|
|
33533
|
-
if (existsSync59(
|
|
33534
|
-
if (existsSync59(
|
|
33535
|
-
if (existsSync59(
|
|
33659
|
+
if (existsSync59(join63(dir, ".github"))) return "github-actions";
|
|
33660
|
+
if (existsSync59(join63(dir, ".gitlab-ci.yml"))) return "gitlab-ci";
|
|
33661
|
+
if (existsSync59(join63(dir, ".circleci"))) return "circleci";
|
|
33536
33662
|
return null;
|
|
33537
33663
|
}
|
|
33538
33664
|
function generateGitHubActions(config) {
|
|
@@ -33634,7 +33760,7 @@ function generateCIConfig(platform3, cwd) {
|
|
|
33634
33760
|
}
|
|
33635
33761
|
function writeCIConfig(platform3, options = {}) {
|
|
33636
33762
|
const projectDir = options.projectDir ?? process.cwd();
|
|
33637
|
-
const outputPath =
|
|
33763
|
+
const outputPath = join63(projectDir, getPlatformPath(platform3));
|
|
33638
33764
|
const content = generateCIConfig(platform3, projectDir);
|
|
33639
33765
|
if (options.dryRun) {
|
|
33640
33766
|
return { action: "would_write", path: outputPath, content };
|
|
@@ -33645,7 +33771,7 @@ function writeCIConfig(platform3, options = {}) {
|
|
|
33645
33771
|
}
|
|
33646
33772
|
function validateCIConfig(platform3, projectDir) {
|
|
33647
33773
|
const dir = projectDir ?? process.cwd();
|
|
33648
|
-
const configPath =
|
|
33774
|
+
const configPath = join63(dir, getPlatformPath(platform3));
|
|
33649
33775
|
if (!existsSync59(configPath)) {
|
|
33650
33776
|
return { valid: false, exists: false, errors: ["Config file not found"] };
|
|
33651
33777
|
}
|
|
@@ -33903,8 +34029,8 @@ function checkDoubleListing(releaseTaskIds, existingReleases) {
|
|
|
33903
34029
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
33904
34030
|
import { existsSync as existsSync61, renameSync as renameSync5 } from "node:fs";
|
|
33905
34031
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
33906
|
-
import { join as
|
|
33907
|
-
import { and as
|
|
34032
|
+
import { join as join65 } from "node:path";
|
|
34033
|
+
import { and as and5, count, desc as desc3, eq as eq7 } from "drizzle-orm";
|
|
33908
34034
|
init_paths();
|
|
33909
34035
|
init_tasks_schema();
|
|
33910
34036
|
|
|
@@ -33913,10 +34039,10 @@ init_src();
|
|
|
33913
34039
|
init_errors3();
|
|
33914
34040
|
init_paths();
|
|
33915
34041
|
import { existsSync as existsSync60, readFileSync as readFileSync43, writeFileSync as writeFileSync7 } from "node:fs";
|
|
33916
|
-
import { join as
|
|
34042
|
+
import { join as join64 } from "node:path";
|
|
33917
34043
|
function readConfigValueSync2(path2, defaultValue, cwd) {
|
|
33918
34044
|
try {
|
|
33919
|
-
const configPath =
|
|
34045
|
+
const configPath = join64(getCleoDir(cwd), "config.json");
|
|
33920
34046
|
if (!existsSync60(configPath)) return defaultValue;
|
|
33921
34047
|
const config = JSON.parse(readFileSync43(configPath, "utf-8"));
|
|
33922
34048
|
const keys = path2.split(".");
|
|
@@ -34013,7 +34139,7 @@ function isVersionBumpConfigured(cwd) {
|
|
|
34013
34139
|
return getVersionBumpConfig(cwd).length > 0;
|
|
34014
34140
|
}
|
|
34015
34141
|
function bumpFile(target, newVersion, projectRoot) {
|
|
34016
|
-
const filePath =
|
|
34142
|
+
const filePath = join64(projectRoot, target.file);
|
|
34017
34143
|
if (!existsSync60(filePath)) {
|
|
34018
34144
|
return {
|
|
34019
34145
|
file: target.file,
|
|
@@ -34152,6 +34278,36 @@ function effectivePageLimit(limit, offset) {
|
|
|
34152
34278
|
function isValidVersion(version) {
|
|
34153
34279
|
return /^v?\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/.test(version);
|
|
34154
34280
|
}
|
|
34281
|
+
function validateCalVerWindow(version, now = /* @__PURE__ */ new Date()) {
|
|
34282
|
+
const normalized = version.startsWith("v") ? version.slice(1) : version;
|
|
34283
|
+
const base = normalized.split("-")[0] ?? normalized;
|
|
34284
|
+
const parts = base.split(".");
|
|
34285
|
+
if (parts.length !== 3) {
|
|
34286
|
+
return { valid: false, message: `Invalid CalVer format: ${version}` };
|
|
34287
|
+
}
|
|
34288
|
+
const tagYear = Number.parseInt(parts[0] ?? "", 10);
|
|
34289
|
+
const tagMonth = Number.parseInt(parts[1] ?? "", 10);
|
|
34290
|
+
if (!Number.isInteger(tagYear) || !Number.isInteger(tagMonth)) {
|
|
34291
|
+
return { valid: false, message: `Invalid CalVer date components: ${version}` };
|
|
34292
|
+
}
|
|
34293
|
+
const currentYear = now.getUTCFullYear();
|
|
34294
|
+
const currentMonth = now.getUTCMonth() + 1;
|
|
34295
|
+
const nextMonth = currentMonth === 12 ? 1 : currentMonth + 1;
|
|
34296
|
+
const nextYear = currentMonth === 12 ? currentYear + 1 : currentYear;
|
|
34297
|
+
const isPreRelease = normalized.includes("-");
|
|
34298
|
+
if (isPreRelease) {
|
|
34299
|
+
const valid2 = (tagYear === currentYear || tagYear === nextYear) && (tagMonth === currentMonth || tagMonth === nextMonth);
|
|
34300
|
+
return {
|
|
34301
|
+
valid: valid2,
|
|
34302
|
+
message: valid2 ? `CalVer OK (pre-release): ${version}` : `Pre-release ${version} outside allowed CalVer range ${currentYear}.${currentMonth} or ${nextYear}.${nextMonth}`
|
|
34303
|
+
};
|
|
34304
|
+
}
|
|
34305
|
+
const valid = tagYear === currentYear && tagMonth === currentMonth;
|
|
34306
|
+
return {
|
|
34307
|
+
valid,
|
|
34308
|
+
message: valid ? `CalVer OK (stable): ${version}` : `${version} does not match current CalVer ${currentYear}.${currentMonth}`
|
|
34309
|
+
};
|
|
34310
|
+
}
|
|
34155
34311
|
function normalizeVersion(version) {
|
|
34156
34312
|
return version.startsWith("v") ? version : `v${version}`;
|
|
34157
34313
|
}
|
|
@@ -34174,7 +34330,7 @@ function rowToManifest(row) {
|
|
|
34174
34330
|
}
|
|
34175
34331
|
async function findLatestPushedVersion(cwd) {
|
|
34176
34332
|
const db = await getDb2(cwd);
|
|
34177
|
-
const rows = await db.select({ version: releaseManifests.version }).from(releaseManifests).where(
|
|
34333
|
+
const rows = await db.select({ version: releaseManifests.version }).from(releaseManifests).where(eq7(releaseManifests.status, "pushed")).orderBy(desc3(releaseManifests.pushedAt)).limit(1).all();
|
|
34178
34334
|
return rows[0]?.version;
|
|
34179
34335
|
}
|
|
34180
34336
|
async function prepareRelease(version, tasks2, notes, loadTasksFn, cwd) {
|
|
@@ -34186,7 +34342,7 @@ async function prepareRelease(version, tasks2, notes, loadTasksFn, cwd) {
|
|
|
34186
34342
|
}
|
|
34187
34343
|
const normalizedVersion = normalizeVersion(version);
|
|
34188
34344
|
const db = await getDb2(cwd);
|
|
34189
|
-
const existing = await db.select().from(releaseManifests).where(
|
|
34345
|
+
const existing = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34190
34346
|
if (existing.length > 0) {
|
|
34191
34347
|
throw new Error(`Release ${normalizedVersion} already exists (status: ${existing[0].status})`);
|
|
34192
34348
|
}
|
|
@@ -34226,7 +34382,7 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
34226
34382
|
}
|
|
34227
34383
|
const normalizedVersion = normalizeVersion(version);
|
|
34228
34384
|
const db = await getDb2(cwd);
|
|
34229
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34385
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34230
34386
|
if (rows.length === 0) {
|
|
34231
34387
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
34232
34388
|
}
|
|
@@ -34363,8 +34519,8 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
34363
34519
|
sections.push("");
|
|
34364
34520
|
}
|
|
34365
34521
|
const changelog = sections.join("\n");
|
|
34366
|
-
await db.update(releaseManifests).set({ changelog }).where(
|
|
34367
|
-
const changelogPath =
|
|
34522
|
+
await db.update(releaseManifests).set({ changelog }).where(eq7(releaseManifests.version, normalizedVersion)).run();
|
|
34523
|
+
const changelogPath = join65(cwd ?? process.cwd(), "CHANGELOG.md");
|
|
34368
34524
|
let existingChangelogContent = "";
|
|
34369
34525
|
try {
|
|
34370
34526
|
existingChangelogContent = await readFile12(changelogPath, "utf8");
|
|
@@ -34401,8 +34557,8 @@ async function listManifestReleases(optionsOrCwd, cwd) {
|
|
|
34401
34557
|
const db = await getDb2(effectiveCwd);
|
|
34402
34558
|
const totalRow = await db.select({ count: count() }).from(releaseManifests).get();
|
|
34403
34559
|
const total = totalRow?.count ?? 0;
|
|
34404
|
-
const conditions = options.status ? [
|
|
34405
|
-
const whereClause = conditions.length > 0 ?
|
|
34560
|
+
const conditions = options.status ? [eq7(releaseManifests.status, options.status)] : [];
|
|
34561
|
+
const whereClause = conditions.length > 0 ? and5(...conditions) : void 0;
|
|
34406
34562
|
const filteredRow = await db.select({ count: count() }).from(releaseManifests).where(whereClause).get();
|
|
34407
34563
|
const filtered = filteredRow?.count ?? 0;
|
|
34408
34564
|
let query = db.select().from(releaseManifests).where(whereClause).orderBy(desc3(releaseManifests.createdAt));
|
|
@@ -34433,7 +34589,7 @@ async function showManifestRelease(version, cwd) {
|
|
|
34433
34589
|
}
|
|
34434
34590
|
const normalizedVersion = normalizeVersion(version);
|
|
34435
34591
|
const db = await getDb2(cwd);
|
|
34436
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34592
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34437
34593
|
if (rows.length === 0) {
|
|
34438
34594
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
34439
34595
|
}
|
|
@@ -34445,7 +34601,7 @@ async function commitRelease(version, cwd) {
|
|
|
34445
34601
|
}
|
|
34446
34602
|
const normalizedVersion = normalizeVersion(version);
|
|
34447
34603
|
const db = await getDb2(cwd);
|
|
34448
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34604
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34449
34605
|
if (rows.length === 0) {
|
|
34450
34606
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
34451
34607
|
}
|
|
@@ -34455,7 +34611,7 @@ async function commitRelease(version, cwd) {
|
|
|
34455
34611
|
);
|
|
34456
34612
|
}
|
|
34457
34613
|
const committedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
34458
|
-
await db.update(releaseManifests).set({ status: "committed", committedAt }).where(
|
|
34614
|
+
await db.update(releaseManifests).set({ status: "committed", committedAt }).where(eq7(releaseManifests.version, normalizedVersion)).run();
|
|
34459
34615
|
return { version: normalizedVersion, status: "committed", committedAt };
|
|
34460
34616
|
}
|
|
34461
34617
|
async function tagRelease(version, cwd) {
|
|
@@ -34464,12 +34620,12 @@ async function tagRelease(version, cwd) {
|
|
|
34464
34620
|
}
|
|
34465
34621
|
const normalizedVersion = normalizeVersion(version);
|
|
34466
34622
|
const db = await getDb2(cwd);
|
|
34467
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34623
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34468
34624
|
if (rows.length === 0) {
|
|
34469
34625
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
34470
34626
|
}
|
|
34471
34627
|
const taggedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
34472
|
-
await db.update(releaseManifests).set({ status: "tagged", taggedAt }).where(
|
|
34628
|
+
await db.update(releaseManifests).set({ status: "tagged", taggedAt }).where(eq7(releaseManifests.version, normalizedVersion)).run();
|
|
34473
34629
|
return { version: normalizedVersion, status: "tagged", taggedAt };
|
|
34474
34630
|
}
|
|
34475
34631
|
async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
@@ -34478,7 +34634,7 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
34478
34634
|
}
|
|
34479
34635
|
const normalizedVersion = normalizeVersion(version);
|
|
34480
34636
|
const db = await getDb2(cwd);
|
|
34481
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34637
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34482
34638
|
if (rows.length === 0) {
|
|
34483
34639
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
34484
34640
|
}
|
|
@@ -34490,6 +34646,15 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
34490
34646
|
status: isValidVersion(normalizedVersion) ? "passed" : "failed",
|
|
34491
34647
|
message: isValidVersion(normalizedVersion) ? "Version format is valid" : "Invalid version format"
|
|
34492
34648
|
});
|
|
34649
|
+
const releaseConfig = loadReleaseConfig(cwd);
|
|
34650
|
+
if (releaseConfig.versioningScheme === "calver") {
|
|
34651
|
+
const calver = validateCalVerWindow(normalizedVersion);
|
|
34652
|
+
gates.push({
|
|
34653
|
+
name: "calver_window",
|
|
34654
|
+
status: calver.valid ? "passed" : "failed",
|
|
34655
|
+
message: calver.message
|
|
34656
|
+
});
|
|
34657
|
+
}
|
|
34493
34658
|
gates.push({
|
|
34494
34659
|
name: "has_tasks",
|
|
34495
34660
|
status: releaseTasks.length > 0 ? "passed" : "failed",
|
|
@@ -34511,10 +34676,10 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
34511
34676
|
message: incompleteTasks.length === 0 ? "All tasks completed" : `${incompleteTasks.length} tasks not completed: ${incompleteTasks.join(", ")}`
|
|
34512
34677
|
});
|
|
34513
34678
|
const projectRoot = cwd ?? getProjectRoot();
|
|
34514
|
-
const monorepoDist =
|
|
34515
|
-
const rootDist =
|
|
34679
|
+
const monorepoDist = join65(projectRoot, "packages", "cleo", "dist", "cli", "index.js");
|
|
34680
|
+
const rootDist = join65(projectRoot, "dist", "cli", "index.js");
|
|
34516
34681
|
const distExists = existsSync61(monorepoDist) || existsSync61(rootDist);
|
|
34517
|
-
const isNodeProject = existsSync61(
|
|
34682
|
+
const isNodeProject = existsSync61(join65(projectRoot, "package.json"));
|
|
34518
34683
|
if (isNodeProject) {
|
|
34519
34684
|
gates.push({
|
|
34520
34685
|
name: "build_artifact",
|
|
@@ -34560,7 +34725,6 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
34560
34725
|
}).trim();
|
|
34561
34726
|
} catch {
|
|
34562
34727
|
}
|
|
34563
|
-
const releaseConfig = loadReleaseConfig(cwd);
|
|
34564
34728
|
const gitFlowCfg = getGitFlowConfig(releaseConfig);
|
|
34565
34729
|
const channelCfg = getChannelConfig(releaseConfig);
|
|
34566
34730
|
const expectedBranch = isPreRelease ? gitFlowCfg.branches.develop : gitFlowCfg.branches.main;
|
|
@@ -34618,7 +34782,7 @@ async function cancelRelease(version, projectRoot) {
|
|
|
34618
34782
|
}
|
|
34619
34783
|
const normalizedVersion = normalizeVersion(version);
|
|
34620
34784
|
const db = await getDb2(projectRoot);
|
|
34621
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34785
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34622
34786
|
if (rows.length === 0) {
|
|
34623
34787
|
return {
|
|
34624
34788
|
success: false,
|
|
@@ -34635,7 +34799,7 @@ async function cancelRelease(version, projectRoot) {
|
|
|
34635
34799
|
version: normalizedVersion
|
|
34636
34800
|
};
|
|
34637
34801
|
}
|
|
34638
|
-
await db.delete(releaseManifests).where(
|
|
34802
|
+
await db.delete(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).run();
|
|
34639
34803
|
return {
|
|
34640
34804
|
success: true,
|
|
34641
34805
|
message: `Release ${normalizedVersion} cancelled and removed`,
|
|
@@ -34648,12 +34812,12 @@ async function rollbackRelease(version, reason, cwd) {
|
|
|
34648
34812
|
}
|
|
34649
34813
|
const normalizedVersion = normalizeVersion(version);
|
|
34650
34814
|
const db = await getDb2(cwd);
|
|
34651
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
34815
|
+
const rows = await db.select().from(releaseManifests).where(eq7(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
34652
34816
|
if (rows.length === 0) {
|
|
34653
34817
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
34654
34818
|
}
|
|
34655
34819
|
const previousStatus = rows[0].status;
|
|
34656
|
-
await db.update(releaseManifests).set({ status: "rolled_back" }).where(
|
|
34820
|
+
await db.update(releaseManifests).set({ status: "rolled_back" }).where(eq7(releaseManifests.version, normalizedVersion)).run();
|
|
34657
34821
|
return {
|
|
34658
34822
|
version: normalizedVersion,
|
|
34659
34823
|
previousStatus,
|
|
@@ -34662,7 +34826,7 @@ async function rollbackRelease(version, reason, cwd) {
|
|
|
34662
34826
|
};
|
|
34663
34827
|
}
|
|
34664
34828
|
async function readPushPolicy(cwd) {
|
|
34665
|
-
const configPath =
|
|
34829
|
+
const configPath = join65(getCleoDirAbsolute(cwd), "config.json");
|
|
34666
34830
|
let config;
|
|
34667
34831
|
try {
|
|
34668
34832
|
const raw = await readFile12(configPath, "utf-8");
|
|
@@ -34763,10 +34927,10 @@ async function markReleasePushed(version, pushedAt, cwd, provenance) {
|
|
|
34763
34927
|
pushedAt,
|
|
34764
34928
|
...provenance?.commitSha != null ? { commitSha: provenance.commitSha } : {},
|
|
34765
34929
|
...provenance?.gitTag != null ? { gitTag: provenance.gitTag } : {}
|
|
34766
|
-
}).where(
|
|
34930
|
+
}).where(eq7(releaseManifests.version, normalizedVersion)).run();
|
|
34767
34931
|
}
|
|
34768
34932
|
async function migrateReleasesJsonToSqlite(projectRoot) {
|
|
34769
|
-
const releasesPath =
|
|
34933
|
+
const releasesPath = join65(getCleoDirAbsolute(projectRoot), "releases.json");
|
|
34770
34934
|
if (!existsSync61(releasesPath)) {
|
|
34771
34935
|
return { migrated: 0 };
|
|
34772
34936
|
}
|
|
@@ -34783,7 +34947,7 @@ async function migrateReleasesJsonToSqlite(projectRoot) {
|
|
|
34783
34947
|
const db = await getDb2(projectRoot);
|
|
34784
34948
|
let migrated = 0;
|
|
34785
34949
|
for (const r of raw.releases) {
|
|
34786
|
-
const existing = await db.select({ id: releaseManifests.id }).from(releaseManifests).where(
|
|
34950
|
+
const existing = await db.select({ id: releaseManifests.id }).from(releaseManifests).where(eq7(releaseManifests.version, r.version)).limit(1).all();
|
|
34787
34951
|
if (existing.length > 0) continue;
|
|
34788
34952
|
const id = `rel-${r.version.replace(/[^a-z0-9]/gi, "-")}`;
|
|
34789
34953
|
await db.insert(releaseManifests).values({
|
|
@@ -35089,11 +35253,11 @@ __export(roadmap_exports, {
|
|
|
35089
35253
|
});
|
|
35090
35254
|
init_data_accessor();
|
|
35091
35255
|
import { existsSync as existsSync62, readFileSync as readFileSync44 } from "node:fs";
|
|
35092
|
-
import { join as
|
|
35256
|
+
import { join as join66 } from "node:path";
|
|
35093
35257
|
async function getRoadmap(opts, accessor) {
|
|
35094
35258
|
const acc = accessor ?? await getAccessor(opts.cwd);
|
|
35095
35259
|
const { tasks: tasks2 } = await acc.queryTasks({});
|
|
35096
|
-
const versionPath =
|
|
35260
|
+
const versionPath = join66(opts.cwd ?? process.cwd(), "VERSION");
|
|
35097
35261
|
const currentVersion = existsSync62(versionPath) ? readFileSync44(versionPath, "utf-8").trim() : "unknown";
|
|
35098
35262
|
const childParentIds = new Set(tasks2.filter((t) => t.parentId).map((t) => t.parentId));
|
|
35099
35263
|
const epics = tasks2.filter((t) => childParentIds.has(t.id));
|
|
@@ -35101,7 +35265,7 @@ async function getRoadmap(opts, accessor) {
|
|
|
35101
35265
|
const completed = epics.filter((e) => e.status === "done");
|
|
35102
35266
|
const releaseHistory = [];
|
|
35103
35267
|
if (opts.includeHistory) {
|
|
35104
|
-
const changelogPath =
|
|
35268
|
+
const changelogPath = join66(opts.cwd ?? process.cwd(), "CHANGELOG.md");
|
|
35105
35269
|
if (existsSync62(changelogPath)) {
|
|
35106
35270
|
const content = readFileSync44(changelogPath, "utf-8");
|
|
35107
35271
|
const versionRegex = /^##\s+\[?v?(\d+\.\d+\.\d+[^\]]*)\]?\s*[-(]?\s*(\d{4}-\d{2}-\d{2})?/gm;
|
|
@@ -35176,6 +35340,10 @@ var CAPABILITY_MATRIX = [
|
|
|
35176
35340
|
{ domain: "tasks", operation: "relates.add", gateway: "mutate", mode: "native" },
|
|
35177
35341
|
{ domain: "tasks", operation: "start", gateway: "mutate", mode: "native" },
|
|
35178
35342
|
{ domain: "tasks", operation: "stop", gateway: "mutate", mode: "native" },
|
|
35343
|
+
// Sync sub-domain (provider-agnostic task reconciliation)
|
|
35344
|
+
{ domain: "tasks", operation: "sync.reconcile", gateway: "mutate", mode: "native" },
|
|
35345
|
+
{ domain: "tasks", operation: "sync.links", gateway: "query", mode: "native" },
|
|
35346
|
+
{ domain: "tasks", operation: "sync.links.remove", gateway: "mutate", mode: "native" },
|
|
35179
35347
|
// === Session Domain ===
|
|
35180
35348
|
// Query operations
|
|
35181
35349
|
{ domain: "session", operation: "status", gateway: "query", mode: "native" },
|
|
@@ -35346,10 +35514,6 @@ var CAPABILITY_MATRIX = [
|
|
|
35346
35514
|
{ domain: "tools", operation: "provider.supports", gateway: "query", mode: "native" },
|
|
35347
35515
|
{ domain: "tools", operation: "provider.hooks", gateway: "query", mode: "native" },
|
|
35348
35516
|
{ domain: "tools", operation: "provider.inject", gateway: "mutate", mode: "native" },
|
|
35349
|
-
// TodoWrite operations
|
|
35350
|
-
{ domain: "tools", operation: "todowrite.status", gateway: "query", mode: "native" },
|
|
35351
|
-
{ domain: "tools", operation: "todowrite.sync", gateway: "mutate", mode: "native" },
|
|
35352
|
-
{ domain: "tools", operation: "todowrite.clear", gateway: "mutate", mode: "native" },
|
|
35353
35517
|
// === Nexus Domain ===
|
|
35354
35518
|
// Query operations
|
|
35355
35519
|
{ domain: "nexus", operation: "status", gateway: "query", mode: "native" },
|
|
@@ -36051,12 +36215,12 @@ import { catalog as catalog2 } from "@cleocode/caamp";
|
|
|
36051
36215
|
// packages/core/src/skills/agents/config.ts
|
|
36052
36216
|
init_paths();
|
|
36053
36217
|
import { existsSync as existsSync65, readFileSync as readFileSync46 } from "node:fs";
|
|
36054
|
-
import { basename as basename11, join as
|
|
36218
|
+
import { basename as basename11, join as join69 } from "node:path";
|
|
36055
36219
|
|
|
36056
36220
|
// packages/core/src/skills/discovery.ts
|
|
36057
36221
|
init_paths();
|
|
36058
36222
|
import { existsSync as existsSync64, readdirSync as readdirSync24, readFileSync as readFileSync45, statSync as statSync17 } from "node:fs";
|
|
36059
|
-
import { basename as basename10, join as
|
|
36223
|
+
import { basename as basename10, join as join68 } from "node:path";
|
|
36060
36224
|
import {
|
|
36061
36225
|
discoverSkill as caampDiscoverSkill,
|
|
36062
36226
|
discoverSkills as caampDiscoverSkills,
|
|
@@ -36146,12 +36310,12 @@ var SKILL_NAME_MAP = {
|
|
|
36146
36310
|
function getSkillSearchPaths(cwd) {
|
|
36147
36311
|
const projectRoot = getProjectRoot(cwd);
|
|
36148
36312
|
const cleoHome = getCleoHome();
|
|
36149
|
-
const projectAgentsSkills =
|
|
36313
|
+
const projectAgentsSkills = join68(getProjectAgentsDir(projectRoot), "skills");
|
|
36150
36314
|
const paths = [
|
|
36151
36315
|
{ scope: "agent-skills", path: getCanonicalSkillsDir(), priority: 1 },
|
|
36152
36316
|
{ scope: "project-custom", path: projectAgentsSkills, priority: 2 }
|
|
36153
36317
|
];
|
|
36154
|
-
const mpCacheDir = process.env["CLEO_SKILLS_MP_CACHE"] ??
|
|
36318
|
+
const mpCacheDir = process.env["CLEO_SKILLS_MP_CACHE"] ?? join68(cleoHome, ".skills-cache");
|
|
36155
36319
|
if (existsSync64(mpCacheDir)) {
|
|
36156
36320
|
paths.push({ scope: "marketplace", path: mpCacheDir, priority: 4 });
|
|
36157
36321
|
}
|
|
@@ -36162,7 +36326,7 @@ function getSkillsDir(cwd) {
|
|
|
36162
36326
|
return getCanonicalSkillsDir();
|
|
36163
36327
|
}
|
|
36164
36328
|
function getSharedDir(cwd) {
|
|
36165
|
-
return
|
|
36329
|
+
return join68(getSkillsDir(cwd), "_shared");
|
|
36166
36330
|
}
|
|
36167
36331
|
function mapSkillName(input) {
|
|
36168
36332
|
if (SKILL_NAME_MAP[input]) {
|
|
@@ -36245,7 +36409,7 @@ function parseFrontmatter3(content) {
|
|
|
36245
36409
|
};
|
|
36246
36410
|
}
|
|
36247
36411
|
function discoverSkill(skillDir) {
|
|
36248
|
-
const skillMdPath =
|
|
36412
|
+
const skillMdPath = join68(skillDir, "SKILL.md");
|
|
36249
36413
|
if (!existsSync64(skillMdPath)) {
|
|
36250
36414
|
return null;
|
|
36251
36415
|
}
|
|
@@ -36270,7 +36434,7 @@ function discoverSkillsInDir(dir) {
|
|
|
36270
36434
|
const entries = readdirSync24(dir);
|
|
36271
36435
|
for (const entry of entries) {
|
|
36272
36436
|
if (entry.startsWith(".") || entry.startsWith("_")) continue;
|
|
36273
|
-
const entryPath =
|
|
36437
|
+
const entryPath = join68(dir, entry);
|
|
36274
36438
|
try {
|
|
36275
36439
|
if (statSync17(entryPath).isDirectory()) {
|
|
36276
36440
|
const skill = discoverSkill(entryPath);
|
|
@@ -36304,14 +36468,14 @@ function findSkill(name2, cwd) {
|
|
|
36304
36468
|
const { canonical } = mapSkillName(name2);
|
|
36305
36469
|
const searchPaths = getSkillSearchPaths(cwd);
|
|
36306
36470
|
for (const sp of searchPaths) {
|
|
36307
|
-
const skillDir =
|
|
36471
|
+
const skillDir = join68(sp.path, canonical);
|
|
36308
36472
|
const skill = discoverSkill(skillDir);
|
|
36309
36473
|
if (skill) return skill;
|
|
36310
36474
|
}
|
|
36311
36475
|
if (canonical.startsWith("ct-")) {
|
|
36312
36476
|
const legacy = canonical.slice(3);
|
|
36313
36477
|
for (const sp of searchPaths) {
|
|
36314
|
-
const skillDir =
|
|
36478
|
+
const skillDir = join68(sp.path, legacy);
|
|
36315
36479
|
const skill = discoverSkill(skillDir);
|
|
36316
36480
|
if (skill) return skill;
|
|
36317
36481
|
}
|
|
@@ -36350,10 +36514,10 @@ function resolveTemplatePath(name2, cwd) {
|
|
|
36350
36514
|
|
|
36351
36515
|
// packages/core/src/skills/agents/config.ts
|
|
36352
36516
|
function getAgentsDir(cwd) {
|
|
36353
|
-
return
|
|
36517
|
+
return join69(getProjectRoot(cwd), "agents");
|
|
36354
36518
|
}
|
|
36355
36519
|
function parseAgentConfig(agentDir) {
|
|
36356
|
-
const agentMdPath =
|
|
36520
|
+
const agentMdPath = join69(agentDir, "AGENT.md");
|
|
36357
36521
|
if (!existsSync65(agentMdPath)) {
|
|
36358
36522
|
return null;
|
|
36359
36523
|
}
|
|
@@ -36369,7 +36533,7 @@ function parseAgentConfig(agentDir) {
|
|
|
36369
36533
|
}
|
|
36370
36534
|
function loadAgentConfig(agentName, cwd) {
|
|
36371
36535
|
const agentsDir = getAgentsDir(cwd);
|
|
36372
|
-
const agentDir =
|
|
36536
|
+
const agentDir = join69(agentsDir, agentName);
|
|
36373
36537
|
return parseAgentConfig(agentDir);
|
|
36374
36538
|
}
|
|
36375
36539
|
function getSubagentConfig(cwd) {
|
|
@@ -36377,7 +36541,7 @@ function getSubagentConfig(cwd) {
|
|
|
36377
36541
|
}
|
|
36378
36542
|
function agentExists(agentName, cwd) {
|
|
36379
36543
|
const agentsDir = getAgentsDir(cwd);
|
|
36380
|
-
const agentMdPath =
|
|
36544
|
+
const agentMdPath = join69(agentsDir, agentName, "AGENT.md");
|
|
36381
36545
|
return existsSync65(agentMdPath);
|
|
36382
36546
|
}
|
|
36383
36547
|
function extractBody(content) {
|
|
@@ -36400,14 +36564,14 @@ function extractBody(content) {
|
|
|
36400
36564
|
// packages/core/src/skills/agents/install.ts
|
|
36401
36565
|
init_paths();
|
|
36402
36566
|
import { existsSync as existsSync66, mkdirSync as mkdirSync14, readdirSync as readdirSync25, readlinkSync, symlinkSync, unlinkSync as unlinkSync4 } from "node:fs";
|
|
36403
|
-
import { basename as basename12, join as
|
|
36567
|
+
import { basename as basename12, join as join70 } from "node:path";
|
|
36404
36568
|
function getAgentInstallDir() {
|
|
36405
36569
|
return getClaudeAgentsDir();
|
|
36406
36570
|
}
|
|
36407
36571
|
function installAgent(agentDir) {
|
|
36408
36572
|
const targetDir = getAgentInstallDir();
|
|
36409
36573
|
const agentName = basename12(agentDir);
|
|
36410
|
-
const targetPath =
|
|
36574
|
+
const targetPath = join70(targetDir, agentName);
|
|
36411
36575
|
if (!existsSync66(targetDir)) {
|
|
36412
36576
|
mkdirSync14(targetDir, { recursive: true });
|
|
36413
36577
|
}
|
|
@@ -36445,8 +36609,8 @@ function installAllAgents(cwd) {
|
|
|
36445
36609
|
const entries = readdirSync25(agentsDir);
|
|
36446
36610
|
for (const entry of entries) {
|
|
36447
36611
|
if (entry.startsWith(".")) continue;
|
|
36448
|
-
const agentDir =
|
|
36449
|
-
const agentMdPath =
|
|
36612
|
+
const agentDir = join70(agentsDir, entry);
|
|
36613
|
+
const agentMdPath = join70(agentDir, "AGENT.md");
|
|
36450
36614
|
if (!existsSync66(agentMdPath)) continue;
|
|
36451
36615
|
const result = installAgent(agentDir);
|
|
36452
36616
|
results.push({
|
|
@@ -36459,7 +36623,7 @@ function installAllAgents(cwd) {
|
|
|
36459
36623
|
}
|
|
36460
36624
|
function uninstallAgent(agentName) {
|
|
36461
36625
|
const targetDir = getAgentInstallDir();
|
|
36462
|
-
const targetPath =
|
|
36626
|
+
const targetPath = join70(targetDir, agentName);
|
|
36463
36627
|
if (!existsSync66(targetPath)) {
|
|
36464
36628
|
return false;
|
|
36465
36629
|
}
|
|
@@ -36474,9 +36638,9 @@ function uninstallAgent(agentName) {
|
|
|
36474
36638
|
// packages/core/src/skills/agents/registry.ts
|
|
36475
36639
|
init_paths();
|
|
36476
36640
|
import { existsSync as existsSync67, mkdirSync as mkdirSync15, readdirSync as readdirSync26, readFileSync as readFileSync47, writeFileSync as writeFileSync8 } from "node:fs";
|
|
36477
|
-
import { dirname as dirname14, join as
|
|
36641
|
+
import { dirname as dirname14, join as join71 } from "node:path";
|
|
36478
36642
|
function getRegistryPath2() {
|
|
36479
|
-
return
|
|
36643
|
+
return join71(getCleoHome(), "agent-registry.json");
|
|
36480
36644
|
}
|
|
36481
36645
|
function readRegistry2() {
|
|
36482
36646
|
const registryPath = getRegistryPath2();
|
|
@@ -36545,7 +36709,7 @@ function syncRegistry(cwd) {
|
|
|
36545
36709
|
const entries = readdirSync26(agentsDir);
|
|
36546
36710
|
for (const entry of entries) {
|
|
36547
36711
|
if (entry.startsWith(".")) continue;
|
|
36548
|
-
const agentDir =
|
|
36712
|
+
const agentDir = join71(agentsDir, entry);
|
|
36549
36713
|
try {
|
|
36550
36714
|
const config = parseAgentConfig(agentDir);
|
|
36551
36715
|
if (config) {
|
|
@@ -36559,7 +36723,7 @@ function syncRegistry(cwd) {
|
|
|
36559
36723
|
if (existingNames.has(name2)) {
|
|
36560
36724
|
result.unchanged.push(name2);
|
|
36561
36725
|
} else {
|
|
36562
|
-
registerAgent(name2,
|
|
36726
|
+
registerAgent(name2, join71(agentsDir, name2), config);
|
|
36563
36727
|
result.added.push(name2);
|
|
36564
36728
|
}
|
|
36565
36729
|
}
|
|
@@ -36579,7 +36743,7 @@ import { catalog } from "@cleocode/caamp";
|
|
|
36579
36743
|
// packages/core/src/skills/injection/token.ts
|
|
36580
36744
|
init_paths();
|
|
36581
36745
|
import { existsSync as existsSync68, readFileSync as readFileSync48 } from "node:fs";
|
|
36582
|
-
import { join as
|
|
36746
|
+
import { join as join72 } from "node:path";
|
|
36583
36747
|
var REQUIRED_TOKENS = ["TASK_ID", "DATE", "TOPIC_SLUG"];
|
|
36584
36748
|
var TOKEN_PATTERNS = {
|
|
36585
36749
|
TASK_ID: /^T\d+$/,
|
|
@@ -36615,7 +36779,7 @@ var CLEO_DEFAULTS = {
|
|
|
36615
36779
|
};
|
|
36616
36780
|
function loadPlaceholders(cwd) {
|
|
36617
36781
|
const projectRoot = getProjectRoot(cwd);
|
|
36618
|
-
const path2 =
|
|
36782
|
+
const path2 = join72(projectRoot, "skills", "_shared", "placeholders.json");
|
|
36619
36783
|
if (!existsSync68(path2)) return null;
|
|
36620
36784
|
try {
|
|
36621
36785
|
return JSON.parse(readFileSync48(path2, "utf-8"));
|
|
@@ -36999,9 +37163,9 @@ init_src();
|
|
|
36999
37163
|
init_errors3();
|
|
37000
37164
|
init_paths();
|
|
37001
37165
|
import { existsSync as existsSync69, readFileSync as readFileSync49 } from "node:fs";
|
|
37002
|
-
import { join as
|
|
37166
|
+
import { join as join73 } from "node:path";
|
|
37003
37167
|
function getProtocolBasePath(cwd) {
|
|
37004
|
-
return
|
|
37168
|
+
return join73(getProjectRoot(cwd), "skills", "_shared", "subagent-protocol-base.md");
|
|
37005
37169
|
}
|
|
37006
37170
|
function loadProtocolBase(cwd) {
|
|
37007
37171
|
const path2 = getProtocolBasePath(cwd);
|
|
@@ -37295,12 +37459,12 @@ init_src();
|
|
|
37295
37459
|
init_errors3();
|
|
37296
37460
|
init_paths();
|
|
37297
37461
|
import { appendFileSync as appendFileSync8, existsSync as existsSync71, mkdirSync as mkdirSync16, readFileSync as readFileSync51, writeFileSync as writeFileSync9 } from "node:fs";
|
|
37298
|
-
import { join as
|
|
37462
|
+
import { join as join74 } from "node:path";
|
|
37299
37463
|
function ensureOutputs(cwd) {
|
|
37300
37464
|
const outputDir = getAgentOutputsDir(cwd);
|
|
37301
37465
|
const absOutputDir = getAgentOutputsAbsolute(cwd);
|
|
37302
37466
|
const manifestPath = getManifestPath(cwd);
|
|
37303
|
-
const archiveDir =
|
|
37467
|
+
const archiveDir = join74(absOutputDir, "archive");
|
|
37304
37468
|
const created = [];
|
|
37305
37469
|
if (!existsSync71(absOutputDir)) {
|
|
37306
37470
|
mkdirSync16(absOutputDir, { recursive: true });
|
|
@@ -37429,13 +37593,13 @@ function rotateManifest(maxEntries = 100, cwd) {
|
|
|
37429
37593
|
if (entries.length <= maxEntries) return 0;
|
|
37430
37594
|
const manifestPath = getManifestPath(cwd);
|
|
37431
37595
|
const absOutputDir = getAgentOutputsAbsolute(cwd);
|
|
37432
|
-
const archiveDir =
|
|
37596
|
+
const archiveDir = join74(absOutputDir, "archive");
|
|
37433
37597
|
const toKeep = entries.slice(-maxEntries);
|
|
37434
37598
|
const toArchive = entries.slice(0, entries.length - maxEntries);
|
|
37435
37599
|
if (!existsSync71(archiveDir)) {
|
|
37436
37600
|
mkdirSync16(archiveDir, { recursive: true });
|
|
37437
37601
|
}
|
|
37438
|
-
const archivePath =
|
|
37602
|
+
const archivePath = join74(archiveDir, `MANIFEST-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.jsonl`);
|
|
37439
37603
|
const archiveContent = toArchive.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
37440
37604
|
appendFileSync8(archivePath, archiveContent, "utf-8");
|
|
37441
37605
|
const keepContent = toKeep.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
@@ -37498,13 +37662,13 @@ function validateEntry(entry) {
|
|
|
37498
37662
|
// packages/core/src/skills/manifests/resolver.ts
|
|
37499
37663
|
init_paths();
|
|
37500
37664
|
import { existsSync as existsSync72, mkdirSync as mkdirSync17, readFileSync as readFileSync52, writeFileSync as writeFileSync10 } from "node:fs";
|
|
37501
|
-
import { join as
|
|
37665
|
+
import { join as join75 } from "node:path";
|
|
37502
37666
|
var DEFAULT_CACHE_TTL = 300;
|
|
37503
37667
|
function getCacheDir() {
|
|
37504
|
-
return process.env["CLEO_MANIFEST_CACHE_DIR"] ??
|
|
37668
|
+
return process.env["CLEO_MANIFEST_CACHE_DIR"] ?? join75(getCleoHome(), "cache");
|
|
37505
37669
|
}
|
|
37506
37670
|
function getCachedManifestPath() {
|
|
37507
|
-
return
|
|
37671
|
+
return join75(getCacheDir(), "skills-manifest.json");
|
|
37508
37672
|
}
|
|
37509
37673
|
function isCacheFresh(cachePath) {
|
|
37510
37674
|
const path2 = cachePath ?? getCachedManifestPath();
|
|
@@ -37578,11 +37742,11 @@ function regenerateCache(cwd) {
|
|
|
37578
37742
|
// packages/core/src/skills/marketplace.ts
|
|
37579
37743
|
init_paths();
|
|
37580
37744
|
import { existsSync as existsSync73, readFileSync as readFileSync53 } from "node:fs";
|
|
37581
|
-
import { join as
|
|
37745
|
+
import { join as join76 } from "node:path";
|
|
37582
37746
|
import { searchSkills as caampSearchSkills, MarketplaceClient } from "@cleocode/caamp";
|
|
37583
37747
|
function loadConfig2(cwd) {
|
|
37584
37748
|
const projectRoot = getProjectRoot(cwd);
|
|
37585
|
-
const configFile =
|
|
37749
|
+
const configFile = join76(projectRoot, ".cleo", "skillsmp.json");
|
|
37586
37750
|
if (!existsSync73(configFile)) return null;
|
|
37587
37751
|
try {
|
|
37588
37752
|
const data = JSON.parse(readFileSync53(configFile, "utf-8"));
|
|
@@ -37770,7 +37934,7 @@ function spawnBatch(taskIds, templateName, cwd, tier) {
|
|
|
37770
37934
|
// packages/core/src/skills/orchestrator/startup.ts
|
|
37771
37935
|
init_paths();
|
|
37772
37936
|
import { existsSync as existsSync75, readFileSync as readFileSync55 } from "node:fs";
|
|
37773
|
-
import { join as
|
|
37937
|
+
import { join as join77 } from "node:path";
|
|
37774
37938
|
var DEFAULT_THRESHOLDS = { warning: 70, critical: 80 };
|
|
37775
37939
|
function getThresholds(config) {
|
|
37776
37940
|
const orc = config?.orchestrator?.contextThresholds;
|
|
@@ -37792,13 +37956,13 @@ function getContextState(sessionId, cwd) {
|
|
|
37792
37956
|
};
|
|
37793
37957
|
let stateFile = "";
|
|
37794
37958
|
if (sessionId) {
|
|
37795
|
-
stateFile =
|
|
37959
|
+
stateFile = join77(cleoDirAbs, "sessions", sessionId, ".context-state.json");
|
|
37796
37960
|
if (!existsSync75(stateFile)) {
|
|
37797
|
-
stateFile =
|
|
37961
|
+
stateFile = join77(cleoDirAbs, `.context-state-${sessionId}.json`);
|
|
37798
37962
|
}
|
|
37799
37963
|
}
|
|
37800
37964
|
if (!stateFile || !existsSync75(stateFile)) {
|
|
37801
|
-
stateFile =
|
|
37965
|
+
stateFile = join77(cleoDirAbs, ".context-state.json");
|
|
37802
37966
|
}
|
|
37803
37967
|
if (!existsSync75(stateFile)) {
|
|
37804
37968
|
return defaultState;
|
|
@@ -37827,7 +37991,7 @@ function getContextState(sessionId, cwd) {
|
|
|
37827
37991
|
async function sessionInit(_epicId, cwd) {
|
|
37828
37992
|
const sessionsPath = getSessionsPath(cwd);
|
|
37829
37993
|
const cleoDirAbs = getCleoDirAbsolute(cwd);
|
|
37830
|
-
const focusPath =
|
|
37994
|
+
const focusPath = join77(cleoDirAbs, "focus.json");
|
|
37831
37995
|
let activeSessions = 0;
|
|
37832
37996
|
let activeSessionId = null;
|
|
37833
37997
|
let activeScope = null;
|
|
@@ -38020,13 +38184,13 @@ async function generateHitlSummary(epicId, stopReason = "context-limit", cwd) {
|
|
|
38020
38184
|
const taskPath = getTaskPath(cwd);
|
|
38021
38185
|
const cleoDirAbs = getCleoDirAbsolute(cwd);
|
|
38022
38186
|
let sessionId = null;
|
|
38023
|
-
const currentSessionFile =
|
|
38187
|
+
const currentSessionFile = join77(cleoDirAbs, ".current-session");
|
|
38024
38188
|
if (existsSync75(currentSessionFile)) {
|
|
38025
38189
|
sessionId = readFileSync55(currentSessionFile, "utf-8").trim() || null;
|
|
38026
38190
|
}
|
|
38027
38191
|
let focusedTask = null;
|
|
38028
38192
|
let progressNote = null;
|
|
38029
|
-
const focusPath =
|
|
38193
|
+
const focusPath = join77(cleoDirAbs, "focus.json");
|
|
38030
38194
|
if (existsSync75(focusPath)) {
|
|
38031
38195
|
try {
|
|
38032
38196
|
const focus = JSON.parse(readFileSync55(focusPath, "utf-8"));
|
|
@@ -38109,7 +38273,7 @@ function priorityRank(priority) {
|
|
|
38109
38273
|
init_src();
|
|
38110
38274
|
init_paths();
|
|
38111
38275
|
import { existsSync as existsSync76, readFileSync as readFileSync56 } from "node:fs";
|
|
38112
|
-
import { join as
|
|
38276
|
+
import { join as join78 } from "node:path";
|
|
38113
38277
|
var KEY_FINDINGS_MIN = 3;
|
|
38114
38278
|
var KEY_FINDINGS_MAX = 7;
|
|
38115
38279
|
var MANIFEST_REQUIRED_FIELDS = [
|
|
@@ -38190,7 +38354,7 @@ function validateSubagentOutput(researchId, cwd) {
|
|
|
38190
38354
|
}
|
|
38191
38355
|
if (entry.file) {
|
|
38192
38356
|
const absOutputDir = getAgentOutputsAbsolute(cwd);
|
|
38193
|
-
const filePath =
|
|
38357
|
+
const filePath = join78(absOutputDir, entry.file);
|
|
38194
38358
|
if (!existsSync76(filePath)) {
|
|
38195
38359
|
issues.push(`FILE_NOT_FOUND: Expected file at ${filePath}`);
|
|
38196
38360
|
}
|
|
@@ -38233,7 +38397,7 @@ function validateManifestIntegrity(cwd) {
|
|
|
38233
38397
|
seenIds.add(entry.id);
|
|
38234
38398
|
if (entry.file) {
|
|
38235
38399
|
const absOutputDir = getAgentOutputsAbsolute(cwd);
|
|
38236
|
-
const filePath =
|
|
38400
|
+
const filePath = join78(absOutputDir, entry.file);
|
|
38237
38401
|
if (!existsSync76(filePath)) {
|
|
38238
38402
|
issues.push(`LINE_${lineNum}_FILE_MISSING: ${entry.file} does not exist`);
|
|
38239
38403
|
}
|
|
@@ -38349,13 +38513,13 @@ function validateOrchestratorCompliance(epicId, cwd) {
|
|
|
38349
38513
|
// packages/core/src/skills/skill-paths.ts
|
|
38350
38514
|
init_paths();
|
|
38351
38515
|
import { existsSync as existsSync77, lstatSync, readlinkSync as readlinkSync2, realpathSync as realpathSync2 } from "node:fs";
|
|
38352
|
-
import { delimiter, join as
|
|
38516
|
+
import { delimiter, join as join79, resolve as resolve9 } from "node:path";
|
|
38353
38517
|
function getCaampCanonical() {
|
|
38354
|
-
return
|
|
38518
|
+
return join79(getAgentsHome(), "skills");
|
|
38355
38519
|
}
|
|
38356
38520
|
function getProjectEmbedded(projectRoot) {
|
|
38357
38521
|
const root = projectRoot ?? process.cwd();
|
|
38358
|
-
return
|
|
38522
|
+
return join79(root, "skills");
|
|
38359
38523
|
}
|
|
38360
38524
|
function getProjectRoot3(cwd) {
|
|
38361
38525
|
return cwd ?? process.cwd();
|
|
@@ -38405,8 +38569,8 @@ function getSkillSearchPaths2(projectRoot) {
|
|
|
38405
38569
|
function resolveSkillPath(skillName, projectRoot) {
|
|
38406
38570
|
const searchPaths = getSkillSearchPaths2(projectRoot);
|
|
38407
38571
|
for (const { path: searchPath } of searchPaths) {
|
|
38408
|
-
const candidate =
|
|
38409
|
-
if (existsSync77(
|
|
38572
|
+
const candidate = join79(searchPath, skillName);
|
|
38573
|
+
if (existsSync77(join79(candidate, "SKILL.md"))) {
|
|
38410
38574
|
return safeRealpath(candidate);
|
|
38411
38575
|
}
|
|
38412
38576
|
}
|
|
@@ -38415,13 +38579,13 @@ function resolveSkillPath(skillName, projectRoot) {
|
|
|
38415
38579
|
function resolveProtocolPath(protocolName, projectRoot) {
|
|
38416
38580
|
const searchPaths = getSkillSearchPaths2(projectRoot);
|
|
38417
38581
|
for (const { path: searchPath } of searchPaths) {
|
|
38418
|
-
const candidate =
|
|
38582
|
+
const candidate = join79(searchPath, "_ct-skills-protocols", `${protocolName}.md`);
|
|
38419
38583
|
if (existsSync77(candidate)) {
|
|
38420
38584
|
return safeRealpath(candidate);
|
|
38421
38585
|
}
|
|
38422
38586
|
}
|
|
38423
38587
|
const root = getProjectRoot3(projectRoot);
|
|
38424
|
-
const legacy =
|
|
38588
|
+
const legacy = join79(root, "src", "protocols", `${protocolName}.md`);
|
|
38425
38589
|
if (existsSync77(legacy)) {
|
|
38426
38590
|
return safeRealpath(legacy);
|
|
38427
38591
|
}
|
|
@@ -38430,11 +38594,11 @@ function resolveProtocolPath(protocolName, projectRoot) {
|
|
|
38430
38594
|
function resolveSharedPath(resourceName, projectRoot) {
|
|
38431
38595
|
const searchPaths = getSkillSearchPaths2(projectRoot);
|
|
38432
38596
|
for (const { path: searchPath } of searchPaths) {
|
|
38433
|
-
const candidate =
|
|
38597
|
+
const candidate = join79(searchPath, "_ct-skills-shared", `${resourceName}.md`);
|
|
38434
38598
|
if (existsSync77(candidate)) {
|
|
38435
38599
|
return safeRealpath(candidate);
|
|
38436
38600
|
}
|
|
38437
|
-
const legacy =
|
|
38601
|
+
const legacy = join79(searchPath, "_shared", `${resourceName}.md`);
|
|
38438
38602
|
if (existsSync77(legacy)) {
|
|
38439
38603
|
return safeRealpath(legacy);
|
|
38440
38604
|
}
|
|
@@ -38460,7 +38624,7 @@ function getSkillSourceType(skillDir, projectRoot) {
|
|
|
38460
38624
|
}
|
|
38461
38625
|
} catch {
|
|
38462
38626
|
}
|
|
38463
|
-
if (normalizedDir.startsWith(resolve9(embeddedDir)) || normalizedDir.startsWith(
|
|
38627
|
+
if (normalizedDir.startsWith(resolve9(embeddedDir)) || normalizedDir.startsWith(join79(root, "skills"))) {
|
|
38464
38628
|
return "embedded";
|
|
38465
38629
|
}
|
|
38466
38630
|
if (normalizedDir.startsWith(caampDir)) {
|
|
@@ -38492,7 +38656,7 @@ function formatDateYMD(date2) {
|
|
|
38492
38656
|
|
|
38493
38657
|
// packages/core/src/skills/validation.ts
|
|
38494
38658
|
import { existsSync as existsSync78, readFileSync as readFileSync57 } from "node:fs";
|
|
38495
|
-
import { basename as basename13, join as
|
|
38659
|
+
import { basename as basename13, join as join80 } from "node:path";
|
|
38496
38660
|
var VALID_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
38497
38661
|
"research",
|
|
38498
38662
|
"consensus",
|
|
@@ -38515,7 +38679,7 @@ function validateSkill(skillDir) {
|
|
|
38515
38679
|
});
|
|
38516
38680
|
return buildResult(dirName, skillDir, issues);
|
|
38517
38681
|
}
|
|
38518
|
-
const skillMdPath =
|
|
38682
|
+
const skillMdPath = join80(skillDir, "SKILL.md");
|
|
38519
38683
|
if (!existsSync78(skillMdPath)) {
|
|
38520
38684
|
issues.push({
|
|
38521
38685
|
severity: "error",
|
|
@@ -38537,7 +38701,7 @@ function validateSkill(skillDir) {
|
|
|
38537
38701
|
}
|
|
38538
38702
|
const optionalFiles = ["README.md", "references"];
|
|
38539
38703
|
for (const file of optionalFiles) {
|
|
38540
|
-
const filePath =
|
|
38704
|
+
const filePath = join80(skillDir, file);
|
|
38541
38705
|
if (!existsSync78(filePath)) {
|
|
38542
38706
|
issues.push({
|
|
38543
38707
|
severity: "info",
|
|
@@ -38686,8 +38850,8 @@ init_paths();
|
|
|
38686
38850
|
init_data_accessor();
|
|
38687
38851
|
import { createHash as createHash8 } from "node:crypto";
|
|
38688
38852
|
import { existsSync as existsSync79 } from "node:fs";
|
|
38689
|
-
import { mkdir as
|
|
38690
|
-
import { dirname as dirname15, join as
|
|
38853
|
+
import { mkdir as mkdir13, readFile as readFile13, writeFile as writeFile10 } from "node:fs/promises";
|
|
38854
|
+
import { dirname as dirname15, join as join81 } from "node:path";
|
|
38691
38855
|
var SNAPSHOT_FORMAT_VERSION = "1.0.0";
|
|
38692
38856
|
function toSnapshotTask(task) {
|
|
38693
38857
|
return {
|
|
@@ -38746,7 +38910,7 @@ async function exportSnapshot(cwd) {
|
|
|
38746
38910
|
async function writeSnapshot(snapshot, outputPath) {
|
|
38747
38911
|
const dir = dirname15(outputPath);
|
|
38748
38912
|
if (!existsSync79(dir)) {
|
|
38749
|
-
await
|
|
38913
|
+
await mkdir13(dir, { recursive: true });
|
|
38750
38914
|
}
|
|
38751
38915
|
await writeFile10(outputPath, JSON.stringify(snapshot, null, 2) + "\n");
|
|
38752
38916
|
}
|
|
@@ -38763,7 +38927,7 @@ async function readSnapshot(inputPath) {
|
|
|
38763
38927
|
function getDefaultSnapshotPath(cwd) {
|
|
38764
38928
|
const cleoDir = getCleoDirAbsolute(cwd);
|
|
38765
38929
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
38766
|
-
return
|
|
38930
|
+
return join81(cleoDir, "snapshots", `snapshot-${timestamp2}.json`);
|
|
38767
38931
|
}
|
|
38768
38932
|
async function importSnapshot(snapshot, cwd) {
|
|
38769
38933
|
const accessor = await getAccessor(cwd);
|
|
@@ -38991,8 +39155,8 @@ async function initializeSpawnAdapters(manifests) {
|
|
|
38991
39155
|
if (!manifest.capabilities?.supportsSpawn) continue;
|
|
38992
39156
|
if (spawnRegistry.hasAdapterForProvider(manifest.provider)) continue;
|
|
38993
39157
|
try {
|
|
38994
|
-
const { join:
|
|
38995
|
-
const modulePath =
|
|
39158
|
+
const { join: join103 } = await import("node:path");
|
|
39159
|
+
const modulePath = join103(manifest.packagePath, manifest.entryPoint);
|
|
38996
39160
|
const adapterModule = await import(modulePath);
|
|
38997
39161
|
let SpawnProviderClass;
|
|
38998
39162
|
for (const [exportName, exportValue] of Object.entries(adapterModule)) {
|
|
@@ -39943,13 +40107,13 @@ async function getArchiveStats(opts, accessor) {
|
|
|
39943
40107
|
// packages/core/src/system/audit.ts
|
|
39944
40108
|
init_data_accessor();
|
|
39945
40109
|
import { existsSync as existsSync80, readFileSync as readFileSync58 } from "node:fs";
|
|
39946
|
-
import { join as
|
|
40110
|
+
import { join as join82 } from "node:path";
|
|
39947
40111
|
async function auditData(projectRoot, opts) {
|
|
39948
|
-
const cleoDir =
|
|
40112
|
+
const cleoDir = join82(projectRoot, ".cleo");
|
|
39949
40113
|
const scope = opts?.scope ?? "all";
|
|
39950
40114
|
const issues = [];
|
|
39951
40115
|
if (scope === "all" || scope === "tasks") {
|
|
39952
|
-
const tasksDbPath =
|
|
40116
|
+
const tasksDbPath = join82(cleoDir, "tasks.db");
|
|
39953
40117
|
if (existsSync80(tasksDbPath)) {
|
|
39954
40118
|
try {
|
|
39955
40119
|
const accessor = await getAccessor(projectRoot);
|
|
@@ -40012,7 +40176,7 @@ async function auditData(projectRoot, opts) {
|
|
|
40012
40176
|
}
|
|
40013
40177
|
}
|
|
40014
40178
|
if (scope === "all" || scope === "sessions") {
|
|
40015
|
-
const sessPath =
|
|
40179
|
+
const sessPath = join82(cleoDir, "sessions.json");
|
|
40016
40180
|
if (existsSync80(sessPath)) {
|
|
40017
40181
|
try {
|
|
40018
40182
|
const data = JSON.parse(readFileSync58(sessPath, "utf-8"));
|
|
@@ -40047,7 +40211,7 @@ async function auditData(projectRoot, opts) {
|
|
|
40047
40211
|
}
|
|
40048
40212
|
}
|
|
40049
40213
|
if (scope === "all") {
|
|
40050
|
-
const seqPath =
|
|
40214
|
+
const seqPath = join82(cleoDir, ".sequence.json");
|
|
40051
40215
|
if (existsSync80(seqPath)) {
|
|
40052
40216
|
try {
|
|
40053
40217
|
const seq = JSON.parse(readFileSync58(seqPath, "utf-8"));
|
|
@@ -40082,22 +40246,22 @@ async function auditData(projectRoot, opts) {
|
|
|
40082
40246
|
init_src();
|
|
40083
40247
|
init_errors3();
|
|
40084
40248
|
import { existsSync as existsSync81, mkdirSync as mkdirSync18, readFileSync as readFileSync59, writeFileSync as writeFileSync11 } from "node:fs";
|
|
40085
|
-
import { join as
|
|
40249
|
+
import { join as join83 } from "node:path";
|
|
40086
40250
|
function createBackup2(projectRoot, opts) {
|
|
40087
|
-
const cleoDir =
|
|
40251
|
+
const cleoDir = join83(projectRoot, ".cleo");
|
|
40088
40252
|
const btype = opts?.type || "snapshot";
|
|
40089
40253
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
40090
40254
|
const backupId = `${btype}-${timestamp2.replace(/[:.]/g, "-")}`;
|
|
40091
|
-
const backupDir =
|
|
40255
|
+
const backupDir = join83(cleoDir, "backups", btype);
|
|
40092
40256
|
if (!existsSync81(backupDir)) {
|
|
40093
40257
|
mkdirSync18(backupDir, { recursive: true });
|
|
40094
40258
|
}
|
|
40095
40259
|
const filesToBackup = ["tasks.db", "brain.db", "config.json", "project-info.json"];
|
|
40096
40260
|
const backedUp = [];
|
|
40097
40261
|
for (const file of filesToBackup) {
|
|
40098
|
-
const src =
|
|
40262
|
+
const src = join83(cleoDir, file);
|
|
40099
40263
|
if (existsSync81(src)) {
|
|
40100
|
-
const dest =
|
|
40264
|
+
const dest = join83(backupDir, `${file}.${backupId}`);
|
|
40101
40265
|
try {
|
|
40102
40266
|
const content = readFileSync59(src);
|
|
40103
40267
|
writeFileSync11(dest, content);
|
|
@@ -40106,7 +40270,7 @@ function createBackup2(projectRoot, opts) {
|
|
|
40106
40270
|
}
|
|
40107
40271
|
}
|
|
40108
40272
|
}
|
|
40109
|
-
const metaPath =
|
|
40273
|
+
const metaPath = join83(backupDir, `${backupId}.meta.json`);
|
|
40110
40274
|
try {
|
|
40111
40275
|
writeFileSync11(
|
|
40112
40276
|
metaPath,
|
|
@@ -40131,15 +40295,15 @@ function restoreBackup(projectRoot, params) {
|
|
|
40131
40295
|
if (!params.backupId) {
|
|
40132
40296
|
throw new CleoError(2 /* INVALID_INPUT */, "backupId is required");
|
|
40133
40297
|
}
|
|
40134
|
-
const cleoDir =
|
|
40298
|
+
const cleoDir = join83(projectRoot, ".cleo");
|
|
40135
40299
|
const backupTypes = ["snapshot", "safety", "migration"];
|
|
40136
40300
|
let metaPath = null;
|
|
40137
40301
|
let backupDir = null;
|
|
40138
40302
|
for (const btype of backupTypes) {
|
|
40139
|
-
const candidateMeta =
|
|
40303
|
+
const candidateMeta = join83(cleoDir, "backups", btype, `${params.backupId}.meta.json`);
|
|
40140
40304
|
if (existsSync81(candidateMeta)) {
|
|
40141
40305
|
metaPath = candidateMeta;
|
|
40142
|
-
backupDir =
|
|
40306
|
+
backupDir = join83(cleoDir, "backups", btype);
|
|
40143
40307
|
break;
|
|
40144
40308
|
}
|
|
40145
40309
|
}
|
|
@@ -40154,11 +40318,11 @@ function restoreBackup(projectRoot, params) {
|
|
|
40154
40318
|
}
|
|
40155
40319
|
const restored = [];
|
|
40156
40320
|
for (const file of meta.files ?? []) {
|
|
40157
|
-
const backupFile =
|
|
40321
|
+
const backupFile = join83(backupDir, `${file}.${params.backupId}`);
|
|
40158
40322
|
if (existsSync81(backupFile)) {
|
|
40159
40323
|
try {
|
|
40160
40324
|
const content = readFileSync59(backupFile);
|
|
40161
|
-
writeFileSync11(
|
|
40325
|
+
writeFileSync11(join83(cleoDir, file), content);
|
|
40162
40326
|
restored.push(file);
|
|
40163
40327
|
} catch {
|
|
40164
40328
|
}
|
|
@@ -40175,12 +40339,12 @@ function restoreBackup(projectRoot, params) {
|
|
|
40175
40339
|
// packages/core/src/system/cleanup.ts
|
|
40176
40340
|
init_src();
|
|
40177
40341
|
import { existsSync as existsSync82, readdirSync as readdirSync27, readFileSync as readFileSync60, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
|
|
40178
|
-
import { join as
|
|
40342
|
+
import { join as join85 } from "node:path";
|
|
40179
40343
|
|
|
40180
40344
|
// packages/core/src/audit-prune.ts
|
|
40181
40345
|
init_logger();
|
|
40182
40346
|
import { createWriteStream, mkdirSync as mkdirSync19 } from "node:fs";
|
|
40183
|
-
import { join as
|
|
40347
|
+
import { join as join84 } from "node:path";
|
|
40184
40348
|
import { Readable } from "node:stream";
|
|
40185
40349
|
import { pipeline } from "node:stream/promises";
|
|
40186
40350
|
import { createGzip } from "node:zlib";
|
|
@@ -40192,7 +40356,7 @@ async function pruneAuditLog(cleoDir, config) {
|
|
|
40192
40356
|
return { rowsArchived: 0, rowsDeleted: 0 };
|
|
40193
40357
|
}
|
|
40194
40358
|
const cutoff = new Date(Date.now() - config.auditRetentionDays * 864e5).toISOString();
|
|
40195
|
-
const projectRoot =
|
|
40359
|
+
const projectRoot = join84(cleoDir, "..");
|
|
40196
40360
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
40197
40361
|
const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
40198
40362
|
const { lt: lt2 } = await import("drizzle-orm");
|
|
@@ -40206,10 +40370,10 @@ async function pruneAuditLog(cleoDir, config) {
|
|
|
40206
40370
|
let rowsArchived = 0;
|
|
40207
40371
|
if (config.archiveBeforePrune) {
|
|
40208
40372
|
try {
|
|
40209
|
-
const archiveDir =
|
|
40373
|
+
const archiveDir = join84(cleoDir, "backups", "logs");
|
|
40210
40374
|
mkdirSync19(archiveDir, { recursive: true });
|
|
40211
40375
|
const dateStamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
40212
|
-
archivePath =
|
|
40376
|
+
archivePath = join84(archiveDir, `audit-${dateStamp}.jsonl.gz`);
|
|
40213
40377
|
const lines = oldRows.map((row) => JSON.stringify(row));
|
|
40214
40378
|
const jsonlContent = lines.join("\n") + "\n";
|
|
40215
40379
|
const gzip = createGzip();
|
|
@@ -40252,7 +40416,7 @@ async function cleanupSystem(projectRoot, params) {
|
|
|
40252
40416
|
"target is required (sessions|backups|logs|archive)"
|
|
40253
40417
|
);
|
|
40254
40418
|
}
|
|
40255
|
-
const cleoDir =
|
|
40419
|
+
const cleoDir = join85(projectRoot, ".cleo");
|
|
40256
40420
|
const dryRun = params.dryRun ?? false;
|
|
40257
40421
|
const items = [];
|
|
40258
40422
|
let prunedRows;
|
|
@@ -40260,7 +40424,7 @@ async function cleanupSystem(projectRoot, params) {
|
|
|
40260
40424
|
let archivePath;
|
|
40261
40425
|
switch (params.target) {
|
|
40262
40426
|
case "sessions": {
|
|
40263
|
-
const sessPath =
|
|
40427
|
+
const sessPath = join85(cleoDir, "sessions.json");
|
|
40264
40428
|
if (existsSync82(sessPath)) {
|
|
40265
40429
|
try {
|
|
40266
40430
|
const data = JSON.parse(readFileSync60(sessPath, "utf-8"));
|
|
@@ -40289,14 +40453,14 @@ async function cleanupSystem(projectRoot, params) {
|
|
|
40289
40453
|
break;
|
|
40290
40454
|
}
|
|
40291
40455
|
case "backups": {
|
|
40292
|
-
const backupBaseDir =
|
|
40456
|
+
const backupBaseDir = join85(cleoDir, "backups");
|
|
40293
40457
|
if (existsSync82(backupBaseDir)) {
|
|
40294
40458
|
for (const typeDir of readdirSync27(backupBaseDir)) {
|
|
40295
|
-
const fullDir =
|
|
40459
|
+
const fullDir = join85(backupBaseDir, typeDir);
|
|
40296
40460
|
try {
|
|
40297
40461
|
for (const file of readdirSync27(fullDir)) {
|
|
40298
40462
|
if (file.endsWith(".meta.json")) {
|
|
40299
|
-
const metaFilePath =
|
|
40463
|
+
const metaFilePath = join85(fullDir, file);
|
|
40300
40464
|
try {
|
|
40301
40465
|
const meta = JSON.parse(readFileSync60(metaFilePath, "utf-8"));
|
|
40302
40466
|
if (params.olderThan && meta.timestamp < params.olderThan) {
|
|
@@ -40306,7 +40470,7 @@ async function cleanupSystem(projectRoot, params) {
|
|
|
40306
40470
|
for (const bf of readdirSync27(fullDir)) {
|
|
40307
40471
|
if (bf.includes(meta.backupId)) {
|
|
40308
40472
|
try {
|
|
40309
|
-
unlinkSync5(
|
|
40473
|
+
unlinkSync5(join85(fullDir, bf));
|
|
40310
40474
|
} catch {
|
|
40311
40475
|
}
|
|
40312
40476
|
}
|
|
@@ -40338,7 +40502,7 @@ async function cleanupSystem(projectRoot, params) {
|
|
|
40338
40502
|
items.push(file);
|
|
40339
40503
|
if (!dryRun) {
|
|
40340
40504
|
try {
|
|
40341
|
-
unlinkSync5(
|
|
40505
|
+
unlinkSync5(join85(cleoDir, file));
|
|
40342
40506
|
} catch {
|
|
40343
40507
|
}
|
|
40344
40508
|
}
|
|
@@ -40368,7 +40532,7 @@ init_paths();
|
|
|
40368
40532
|
import { execFile as execFile6, execFileSync as execFileSync10 } from "node:child_process";
|
|
40369
40533
|
import { existsSync as existsSync86, readFileSync as readFileSync63, statSync as statSync19 } from "node:fs";
|
|
40370
40534
|
import { createRequire as createRequire4 } from "node:module";
|
|
40371
|
-
import { join as
|
|
40535
|
+
import { join as join89 } from "node:path";
|
|
40372
40536
|
import { promisify as promisify6 } from "node:util";
|
|
40373
40537
|
|
|
40374
40538
|
// packages/core/src/platform.ts
|
|
@@ -40395,25 +40559,25 @@ import {
|
|
|
40395
40559
|
unlinkSync as unlinkSync6,
|
|
40396
40560
|
writeFileSync as writeFileSync13
|
|
40397
40561
|
} from "node:fs";
|
|
40398
|
-
import { basename as basename14, dirname as dirname16, join as
|
|
40562
|
+
import { basename as basename14, dirname as dirname16, join as join87 } from "node:path";
|
|
40399
40563
|
import * as lockfile2 from "proper-lockfile";
|
|
40400
40564
|
var MAX_BACKUPS = 10;
|
|
40401
40565
|
function rotateBackup(filePath) {
|
|
40402
40566
|
const dir = dirname16(filePath);
|
|
40403
40567
|
const name2 = basename14(filePath);
|
|
40404
|
-
const backupDir =
|
|
40568
|
+
const backupDir = join87(dir, ".backups");
|
|
40405
40569
|
if (!existsSync84(backupDir)) {
|
|
40406
40570
|
mkdirSync20(backupDir, { recursive: true });
|
|
40407
40571
|
}
|
|
40408
40572
|
for (let i = MAX_BACKUPS; i >= 1; i--) {
|
|
40409
|
-
const current =
|
|
40573
|
+
const current = join87(backupDir, `${name2}.${i}`);
|
|
40410
40574
|
if (i === MAX_BACKUPS) {
|
|
40411
40575
|
try {
|
|
40412
40576
|
unlinkSync6(current);
|
|
40413
40577
|
} catch {
|
|
40414
40578
|
}
|
|
40415
40579
|
} else {
|
|
40416
|
-
const next =
|
|
40580
|
+
const next = join87(backupDir, `${name2}.${i + 1}`);
|
|
40417
40581
|
try {
|
|
40418
40582
|
if (existsSync84(current)) renameSync6(current, next);
|
|
40419
40583
|
} catch {
|
|
@@ -40422,13 +40586,13 @@ function rotateBackup(filePath) {
|
|
|
40422
40586
|
}
|
|
40423
40587
|
try {
|
|
40424
40588
|
const content = readFileSync61(filePath, "utf-8");
|
|
40425
|
-
writeFileSync13(
|
|
40589
|
+
writeFileSync13(join87(backupDir, `${name2}.1`), content, "utf-8");
|
|
40426
40590
|
} catch {
|
|
40427
40591
|
}
|
|
40428
40592
|
}
|
|
40429
40593
|
function writeJsonFileAtomic(filePath, data, indent = 2) {
|
|
40430
40594
|
const dir = dirname16(filePath);
|
|
40431
|
-
const tempPath =
|
|
40595
|
+
const tempPath = join87(dir, `.${basename14(filePath)}.${randomBytes8(6).toString("hex")}.tmp`);
|
|
40432
40596
|
const content = JSON.stringify(data, null, indent) + "\n";
|
|
40433
40597
|
writeFileSync13(tempPath, content, "utf-8");
|
|
40434
40598
|
try {
|
|
@@ -40445,7 +40609,7 @@ function writeJsonFileAtomic(filePath, data, indent = 2) {
|
|
|
40445
40609
|
}
|
|
40446
40610
|
}
|
|
40447
40611
|
function getDataPath(projectRoot, filename) {
|
|
40448
|
-
return
|
|
40612
|
+
return join87(projectRoot, ".cleo", filename);
|
|
40449
40613
|
}
|
|
40450
40614
|
|
|
40451
40615
|
// packages/core/src/platform.ts
|
|
@@ -40569,7 +40733,7 @@ init_data_accessor();
|
|
|
40569
40733
|
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
40570
40734
|
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync85, readFileSync as readFileSync62, statSync as statSync18 } from "node:fs";
|
|
40571
40735
|
import { homedir as homedir4 } from "node:os";
|
|
40572
|
-
import { join as
|
|
40736
|
+
import { join as join88 } from "node:path";
|
|
40573
40737
|
|
|
40574
40738
|
// packages/core/src/constants.ts
|
|
40575
40739
|
var CORE_PROTECTED_FILES = [
|
|
@@ -40596,7 +40760,7 @@ function checkCliInstallation(cleoHome = getCleoHome()) {
|
|
|
40596
40760
|
}
|
|
40597
40761
|
var VERSION_REGEX = /^\d+\.\d+\.\d+$/;
|
|
40598
40762
|
function checkCliVersion(cleoHome = getCleoHome()) {
|
|
40599
|
-
const versionFile =
|
|
40763
|
+
const versionFile = join88(cleoHome, "VERSION");
|
|
40600
40764
|
if (!existsSync85(versionFile)) {
|
|
40601
40765
|
return {
|
|
40602
40766
|
id: "cli_version",
|
|
@@ -40619,7 +40783,7 @@ function checkCliVersion(cleoHome = getCleoHome()) {
|
|
|
40619
40783
|
};
|
|
40620
40784
|
}
|
|
40621
40785
|
function checkDocsAccessibility(cleoHome = getCleoHome()) {
|
|
40622
|
-
const docsFile =
|
|
40786
|
+
const docsFile = join88(cleoHome, "templates", "CLEO-INJECTION.md");
|
|
40623
40787
|
if (!existsSync85(docsFile)) {
|
|
40624
40788
|
return {
|
|
40625
40789
|
id: "docs_accessibility",
|
|
@@ -40653,7 +40817,7 @@ function checkDocsAccessibility(cleoHome = getCleoHome()) {
|
|
|
40653
40817
|
};
|
|
40654
40818
|
}
|
|
40655
40819
|
function checkAtReferenceResolution(cleoHome = getCleoHome()) {
|
|
40656
|
-
const docsFile =
|
|
40820
|
+
const docsFile = join88(cleoHome, "templates", "CLEO-INJECTION.md");
|
|
40657
40821
|
const reference = "@~/.cleo/templates/CLEO-INJECTION.md";
|
|
40658
40822
|
if (!existsSync85(docsFile)) {
|
|
40659
40823
|
return {
|
|
@@ -40701,7 +40865,7 @@ function checkAtReferenceResolution(cleoHome = getCleoHome()) {
|
|
|
40701
40865
|
}
|
|
40702
40866
|
function checkAgentsMdHub(projectRoot) {
|
|
40703
40867
|
const root = projectRoot ?? process.cwd();
|
|
40704
|
-
const agentsMdPath =
|
|
40868
|
+
const agentsMdPath = join88(root, "AGENTS.md");
|
|
40705
40869
|
if (!existsSync85(agentsMdPath)) {
|
|
40706
40870
|
return {
|
|
40707
40871
|
id: "agents_md_hub",
|
|
@@ -40746,7 +40910,7 @@ function checkAgentsMdHub(projectRoot) {
|
|
|
40746
40910
|
}
|
|
40747
40911
|
function checkRootGitignore(projectRoot) {
|
|
40748
40912
|
const root = projectRoot ?? process.cwd();
|
|
40749
|
-
const gitignorePath =
|
|
40913
|
+
const gitignorePath = join88(root, ".gitignore");
|
|
40750
40914
|
if (!existsSync85(gitignorePath)) {
|
|
40751
40915
|
return {
|
|
40752
40916
|
id: "root_gitignore",
|
|
@@ -40797,7 +40961,7 @@ function checkRootGitignore(projectRoot) {
|
|
|
40797
40961
|
}
|
|
40798
40962
|
function checkCleoGitignore(projectRoot) {
|
|
40799
40963
|
const root = projectRoot ?? process.cwd();
|
|
40800
|
-
const gitignorePath =
|
|
40964
|
+
const gitignorePath = join88(root, ".cleo", ".gitignore");
|
|
40801
40965
|
if (!existsSync85(gitignorePath)) {
|
|
40802
40966
|
return {
|
|
40803
40967
|
id: "cleo_gitignore",
|
|
@@ -40827,8 +40991,8 @@ function checkCleoGitignore(projectRoot) {
|
|
|
40827
40991
|
} catch {
|
|
40828
40992
|
try {
|
|
40829
40993
|
const templatePaths = [
|
|
40830
|
-
|
|
40831
|
-
|
|
40994
|
+
join88(root, "templates", "cleo-gitignore"),
|
|
40995
|
+
join88(getCleoHome(), "templates", "cleo-gitignore")
|
|
40832
40996
|
];
|
|
40833
40997
|
for (const tp of templatePaths) {
|
|
40834
40998
|
if (existsSync85(tp)) {
|
|
@@ -40869,7 +41033,7 @@ function detectStorageEngine(_projectRoot) {
|
|
|
40869
41033
|
}
|
|
40870
41034
|
function checkVitalFilesTracked(projectRoot) {
|
|
40871
41035
|
const root = projectRoot ?? process.cwd();
|
|
40872
|
-
const gitDir =
|
|
41036
|
+
const gitDir = join88(root, ".git");
|
|
40873
41037
|
if (!existsSync85(gitDir)) {
|
|
40874
41038
|
return {
|
|
40875
41039
|
id: "vital_files_tracked",
|
|
@@ -40884,7 +41048,7 @@ function checkVitalFilesTracked(projectRoot) {
|
|
|
40884
41048
|
const vitalFiles = CORE_PROTECTED_FILES.map((f) => `.cleo/${f}`);
|
|
40885
41049
|
const untracked = [];
|
|
40886
41050
|
for (const file of vitalFiles) {
|
|
40887
|
-
const fullPath =
|
|
41051
|
+
const fullPath = join88(root, file);
|
|
40888
41052
|
if (!existsSync85(fullPath)) continue;
|
|
40889
41053
|
try {
|
|
40890
41054
|
execFileSync9("git", ["ls-files", "--error-unmatch", file], {
|
|
@@ -40916,7 +41080,7 @@ function checkVitalFilesTracked(projectRoot) {
|
|
|
40916
41080
|
}
|
|
40917
41081
|
function checkCoreFilesNotIgnored(projectRoot) {
|
|
40918
41082
|
const root = projectRoot ?? process.cwd();
|
|
40919
|
-
const gitDir =
|
|
41083
|
+
const gitDir = join88(root, ".git");
|
|
40920
41084
|
if (!existsSync85(gitDir)) {
|
|
40921
41085
|
return {
|
|
40922
41086
|
id: "core_files_not_ignored",
|
|
@@ -40930,7 +41094,7 @@ function checkCoreFilesNotIgnored(projectRoot) {
|
|
|
40930
41094
|
const ignoredFiles = [];
|
|
40931
41095
|
for (const file of CORE_PROTECTED_FILES) {
|
|
40932
41096
|
const relPath = `.cleo/${file}`;
|
|
40933
|
-
const fullPath =
|
|
41097
|
+
const fullPath = join88(root, relPath);
|
|
40934
41098
|
if (!existsSync85(fullPath)) continue;
|
|
40935
41099
|
try {
|
|
40936
41100
|
execFileSync9("git", ["check-ignore", "-q", relPath], {
|
|
@@ -40962,7 +41126,7 @@ function checkCoreFilesNotIgnored(projectRoot) {
|
|
|
40962
41126
|
}
|
|
40963
41127
|
function checkSqliteNotTracked(projectRoot) {
|
|
40964
41128
|
const root = projectRoot ?? process.cwd();
|
|
40965
|
-
const gitDir =
|
|
41129
|
+
const gitDir = join88(root, ".git");
|
|
40966
41130
|
if (!existsSync85(gitDir)) {
|
|
40967
41131
|
return {
|
|
40968
41132
|
id: "sqlite_not_tracked",
|
|
@@ -40974,7 +41138,7 @@ function checkSqliteNotTracked(projectRoot) {
|
|
|
40974
41138
|
};
|
|
40975
41139
|
}
|
|
40976
41140
|
const sqliteFile = ".cleo/tasks.db";
|
|
40977
|
-
const fullPath =
|
|
41141
|
+
const fullPath = join88(root, sqliteFile);
|
|
40978
41142
|
if (!existsSync85(fullPath)) {
|
|
40979
41143
|
return {
|
|
40980
41144
|
id: "sqlite_not_tracked",
|
|
@@ -41011,7 +41175,7 @@ function checkSqliteNotTracked(projectRoot) {
|
|
|
41011
41175
|
}
|
|
41012
41176
|
function checkLegacyAgentOutputs(projectRoot) {
|
|
41013
41177
|
const root = projectRoot ?? process.cwd();
|
|
41014
|
-
const cleoDir =
|
|
41178
|
+
const cleoDir = join88(root, ".cleo");
|
|
41015
41179
|
const detection = detectLegacyAgentOutputs(root, cleoDir);
|
|
41016
41180
|
if (detection.hasLegacy) {
|
|
41017
41181
|
return {
|
|
@@ -41037,7 +41201,7 @@ function checkCaampMarkerIntegrity(projectRoot) {
|
|
|
41037
41201
|
const files = ["CLAUDE.md", "AGENTS.md"];
|
|
41038
41202
|
const issues = [];
|
|
41039
41203
|
for (const file of files) {
|
|
41040
|
-
const filePath =
|
|
41204
|
+
const filePath = join88(root, file);
|
|
41041
41205
|
if (!existsSync85(filePath)) continue;
|
|
41042
41206
|
let content;
|
|
41043
41207
|
try {
|
|
@@ -41075,7 +41239,7 @@ function checkCaampMarkerIntegrity(projectRoot) {
|
|
|
41075
41239
|
}
|
|
41076
41240
|
function checkAtReferenceTargetExists(projectRoot) {
|
|
41077
41241
|
const root = projectRoot ?? process.cwd();
|
|
41078
|
-
const agentsPath =
|
|
41242
|
+
const agentsPath = join88(root, "AGENTS.md");
|
|
41079
41243
|
if (!existsSync85(agentsPath)) {
|
|
41080
41244
|
return {
|
|
41081
41245
|
id: "at_reference_targets",
|
|
@@ -41115,7 +41279,7 @@ function checkAtReferenceTargetExists(projectRoot) {
|
|
|
41115
41279
|
const missing = [];
|
|
41116
41280
|
for (const ref of refs) {
|
|
41117
41281
|
const rawPath = ref.slice(1).trim();
|
|
41118
|
-
const resolvedPath = rawPath.startsWith("~/") ?
|
|
41282
|
+
const resolvedPath = rawPath.startsWith("~/") ? join88(homedir4(), rawPath.slice(2)) : join88(root, rawPath);
|
|
41119
41283
|
if (!existsSync85(resolvedPath)) {
|
|
41120
41284
|
missing.push(rawPath);
|
|
41121
41285
|
}
|
|
@@ -41142,8 +41306,8 @@ function checkAtReferenceTargetExists(projectRoot) {
|
|
|
41142
41306
|
function checkTemplateFreshness(projectRoot, cleoHome) {
|
|
41143
41307
|
const root = projectRoot ?? process.cwd();
|
|
41144
41308
|
const home = cleoHome ?? getCleoHome();
|
|
41145
|
-
const sourcePath =
|
|
41146
|
-
const deployedPath =
|
|
41309
|
+
const sourcePath = join88(root, "templates", "CLEO-INJECTION.md");
|
|
41310
|
+
const deployedPath = join88(home, "templates", "CLEO-INJECTION.md");
|
|
41147
41311
|
if (!existsSync85(sourcePath)) {
|
|
41148
41312
|
return {
|
|
41149
41313
|
id: "template_freshness",
|
|
@@ -41187,7 +41351,7 @@ function checkTemplateFreshness(projectRoot, cleoHome) {
|
|
|
41187
41351
|
}
|
|
41188
41352
|
function checkTierMarkersPresent(cleoHome) {
|
|
41189
41353
|
const home = cleoHome ?? getCleoHome();
|
|
41190
|
-
const templatePath =
|
|
41354
|
+
const templatePath = join88(home, "templates", "CLEO-INJECTION.md");
|
|
41191
41355
|
if (!existsSync85(templatePath)) {
|
|
41192
41356
|
return {
|
|
41193
41357
|
id: "tier_markers_present",
|
|
@@ -41309,7 +41473,7 @@ function checkGlobalSchemaHealth(_projectRoot) {
|
|
|
41309
41473
|
}
|
|
41310
41474
|
function checkNoLocalSchemas(projectRoot) {
|
|
41311
41475
|
const root = projectRoot ?? process.cwd();
|
|
41312
|
-
const localSchemasDir =
|
|
41476
|
+
const localSchemasDir = join88(root, ".cleo", "schemas");
|
|
41313
41477
|
if (!existsSync85(localSchemasDir)) {
|
|
41314
41478
|
return {
|
|
41315
41479
|
id: "no_local_schemas",
|
|
@@ -41374,13 +41538,13 @@ var databaseSyncCtor = (() => {
|
|
|
41374
41538
|
})();
|
|
41375
41539
|
var STALE_JSON_FILES = ["todo.json", "sessions.json", "todo-archive.json"];
|
|
41376
41540
|
function resolveStructuredLogPath(cleoDir) {
|
|
41377
|
-
const defaultPath =
|
|
41378
|
-
const configPath =
|
|
41541
|
+
const defaultPath = join89(cleoDir, "logs", "cleo.log");
|
|
41542
|
+
const configPath = join89(cleoDir, "config.json");
|
|
41379
41543
|
if (!existsSync86(configPath)) return defaultPath;
|
|
41380
41544
|
try {
|
|
41381
41545
|
const config = JSON.parse(readFileSync63(configPath, "utf-8"));
|
|
41382
41546
|
if (!config.logging?.filePath) return defaultPath;
|
|
41383
|
-
return
|
|
41547
|
+
return join89(cleoDir, config.logging.filePath);
|
|
41384
41548
|
} catch {
|
|
41385
41549
|
return defaultPath;
|
|
41386
41550
|
}
|
|
@@ -41422,14 +41586,14 @@ function checkAuditLogAvailability(dbPath) {
|
|
|
41422
41586
|
}
|
|
41423
41587
|
}
|
|
41424
41588
|
function getSystemHealth(projectRoot, opts) {
|
|
41425
|
-
const cleoDir =
|
|
41589
|
+
const cleoDir = join89(projectRoot, ".cleo");
|
|
41426
41590
|
const checks = [];
|
|
41427
41591
|
if (existsSync86(cleoDir)) {
|
|
41428
41592
|
checks.push({ name: "cleo_dir", status: "pass", message: ".cleo directory exists" });
|
|
41429
41593
|
} else {
|
|
41430
41594
|
checks.push({ name: "cleo_dir", status: "fail", message: ".cleo directory not found" });
|
|
41431
41595
|
}
|
|
41432
|
-
const dbPath =
|
|
41596
|
+
const dbPath = join89(cleoDir, "tasks.db");
|
|
41433
41597
|
if (existsSync86(dbPath)) {
|
|
41434
41598
|
try {
|
|
41435
41599
|
const dbSize = statSync19(dbPath).size;
|
|
@@ -41451,7 +41615,7 @@ function getSystemHealth(projectRoot, opts) {
|
|
|
41451
41615
|
if (existsSync86(dbPath)) {
|
|
41452
41616
|
checks.push(checkAuditLogAvailability(dbPath));
|
|
41453
41617
|
}
|
|
41454
|
-
const configPath =
|
|
41618
|
+
const configPath = join89(cleoDir, "config.json");
|
|
41455
41619
|
if (existsSync86(configPath)) {
|
|
41456
41620
|
try {
|
|
41457
41621
|
JSON.parse(readFileSync63(configPath, "utf-8"));
|
|
@@ -41467,7 +41631,7 @@ function getSystemHealth(projectRoot, opts) {
|
|
|
41467
41631
|
checks.push({ name: "config_json", status: "warn", message: "config.json not found" });
|
|
41468
41632
|
}
|
|
41469
41633
|
if (existsSync86(dbPath)) {
|
|
41470
|
-
const staleFiles = STALE_JSON_FILES.filter((f) => existsSync86(
|
|
41634
|
+
const staleFiles = STALE_JSON_FILES.filter((f) => existsSync86(join89(cleoDir, f)));
|
|
41471
41635
|
if (staleFiles.length > 0) {
|
|
41472
41636
|
checks.push({
|
|
41473
41637
|
name: "stale_json",
|
|
@@ -41491,7 +41655,7 @@ function getSystemHealth(projectRoot, opts) {
|
|
|
41491
41655
|
message: `structured log not found: ${logPath}`
|
|
41492
41656
|
});
|
|
41493
41657
|
}
|
|
41494
|
-
const backupDir =
|
|
41658
|
+
const backupDir = join89(cleoDir, ".backups");
|
|
41495
41659
|
if (existsSync86(backupDir)) {
|
|
41496
41660
|
checks.push({ name: "backups_dir", status: "pass", message: ".backups directory exists" });
|
|
41497
41661
|
} else {
|
|
@@ -41504,7 +41668,7 @@ function getSystemHealth(projectRoot, opts) {
|
|
|
41504
41668
|
}
|
|
41505
41669
|
let version = "unknown";
|
|
41506
41670
|
try {
|
|
41507
|
-
const pkgPath =
|
|
41671
|
+
const pkgPath = join89(projectRoot, "package.json");
|
|
41508
41672
|
if (existsSync86(pkgPath)) {
|
|
41509
41673
|
const pkg = JSON.parse(readFileSync63(pkgPath, "utf-8"));
|
|
41510
41674
|
version = pkg.version || "unknown";
|
|
@@ -41540,8 +41704,8 @@ async function getSystemDiagnostics(projectRoot, opts) {
|
|
|
41540
41704
|
details: preflight.summary
|
|
41541
41705
|
});
|
|
41542
41706
|
}
|
|
41543
|
-
const cleoDir =
|
|
41544
|
-
const dbPath =
|
|
41707
|
+
const cleoDir = join89(projectRoot, ".cleo");
|
|
41708
|
+
const dbPath = join89(cleoDir, "tasks.db");
|
|
41545
41709
|
if (existsSync86(dbPath)) {
|
|
41546
41710
|
try {
|
|
41547
41711
|
const accessor = await getAccessor(projectRoot);
|
|
@@ -41681,7 +41845,7 @@ function mapSchemaCheckResult(sr) {
|
|
|
41681
41845
|
};
|
|
41682
41846
|
}
|
|
41683
41847
|
function checkContributorChannel(projectRoot) {
|
|
41684
|
-
const configPath =
|
|
41848
|
+
const configPath = join89(projectRoot, ".cleo", "config.json");
|
|
41685
41849
|
if (!existsSync86(configPath)) {
|
|
41686
41850
|
return { check: "contributor_channel", status: "ok", message: "Not a contributor project" };
|
|
41687
41851
|
}
|
|
@@ -41698,7 +41862,7 @@ function checkContributorChannel(projectRoot) {
|
|
|
41698
41862
|
return { check: "contributor_channel", status: "ok", message: "Not a contributor project" };
|
|
41699
41863
|
}
|
|
41700
41864
|
const pathDirs = (process.env["PATH"] ?? "").split(":").filter(Boolean);
|
|
41701
|
-
const devCliOnPath = pathDirs.some((dir) => existsSync86(
|
|
41865
|
+
const devCliOnPath = pathDirs.some((dir) => existsSync86(join89(dir, devCli)));
|
|
41702
41866
|
if (!devCliOnPath) {
|
|
41703
41867
|
return {
|
|
41704
41868
|
check: "contributor_channel",
|
|
@@ -41731,14 +41895,14 @@ async function coreDoctorReport(projectRoot) {
|
|
|
41731
41895
|
status: gitPath ? "ok" : "warning",
|
|
41732
41896
|
message: gitPath ? `git found: ${gitPath}` : "git not found (optional, needed for version control features)"
|
|
41733
41897
|
});
|
|
41734
|
-
const cleoDir =
|
|
41898
|
+
const cleoDir = join89(projectRoot, ".cleo");
|
|
41735
41899
|
const dirExists = existsSync86(cleoDir);
|
|
41736
41900
|
checks.push({
|
|
41737
41901
|
check: "project_dir",
|
|
41738
41902
|
status: dirExists ? "ok" : "error",
|
|
41739
41903
|
message: dirExists ? `Project dir: ${cleoDir}` : `Project dir not found: ${cleoDir}. Run: cleo init`
|
|
41740
41904
|
});
|
|
41741
|
-
const dbPath =
|
|
41905
|
+
const dbPath = join89(cleoDir, "tasks.db");
|
|
41742
41906
|
const dbExists2 = existsSync86(dbPath);
|
|
41743
41907
|
const dbSize = await fileSize(dbPath);
|
|
41744
41908
|
checks.push({
|
|
@@ -41788,14 +41952,14 @@ async function coreDoctorReport(projectRoot) {
|
|
|
41788
41952
|
} catch {
|
|
41789
41953
|
}
|
|
41790
41954
|
}
|
|
41791
|
-
const configPath =
|
|
41955
|
+
const configPath = join89(cleoDir, "config.json");
|
|
41792
41956
|
const configExists = existsSync86(configPath);
|
|
41793
41957
|
checks.push({
|
|
41794
41958
|
check: "config_file",
|
|
41795
41959
|
status: configExists ? "ok" : "warning",
|
|
41796
41960
|
message: configExists ? "config.json present" : "config.json not found (using defaults)"
|
|
41797
41961
|
});
|
|
41798
|
-
const staleJsonFiles = STALE_JSON_FILES.filter((f) => existsSync86(
|
|
41962
|
+
const staleJsonFiles = STALE_JSON_FILES.filter((f) => existsSync86(join89(cleoDir, f)));
|
|
41799
41963
|
if (dbExists2 && staleJsonFiles.length > 0) {
|
|
41800
41964
|
checks.push({
|
|
41801
41965
|
check: "stale_json",
|
|
@@ -41811,7 +41975,7 @@ async function coreDoctorReport(projectRoot) {
|
|
|
41811
41975
|
status: logExists ? "ok" : "warning",
|
|
41812
41976
|
message: logExists ? `structured log present: ${logPath}` : `structured log not found: ${logPath}`
|
|
41813
41977
|
});
|
|
41814
|
-
const rootGitignorePath =
|
|
41978
|
+
const rootGitignorePath = join89(projectRoot, ".gitignore");
|
|
41815
41979
|
if (existsSync86(rootGitignorePath)) {
|
|
41816
41980
|
try {
|
|
41817
41981
|
const gitignoreContent = readFileSync63(rootGitignorePath, "utf-8");
|
|
@@ -41833,7 +41997,7 @@ async function coreDoctorReport(projectRoot) {
|
|
|
41833
41997
|
checks.push(mapCheckResult(checkVitalFilesTracked(projectRoot)));
|
|
41834
41998
|
checks.push(mapCheckResult(checkCoreFilesNotIgnored(projectRoot)));
|
|
41835
41999
|
checks.push(mapCheckResult(checkLegacyAgentOutputs(projectRoot)));
|
|
41836
|
-
const cleoGitHeadExists = existsSync86(
|
|
42000
|
+
const cleoGitHeadExists = existsSync86(join89(cleoDir, ".git", "HEAD"));
|
|
41837
42001
|
checks.push({
|
|
41838
42002
|
check: "cleo_git_repo",
|
|
41839
42003
|
status: cleoGitHeadExists ? "ok" : "warning",
|
|
@@ -41849,15 +42013,15 @@ async function coreDoctorReport(projectRoot) {
|
|
|
41849
42013
|
checks.push(mapCheckResult(checkProjectContext(projectRoot)));
|
|
41850
42014
|
checks.push(mapCheckResult(checkInjection2(projectRoot)));
|
|
41851
42015
|
checks.push(checkContributorChannel(projectRoot));
|
|
41852
|
-
const agentDefPath =
|
|
42016
|
+
const agentDefPath = join89(getAgentsHome(), "agents", "cleo-subagent");
|
|
41853
42017
|
checks.push({
|
|
41854
42018
|
check: "agent_definition",
|
|
41855
42019
|
status: existsSync86(agentDefPath) ? "ok" : "warning",
|
|
41856
42020
|
message: existsSync86(agentDefPath) ? "cleo-subagent agent definition installed" : "cleo-subagent not found \u2014 run: cleo init",
|
|
41857
42021
|
...existsSync86(agentDefPath) ? {} : { fix: "cleo init" }
|
|
41858
42022
|
});
|
|
41859
|
-
const gitDir =
|
|
41860
|
-
const gitHubTemplatesDir =
|
|
42023
|
+
const gitDir = join89(projectRoot, ".git");
|
|
42024
|
+
const gitHubTemplatesDir = join89(projectRoot, ".github", "ISSUE_TEMPLATE");
|
|
41861
42025
|
if (existsSync86(gitDir)) {
|
|
41862
42026
|
checks.push({
|
|
41863
42027
|
check: "github_templates",
|
|
@@ -41893,11 +42057,11 @@ async function coreDoctorReport(projectRoot) {
|
|
|
41893
42057
|
init_paths();
|
|
41894
42058
|
init_data_accessor();
|
|
41895
42059
|
import { existsSync as existsSync87, readFileSync as readFileSync64 } from "node:fs";
|
|
41896
|
-
import { join as
|
|
42060
|
+
import { join as join90 } from "node:path";
|
|
41897
42061
|
async function generateInjection(projectRoot, accessor) {
|
|
41898
42062
|
let version = "unknown";
|
|
41899
42063
|
try {
|
|
41900
|
-
const pkgPath =
|
|
42064
|
+
const pkgPath = join90(projectRoot, "package.json");
|
|
41901
42065
|
if (existsSync87(pkgPath)) {
|
|
41902
42066
|
const pkg = JSON.parse(readFileSync64(pkgPath, "utf-8"));
|
|
41903
42067
|
version = pkg.version || "unknown";
|
|
@@ -42031,9 +42195,9 @@ async function getLabels(cwd, accessor) {
|
|
|
42031
42195
|
|
|
42032
42196
|
// packages/core/src/system/metrics.ts
|
|
42033
42197
|
import { existsSync as existsSync88, readFileSync as readFileSync65 } from "node:fs";
|
|
42034
|
-
import { join as
|
|
42198
|
+
import { join as join91 } from "node:path";
|
|
42035
42199
|
async function getSystemMetrics(projectRoot, opts, accessor) {
|
|
42036
|
-
const cleoDir =
|
|
42200
|
+
const cleoDir = join91(projectRoot, ".cleo");
|
|
42037
42201
|
let complianceEntries = readComplianceJsonl(projectRoot);
|
|
42038
42202
|
if (opts?.since) {
|
|
42039
42203
|
complianceEntries = complianceEntries.filter((e) => e.timestamp >= opts.since);
|
|
@@ -42060,7 +42224,7 @@ async function getSystemMetrics(projectRoot, opts, accessor) {
|
|
|
42060
42224
|
sessionsActive = sessions2.filter((s) => s.status === "active").length;
|
|
42061
42225
|
sessionsCompleted = sessions2.filter((s) => s.status === "ended").length;
|
|
42062
42226
|
} else {
|
|
42063
|
-
const sessionsPath =
|
|
42227
|
+
const sessionsPath = join91(cleoDir, "sessions.json");
|
|
42064
42228
|
if (existsSync88(sessionsPath)) {
|
|
42065
42229
|
const sessionsData = JSON.parse(readFileSync65(sessionsPath, "utf-8"));
|
|
42066
42230
|
const sessions2 = sessionsData.sessions ?? [];
|
|
@@ -42085,9 +42249,9 @@ init_src();
|
|
|
42085
42249
|
init_errors3();
|
|
42086
42250
|
init_data_accessor();
|
|
42087
42251
|
import { existsSync as existsSync89 } from "node:fs";
|
|
42088
|
-
import { join as
|
|
42252
|
+
import { join as join92 } from "node:path";
|
|
42089
42253
|
async function getMigrationStatus2(projectRoot, opts) {
|
|
42090
|
-
const taskPath =
|
|
42254
|
+
const taskPath = join92(projectRoot, ".cleo", "tasks.db");
|
|
42091
42255
|
let currentVersion = "unknown";
|
|
42092
42256
|
if (existsSync89(taskPath)) {
|
|
42093
42257
|
try {
|
|
@@ -42119,7 +42283,7 @@ init_paths();
|
|
|
42119
42283
|
import { execFile as execFile7 } from "node:child_process";
|
|
42120
42284
|
import { existsSync as existsSync90 } from "node:fs";
|
|
42121
42285
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
42122
|
-
import { basename as basename15, join as
|
|
42286
|
+
import { basename as basename15, join as join93 } from "node:path";
|
|
42123
42287
|
import { promisify as promisify7 } from "node:util";
|
|
42124
42288
|
function normalizeChannel(value) {
|
|
42125
42289
|
if (!value) return null;
|
|
@@ -42152,7 +42316,7 @@ function getExpectedNaming(channel) {
|
|
|
42152
42316
|
}
|
|
42153
42317
|
}
|
|
42154
42318
|
async function parseVersionFile(dataRoot) {
|
|
42155
|
-
const versionPath =
|
|
42319
|
+
const versionPath = join93(dataRoot, "VERSION");
|
|
42156
42320
|
if (!existsSync90(versionPath)) return null;
|
|
42157
42321
|
let content;
|
|
42158
42322
|
try {
|
|
@@ -42182,9 +42346,9 @@ async function parseVersionFile(dataRoot) {
|
|
|
42182
42346
|
async function getPackageInfo(sourceDir) {
|
|
42183
42347
|
const candidates = [];
|
|
42184
42348
|
if (sourceDir && sourceDir !== "unknown" && sourceDir !== "npm") {
|
|
42185
|
-
candidates.push(
|
|
42349
|
+
candidates.push(join93(sourceDir, "package.json"));
|
|
42186
42350
|
}
|
|
42187
|
-
candidates.push(
|
|
42351
|
+
candidates.push(join93(process.cwd(), "package.json"));
|
|
42188
42352
|
for (const candidate of candidates) {
|
|
42189
42353
|
try {
|
|
42190
42354
|
const raw = await readFile15(candidate, "utf-8");
|
|
@@ -42264,13 +42428,13 @@ init_src();
|
|
|
42264
42428
|
init_errors3();
|
|
42265
42429
|
init_data_accessor();
|
|
42266
42430
|
import { existsSync as existsSync91, readFileSync as readFileSync66, writeFileSync as writeFileSync14 } from "node:fs";
|
|
42267
|
-
import { join as
|
|
42431
|
+
import { join as join94 } from "node:path";
|
|
42268
42432
|
function safestop(projectRoot, opts) {
|
|
42269
42433
|
const dryRun = opts?.dryRun ?? false;
|
|
42270
42434
|
const reason = opts?.reason ?? "Manual safestop";
|
|
42271
42435
|
let sessionEnded = false;
|
|
42272
42436
|
if (!dryRun && !opts?.noSessionEnd) {
|
|
42273
|
-
const sessPath =
|
|
42437
|
+
const sessPath = join94(projectRoot, ".cleo", "sessions.json");
|
|
42274
42438
|
if (existsSync91(sessPath)) {
|
|
42275
42439
|
try {
|
|
42276
42440
|
const data = JSON.parse(readFileSync66(sessPath, "utf-8"));
|
|
@@ -42298,7 +42462,7 @@ async function uncancelTask(projectRoot, params) {
|
|
|
42298
42462
|
if (!params.taskId) {
|
|
42299
42463
|
throw new CleoError(2 /* INVALID_INPUT */, "taskId is required");
|
|
42300
42464
|
}
|
|
42301
|
-
const taskDbPath =
|
|
42465
|
+
const taskDbPath = join94(projectRoot, ".cleo", "tasks.db");
|
|
42302
42466
|
if (!existsSync91(taskDbPath)) {
|
|
42303
42467
|
throw new CleoError(8 /* CONFIG_ERROR */, "No tasks.db found");
|
|
42304
42468
|
}
|
|
@@ -42355,11 +42519,9 @@ async function uncancelTask(projectRoot, params) {
|
|
|
42355
42519
|
// packages/core/src/task-work/index.ts
|
|
42356
42520
|
var task_work_exports = {};
|
|
42357
42521
|
__export(task_work_exports, {
|
|
42358
|
-
analyzeTodoWriteChanges: () => analyzeChanges,
|
|
42359
42522
|
currentTask: () => currentTask,
|
|
42360
42523
|
getTaskHistory: () => getTaskHistory,
|
|
42361
42524
|
getWorkHistory: () => getWorkHistory,
|
|
42362
|
-
mergeTodoWriteState: () => mergeTodoWriteState,
|
|
42363
42525
|
startTask: () => startTask,
|
|
42364
42526
|
stopTask: () => stopTask
|
|
42365
42527
|
});
|
|
@@ -42380,153 +42542,6 @@ function getUnresolvedDeps(taskId, tasks2) {
|
|
|
42380
42542
|
|
|
42381
42543
|
// packages/core/src/task-work/index.ts
|
|
42382
42544
|
init_handlers();
|
|
42383
|
-
|
|
42384
|
-
// packages/core/src/task-work/todowrite-merge.ts
|
|
42385
|
-
init_src();
|
|
42386
|
-
init_errors3();
|
|
42387
|
-
init_paths();
|
|
42388
|
-
init_data_accessor();
|
|
42389
|
-
init_json2();
|
|
42390
|
-
init_add();
|
|
42391
|
-
init_complete();
|
|
42392
|
-
init_update2();
|
|
42393
|
-
import { readFile as readFile16, rm as rm3, stat as stat2 } from "node:fs/promises";
|
|
42394
|
-
import { join as join96 } from "node:path";
|
|
42395
|
-
function parseTaskId(content) {
|
|
42396
|
-
const match = content.match(/^\[T(\d+)\]/);
|
|
42397
|
-
return match ? `T${match[1]}` : null;
|
|
42398
|
-
}
|
|
42399
|
-
function stripPrefixes(content) {
|
|
42400
|
-
return content.replace(/^\[T\d+\]\s*/, "").replace(/^\[!\]\s*/, "").replace(/^\[BLOCKED\]\s*/, "");
|
|
42401
|
-
}
|
|
42402
|
-
function analyzeChanges(todowriteState, injectedIds) {
|
|
42403
|
-
const foundIds = [];
|
|
42404
|
-
const completed = [];
|
|
42405
|
-
const progressed = [];
|
|
42406
|
-
const newTasks = [];
|
|
42407
|
-
for (const item of todowriteState.todos) {
|
|
42408
|
-
const taskId = parseTaskId(item.content);
|
|
42409
|
-
if (taskId) {
|
|
42410
|
-
foundIds.push(taskId);
|
|
42411
|
-
if (item.status === "completed") {
|
|
42412
|
-
completed.push(taskId);
|
|
42413
|
-
} else if (item.status === "in_progress") {
|
|
42414
|
-
progressed.push(taskId);
|
|
42415
|
-
}
|
|
42416
|
-
} else {
|
|
42417
|
-
const cleanTitle = stripPrefixes(item.content);
|
|
42418
|
-
if (cleanTitle.trim()) {
|
|
42419
|
-
newTasks.push(cleanTitle);
|
|
42420
|
-
}
|
|
42421
|
-
}
|
|
42422
|
-
}
|
|
42423
|
-
const foundSet = new Set(foundIds);
|
|
42424
|
-
const removed = injectedIds.filter((id) => !foundSet.has(id));
|
|
42425
|
-
return { completed, progressed, newTasks, removed };
|
|
42426
|
-
}
|
|
42427
|
-
async function mergeTodoWriteState(options) {
|
|
42428
|
-
const { file, dryRun = false, defaultPhase, cwd } = options;
|
|
42429
|
-
const acc = options.accessor ?? await getAccessor(cwd);
|
|
42430
|
-
try {
|
|
42431
|
-
await stat2(file);
|
|
42432
|
-
} catch {
|
|
42433
|
-
throw new CleoError(4 /* NOT_FOUND */, `File not found: ${file}`);
|
|
42434
|
-
}
|
|
42435
|
-
const content = await readFile16(file, "utf-8");
|
|
42436
|
-
let todowriteState;
|
|
42437
|
-
try {
|
|
42438
|
-
todowriteState = JSON.parse(content);
|
|
42439
|
-
} catch {
|
|
42440
|
-
throw new CleoError(2 /* INVALID_INPUT */, `Invalid JSON in ${file}`);
|
|
42441
|
-
}
|
|
42442
|
-
if (!todowriteState.todos || !Array.isArray(todowriteState.todos)) {
|
|
42443
|
-
throw new CleoError(2 /* INVALID_INPUT */, 'File must contain a "todos" array');
|
|
42444
|
-
}
|
|
42445
|
-
const cleoDir = getCleoDir(cwd);
|
|
42446
|
-
const stateFile = join96(cleoDir, "sync", "todowrite-session.json");
|
|
42447
|
-
let sessionState = null;
|
|
42448
|
-
try {
|
|
42449
|
-
sessionState = await readJson(stateFile);
|
|
42450
|
-
} catch {
|
|
42451
|
-
}
|
|
42452
|
-
const injectedIds = sessionState?.injected_tasks ?? [];
|
|
42453
|
-
const changes = analyzeChanges(todowriteState, injectedIds);
|
|
42454
|
-
const totalChanges = changes.completed.length + changes.progressed.length + changes.newTasks.length;
|
|
42455
|
-
if (totalChanges === 0) {
|
|
42456
|
-
return {
|
|
42457
|
-
dryRun,
|
|
42458
|
-
changes: {
|
|
42459
|
-
completed: 0,
|
|
42460
|
-
progressed: 0,
|
|
42461
|
-
new: 0,
|
|
42462
|
-
removed: changes.removed.length,
|
|
42463
|
-
applied: 0
|
|
42464
|
-
},
|
|
42465
|
-
sessionCleared: false
|
|
42466
|
-
};
|
|
42467
|
-
}
|
|
42468
|
-
let appliedCount = 0;
|
|
42469
|
-
if (!dryRun) {
|
|
42470
|
-
const { tasks: allTasks } = await acc.queryTasks({});
|
|
42471
|
-
for (const taskId of changes.completed) {
|
|
42472
|
-
const task = allTasks.find((t) => t.id === taskId);
|
|
42473
|
-
if (!task) continue;
|
|
42474
|
-
if (task.status === "done") continue;
|
|
42475
|
-
try {
|
|
42476
|
-
await completeTask({ taskId, notes: "Completed via TodoWrite session sync" }, cwd, acc);
|
|
42477
|
-
appliedCount++;
|
|
42478
|
-
} catch {
|
|
42479
|
-
}
|
|
42480
|
-
}
|
|
42481
|
-
for (const taskId of changes.progressed) {
|
|
42482
|
-
const task = allTasks.find((t) => t.id === taskId);
|
|
42483
|
-
if (!task) continue;
|
|
42484
|
-
if (task.status !== "pending" && task.status !== "blocked") continue;
|
|
42485
|
-
try {
|
|
42486
|
-
await updateTask(
|
|
42487
|
-
{ taskId, status: "active", notes: "Progressed during TodoWrite session" },
|
|
42488
|
-
cwd,
|
|
42489
|
-
acc
|
|
42490
|
-
);
|
|
42491
|
-
appliedCount++;
|
|
42492
|
-
} catch {
|
|
42493
|
-
}
|
|
42494
|
-
}
|
|
42495
|
-
for (const title of changes.newTasks) {
|
|
42496
|
-
try {
|
|
42497
|
-
await addTask(
|
|
42498
|
-
{
|
|
42499
|
-
title,
|
|
42500
|
-
description: "Created during TodoWrite session",
|
|
42501
|
-
labels: ["session-created"],
|
|
42502
|
-
...defaultPhase ? { phase: defaultPhase, addPhase: true } : {}
|
|
42503
|
-
},
|
|
42504
|
-
cwd,
|
|
42505
|
-
acc
|
|
42506
|
-
);
|
|
42507
|
-
appliedCount++;
|
|
42508
|
-
} catch {
|
|
42509
|
-
}
|
|
42510
|
-
}
|
|
42511
|
-
try {
|
|
42512
|
-
await rm3(stateFile);
|
|
42513
|
-
} catch {
|
|
42514
|
-
}
|
|
42515
|
-
}
|
|
42516
|
-
return {
|
|
42517
|
-
dryRun,
|
|
42518
|
-
changes: {
|
|
42519
|
-
completed: changes.completed.length,
|
|
42520
|
-
progressed: changes.progressed.length,
|
|
42521
|
-
new: changes.newTasks.length,
|
|
42522
|
-
removed: changes.removed.length,
|
|
42523
|
-
applied: dryRun ? 0 : appliedCount
|
|
42524
|
-
},
|
|
42525
|
-
sessionCleared: !dryRun
|
|
42526
|
-
};
|
|
42527
|
-
}
|
|
42528
|
-
|
|
42529
|
-
// packages/core/src/task-work/index.ts
|
|
42530
42545
|
async function currentTask(cwd, accessor) {
|
|
42531
42546
|
const acc = accessor ?? await getAccessor(cwd);
|
|
42532
42547
|
const focus = await acc.getMetaValue("focus_state");
|
|
@@ -43088,7 +43103,7 @@ __export(templates_exports, {
|
|
|
43088
43103
|
|
|
43089
43104
|
// packages/core/src/templates/parser.ts
|
|
43090
43105
|
import { existsSync as existsSync92, readdirSync as readdirSync29, readFileSync as readFileSync67 } from "fs";
|
|
43091
|
-
import { join as
|
|
43106
|
+
import { join as join95 } from "path";
|
|
43092
43107
|
import { parse as parseYaml } from "yaml";
|
|
43093
43108
|
var SUFFIX_PATTERNS = ["_report", "_request", "_question"];
|
|
43094
43109
|
function deriveSubcommand(filename) {
|
|
@@ -43103,7 +43118,7 @@ function deriveSubcommand(filename) {
|
|
|
43103
43118
|
return firstWord.toLowerCase();
|
|
43104
43119
|
}
|
|
43105
43120
|
function parseTemplateFile2(templateDir, filename) {
|
|
43106
|
-
const filePath =
|
|
43121
|
+
const filePath = join95(templateDir, filename);
|
|
43107
43122
|
const raw = readFileSync67(filePath, "utf-8");
|
|
43108
43123
|
const parsed = parseYaml(raw);
|
|
43109
43124
|
const name2 = typeof parsed.name === "string" ? parsed.name : filename;
|
|
@@ -43153,7 +43168,7 @@ function parseTemplateFile2(templateDir, filename) {
|
|
|
43153
43168
|
};
|
|
43154
43169
|
}
|
|
43155
43170
|
function parseIssueTemplates2(projectRoot) {
|
|
43156
|
-
const templateDir =
|
|
43171
|
+
const templateDir = join95(projectRoot, ".github", "ISSUE_TEMPLATE");
|
|
43157
43172
|
if (!existsSync92(templateDir)) {
|
|
43158
43173
|
return {
|
|
43159
43174
|
success: false,
|
|
@@ -43305,7 +43320,7 @@ __export(ui_exports, {
|
|
|
43305
43320
|
// packages/core/src/ui/aliases.ts
|
|
43306
43321
|
import { existsSync as existsSync93, readFileSync as readFileSync68, writeFileSync as writeFileSync15 } from "node:fs";
|
|
43307
43322
|
import { homedir as homedir5, platform as platform2 } from "node:os";
|
|
43308
|
-
import { join as
|
|
43323
|
+
import { join as join96 } from "node:path";
|
|
43309
43324
|
var MARKER_START = "# CLEO-CLAUDE-ALIASES:START";
|
|
43310
43325
|
var MARKER_END = "# CLEO-CLAUDE-ALIASES:END";
|
|
43311
43326
|
var ALIASES_VERSION = "1.0.0";
|
|
@@ -43327,16 +43342,16 @@ function getRcFilePath(shell) {
|
|
|
43327
43342
|
const sh = shell ?? getCurrentShell();
|
|
43328
43343
|
switch (sh) {
|
|
43329
43344
|
case "bash":
|
|
43330
|
-
return
|
|
43345
|
+
return join96(home, ".bashrc");
|
|
43331
43346
|
case "zsh":
|
|
43332
|
-
return
|
|
43347
|
+
return join96(home, ".zshrc");
|
|
43333
43348
|
case "powershell":
|
|
43334
|
-
return
|
|
43349
|
+
return join96(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
43335
43350
|
case "cmd":
|
|
43336
43351
|
return "";
|
|
43337
43352
|
// CMD doesn't have a standard RC
|
|
43338
43353
|
default:
|
|
43339
|
-
return
|
|
43354
|
+
return join96(home, ".bashrc");
|
|
43340
43355
|
}
|
|
43341
43356
|
}
|
|
43342
43357
|
function detectAvailableShells() {
|
|
@@ -43576,7 +43591,7 @@ ${markdown}`);
|
|
|
43576
43591
|
|
|
43577
43592
|
// packages/core/src/ui/command-registry.ts
|
|
43578
43593
|
import { existsSync as existsSync95, readdirSync as readdirSync30, readFileSync as readFileSync70 } from "node:fs";
|
|
43579
|
-
import { basename as basename16, join as
|
|
43594
|
+
import { basename as basename16, join as join97 } from "node:path";
|
|
43580
43595
|
var CLEO_HEADER_START = "###CLEO";
|
|
43581
43596
|
var CLEO_HEADER_END = "###END";
|
|
43582
43597
|
function parseCommandHeader(scriptPath) {
|
|
@@ -43662,7 +43677,7 @@ function scanAllCommands(scriptsDir) {
|
|
|
43662
43677
|
if (!existsSync95(scriptsDir)) return registry;
|
|
43663
43678
|
for (const file of readdirSync30(scriptsDir)) {
|
|
43664
43679
|
if (!file.endsWith(".sh") && !file.endsWith(".ts")) continue;
|
|
43665
|
-
const meta = parseCommandHeader(
|
|
43680
|
+
const meta = parseCommandHeader(join97(scriptsDir, file));
|
|
43666
43681
|
if (meta) {
|
|
43667
43682
|
registry.set(meta.command, meta);
|
|
43668
43683
|
}
|
|
@@ -44006,7 +44021,7 @@ function calculateOrchestrationOverhead(orchestratorTokens, totalSubagentTokens,
|
|
|
44006
44021
|
|
|
44007
44022
|
// packages/core/src/validation/docs-sync.ts
|
|
44008
44023
|
import { existsSync as existsSync96, readdirSync as readdirSync31, readFileSync as readFileSync71 } from "node:fs";
|
|
44009
|
-
import { join as
|
|
44024
|
+
import { join as join98 } from "node:path";
|
|
44010
44025
|
function getScriptCommands(scriptsDir) {
|
|
44011
44026
|
if (!existsSync96(scriptsDir)) return [];
|
|
44012
44027
|
try {
|
|
@@ -44099,13 +44114,13 @@ var CRITICAL_COMMANDS = [
|
|
|
44099
44114
|
];
|
|
44100
44115
|
function detectDrift(mode = "full", projectRoot = ".") {
|
|
44101
44116
|
const issues = [];
|
|
44102
|
-
const scriptsDir =
|
|
44103
|
-
const indexPath =
|
|
44117
|
+
const scriptsDir = join98(projectRoot, "scripts");
|
|
44118
|
+
const indexPath = join98(projectRoot, "docs/commands/COMMANDS-INDEX.json");
|
|
44104
44119
|
issues.push(...checkCommandsSync(scriptsDir, indexPath));
|
|
44105
|
-
const wrapperPath =
|
|
44120
|
+
const wrapperPath = join98(projectRoot, "installer/lib/link.sh");
|
|
44106
44121
|
issues.push(...checkWrapperSync(wrapperPath, indexPath));
|
|
44107
44122
|
if (mode === "full") {
|
|
44108
|
-
const readmePath =
|
|
44123
|
+
const readmePath = join98(projectRoot, "README.md");
|
|
44109
44124
|
if (existsSync96(readmePath)) {
|
|
44110
44125
|
try {
|
|
44111
44126
|
const readme = readFileSync71(readmePath, "utf-8");
|
|
@@ -44143,13 +44158,13 @@ function shouldRunDriftDetection(enabled = true, autoCheck = false, command, cri
|
|
|
44143
44158
|
init_paths();
|
|
44144
44159
|
import { createHash as createHash10 } from "node:crypto";
|
|
44145
44160
|
import { existsSync as existsSync97, mkdirSync as mkdirSync21, readFileSync as readFileSync72, unlinkSync as unlinkSync7, writeFileSync as writeFileSync17 } from "node:fs";
|
|
44146
|
-
import { dirname as dirname17, join as
|
|
44161
|
+
import { dirname as dirname17, join as join99 } from "node:path";
|
|
44147
44162
|
var CACHE_VERSION = "1.0.0";
|
|
44148
44163
|
var CACHE_TTL_SECONDS = 300;
|
|
44149
44164
|
var CACHE_FILE2 = "doctor-project-cache.json";
|
|
44150
44165
|
function getCacheFilePath(cleoHome) {
|
|
44151
44166
|
const home = cleoHome ?? getCleoHome();
|
|
44152
|
-
return
|
|
44167
|
+
return join99(home, CACHE_FILE2);
|
|
44153
44168
|
}
|
|
44154
44169
|
function initCacheFile(cacheFile) {
|
|
44155
44170
|
const cache = {
|
|
@@ -44193,8 +44208,8 @@ function getCachedValidation(projectHash, projectPath, cacheFile) {
|
|
|
44193
44208
|
const now = Date.now();
|
|
44194
44209
|
const age = (now - lastValidated) / 1e3;
|
|
44195
44210
|
if (age > (entry.ttl || CACHE_TTL_SECONDS)) return null;
|
|
44196
|
-
const currentTasksDbHash = getFileHash(
|
|
44197
|
-
const currentConfigHash = getFileHash(
|
|
44211
|
+
const currentTasksDbHash = getFileHash(join99(projectPath, ".cleo", "tasks.db"));
|
|
44212
|
+
const currentConfigHash = getFileHash(join99(projectPath, ".cleo", "config.json"));
|
|
44198
44213
|
if (currentTasksDbHash !== (entry.fileHashes["tasks.db"] ?? "")) return null;
|
|
44199
44214
|
if (currentConfigHash !== (entry.fileHashes["config.json"] ?? "")) return null;
|
|
44200
44215
|
return entry;
|
|
@@ -44205,8 +44220,8 @@ function cacheValidationResult(projectHash, projectPath, validationStatus, issue
|
|
|
44205
44220
|
if (!cache) {
|
|
44206
44221
|
cache = initCacheFile(cachePath);
|
|
44207
44222
|
}
|
|
44208
|
-
const tasksDbHash = getFileHash(
|
|
44209
|
-
const configHash = getFileHash(
|
|
44223
|
+
const tasksDbHash = getFileHash(join99(projectPath, ".cleo", "tasks.db"));
|
|
44224
|
+
const configHash = getFileHash(join99(projectPath, ".cleo", "config.json"));
|
|
44210
44225
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
44211
44226
|
cache.projects[projectHash] = {
|
|
44212
44227
|
path: projectPath,
|
|
@@ -45204,7 +45219,7 @@ function formatGapReport(report) {
|
|
|
45204
45219
|
// packages/core/src/validation/manifest.ts
|
|
45205
45220
|
init_paths();
|
|
45206
45221
|
import { existsSync as existsSync98 } from "node:fs";
|
|
45207
|
-
import { appendFile as appendFile3, mkdir as
|
|
45222
|
+
import { appendFile as appendFile3, mkdir as mkdir15, readFile as readFile16 } from "node:fs/promises";
|
|
45208
45223
|
import { dirname as dirname18 } from "node:path";
|
|
45209
45224
|
var DEFAULT_MANIFEST_PATH = ".cleo/agent-outputs/MANIFEST.jsonl";
|
|
45210
45225
|
var DEFAULT_COMPLIANCE_PATH = ".cleo/metrics/COMPLIANCE.jsonl";
|
|
@@ -45217,7 +45232,7 @@ async function findManifestEntry(taskId, manifestPath) {
|
|
|
45217
45232
|
}
|
|
45218
45233
|
}
|
|
45219
45234
|
if (!existsSync98(manifestPath)) return null;
|
|
45220
|
-
const content = await
|
|
45235
|
+
const content = await readFile16(manifestPath, "utf-8");
|
|
45221
45236
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
45222
45237
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
45223
45238
|
const line2 = lines[i];
|
|
@@ -45329,7 +45344,7 @@ async function validateManifestEntry(taskId, manifestEntry, manifestPath = DEFAU
|
|
|
45329
45344
|
}
|
|
45330
45345
|
async function logRealCompliance(taskId, validationResult, agentType = "unknown", compliancePath = DEFAULT_COMPLIANCE_PATH) {
|
|
45331
45346
|
const metricsDir = dirname18(compliancePath);
|
|
45332
|
-
await
|
|
45347
|
+
await mkdir15(metricsDir, { recursive: true });
|
|
45333
45348
|
const { score, pass, violations } = validationResult;
|
|
45334
45349
|
const violationCount = violations.length;
|
|
45335
45350
|
let severity = "none";
|
|
@@ -46124,25 +46139,25 @@ init_hooks();
|
|
|
46124
46139
|
init_injection();
|
|
46125
46140
|
init_memory_bridge();
|
|
46126
46141
|
import { existsSync as existsSync100, readdirSync as readdirSync33, readFileSync as readFileSync74 } from "node:fs";
|
|
46127
|
-
import { copyFile as copyFile3, lstat, mkdir as
|
|
46128
|
-
import { basename as basename17, dirname as dirname19, join as
|
|
46142
|
+
import { copyFile as copyFile3, lstat, mkdir as mkdir16, readFile as readFile17, symlink, unlink as unlink4, writeFile as writeFile11 } from "node:fs/promises";
|
|
46143
|
+
import { basename as basename17, dirname as dirname19, join as join100 } from "node:path";
|
|
46129
46144
|
init_paths();
|
|
46130
46145
|
init_scaffold();
|
|
46131
46146
|
init_schema_management();
|
|
46132
46147
|
init_json2();
|
|
46133
46148
|
async function initAgentDefinition(created, warnings) {
|
|
46134
46149
|
const packageRoot = getPackageRoot();
|
|
46135
|
-
const agentSourceDir =
|
|
46150
|
+
const agentSourceDir = join100(packageRoot, "agents", "cleo-subagent");
|
|
46136
46151
|
if (!existsSync100(agentSourceDir)) {
|
|
46137
46152
|
warnings.push("agents/cleo-subagent/ not found in package, skipping agent definition install");
|
|
46138
46153
|
return;
|
|
46139
46154
|
}
|
|
46140
|
-
const globalAgentsDir =
|
|
46141
|
-
await
|
|
46155
|
+
const globalAgentsDir = join100(getAgentsHome(), "agents", "cleo-subagent");
|
|
46156
|
+
await mkdir16(dirname19(globalAgentsDir), { recursive: true });
|
|
46142
46157
|
try {
|
|
46143
46158
|
try {
|
|
46144
|
-
const
|
|
46145
|
-
if (
|
|
46159
|
+
const stat2 = await lstat(globalAgentsDir);
|
|
46160
|
+
if (stat2.isSymbolicLink() || stat2.isDirectory()) {
|
|
46146
46161
|
return;
|
|
46147
46162
|
}
|
|
46148
46163
|
} catch {
|
|
@@ -46151,10 +46166,10 @@ async function initAgentDefinition(created, warnings) {
|
|
|
46151
46166
|
created.push("agent: cleo-subagent (symlinked)");
|
|
46152
46167
|
} catch (_err) {
|
|
46153
46168
|
try {
|
|
46154
|
-
await
|
|
46169
|
+
await mkdir16(globalAgentsDir, { recursive: true });
|
|
46155
46170
|
const files = readdirSync33(agentSourceDir);
|
|
46156
46171
|
for (const file of files) {
|
|
46157
|
-
await copyFile3(
|
|
46172
|
+
await copyFile3(join100(agentSourceDir, file), join100(globalAgentsDir, file));
|
|
46158
46173
|
}
|
|
46159
46174
|
created.push("agent: cleo-subagent (copied)");
|
|
46160
46175
|
} catch (copyErr) {
|
|
@@ -46174,12 +46189,12 @@ async function initCoreSkills(created, warnings) {
|
|
|
46174
46189
|
const packageRoot = getPackageRoot();
|
|
46175
46190
|
let ctSkillsRoot = null;
|
|
46176
46191
|
try {
|
|
46177
|
-
const bundledPath =
|
|
46178
|
-
if (existsSync100(
|
|
46192
|
+
const bundledPath = join100(packageRoot, "packages", "skills");
|
|
46193
|
+
if (existsSync100(join100(bundledPath, "skills.json"))) {
|
|
46179
46194
|
ctSkillsRoot = bundledPath;
|
|
46180
46195
|
} else {
|
|
46181
|
-
const ctSkillsPath =
|
|
46182
|
-
if (existsSync100(
|
|
46196
|
+
const ctSkillsPath = join100(packageRoot, "node_modules", "@cleocode", "skills");
|
|
46197
|
+
if (existsSync100(join100(ctSkillsPath, "skills.json"))) {
|
|
46183
46198
|
ctSkillsRoot = ctSkillsPath;
|
|
46184
46199
|
}
|
|
46185
46200
|
}
|
|
@@ -46194,13 +46209,13 @@ async function initCoreSkills(created, warnings) {
|
|
|
46194
46209
|
} catch {
|
|
46195
46210
|
warnings.push("Failed to register skill library with CAAMP");
|
|
46196
46211
|
}
|
|
46197
|
-
const catalogPath =
|
|
46212
|
+
const catalogPath = join100(ctSkillsRoot, "skills.json");
|
|
46198
46213
|
const catalog3 = JSON.parse(readFileSync74(catalogPath, "utf-8"));
|
|
46199
46214
|
const skills = catalog3.skills ?? [];
|
|
46200
46215
|
const coreSkills = skills.filter((s) => s.tier <= 2);
|
|
46201
46216
|
const installed = [];
|
|
46202
46217
|
for (const skill of coreSkills) {
|
|
46203
|
-
const skillSourceDir = dirname19(
|
|
46218
|
+
const skillSourceDir = dirname19(join100(ctSkillsRoot, skill.path));
|
|
46204
46219
|
if (!existsSync100(skillSourceDir)) {
|
|
46205
46220
|
continue;
|
|
46206
46221
|
}
|
|
@@ -46244,33 +46259,33 @@ async function initNexusRegistration(projectRoot, created, warnings) {
|
|
|
46244
46259
|
}
|
|
46245
46260
|
}
|
|
46246
46261
|
async function installGitHubTemplates(projectRoot, created, skipped) {
|
|
46247
|
-
if (!existsSync100(
|
|
46262
|
+
if (!existsSync100(join100(projectRoot, ".git"))) {
|
|
46248
46263
|
return;
|
|
46249
46264
|
}
|
|
46250
|
-
const githubDir =
|
|
46251
|
-
const issueTemplateDir =
|
|
46265
|
+
const githubDir = join100(projectRoot, ".github");
|
|
46266
|
+
const issueTemplateDir = join100(githubDir, "ISSUE_TEMPLATE");
|
|
46252
46267
|
const packageRoot = getPackageRoot();
|
|
46253
|
-
const templateSrcDir =
|
|
46268
|
+
const templateSrcDir = join100(packageRoot, "templates", "github");
|
|
46254
46269
|
if (!existsSync100(templateSrcDir)) {
|
|
46255
46270
|
return;
|
|
46256
46271
|
}
|
|
46257
|
-
await
|
|
46258
|
-
const issueSrcDir =
|
|
46272
|
+
await mkdir16(issueTemplateDir, { recursive: true });
|
|
46273
|
+
const issueSrcDir = join100(templateSrcDir, "ISSUE_TEMPLATE");
|
|
46259
46274
|
if (existsSync100(issueSrcDir)) {
|
|
46260
46275
|
const issueFiles = readdirSync33(issueSrcDir);
|
|
46261
46276
|
for (const file of issueFiles) {
|
|
46262
|
-
const dest =
|
|
46277
|
+
const dest = join100(issueTemplateDir, file);
|
|
46263
46278
|
if (existsSync100(dest)) {
|
|
46264
46279
|
skipped.push(`.github/ISSUE_TEMPLATE/${file}`);
|
|
46265
46280
|
continue;
|
|
46266
46281
|
}
|
|
46267
|
-
const content = readFileSync74(
|
|
46282
|
+
const content = readFileSync74(join100(issueSrcDir, file), "utf-8");
|
|
46268
46283
|
await writeFile11(dest, content, "utf-8");
|
|
46269
46284
|
created.push(`.github/ISSUE_TEMPLATE/${file}`);
|
|
46270
46285
|
}
|
|
46271
46286
|
}
|
|
46272
|
-
const prTemplateSrc =
|
|
46273
|
-
const prTemplateDest =
|
|
46287
|
+
const prTemplateSrc = join100(templateSrcDir, "pull_request_template.md");
|
|
46288
|
+
const prTemplateDest = join100(githubDir, "pull_request_template.md");
|
|
46274
46289
|
if (existsSync100(prTemplateSrc)) {
|
|
46275
46290
|
if (existsSync100(prTemplateDest)) {
|
|
46276
46291
|
skipped.push(".github/pull_request_template.md");
|
|
@@ -46309,7 +46324,7 @@ async function initProject(opts = {}) {
|
|
|
46309
46324
|
}
|
|
46310
46325
|
const cleoDir = getCleoDirAbsolute();
|
|
46311
46326
|
const projRoot = getProjectRoot();
|
|
46312
|
-
const alreadyInitialized = existsSync100(cleoDir) && (existsSync100(
|
|
46327
|
+
const alreadyInitialized = existsSync100(cleoDir) && (existsSync100(join100(cleoDir, "tasks.db")) || existsSync100(join100(cleoDir, "config.json")));
|
|
46313
46328
|
if (alreadyInitialized && !opts.force) {
|
|
46314
46329
|
throw new CleoError(
|
|
46315
46330
|
1 /* GENERAL_ERROR */,
|
|
@@ -46333,7 +46348,7 @@ async function initProject(opts = {}) {
|
|
|
46333
46348
|
}
|
|
46334
46349
|
try {
|
|
46335
46350
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
46336
|
-
await getDb3(
|
|
46351
|
+
await getDb3(join100(cleoDir, ".."));
|
|
46337
46352
|
created.push("tasks.db");
|
|
46338
46353
|
} catch (err) {
|
|
46339
46354
|
created.push(`tasks.db (deferred: ${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -46354,7 +46369,7 @@ async function initProject(opts = {}) {
|
|
|
46354
46369
|
created.push(".gitignore");
|
|
46355
46370
|
}
|
|
46356
46371
|
} else {
|
|
46357
|
-
const gitignorePath =
|
|
46372
|
+
const gitignorePath = join100(cleoDir, ".gitignore");
|
|
46358
46373
|
if (existsSync100(gitignorePath)) {
|
|
46359
46374
|
skipped.push(".gitignore");
|
|
46360
46375
|
} else {
|
|
@@ -46366,12 +46381,12 @@ async function initProject(opts = {}) {
|
|
|
46366
46381
|
}
|
|
46367
46382
|
}
|
|
46368
46383
|
}
|
|
46369
|
-
const legacySequencePath =
|
|
46384
|
+
const legacySequencePath = join100(cleoDir, ".sequence");
|
|
46370
46385
|
try {
|
|
46371
46386
|
await unlink4(legacySequencePath);
|
|
46372
46387
|
} catch {
|
|
46373
46388
|
}
|
|
46374
|
-
const legacySequenceJsonPath =
|
|
46389
|
+
const legacySequenceJsonPath = join100(cleoDir, ".sequence.json");
|
|
46375
46390
|
try {
|
|
46376
46391
|
await unlink4(legacySequenceJsonPath);
|
|
46377
46392
|
} catch {
|
|
@@ -46533,8 +46548,8 @@ function isAutoInitEnabled() {
|
|
|
46533
46548
|
}
|
|
46534
46549
|
async function ensureInitialized(projectRoot) {
|
|
46535
46550
|
const root = projectRoot ?? getProjectRoot();
|
|
46536
|
-
const cleoDir =
|
|
46537
|
-
const isInit = existsSync100(cleoDir) && (existsSync100(
|
|
46551
|
+
const cleoDir = join100(root, ".cleo");
|
|
46552
|
+
const isInit = existsSync100(cleoDir) && (existsSync100(join100(cleoDir, "tasks.db")) || existsSync100(join100(cleoDir, "config.json")));
|
|
46538
46553
|
if (isInit) {
|
|
46539
46554
|
return { initialized: true };
|
|
46540
46555
|
}
|
|
@@ -46546,10 +46561,10 @@ async function ensureInitialized(projectRoot) {
|
|
|
46546
46561
|
}
|
|
46547
46562
|
async function getVersion2(projectRoot) {
|
|
46548
46563
|
const root = projectRoot ?? getProjectRoot();
|
|
46549
|
-
const versionPaths = [
|
|
46564
|
+
const versionPaths = [join100(root, "VERSION"), join100(root, "..", "VERSION")];
|
|
46550
46565
|
for (const versionPath of versionPaths) {
|
|
46551
46566
|
try {
|
|
46552
|
-
const content = await
|
|
46567
|
+
const content = await readFile17(versionPath, "utf-8");
|
|
46553
46568
|
const version = content.trim();
|
|
46554
46569
|
if (version) {
|
|
46555
46570
|
return { version };
|
|
@@ -46557,7 +46572,7 @@ async function getVersion2(projectRoot) {
|
|
|
46557
46572
|
} catch {
|
|
46558
46573
|
}
|
|
46559
46574
|
}
|
|
46560
|
-
const pkg = await readJson(
|
|
46575
|
+
const pkg = await readJson(join100(root, "package.json"));
|
|
46561
46576
|
if (pkg?.version) {
|
|
46562
46577
|
return { version: pkg.version };
|
|
46563
46578
|
}
|
|
@@ -46570,15 +46585,15 @@ init_logger();
|
|
|
46570
46585
|
|
|
46571
46586
|
// packages/core/src/output.ts
|
|
46572
46587
|
init_errors3();
|
|
46573
|
-
import { randomUUID as
|
|
46588
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
46574
46589
|
|
|
46575
46590
|
// packages/core/src/sessions/context-alert.ts
|
|
46576
46591
|
init_paths();
|
|
46577
46592
|
import { existsSync as existsSync101, readFileSync as readFileSync75, writeFileSync as writeFileSync18 } from "node:fs";
|
|
46578
|
-
import { join as
|
|
46593
|
+
import { join as join101 } from "node:path";
|
|
46579
46594
|
function getCurrentSessionId(cwd) {
|
|
46580
46595
|
if (process.env.CLEO_SESSION) return process.env.CLEO_SESSION;
|
|
46581
|
-
const sessionFile =
|
|
46596
|
+
const sessionFile = join101(getCleoDir(cwd), ".current-session");
|
|
46582
46597
|
if (existsSync101(sessionFile)) {
|
|
46583
46598
|
return readFileSync75(sessionFile, "utf-8").trim() || null;
|
|
46584
46599
|
}
|
|
@@ -46603,7 +46618,7 @@ function createCliMeta(operation, mvi = "standard") {
|
|
|
46603
46618
|
schemaVersion: "2026.2.1",
|
|
46604
46619
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
46605
46620
|
operation,
|
|
46606
|
-
requestId:
|
|
46621
|
+
requestId: randomUUID5(),
|
|
46607
46622
|
transport: "cli",
|
|
46608
46623
|
strict: true,
|
|
46609
46624
|
mvi,
|
|
@@ -46656,13 +46671,13 @@ init_paths();
|
|
|
46656
46671
|
// packages/core/src/project-info.ts
|
|
46657
46672
|
init_paths();
|
|
46658
46673
|
import { existsSync as existsSync102, readFileSync as readFileSync76 } from "node:fs";
|
|
46659
|
-
import { readFile as
|
|
46660
|
-
import { join as
|
|
46674
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
46675
|
+
import { join as join102 } from "node:path";
|
|
46661
46676
|
async function getProjectInfo(cwd) {
|
|
46662
46677
|
const projectRoot = cwd ?? process.cwd();
|
|
46663
46678
|
const cleoDir = getCleoDirAbsolute(projectRoot);
|
|
46664
|
-
const infoPath =
|
|
46665
|
-
const raw = await
|
|
46679
|
+
const infoPath = join102(cleoDir, "project-info.json");
|
|
46680
|
+
const raw = await readFile18(infoPath, "utf-8");
|
|
46666
46681
|
const data = JSON.parse(raw);
|
|
46667
46682
|
if (typeof data.projectHash !== "string" || data.projectHash.length === 0) {
|
|
46668
46683
|
throw new Error(`project-info.json missing required field: projectHash`);
|
|
@@ -46679,7 +46694,7 @@ async function getProjectInfo(cwd) {
|
|
|
46679
46694
|
function getProjectInfoSync(cwd) {
|
|
46680
46695
|
const projectRoot = cwd ?? process.cwd();
|
|
46681
46696
|
const cleoDir = getCleoDirAbsolute(projectRoot);
|
|
46682
|
-
const infoPath =
|
|
46697
|
+
const infoPath = join102(cleoDir, "project-info.json");
|
|
46683
46698
|
if (!existsSync102(infoPath)) return null;
|
|
46684
46699
|
try {
|
|
46685
46700
|
const raw = readFileSync76(infoPath, "utf-8");
|
|
@@ -46940,9 +46955,9 @@ var Cleo = class _Cleo {
|
|
|
46940
46955
|
},
|
|
46941
46956
|
store
|
|
46942
46957
|
),
|
|
46943
|
-
|
|
46944
|
-
|
|
46945
|
-
|
|
46958
|
+
getLinks: (providerId) => getLinksByProvider(providerId, root),
|
|
46959
|
+
getTaskLinks: (taskId) => getLinksByTaskId(taskId, root),
|
|
46960
|
+
removeProviderLinks: (providerId) => removeLinksByProvider(providerId, root)
|
|
46946
46961
|
};
|
|
46947
46962
|
}
|
|
46948
46963
|
};
|