@cleocode/core 2026.4.48 → 2026.4.49
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.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +730 -362
- package/dist/index.js.map +4 -4
- package/dist/internal.d.ts +4 -2
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1061 -683
- package/dist/internal.js.map +4 -4
- package/dist/nexus/index.d.ts +1 -1
- package/dist/nexus/index.d.ts.map +1 -1
- package/dist/nexus/registry.d.ts +25 -0
- package/dist/nexus/registry.d.ts.map +1 -1
- package/dist/store/nexus-schema.d.ts +64 -0
- package/dist/store/nexus-schema.d.ts.map +1 -1
- package/dist/store/nexus-validation-schemas.d.ts +128 -0
- package/dist/store/nexus-validation-schemas.d.ts.map +1 -1
- package/dist/telemetry/index.d.ts +107 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/schema.d.ts +228 -0
- package/dist/telemetry/schema.d.ts.map +1 -0
- package/dist/telemetry/sqlite.d.ts +33 -0
- package/dist/telemetry/sqlite.d.ts.map +1 -0
- package/migrations/drizzle-telemetry/20260415000001_t624-initial/migration.sql +23 -0
- package/migrations/drizzle-telemetry/20260415000001_t624-initial/snapshot.json +35 -0
- package/package.json +8 -8
- package/src/__tests__/telemetry.test.ts +221 -0
- package/src/index.ts +1 -0
- package/src/internal.ts +20 -1
- package/src/nexus/index.ts +2 -0
- package/src/nexus/registry.ts +103 -1
- package/src/store/nexus-schema.ts +9 -0
- package/src/telemetry/index.ts +341 -0
- package/src/telemetry/schema.ts +68 -0
- package/src/telemetry/sqlite.ts +140 -0
package/dist/index.js
CHANGED
|
@@ -730,15 +730,15 @@ function getLogDir() {
|
|
|
730
730
|
return currentLogDir;
|
|
731
731
|
}
|
|
732
732
|
function closeLogger() {
|
|
733
|
-
return new Promise((
|
|
733
|
+
return new Promise((resolve12) => {
|
|
734
734
|
if (rootLogger) {
|
|
735
735
|
rootLogger.flush(() => {
|
|
736
736
|
rootLogger = null;
|
|
737
737
|
currentLogDir = null;
|
|
738
|
-
|
|
738
|
+
resolve12();
|
|
739
739
|
});
|
|
740
740
|
} else {
|
|
741
|
-
|
|
741
|
+
resolve12();
|
|
742
742
|
}
|
|
743
743
|
});
|
|
744
744
|
}
|
|
@@ -1546,10 +1546,10 @@ var init_subquery = __esm({
|
|
|
1546
1546
|
init_entity();
|
|
1547
1547
|
Subquery = class {
|
|
1548
1548
|
static [entityKind] = "Subquery";
|
|
1549
|
-
constructor(
|
|
1549
|
+
constructor(sql14, fields, alias, isWith = false, usedTables = []) {
|
|
1550
1550
|
this._ = {
|
|
1551
1551
|
brand: "Subquery",
|
|
1552
|
-
sql:
|
|
1552
|
+
sql: sql14,
|
|
1553
1553
|
selectedFields: fields,
|
|
1554
1554
|
alias,
|
|
1555
1555
|
isWith,
|
|
@@ -1900,7 +1900,7 @@ var init_sql = __esm({
|
|
|
1900
1900
|
return new SQL([new StringChunk(str)]);
|
|
1901
1901
|
}
|
|
1902
1902
|
_sql.raw = raw;
|
|
1903
|
-
function
|
|
1903
|
+
function join109(chunks, separator) {
|
|
1904
1904
|
const result = [];
|
|
1905
1905
|
for (const [i, chunk] of chunks.entries()) {
|
|
1906
1906
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -1908,7 +1908,7 @@ var init_sql = __esm({
|
|
|
1908
1908
|
}
|
|
1909
1909
|
return new SQL(result);
|
|
1910
1910
|
}
|
|
1911
|
-
_sql.join =
|
|
1911
|
+
_sql.join = join109;
|
|
1912
1912
|
function identifier(value) {
|
|
1913
1913
|
return new Name(value);
|
|
1914
1914
|
}
|
|
@@ -1929,8 +1929,8 @@ var init_sql = __esm({
|
|
|
1929
1929
|
isSelectionField = false;
|
|
1930
1930
|
/** @internal */
|
|
1931
1931
|
origin;
|
|
1932
|
-
constructor(
|
|
1933
|
-
this.sql =
|
|
1932
|
+
constructor(sql14, fieldAlias) {
|
|
1933
|
+
this.sql = sql14;
|
|
1934
1934
|
this.fieldAlias = fieldAlias;
|
|
1935
1935
|
}
|
|
1936
1936
|
getSQL() {
|
|
@@ -2634,17 +2634,17 @@ var init_custom = __esm({
|
|
|
2634
2634
|
mapFromJsonValue(value) {
|
|
2635
2635
|
return typeof this.mapJson === "function" ? this.mapJson(value) : this.mapFromDriverValue(value);
|
|
2636
2636
|
}
|
|
2637
|
-
jsonSelectIdentifier(identifier,
|
|
2638
|
-
if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier,
|
|
2637
|
+
jsonSelectIdentifier(identifier, sql14) {
|
|
2638
|
+
if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier, sql14);
|
|
2639
2639
|
const rawType = this.getSQLType().toLowerCase();
|
|
2640
2640
|
const parenPos = rawType.indexOf("(");
|
|
2641
2641
|
switch (parenPos + 1 ? rawType.slice(0, parenPos) : rawType) {
|
|
2642
2642
|
case "numeric":
|
|
2643
2643
|
case "decimal":
|
|
2644
2644
|
case "bigint":
|
|
2645
|
-
return
|
|
2645
|
+
return sql14`cast(${identifier} as text)`;
|
|
2646
2646
|
case "blob":
|
|
2647
|
-
return
|
|
2647
|
+
return sql14`hex(${identifier})`;
|
|
2648
2648
|
default:
|
|
2649
2649
|
return identifier;
|
|
2650
2650
|
}
|
|
@@ -3812,8 +3812,8 @@ var init_custom2 = __esm({
|
|
|
3812
3812
|
mapFromJsonValue(value) {
|
|
3813
3813
|
return typeof this.mapJson === "function" ? this.mapJson(value) : this.mapFromDriverValue(value);
|
|
3814
3814
|
}
|
|
3815
|
-
jsonSelectIdentifier(identifier,
|
|
3816
|
-
if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier,
|
|
3815
|
+
jsonSelectIdentifier(identifier, sql14, arrayDimensions) {
|
|
3816
|
+
if (typeof this.forJsonSelect === "function") return this.forJsonSelect(identifier, sql14, arrayDimensions);
|
|
3817
3817
|
const rawType = this.getSQLType().toLowerCase();
|
|
3818
3818
|
const parenPos = rawType.indexOf("(");
|
|
3819
3819
|
switch (parenPos + 1 ? rawType.slice(0, parenPos) : rawType) {
|
|
@@ -3823,7 +3823,7 @@ var init_custom2 = __esm({
|
|
|
3823
3823
|
case "numeric":
|
|
3824
3824
|
case "bigint": {
|
|
3825
3825
|
const arrVal = "[]".repeat(arrayDimensions ?? 0);
|
|
3826
|
-
return
|
|
3826
|
+
return sql14`${identifier}::text${sql14.raw(arrVal).if(arrayDimensions)}`;
|
|
3827
3827
|
}
|
|
3828
3828
|
default:
|
|
3829
3829
|
return identifier;
|
|
@@ -6682,7 +6682,7 @@ var init_select2 = __esm({
|
|
|
6682
6682
|
const baseTableName = this.tableName;
|
|
6683
6683
|
const tableName = getTableLikeName(table);
|
|
6684
6684
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
6685
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
6685
|
+
if (typeof tableName === "string" && this.config.joins?.some((join109) => join109.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
6686
6686
|
if (!this.isPartialSelect) {
|
|
6687
6687
|
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
|
|
6688
6688
|
if (typeof tableName === "string" && !is(table, SQL)) {
|
|
@@ -7704,8 +7704,8 @@ var init_dialect = __esm({
|
|
|
7704
7704
|
const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
|
|
7705
7705
|
return sql`${withSql}insert into ${table} ${insertOrder} ${valuesSql}${onConflict?.length ? sql.join(onConflict) : void 0}${returningSql}`;
|
|
7706
7706
|
}
|
|
7707
|
-
sqlToQuery(
|
|
7708
|
-
return
|
|
7707
|
+
sqlToQuery(sql14, invokeSource) {
|
|
7708
|
+
return sql14.toQuery({
|
|
7709
7709
|
casing: this.casing,
|
|
7710
7710
|
escapeName: this.escapeName,
|
|
7711
7711
|
escapeParam: this.escapeParam,
|
|
@@ -7967,7 +7967,7 @@ var init_dialect = __esm({
|
|
|
7967
7967
|
if (!joins2) return;
|
|
7968
7968
|
const withEntries = Object.entries(joins2).filter(([_, v]) => v);
|
|
7969
7969
|
if (!withEntries.length) return;
|
|
7970
|
-
return sql.join(withEntries.map(([k,
|
|
7970
|
+
return sql.join(withEntries.map(([k, join109]) => {
|
|
7971
7971
|
const relation = tableConfig.relations[k];
|
|
7972
7972
|
const isSingle2 = is(relation, One3);
|
|
7973
7973
|
const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
|
|
@@ -7978,7 +7978,7 @@ var init_dialect = __esm({
|
|
|
7978
7978
|
table: targetTable,
|
|
7979
7979
|
mode: isSingle2 ? "first" : "many",
|
|
7980
7980
|
schema,
|
|
7981
|
-
queryConfig:
|
|
7981
|
+
queryConfig: join109,
|
|
7982
7982
|
tableConfig: schema[relation.targetTableName],
|
|
7983
7983
|
relationWhere: filter,
|
|
7984
7984
|
isNested: true,
|
|
@@ -7992,7 +7992,7 @@ var init_dialect = __esm({
|
|
|
7992
7992
|
key: k,
|
|
7993
7993
|
selection: innerQuery.selection,
|
|
7994
7994
|
isArray: !isSingle2,
|
|
7995
|
-
isOptional: (relation.optional ?? false) ||
|
|
7995
|
+
isOptional: (relation.optional ?? false) || join109 !== true && !!join109.where
|
|
7996
7996
|
});
|
|
7997
7997
|
const jsonColumns = sql.join(innerQuery.selection.map((s) => {
|
|
7998
7998
|
return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb2}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
|
|
@@ -8391,7 +8391,7 @@ var init_update = __esm({
|
|
|
8391
8391
|
createJoin(joinType) {
|
|
8392
8392
|
return ((table, on) => {
|
|
8393
8393
|
const tableName = getTableLikeName(table);
|
|
8394
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
8394
|
+
if (typeof tableName === "string" && this.config.joins.some((join109) => join109.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
8395
8395
|
if (typeof on === "function") {
|
|
8396
8396
|
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;
|
|
8397
8397
|
on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
|
|
@@ -8802,8 +8802,8 @@ var init_db = __esm({
|
|
|
8802
8802
|
});
|
|
8803
8803
|
|
|
8804
8804
|
// node_modules/.pnpm/drizzle-orm@1.0.0-beta.19-d95b7a4_@sinclair+typebox@0.34.49_@types+mssql@9.1.9_@azure+c_7d603f9dc53f6bedf2f8e8db5954b691/node_modules/drizzle-orm/cache/core/cache.js
|
|
8805
|
-
async function hashQuery(
|
|
8806
|
-
const dataToHash = `${
|
|
8805
|
+
async function hashQuery(sql14, params) {
|
|
8806
|
+
const dataToHash = `${sql14}-${JSON.stringify(params, (_, v) => typeof v === "bigint" ? `${v}n` : v)}`;
|
|
8807
8807
|
const data = new TextEncoder().encode(dataToHash);
|
|
8808
8808
|
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
8809
8809
|
return [...new Uint8Array(hashBuffer)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
@@ -8982,8 +8982,8 @@ var init_session3 = __esm({
|
|
|
8982
8982
|
values(query) {
|
|
8983
8983
|
return this.prepareOneTimeQuery(this.dialect.sqlToQuery(query), void 0, "run", false).values();
|
|
8984
8984
|
}
|
|
8985
|
-
async count(
|
|
8986
|
-
return (await this.values(
|
|
8985
|
+
async count(sql14) {
|
|
8986
|
+
return (await this.values(sql14))[0][0];
|
|
8987
8987
|
}
|
|
8988
8988
|
/** @internal */
|
|
8989
8989
|
extractRawValuesValueFromBatchResult(_result) {
|
|
@@ -11670,12 +11670,12 @@ function detachAgentFromProject(db, agentId) {
|
|
|
11670
11670
|
}
|
|
11671
11671
|
function listProjectAgentRefs(db, opts) {
|
|
11672
11672
|
const enabledOnly = opts?.enabledOnly ?? true;
|
|
11673
|
-
const
|
|
11673
|
+
const sql14 = enabledOnly ? `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
|
|
11674
11674
|
FROM project_agent_refs WHERE enabled = 1
|
|
11675
11675
|
ORDER BY attached_at DESC` : `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
|
|
11676
11676
|
FROM project_agent_refs
|
|
11677
11677
|
ORDER BY attached_at DESC`;
|
|
11678
|
-
const rows = db.prepare(
|
|
11678
|
+
const rows = db.prepare(sql14).all();
|
|
11679
11679
|
return rows.map((r) => ({
|
|
11680
11680
|
agentId: r.agent_id,
|
|
11681
11681
|
attachedAt: r.attached_at,
|
|
@@ -12020,12 +12020,21 @@ var init_nexus_schema = __esm({
|
|
|
12020
12020
|
permissions: text("permissions").notNull().default("read"),
|
|
12021
12021
|
lastSync: text("last_sync").notNull().default(sql3`(datetime('now'))`),
|
|
12022
12022
|
taskCount: integer("task_count").notNull().default(0),
|
|
12023
|
-
labelsJson: text("labels_json").notNull().default("[]")
|
|
12023
|
+
labelsJson: text("labels_json").notNull().default("[]"),
|
|
12024
|
+
/** Absolute path to the project's brain.db file. */
|
|
12025
|
+
brainDbPath: text("brain_db_path"),
|
|
12026
|
+
/** Absolute path to the project's tasks.db file. */
|
|
12027
|
+
tasksDbPath: text("tasks_db_path"),
|
|
12028
|
+
/** ISO 8601 timestamp of the last successful code intelligence index run. */
|
|
12029
|
+
lastIndexed: text("last_indexed"),
|
|
12030
|
+
/** JSON object with per-project code intelligence stats (node_count, relation_count, file_count). */
|
|
12031
|
+
statsJson: text("stats_json").notNull().default("{}")
|
|
12024
12032
|
},
|
|
12025
12033
|
(table) => [
|
|
12026
12034
|
index("idx_project_registry_hash").on(table.projectHash),
|
|
12027
12035
|
index("idx_project_registry_health").on(table.healthStatus),
|
|
12028
|
-
index("idx_project_registry_name").on(table.name)
|
|
12036
|
+
index("idx_project_registry_name").on(table.name),
|
|
12037
|
+
index("idx_project_registry_last_indexed").on(table.lastIndexed)
|
|
12029
12038
|
]
|
|
12030
12039
|
);
|
|
12031
12040
|
nexusAuditLog = sqliteTable(
|
|
@@ -16529,7 +16538,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
16529
16538
|
return result;
|
|
16530
16539
|
}
|
|
16531
16540
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
16532
|
-
const { and:
|
|
16541
|
+
const { and: and11, eq: eq13 } = await import("drizzle-orm");
|
|
16533
16542
|
const db = await getDb3(projectRoot);
|
|
16534
16543
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
16535
16544
|
for (const filePath of matchingFiles) {
|
|
@@ -16564,7 +16573,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
16564
16573
|
await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
|
|
16565
16574
|
}
|
|
16566
16575
|
result.synced++;
|
|
16567
|
-
await db.delete(adrTaskLinks).where(
|
|
16576
|
+
await db.delete(adrTaskLinks).where(and11(eq13(adrTaskLinks.adrId, record2.id), eq13(adrTaskLinks.taskId, taskId)));
|
|
16568
16577
|
await db.insert(adrTaskLinks).values({ adrId: record2.id, taskId, linkType: "implements" });
|
|
16569
16578
|
result.linked.push({ adrId: record2.id, taskId });
|
|
16570
16579
|
if (fm["Related ADRs"]) {
|
|
@@ -17362,7 +17371,7 @@ async function withRetry(fn, policy) {
|
|
|
17362
17371
|
if (!shouldRetry(err, attempt, effectivePolicy)) break;
|
|
17363
17372
|
const delay = calculateDelay(attempt, effectivePolicy);
|
|
17364
17373
|
totalDelayMs += delay;
|
|
17365
|
-
await new Promise((
|
|
17374
|
+
await new Promise((resolve12) => setTimeout(resolve12, delay));
|
|
17366
17375
|
}
|
|
17367
17376
|
}
|
|
17368
17377
|
const error48 = lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
@@ -18058,7 +18067,7 @@ function analyzeStructure(projectRoot) {
|
|
|
18058
18067
|
}
|
|
18059
18068
|
function countFiles(dir, depth = 0) {
|
|
18060
18069
|
if (depth > 5) return 0;
|
|
18061
|
-
let
|
|
18070
|
+
let count3 = 0;
|
|
18062
18071
|
const entries = safeReaddir2(dir);
|
|
18063
18072
|
for (const entry of entries) {
|
|
18064
18073
|
if (EXCLUDED_DIRS.has(entry) || entry.startsWith(".")) continue;
|
|
@@ -18066,14 +18075,14 @@ function countFiles(dir, depth = 0) {
|
|
|
18066
18075
|
try {
|
|
18067
18076
|
const stat2 = statSync3(entryPath);
|
|
18068
18077
|
if (stat2.isDirectory()) {
|
|
18069
|
-
|
|
18078
|
+
count3 += countFiles(entryPath, depth + 1);
|
|
18070
18079
|
} else {
|
|
18071
|
-
|
|
18080
|
+
count3++;
|
|
18072
18081
|
}
|
|
18073
18082
|
} catch {
|
|
18074
18083
|
}
|
|
18075
18084
|
}
|
|
18076
|
-
return
|
|
18085
|
+
return count3;
|
|
18077
18086
|
}
|
|
18078
18087
|
function safeReaddir2(dir) {
|
|
18079
18088
|
try {
|
|
@@ -19432,8 +19441,8 @@ function checkFts5Available(nativeDb) {
|
|
|
19432
19441
|
}
|
|
19433
19442
|
return _fts5Available;
|
|
19434
19443
|
}
|
|
19435
|
-
function execDDL(nativeDb,
|
|
19436
|
-
nativeDb.prepare(
|
|
19444
|
+
function execDDL(nativeDb, sql14) {
|
|
19445
|
+
nativeDb.prepare(sql14).run();
|
|
19437
19446
|
}
|
|
19438
19447
|
function ensureFts5Tables(nativeDb) {
|
|
19439
19448
|
if (!checkFts5Available(nativeDb)) {
|
|
@@ -20266,8 +20275,8 @@ __export(memory_bridge_exports, {
|
|
|
20266
20275
|
});
|
|
20267
20276
|
import { existsSync as existsSync27, mkdirSync as mkdirSync7, readFileSync as readFileSync15, writeFileSync as writeFileSync2 } from "node:fs";
|
|
20268
20277
|
import { join as join30 } from "node:path";
|
|
20269
|
-
function typedAll2(db,
|
|
20270
|
-
return db.prepare(
|
|
20278
|
+
function typedAll2(db, sql14, ...params) {
|
|
20279
|
+
return db.prepare(sql14).all(...params);
|
|
20271
20280
|
}
|
|
20272
20281
|
async function generateMemoryBridgeContent(projectRoot, config2) {
|
|
20273
20282
|
const cfg = { ...DEFAULT_CONFIG, ...config2 };
|
|
@@ -20589,7 +20598,7 @@ async function queryAudit(options) {
|
|
|
20589
20598
|
try {
|
|
20590
20599
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
20591
20600
|
const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
20592
|
-
const { and:
|
|
20601
|
+
const { and: and11, eq: eq13, gte: gte3, or: or5 } = await import("drizzle-orm");
|
|
20593
20602
|
const db = await getDb3(process.cwd());
|
|
20594
20603
|
const conditions = [];
|
|
20595
20604
|
if (options?.sessionId) conditions.push(eq13(auditLog2.sessionId, options.sessionId));
|
|
@@ -20601,7 +20610,7 @@ async function queryAudit(options) {
|
|
|
20601
20610
|
if (options?.taskId) conditions.push(eq13(auditLog2.taskId, options.taskId));
|
|
20602
20611
|
if (options?.since) conditions.push(gte3(auditLog2.timestamp, options.since));
|
|
20603
20612
|
const limit = options?.limit ?? 1e3;
|
|
20604
|
-
const rows = await db.select().from(auditLog2).where(conditions.length > 0 ?
|
|
20613
|
+
const rows = await db.select().from(auditLog2).where(conditions.length > 0 ? and11(...conditions) : void 0).orderBy(auditLog2.timestamp).limit(limit);
|
|
20605
20614
|
return rows.map((row) => ({
|
|
20606
20615
|
timestamp: row.timestamp,
|
|
20607
20616
|
sessionId: row.sessionId,
|
|
@@ -20729,8 +20738,8 @@ async function gradeSession(sessionId, cwd) {
|
|
|
20729
20738
|
);
|
|
20730
20739
|
let hygieneScore = 20;
|
|
20731
20740
|
for (const addCall of addCalls) {
|
|
20732
|
-
const
|
|
20733
|
-
if (!
|
|
20741
|
+
const desc6 = addCall.params?.description;
|
|
20742
|
+
if (!desc6 || desc6.trim().length === 0) {
|
|
20734
20743
|
hygieneScore -= 5;
|
|
20735
20744
|
result.flags.push(
|
|
20736
20745
|
`tasks.add without description (taskId: ${addCall.metadata?.taskId ?? "unknown"})`
|
|
@@ -20959,9 +20968,9 @@ __export(decisions_exports, {
|
|
|
20959
20968
|
async function nextDecisionId(projectRoot) {
|
|
20960
20969
|
const { getBrainDb: getBrainDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
20961
20970
|
const { brainDecisions: brainDecisions2 } = await Promise.resolve().then(() => (init_brain_schema(), brain_schema_exports));
|
|
20962
|
-
const { desc:
|
|
20971
|
+
const { desc: desc6 } = await import("drizzle-orm");
|
|
20963
20972
|
const db = await getBrainDb2(projectRoot);
|
|
20964
|
-
const rows = await db.select({ id: brainDecisions2.id }).from(brainDecisions2).orderBy(
|
|
20973
|
+
const rows = await db.select({ id: brainDecisions2.id }).from(brainDecisions2).orderBy(desc6(brainDecisions2.id)).limit(1);
|
|
20965
20974
|
if (rows.length === 0) {
|
|
20966
20975
|
return "D001";
|
|
20967
20976
|
}
|
|
@@ -21387,7 +21396,7 @@ var init_values = __esm({
|
|
|
21387
21396
|
var sleep;
|
|
21388
21397
|
var init_sleep = __esm({
|
|
21389
21398
|
"node_modules/.pnpm/@anthropic-ai+sdk@0.88.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/internal/utils/sleep.mjs"() {
|
|
21390
|
-
sleep = (ms) => new Promise((
|
|
21399
|
+
sleep = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
21391
21400
|
}
|
|
21392
21401
|
});
|
|
21393
21402
|
|
|
@@ -22165,8 +22174,8 @@ var init_api_promise = __esm({
|
|
|
22165
22174
|
init_parse2();
|
|
22166
22175
|
APIPromise = class _APIPromise extends Promise {
|
|
22167
22176
|
constructor(client, responsePromise, parseResponse = defaultParseResponse) {
|
|
22168
|
-
super((
|
|
22169
|
-
|
|
22177
|
+
super((resolve12) => {
|
|
22178
|
+
resolve12(null);
|
|
22170
22179
|
});
|
|
22171
22180
|
this.responsePromise = responsePromise;
|
|
22172
22181
|
this.parseResponse = parseResponse;
|
|
@@ -23602,12 +23611,12 @@ var init_BetaMessageStream = __esm({
|
|
|
23602
23611
|
}
|
|
23603
23612
|
return this._emit("error", new AnthropicError(String(error48)));
|
|
23604
23613
|
});
|
|
23605
|
-
__classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((
|
|
23606
|
-
__classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise,
|
|
23614
|
+
__classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((resolve12, reject) => {
|
|
23615
|
+
__classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise, resolve12, "f");
|
|
23607
23616
|
__classPrivateFieldSet(this, _BetaMessageStream_rejectConnectedPromise, reject, "f");
|
|
23608
23617
|
}), "f");
|
|
23609
|
-
__classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((
|
|
23610
|
-
__classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise,
|
|
23618
|
+
__classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((resolve12, reject) => {
|
|
23619
|
+
__classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise, resolve12, "f");
|
|
23611
23620
|
__classPrivateFieldSet(this, _BetaMessageStream_rejectEndPromise, reject, "f");
|
|
23612
23621
|
}), "f");
|
|
23613
23622
|
__classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -23777,11 +23786,11 @@ var init_BetaMessageStream = __esm({
|
|
|
23777
23786
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
23778
23787
|
*/
|
|
23779
23788
|
emitted(event) {
|
|
23780
|
-
return new Promise((
|
|
23789
|
+
return new Promise((resolve12, reject) => {
|
|
23781
23790
|
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
|
|
23782
23791
|
if (event !== "error")
|
|
23783
23792
|
this.once("error", reject);
|
|
23784
|
-
this.once(event,
|
|
23793
|
+
this.once(event, resolve12);
|
|
23785
23794
|
});
|
|
23786
23795
|
}
|
|
23787
23796
|
async done() {
|
|
@@ -24124,7 +24133,7 @@ var init_BetaMessageStream = __esm({
|
|
|
24124
24133
|
if (done) {
|
|
24125
24134
|
return { value: void 0, done: true };
|
|
24126
24135
|
}
|
|
24127
|
-
return new Promise((
|
|
24136
|
+
return new Promise((resolve12, reject) => readQueue.push({ resolve: resolve12, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
24128
24137
|
}
|
|
24129
24138
|
const chunk = pushQueue.shift();
|
|
24130
24139
|
return { value: chunk, done: false };
|
|
@@ -24195,13 +24204,13 @@ Wrap your summary in <summary></summary> tags.`;
|
|
|
24195
24204
|
|
|
24196
24205
|
// node_modules/.pnpm/@anthropic-ai+sdk@0.88.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/lib/tools/BetaToolRunner.mjs
|
|
24197
24206
|
function promiseWithResolvers() {
|
|
24198
|
-
let
|
|
24207
|
+
let resolve12;
|
|
24199
24208
|
let reject;
|
|
24200
24209
|
const promise2 = new Promise((res, rej) => {
|
|
24201
|
-
|
|
24210
|
+
resolve12 = res;
|
|
24202
24211
|
reject = rej;
|
|
24203
24212
|
});
|
|
24204
|
-
return { promise: promise2, resolve:
|
|
24213
|
+
return { promise: promise2, resolve: resolve12, reject };
|
|
24205
24214
|
}
|
|
24206
24215
|
async function generateToolResponse(params, lastMessage = params.messages.at(-1), requestOptions) {
|
|
24207
24216
|
if (!lastMessage || lastMessage.role !== "assistant" || !lastMessage.content || typeof lastMessage.content === "string") {
|
|
@@ -26021,12 +26030,12 @@ var init_MessageStream = __esm({
|
|
|
26021
26030
|
}
|
|
26022
26031
|
return this._emit("error", new AnthropicError(String(error48)));
|
|
26023
26032
|
});
|
|
26024
|
-
__classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((
|
|
26025
|
-
__classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise,
|
|
26033
|
+
__classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((resolve12, reject) => {
|
|
26034
|
+
__classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise, resolve12, "f");
|
|
26026
26035
|
__classPrivateFieldSet(this, _MessageStream_rejectConnectedPromise, reject, "f");
|
|
26027
26036
|
}), "f");
|
|
26028
|
-
__classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((
|
|
26029
|
-
__classPrivateFieldSet(this, _MessageStream_resolveEndPromise,
|
|
26037
|
+
__classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((resolve12, reject) => {
|
|
26038
|
+
__classPrivateFieldSet(this, _MessageStream_resolveEndPromise, resolve12, "f");
|
|
26030
26039
|
__classPrivateFieldSet(this, _MessageStream_rejectEndPromise, reject, "f");
|
|
26031
26040
|
}), "f");
|
|
26032
26041
|
__classPrivateFieldGet(this, _MessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -26196,11 +26205,11 @@ var init_MessageStream = __esm({
|
|
|
26196
26205
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
26197
26206
|
*/
|
|
26198
26207
|
emitted(event) {
|
|
26199
|
-
return new Promise((
|
|
26208
|
+
return new Promise((resolve12, reject) => {
|
|
26200
26209
|
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
|
|
26201
26210
|
if (event !== "error")
|
|
26202
26211
|
this.once("error", reject);
|
|
26203
|
-
this.once(event,
|
|
26212
|
+
this.once(event, resolve12);
|
|
26204
26213
|
});
|
|
26205
26214
|
}
|
|
26206
26215
|
async done() {
|
|
@@ -26518,7 +26527,7 @@ var init_MessageStream = __esm({
|
|
|
26518
26527
|
if (done) {
|
|
26519
26528
|
return { value: void 0, done: true };
|
|
26520
26529
|
}
|
|
26521
|
-
return new Promise((
|
|
26530
|
+
return new Promise((resolve12, reject) => readQueue.push({ resolve: resolve12, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
26522
26531
|
}
|
|
26523
26532
|
const chunk = pushQueue.shift();
|
|
26524
26533
|
return { value: chunk, done: false };
|
|
@@ -30286,8 +30295,8 @@ var init_schemas = __esm({
|
|
|
30286
30295
|
});
|
|
30287
30296
|
$ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def2) => {
|
|
30288
30297
|
$ZodType.init(inst, def2);
|
|
30289
|
-
const
|
|
30290
|
-
if (!
|
|
30298
|
+
const desc6 = Object.getOwnPropertyDescriptor(def2, "shape");
|
|
30299
|
+
if (!desc6?.get) {
|
|
30291
30300
|
const sh = def2.shape;
|
|
30292
30301
|
Object.defineProperty(def2, "shape", {
|
|
30293
30302
|
get: () => {
|
|
@@ -31529,8 +31538,8 @@ var init_az = __esm({
|
|
|
31529
31538
|
});
|
|
31530
31539
|
|
|
31531
31540
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/be.js
|
|
31532
|
-
function getBelarusianPlural(
|
|
31533
|
-
const absCount = Math.abs(
|
|
31541
|
+
function getBelarusianPlural(count3, one, few, many) {
|
|
31542
|
+
const absCount = Math.abs(count3);
|
|
31534
31543
|
const lastDigit = absCount % 10;
|
|
31535
31544
|
const lastTwoDigits = absCount % 100;
|
|
31536
31545
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -33444,8 +33453,8 @@ var init_hu = __esm({
|
|
|
33444
33453
|
});
|
|
33445
33454
|
|
|
33446
33455
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/hy.js
|
|
33447
|
-
function getArmenianPlural(
|
|
33448
|
-
return Math.abs(
|
|
33456
|
+
function getArmenianPlural(count3, one, many) {
|
|
33457
|
+
return Math.abs(count3) === 1 ? one : many;
|
|
33449
33458
|
}
|
|
33450
33459
|
function withDefiniteArticle(word) {
|
|
33451
33460
|
if (!word)
|
|
@@ -35560,8 +35569,8 @@ var init_pt = __esm({
|
|
|
35560
35569
|
});
|
|
35561
35570
|
|
|
35562
35571
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/ru.js
|
|
35563
|
-
function getRussianPlural(
|
|
35564
|
-
const absCount = Math.abs(
|
|
35572
|
+
function getRussianPlural(count3, one, few, many) {
|
|
35573
|
+
const absCount = Math.abs(count3);
|
|
35565
35574
|
const lastDigit = absCount % 10;
|
|
35566
35575
|
const lastTwoDigits = absCount % 100;
|
|
35567
35576
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -43275,8 +43284,8 @@ async function strengthenCoRetrievedEdges(projectRoot) {
|
|
|
43275
43284
|
}
|
|
43276
43285
|
}
|
|
43277
43286
|
let strengthened = 0;
|
|
43278
|
-
for (const [pair,
|
|
43279
|
-
if (
|
|
43287
|
+
for (const [pair, count3] of coOccurrence) {
|
|
43288
|
+
if (count3 < 3) continue;
|
|
43280
43289
|
const [fromId, toId] = pair.split("|");
|
|
43281
43290
|
if (!fromId || !toId) continue;
|
|
43282
43291
|
const nodeFrom = `observation:${fromId}`;
|
|
@@ -43624,8 +43633,8 @@ async function runObserver(projectRoot, sessionId) {
|
|
|
43624
43633
|
} catch {
|
|
43625
43634
|
return empty;
|
|
43626
43635
|
}
|
|
43627
|
-
const
|
|
43628
|
-
if (
|
|
43636
|
+
const count3 = countSessionObservations(sessionId);
|
|
43637
|
+
if (count3 < cfg.threshold) return empty;
|
|
43629
43638
|
const observations = fetchSessionObservations(sessionId, OBSERVER_BATCH_LIMIT);
|
|
43630
43639
|
if (observations.length < 2) return empty;
|
|
43631
43640
|
const observationList = observations.map(
|
|
@@ -50661,14 +50670,14 @@ async function validateEpicCreation(options, cwd) {
|
|
|
50661
50670
|
const mode = await getLifecycleMode(cwd);
|
|
50662
50671
|
if (mode === "off") return { valid: true };
|
|
50663
50672
|
const ac = options.acceptance ?? [];
|
|
50664
|
-
const
|
|
50673
|
+
const desc6 = (options.description ?? "").trim();
|
|
50665
50674
|
const violations = [];
|
|
50666
50675
|
if (ac.length < EPIC_MIN_AC) {
|
|
50667
50676
|
violations.push(
|
|
50668
50677
|
`Epic requires at least ${EPIC_MIN_AC} acceptance criteria (${ac.length} provided). Regular tasks need ${TASK_MIN_AC}.`
|
|
50669
50678
|
);
|
|
50670
50679
|
}
|
|
50671
|
-
if (!
|
|
50680
|
+
if (!desc6) {
|
|
50672
50681
|
violations.push("Epic must have a non-empty description (used as completion criteria).");
|
|
50673
50682
|
}
|
|
50674
50683
|
if (violations.length === 0) return { valid: true };
|
|
@@ -51589,7 +51598,7 @@ function migrateAgentOutputs(projectRoot, cleoDir) {
|
|
|
51589
51598
|
};
|
|
51590
51599
|
}
|
|
51591
51600
|
function copyDirContents(srcDir, dstDir, manifestLines, copiedFiles) {
|
|
51592
|
-
let
|
|
51601
|
+
let count3 = 0;
|
|
51593
51602
|
const entries = readdirSync21(srcDir);
|
|
51594
51603
|
for (const entry of entries) {
|
|
51595
51604
|
if (entry === "MANIFEST.jsonl") {
|
|
@@ -51607,7 +51616,7 @@ function copyDirContents(srcDir, dstDir, manifestLines, copiedFiles) {
|
|
|
51607
51616
|
try {
|
|
51608
51617
|
copyFileSync6(join55(srcPath, sf), join55(dstPath, sf));
|
|
51609
51618
|
copiedFiles.add(sf);
|
|
51610
|
-
|
|
51619
|
+
count3++;
|
|
51611
51620
|
} catch {
|
|
51612
51621
|
}
|
|
51613
51622
|
}
|
|
@@ -51615,12 +51624,12 @@ function copyDirContents(srcDir, dstDir, manifestLines, copiedFiles) {
|
|
|
51615
51624
|
} else if (!copiedFiles.has(entry)) {
|
|
51616
51625
|
copyFileSync6(srcPath, dstPath);
|
|
51617
51626
|
copiedFiles.add(entry);
|
|
51618
|
-
|
|
51627
|
+
count3++;
|
|
51619
51628
|
}
|
|
51620
51629
|
} catch {
|
|
51621
51630
|
}
|
|
51622
51631
|
}
|
|
51623
|
-
return
|
|
51632
|
+
return count3;
|
|
51624
51633
|
}
|
|
51625
51634
|
function collectManifestLines(manifestPath, out) {
|
|
51626
51635
|
try {
|
|
@@ -51840,13 +51849,14 @@ __export(registry_exports3, {
|
|
|
51840
51849
|
nexusSync: () => nexusSync,
|
|
51841
51850
|
nexusSyncAll: () => nexusSyncAll,
|
|
51842
51851
|
nexusUnregister: () => nexusUnregister,
|
|
51852
|
+
nexusUpdateIndexStats: () => nexusUpdateIndexStats,
|
|
51843
51853
|
readRegistry: () => readRegistry,
|
|
51844
51854
|
readRegistryRequired: () => readRegistryRequired,
|
|
51845
51855
|
resetNexusDbState: () => resetNexusDbState
|
|
51846
51856
|
});
|
|
51847
51857
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
51848
51858
|
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
51849
|
-
import { basename as basename9, join as join62 } from "node:path";
|
|
51859
|
+
import { basename as basename9, join as join62, resolve as resolve7 } from "node:path";
|
|
51850
51860
|
function getNexusHome() {
|
|
51851
51861
|
return process.env["NEXUS_HOME"] ?? join62(getCleoHome(), "nexus");
|
|
51852
51862
|
}
|
|
@@ -51863,6 +51873,17 @@ function rowToProject(row) {
|
|
|
51863
51873
|
} catch {
|
|
51864
51874
|
labels = [];
|
|
51865
51875
|
}
|
|
51876
|
+
let stats2 = { nodeCount: 0, relationCount: 0, fileCount: 0 };
|
|
51877
|
+
try {
|
|
51878
|
+
const parsed = JSON.parse(row.statsJson ?? "{}");
|
|
51879
|
+
stats2 = {
|
|
51880
|
+
nodeCount: parsed.nodeCount ?? 0,
|
|
51881
|
+
relationCount: parsed.relationCount ?? 0,
|
|
51882
|
+
fileCount: parsed.fileCount ?? 0
|
|
51883
|
+
};
|
|
51884
|
+
} catch {
|
|
51885
|
+
stats2 = { nodeCount: 0, relationCount: 0, fileCount: 0 };
|
|
51886
|
+
}
|
|
51866
51887
|
return {
|
|
51867
51888
|
hash: row.projectHash,
|
|
51868
51889
|
projectId: row.projectId,
|
|
@@ -51875,7 +51896,11 @@ function rowToProject(row) {
|
|
|
51875
51896
|
permissions: row.permissions,
|
|
51876
51897
|
lastSync: row.lastSync,
|
|
51877
51898
|
taskCount: row.taskCount,
|
|
51878
|
-
labels
|
|
51899
|
+
labels,
|
|
51900
|
+
brainDbPath: row.brainDbPath ?? null,
|
|
51901
|
+
tasksDbPath: row.tasksDbPath ?? null,
|
|
51902
|
+
lastIndexed: row.lastIndexed ?? null,
|
|
51903
|
+
stats: stats2
|
|
51879
51904
|
};
|
|
51880
51905
|
}
|
|
51881
51906
|
async function writeNexusAudit(fields) {
|
|
@@ -51971,10 +51996,10 @@ async function readProjectMeta(projectPath) {
|
|
|
51971
51996
|
}
|
|
51972
51997
|
async function readProjectId(projectPath) {
|
|
51973
51998
|
try {
|
|
51974
|
-
const { readFileSync:
|
|
51999
|
+
const { readFileSync: readFileSync79, existsSync: existsSync109 } = await import("node:fs");
|
|
51975
52000
|
const infoPath = join62(projectPath, ".cleo", "project-info.json");
|
|
51976
|
-
if (!
|
|
51977
|
-
const data = JSON.parse(
|
|
52001
|
+
if (!existsSync109(infoPath)) return "";
|
|
52002
|
+
const data = JSON.parse(readFileSync79(infoPath, "utf-8"));
|
|
51978
52003
|
return typeof data.projectId === "string" ? data.projectId : "";
|
|
51979
52004
|
} catch {
|
|
51980
52005
|
return "";
|
|
@@ -52015,13 +52040,18 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
52015
52040
|
const meta3 = await readProjectMeta(projectPath);
|
|
52016
52041
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
52017
52042
|
let projectId = await readProjectId(projectPath);
|
|
52043
|
+
const resolvedPath = resolve7(projectPath);
|
|
52044
|
+
const brainDbPath = join62(resolvedPath, ".cleo", "brain.db");
|
|
52045
|
+
const tasksDbPath = join62(resolvedPath, ".cleo", "tasks.db");
|
|
52018
52046
|
if (existing) {
|
|
52019
52047
|
await db.update(projectRegistry).set({
|
|
52020
52048
|
permissions,
|
|
52021
52049
|
lastSync: now,
|
|
52022
52050
|
taskCount: meta3.taskCount,
|
|
52023
52051
|
labelsJson: JSON.stringify(meta3.labels),
|
|
52024
|
-
lastSeen: now
|
|
52052
|
+
lastSeen: now,
|
|
52053
|
+
brainDbPath,
|
|
52054
|
+
tasksDbPath
|
|
52025
52055
|
}).where(eq13(projectRegistry.projectHash, projectHash));
|
|
52026
52056
|
} else {
|
|
52027
52057
|
if (!projectId) {
|
|
@@ -52039,7 +52069,10 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
52039
52069
|
permissions,
|
|
52040
52070
|
lastSync: now,
|
|
52041
52071
|
taskCount: meta3.taskCount,
|
|
52042
|
-
labelsJson: JSON.stringify(meta3.labels)
|
|
52072
|
+
labelsJson: JSON.stringify(meta3.labels),
|
|
52073
|
+
brainDbPath,
|
|
52074
|
+
tasksDbPath,
|
|
52075
|
+
statsJson: "{}"
|
|
52043
52076
|
});
|
|
52044
52077
|
}
|
|
52045
52078
|
await writeNexusAudit({
|
|
@@ -52155,6 +52188,41 @@ async function nexusSyncAll() {
|
|
|
52155
52188
|
});
|
|
52156
52189
|
return { synced, failed };
|
|
52157
52190
|
}
|
|
52191
|
+
async function nexusUpdateIndexStats(projectPath, stats2) {
|
|
52192
|
+
if (!projectPath) return;
|
|
52193
|
+
const projectHash = generateProjectHash(projectPath);
|
|
52194
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
52195
|
+
try {
|
|
52196
|
+
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
52197
|
+
const { eq: eq13 } = await import("drizzle-orm");
|
|
52198
|
+
const db = await getNexusDb2();
|
|
52199
|
+
const rows = await db.select().from(projectRegistry).where(eq13(projectRegistry.projectHash, projectHash));
|
|
52200
|
+
if (rows.length === 0) {
|
|
52201
|
+
try {
|
|
52202
|
+
await nexusRegister(projectPath);
|
|
52203
|
+
} catch {
|
|
52204
|
+
}
|
|
52205
|
+
}
|
|
52206
|
+
await db.update(projectRegistry).set({
|
|
52207
|
+
lastIndexed: now,
|
|
52208
|
+
statsJson: JSON.stringify(stats2),
|
|
52209
|
+
lastSeen: now
|
|
52210
|
+
}).where(eq13(projectRegistry.projectHash, projectHash));
|
|
52211
|
+
await writeNexusAudit({
|
|
52212
|
+
action: "update-index-stats",
|
|
52213
|
+
projectHash,
|
|
52214
|
+
operation: "update-index-stats",
|
|
52215
|
+
success: true,
|
|
52216
|
+
details: {
|
|
52217
|
+
nodeCount: stats2.nodeCount,
|
|
52218
|
+
relationCount: stats2.relationCount,
|
|
52219
|
+
fileCount: stats2.fileCount
|
|
52220
|
+
}
|
|
52221
|
+
});
|
|
52222
|
+
} catch (err) {
|
|
52223
|
+
getLogger("nexus").warn({ err }, "nexus: failed to update index stats");
|
|
52224
|
+
}
|
|
52225
|
+
}
|
|
52158
52226
|
async function nexusSetPermission(nameOrHash, permission) {
|
|
52159
52227
|
const project = await nexusGetProject(nameOrHash);
|
|
52160
52228
|
if (!project) {
|
|
@@ -54147,29 +54215,29 @@ var init_dependencies = __esm({
|
|
|
54147
54215
|
});
|
|
54148
54216
|
|
|
54149
54217
|
// packages/core/src/discovery.ts
|
|
54150
|
-
import { existsSync as
|
|
54151
|
-
import { join as
|
|
54218
|
+
import { existsSync as existsSync105, readdirSync as readdirSync34, statSync as statSync20 } from "node:fs";
|
|
54219
|
+
import { join as join105, resolve as resolve11 } from "node:path";
|
|
54152
54220
|
function countMeaningfulTopLevelFiles(directory) {
|
|
54153
|
-
if (!
|
|
54221
|
+
if (!existsSync105(directory)) return 0;
|
|
54154
54222
|
try {
|
|
54155
54223
|
const entries = readdirSync34(directory);
|
|
54156
|
-
let
|
|
54224
|
+
let count3 = 0;
|
|
54157
54225
|
for (const entry of entries) {
|
|
54158
54226
|
if (entry.startsWith(".") || entry === ".cleo" || entry === "node_modules" || entry === "target" || entry === "dist" || entry === "build") {
|
|
54159
54227
|
continue;
|
|
54160
54228
|
}
|
|
54161
|
-
|
|
54229
|
+
count3 += 1;
|
|
54162
54230
|
}
|
|
54163
|
-
return
|
|
54231
|
+
return count3;
|
|
54164
54232
|
} catch {
|
|
54165
54233
|
return 0;
|
|
54166
54234
|
}
|
|
54167
54235
|
}
|
|
54168
54236
|
function classifyProject(directory) {
|
|
54169
|
-
const root =
|
|
54237
|
+
const root = resolve11(directory ?? process.cwd());
|
|
54170
54238
|
const signals = [];
|
|
54171
|
-
const gitPath =
|
|
54172
|
-
const hasGit =
|
|
54239
|
+
const gitPath = join105(root, ".git");
|
|
54240
|
+
const hasGit = existsSync105(gitPath);
|
|
54173
54241
|
if (hasGit) {
|
|
54174
54242
|
signals.push({
|
|
54175
54243
|
id: "git-dir",
|
|
@@ -54178,8 +54246,8 @@ function classifyProject(directory) {
|
|
|
54178
54246
|
});
|
|
54179
54247
|
}
|
|
54180
54248
|
for (const manifest of MANIFESTS) {
|
|
54181
|
-
const manifestPath =
|
|
54182
|
-
if (
|
|
54249
|
+
const manifestPath = join105(root, manifest.file);
|
|
54250
|
+
if (existsSync105(manifestPath)) {
|
|
54183
54251
|
signals.push({
|
|
54184
54252
|
id: manifest.signal,
|
|
54185
54253
|
description: manifest.description,
|
|
@@ -54188,8 +54256,8 @@ function classifyProject(directory) {
|
|
|
54188
54256
|
}
|
|
54189
54257
|
}
|
|
54190
54258
|
for (const dir of SOURCE_DIRS) {
|
|
54191
|
-
const srcPath =
|
|
54192
|
-
if (
|
|
54259
|
+
const srcPath = join105(root, dir);
|
|
54260
|
+
if (existsSync105(srcPath) && isNonEmptyDir(srcPath)) {
|
|
54193
54261
|
signals.push({
|
|
54194
54262
|
id: "source-dir",
|
|
54195
54263
|
description: `Source directory ${dir}/ contains files`,
|
|
@@ -54199,8 +54267,8 @@ function classifyProject(directory) {
|
|
|
54199
54267
|
}
|
|
54200
54268
|
}
|
|
54201
54269
|
for (const marker of DOCS_MARKERS) {
|
|
54202
|
-
const markerPath =
|
|
54203
|
-
if (
|
|
54270
|
+
const markerPath = join105(root, marker.path);
|
|
54271
|
+
if (existsSync105(markerPath)) {
|
|
54204
54272
|
signals.push({
|
|
54205
54273
|
id: marker.signal,
|
|
54206
54274
|
description: `${marker.path} present`,
|
|
@@ -54273,18 +54341,18 @@ __export(init_exports, {
|
|
|
54273
54341
|
resolveSeedAgentsDir: () => resolveSeedAgentsDir,
|
|
54274
54342
|
updateDocs: () => updateDocs
|
|
54275
54343
|
});
|
|
54276
|
-
import { existsSync as
|
|
54344
|
+
import { existsSync as existsSync106, readdirSync as readdirSync35, readFileSync as readFileSync76 } from "node:fs";
|
|
54277
54345
|
import { copyFile as copyFile4, lstat, mkdir as mkdir16, readFile as readFile19, symlink, unlink as unlink4, writeFile as writeFile11 } from "node:fs/promises";
|
|
54278
54346
|
import { platform as platform4 } from "node:os";
|
|
54279
|
-
import { basename as basename17, dirname as
|
|
54347
|
+
import { basename as basename17, dirname as dirname23, join as join106 } from "node:path";
|
|
54280
54348
|
async function resolveSeedAgentsDir() {
|
|
54281
54349
|
try {
|
|
54282
54350
|
const { createRequire: createRequire10 } = await import("node:module");
|
|
54283
54351
|
const req = createRequire10(import.meta.url);
|
|
54284
54352
|
const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
|
|
54285
|
-
const agentsPkgRoot =
|
|
54286
|
-
const candidate =
|
|
54287
|
-
if (
|
|
54353
|
+
const agentsPkgRoot = dirname23(agentsPkgMain);
|
|
54354
|
+
const candidate = join106(agentsPkgRoot, "seed-agents");
|
|
54355
|
+
if (existsSync106(candidate)) {
|
|
54288
54356
|
return candidate;
|
|
54289
54357
|
}
|
|
54290
54358
|
} catch {
|
|
@@ -54292,17 +54360,17 @@ async function resolveSeedAgentsDir() {
|
|
|
54292
54360
|
const packageRoot = getPackageRoot();
|
|
54293
54361
|
const candidates = [
|
|
54294
54362
|
// Workspace fallback: bundled alongside core under packages/agents/seed-agents
|
|
54295
|
-
|
|
54363
|
+
join106(packageRoot, "agents", "seed-agents"),
|
|
54296
54364
|
// Sibling-package layout (e.g. node_modules/@cleocode/core -> ../agents)
|
|
54297
|
-
|
|
54365
|
+
join106(packageRoot, "..", "agents", "seed-agents"),
|
|
54298
54366
|
// Bundled CLI: packages/cleo/dist -> ../../agents/seed-agents
|
|
54299
|
-
|
|
54367
|
+
join106(packageRoot, "..", "..", "agents", "seed-agents"),
|
|
54300
54368
|
// Bundled CLI dist subdir: packages/cleo/dist/cli -> ../../../packages/agents
|
|
54301
|
-
|
|
54369
|
+
join106(packageRoot, "..", "..", "packages", "agents", "seed-agents"),
|
|
54302
54370
|
// Monorepo workspace from repo root
|
|
54303
|
-
|
|
54371
|
+
join106(packageRoot, "..", "..", "..", "packages", "agents", "seed-agents")
|
|
54304
54372
|
];
|
|
54305
|
-
return candidates.find((p) =>
|
|
54373
|
+
return candidates.find((p) => existsSync106(p)) ?? null;
|
|
54306
54374
|
}
|
|
54307
54375
|
async function initAgentDefinition(created, warnings) {
|
|
54308
54376
|
let agentSourceDir = null;
|
|
@@ -54310,17 +54378,17 @@ async function initAgentDefinition(created, warnings) {
|
|
|
54310
54378
|
const { createRequire: createRequire10 } = await import("node:module");
|
|
54311
54379
|
const req = createRequire10(import.meta.url);
|
|
54312
54380
|
const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
|
|
54313
|
-
const agentsPkgRoot =
|
|
54314
|
-
const candidate =
|
|
54315
|
-
if (
|
|
54381
|
+
const agentsPkgRoot = dirname23(agentsPkgMain);
|
|
54382
|
+
const candidate = join106(agentsPkgRoot, "cleo-subagent");
|
|
54383
|
+
if (existsSync106(candidate)) {
|
|
54316
54384
|
agentSourceDir = candidate;
|
|
54317
54385
|
}
|
|
54318
54386
|
} catch {
|
|
54319
54387
|
}
|
|
54320
54388
|
if (!agentSourceDir) {
|
|
54321
54389
|
const packageRoot = getPackageRoot();
|
|
54322
|
-
const bundled =
|
|
54323
|
-
if (
|
|
54390
|
+
const bundled = join106(packageRoot, "agents", "cleo-subagent");
|
|
54391
|
+
if (existsSync106(bundled)) {
|
|
54324
54392
|
agentSourceDir = bundled;
|
|
54325
54393
|
}
|
|
54326
54394
|
}
|
|
@@ -54328,8 +54396,8 @@ async function initAgentDefinition(created, warnings) {
|
|
|
54328
54396
|
warnings.push("agents/cleo-subagent/ not found in package, skipping agent definition install");
|
|
54329
54397
|
return;
|
|
54330
54398
|
}
|
|
54331
|
-
const globalAgentsDir =
|
|
54332
|
-
await mkdir16(
|
|
54399
|
+
const globalAgentsDir = join106(getAgentsHome(), "agents", "cleo-subagent");
|
|
54400
|
+
await mkdir16(dirname23(globalAgentsDir), { recursive: true });
|
|
54333
54401
|
try {
|
|
54334
54402
|
try {
|
|
54335
54403
|
const stat2 = await lstat(globalAgentsDir);
|
|
@@ -54352,7 +54420,7 @@ async function initAgentDefinition(created, warnings) {
|
|
|
54352
54420
|
await mkdir16(globalAgentsDir, { recursive: true });
|
|
54353
54421
|
const files = readdirSync35(agentSourceDir);
|
|
54354
54422
|
for (const file2 of files) {
|
|
54355
|
-
await copyFile4(
|
|
54423
|
+
await copyFile4(join106(agentSourceDir, file2), join106(globalAgentsDir, file2));
|
|
54356
54424
|
}
|
|
54357
54425
|
created.push("agent: cleo-subagent (copied)");
|
|
54358
54426
|
} catch (copyErr) {
|
|
@@ -54377,20 +54445,20 @@ async function initCoreSkills(created, warnings) {
|
|
|
54377
54445
|
const { createRequire: createRequire10 } = await import("node:module");
|
|
54378
54446
|
const req = createRequire10(import.meta.url);
|
|
54379
54447
|
const skillsPkgMain = req.resolve("@cleocode/skills/package.json");
|
|
54380
|
-
const skillsPkgRoot =
|
|
54381
|
-
if (
|
|
54448
|
+
const skillsPkgRoot = dirname23(skillsPkgMain);
|
|
54449
|
+
if (existsSync106(join106(skillsPkgRoot, "skills.json"))) {
|
|
54382
54450
|
ctSkillsRoot = skillsPkgRoot;
|
|
54383
54451
|
}
|
|
54384
54452
|
} catch {
|
|
54385
54453
|
}
|
|
54386
54454
|
if (!ctSkillsRoot) {
|
|
54387
54455
|
try {
|
|
54388
|
-
const bundledPath =
|
|
54389
|
-
if (
|
|
54456
|
+
const bundledPath = join106(packageRoot, "packages", "skills");
|
|
54457
|
+
if (existsSync106(join106(bundledPath, "skills.json"))) {
|
|
54390
54458
|
ctSkillsRoot = bundledPath;
|
|
54391
54459
|
} else {
|
|
54392
|
-
const ctSkillsPath =
|
|
54393
|
-
if (
|
|
54460
|
+
const ctSkillsPath = join106(packageRoot, "node_modules", "@cleocode", "skills");
|
|
54461
|
+
if (existsSync106(join106(ctSkillsPath, "skills.json"))) {
|
|
54394
54462
|
ctSkillsRoot = ctSkillsPath;
|
|
54395
54463
|
}
|
|
54396
54464
|
}
|
|
@@ -54406,14 +54474,14 @@ async function initCoreSkills(created, warnings) {
|
|
|
54406
54474
|
} catch {
|
|
54407
54475
|
warnings.push("Failed to register skill library with CAAMP");
|
|
54408
54476
|
}
|
|
54409
|
-
const catalogPath =
|
|
54410
|
-
const catalog3 = JSON.parse(
|
|
54477
|
+
const catalogPath = join106(ctSkillsRoot, "skills.json");
|
|
54478
|
+
const catalog3 = JSON.parse(readFileSync76(catalogPath, "utf-8"));
|
|
54411
54479
|
const skills = catalog3.skills ?? [];
|
|
54412
54480
|
const coreSkills = skills.filter((s) => s.tier <= 2);
|
|
54413
54481
|
const installed = [];
|
|
54414
54482
|
for (const skill of coreSkills) {
|
|
54415
|
-
const skillSourceDir =
|
|
54416
|
-
if (!
|
|
54483
|
+
const skillSourceDir = dirname23(join106(ctSkillsRoot, skill.path));
|
|
54484
|
+
if (!existsSync106(skillSourceDir)) {
|
|
54417
54485
|
continue;
|
|
54418
54486
|
}
|
|
54419
54487
|
try {
|
|
@@ -54456,38 +54524,38 @@ async function initNexusRegistration(projectRoot, created, warnings) {
|
|
|
54456
54524
|
}
|
|
54457
54525
|
}
|
|
54458
54526
|
async function installGitHubTemplates(projectRoot, created, skipped) {
|
|
54459
|
-
if (!
|
|
54527
|
+
if (!existsSync106(join106(projectRoot, ".git"))) {
|
|
54460
54528
|
return;
|
|
54461
54529
|
}
|
|
54462
|
-
const githubDir =
|
|
54463
|
-
const issueTemplateDir =
|
|
54530
|
+
const githubDir = join106(projectRoot, ".github");
|
|
54531
|
+
const issueTemplateDir = join106(githubDir, "ISSUE_TEMPLATE");
|
|
54464
54532
|
const packageRoot = getPackageRoot();
|
|
54465
|
-
const templateSrcDir =
|
|
54466
|
-
if (!
|
|
54533
|
+
const templateSrcDir = join106(packageRoot, "templates", "github");
|
|
54534
|
+
if (!existsSync106(templateSrcDir)) {
|
|
54467
54535
|
return;
|
|
54468
54536
|
}
|
|
54469
54537
|
await mkdir16(issueTemplateDir, { recursive: true });
|
|
54470
|
-
const issueSrcDir =
|
|
54471
|
-
if (
|
|
54538
|
+
const issueSrcDir = join106(templateSrcDir, "ISSUE_TEMPLATE");
|
|
54539
|
+
if (existsSync106(issueSrcDir)) {
|
|
54472
54540
|
const issueFiles = readdirSync35(issueSrcDir);
|
|
54473
54541
|
for (const file2 of issueFiles) {
|
|
54474
|
-
const dest =
|
|
54475
|
-
if (
|
|
54542
|
+
const dest = join106(issueTemplateDir, file2);
|
|
54543
|
+
if (existsSync106(dest)) {
|
|
54476
54544
|
skipped.push(`.github/ISSUE_TEMPLATE/${file2}`);
|
|
54477
54545
|
continue;
|
|
54478
54546
|
}
|
|
54479
|
-
const content =
|
|
54547
|
+
const content = readFileSync76(join106(issueSrcDir, file2), "utf-8");
|
|
54480
54548
|
await writeFile11(dest, content, "utf-8");
|
|
54481
54549
|
created.push(`.github/ISSUE_TEMPLATE/${file2}`);
|
|
54482
54550
|
}
|
|
54483
54551
|
}
|
|
54484
|
-
const prTemplateSrc =
|
|
54485
|
-
const prTemplateDest =
|
|
54486
|
-
if (
|
|
54487
|
-
if (
|
|
54552
|
+
const prTemplateSrc = join106(templateSrcDir, "pull_request_template.md");
|
|
54553
|
+
const prTemplateDest = join106(githubDir, "pull_request_template.md");
|
|
54554
|
+
if (existsSync106(prTemplateSrc)) {
|
|
54555
|
+
if (existsSync106(prTemplateDest)) {
|
|
54488
54556
|
skipped.push(".github/pull_request_template.md");
|
|
54489
54557
|
} else {
|
|
54490
|
-
const content =
|
|
54558
|
+
const content = readFileSync76(prTemplateSrc, "utf-8");
|
|
54491
54559
|
await writeFile11(prTemplateDest, content, "utf-8");
|
|
54492
54560
|
created.push(".github/pull_request_template.md");
|
|
54493
54561
|
}
|
|
@@ -54517,8 +54585,8 @@ async function updateDocs() {
|
|
|
54517
54585
|
}
|
|
54518
54586
|
async function initProject(opts = {}) {
|
|
54519
54587
|
const cleoDir = getCleoDirAbsolute();
|
|
54520
|
-
const projRoot =
|
|
54521
|
-
const alreadyInitialized =
|
|
54588
|
+
const projRoot = dirname23(cleoDir);
|
|
54589
|
+
const alreadyInitialized = existsSync106(cleoDir) && (existsSync106(join106(cleoDir, "tasks.db")) || existsSync106(join106(cleoDir, "config.json")));
|
|
54522
54590
|
if (alreadyInitialized && !opts.force) {
|
|
54523
54591
|
throw new CleoError(
|
|
54524
54592
|
1 /* GENERAL_ERROR */,
|
|
@@ -54550,7 +54618,7 @@ async function initProject(opts = {}) {
|
|
|
54550
54618
|
}
|
|
54551
54619
|
try {
|
|
54552
54620
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
54553
|
-
await getDb3(
|
|
54621
|
+
await getDb3(join106(cleoDir, ".."));
|
|
54554
54622
|
created.push("tasks.db");
|
|
54555
54623
|
} catch (err) {
|
|
54556
54624
|
created.push(`tasks.db (deferred: ${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -54580,8 +54648,8 @@ async function initProject(opts = {}) {
|
|
|
54580
54648
|
created.push(".gitignore");
|
|
54581
54649
|
}
|
|
54582
54650
|
} else {
|
|
54583
|
-
const gitignorePath =
|
|
54584
|
-
if (
|
|
54651
|
+
const gitignorePath = join106(cleoDir, ".gitignore");
|
|
54652
|
+
if (existsSync106(gitignorePath)) {
|
|
54585
54653
|
skipped.push(".gitignore");
|
|
54586
54654
|
} else {
|
|
54587
54655
|
const gitignoreResult = await ensureGitignore(projRoot);
|
|
@@ -54592,12 +54660,12 @@ async function initProject(opts = {}) {
|
|
|
54592
54660
|
}
|
|
54593
54661
|
}
|
|
54594
54662
|
}
|
|
54595
|
-
const legacySequencePath =
|
|
54663
|
+
const legacySequencePath = join106(cleoDir, ".sequence");
|
|
54596
54664
|
try {
|
|
54597
54665
|
await unlink4(legacySequencePath);
|
|
54598
54666
|
} catch {
|
|
54599
54667
|
}
|
|
54600
|
-
const legacySequenceJsonPath =
|
|
54668
|
+
const legacySequenceJsonPath = join106(cleoDir, ".sequence.json");
|
|
54601
54669
|
try {
|
|
54602
54670
|
await unlink4(legacySequenceJsonPath);
|
|
54603
54671
|
} catch {
|
|
@@ -54753,15 +54821,15 @@ async function initProject(opts = {}) {
|
|
|
54753
54821
|
if (opts.installSeedAgents) {
|
|
54754
54822
|
try {
|
|
54755
54823
|
const seedDir = await resolveSeedAgentsDir();
|
|
54756
|
-
if (seedDir &&
|
|
54757
|
-
const targetDir =
|
|
54824
|
+
if (seedDir && existsSync106(seedDir)) {
|
|
54825
|
+
const targetDir = join106(projRoot, ".cleo", "agents");
|
|
54758
54826
|
await mkdir16(targetDir, { recursive: true });
|
|
54759
54827
|
const seeds = readdirSync35(seedDir).filter((f) => f.endsWith(".cant"));
|
|
54760
54828
|
let installed = 0;
|
|
54761
54829
|
for (const seed of seeds) {
|
|
54762
|
-
const dst =
|
|
54763
|
-
if (!
|
|
54764
|
-
await copyFile4(
|
|
54830
|
+
const dst = join106(targetDir, seed);
|
|
54831
|
+
if (!existsSync106(dst)) {
|
|
54832
|
+
await copyFile4(join106(seedDir, seed), dst);
|
|
54765
54833
|
installed++;
|
|
54766
54834
|
}
|
|
54767
54835
|
}
|
|
@@ -54844,8 +54912,8 @@ function isAutoInitEnabled() {
|
|
|
54844
54912
|
}
|
|
54845
54913
|
async function ensureInitialized(projectRoot) {
|
|
54846
54914
|
const root = projectRoot ?? getProjectRoot();
|
|
54847
|
-
const cleoDir =
|
|
54848
|
-
const isInit =
|
|
54915
|
+
const cleoDir = join106(root, ".cleo");
|
|
54916
|
+
const isInit = existsSync106(cleoDir) && (existsSync106(join106(cleoDir, "tasks.db")) || existsSync106(join106(cleoDir, "config.json")));
|
|
54849
54917
|
if (isInit) {
|
|
54850
54918
|
return { initialized: true };
|
|
54851
54919
|
}
|
|
@@ -54857,7 +54925,7 @@ async function ensureInitialized(projectRoot) {
|
|
|
54857
54925
|
}
|
|
54858
54926
|
async function getVersion2(projectRoot) {
|
|
54859
54927
|
const root = projectRoot ?? getProjectRoot();
|
|
54860
|
-
const versionPaths = [
|
|
54928
|
+
const versionPaths = [join106(root, "VERSION"), join106(root, "..", "VERSION")];
|
|
54861
54929
|
for (const versionPath of versionPaths) {
|
|
54862
54930
|
try {
|
|
54863
54931
|
const content = await readFile19(versionPath, "utf-8");
|
|
@@ -54868,16 +54936,16 @@ async function getVersion2(projectRoot) {
|
|
|
54868
54936
|
} catch {
|
|
54869
54937
|
}
|
|
54870
54938
|
}
|
|
54871
|
-
const pkg = await readJson(
|
|
54939
|
+
const pkg = await readJson(join106(root, "package.json"));
|
|
54872
54940
|
if (pkg?.version) {
|
|
54873
54941
|
return { version: pkg.version };
|
|
54874
54942
|
}
|
|
54875
54943
|
return { version: "0.0.0" };
|
|
54876
54944
|
}
|
|
54877
54945
|
async function deployStarterBundle(cleoDir, created, warnings) {
|
|
54878
|
-
const cantDir =
|
|
54879
|
-
const cantAgentsDir =
|
|
54880
|
-
const hasCantFiles =
|
|
54946
|
+
const cantDir = join106(cleoDir, "cant");
|
|
54947
|
+
const cantAgentsDir = join106(cantDir, "agents");
|
|
54948
|
+
const hasCantFiles = existsSync106(cantDir) && readdirSync35(cantDir, { recursive: true }).some(
|
|
54881
54949
|
(f) => typeof f === "string" && f.endsWith(".cant")
|
|
54882
54950
|
);
|
|
54883
54951
|
if (hasCantFiles) return;
|
|
@@ -54886,9 +54954,9 @@ async function deployStarterBundle(cleoDir, created, warnings) {
|
|
|
54886
54954
|
const { createRequire: createRequire10 } = await import("node:module");
|
|
54887
54955
|
const req = createRequire10(import.meta.url);
|
|
54888
54956
|
const cleoOsPkgMain = req.resolve("@cleocode/cleo-os/package.json");
|
|
54889
|
-
const cleoOsPkgRoot =
|
|
54890
|
-
const candidate =
|
|
54891
|
-
if (
|
|
54957
|
+
const cleoOsPkgRoot = dirname23(cleoOsPkgMain);
|
|
54958
|
+
const candidate = join106(cleoOsPkgRoot, "starter-bundle");
|
|
54959
|
+
if (existsSync106(candidate)) {
|
|
54892
54960
|
starterBundleSrc = candidate;
|
|
54893
54961
|
}
|
|
54894
54962
|
} catch {
|
|
@@ -54896,10 +54964,10 @@ async function deployStarterBundle(cleoDir, created, warnings) {
|
|
|
54896
54964
|
if (!starterBundleSrc) {
|
|
54897
54965
|
const packageRoot = getPackageRoot();
|
|
54898
54966
|
const fallbacks = [
|
|
54899
|
-
|
|
54900
|
-
|
|
54967
|
+
join106(packageRoot, "..", "cleo-os", "starter-bundle"),
|
|
54968
|
+
join106(packageRoot, "..", "..", "packages", "cleo-os", "starter-bundle")
|
|
54901
54969
|
];
|
|
54902
|
-
starterBundleSrc = fallbacks.find((p) =>
|
|
54970
|
+
starterBundleSrc = fallbacks.find((p) => existsSync106(p)) ?? null;
|
|
54903
54971
|
}
|
|
54904
54972
|
if (!starterBundleSrc) {
|
|
54905
54973
|
warnings.push(
|
|
@@ -54909,30 +54977,30 @@ async function deployStarterBundle(cleoDir, created, warnings) {
|
|
|
54909
54977
|
}
|
|
54910
54978
|
await mkdir16(cantDir, { recursive: true });
|
|
54911
54979
|
await mkdir16(cantAgentsDir, { recursive: true });
|
|
54912
|
-
const teamSrc =
|
|
54913
|
-
const teamDst =
|
|
54914
|
-
if (
|
|
54980
|
+
const teamSrc = join106(starterBundleSrc, "team.cant");
|
|
54981
|
+
const teamDst = join106(cantDir, "team.cant");
|
|
54982
|
+
if (existsSync106(teamSrc) && !existsSync106(teamDst)) {
|
|
54915
54983
|
await copyFile4(teamSrc, teamDst);
|
|
54916
54984
|
}
|
|
54917
|
-
const agentsSrc =
|
|
54918
|
-
if (
|
|
54985
|
+
const agentsSrc = join106(starterBundleSrc, "agents");
|
|
54986
|
+
if (existsSync106(agentsSrc)) {
|
|
54919
54987
|
const agentFiles = readdirSync35(agentsSrc).filter((f) => f.endsWith(".cant"));
|
|
54920
54988
|
for (const agentFile of agentFiles) {
|
|
54921
|
-
const dst =
|
|
54922
|
-
if (!
|
|
54923
|
-
await copyFile4(
|
|
54989
|
+
const dst = join106(cantAgentsDir, agentFile);
|
|
54990
|
+
if (!existsSync106(dst)) {
|
|
54991
|
+
await copyFile4(join106(agentsSrc, agentFile), dst);
|
|
54924
54992
|
}
|
|
54925
54993
|
}
|
|
54926
54994
|
}
|
|
54927
|
-
const identitySrc =
|
|
54928
|
-
const identityDst =
|
|
54929
|
-
if (
|
|
54995
|
+
const identitySrc = join106(starterBundleSrc, "CLEOOS-IDENTITY.md");
|
|
54996
|
+
const identityDst = join106(cleoDir, "CLEOOS-IDENTITY.md");
|
|
54997
|
+
if (existsSync106(identitySrc) && !existsSync106(identityDst)) {
|
|
54930
54998
|
await copyFile4(identitySrc, identityDst);
|
|
54931
54999
|
}
|
|
54932
55000
|
try {
|
|
54933
55001
|
const { getCleoHome: getCleoHome2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
54934
|
-
const globalIdentityDst =
|
|
54935
|
-
if (
|
|
55002
|
+
const globalIdentityDst = join106(getCleoHome2(), "CLEOOS-IDENTITY.md");
|
|
55003
|
+
if (existsSync106(identitySrc) && !existsSync106(globalIdentityDst)) {
|
|
54936
55004
|
await copyFile4(identitySrc, globalIdentityDst);
|
|
54937
55005
|
}
|
|
54938
55006
|
} catch {
|
|
@@ -56483,8 +56551,8 @@ function providerInstalled() {
|
|
|
56483
56551
|
}
|
|
56484
56552
|
function providerCount() {
|
|
56485
56553
|
try {
|
|
56486
|
-
const
|
|
56487
|
-
return { success: true, data: { count:
|
|
56554
|
+
const count3 = getProviderCount();
|
|
56555
|
+
return { success: true, data: { count: count3 } };
|
|
56488
56556
|
} catch (err) {
|
|
56489
56557
|
return {
|
|
56490
56558
|
success: false,
|
|
@@ -57292,7 +57360,7 @@ var SseTransport = class {
|
|
|
57292
57360
|
// --------------------------------------------------------------------------
|
|
57293
57361
|
/** Establish SSE connection. Resolves when open, rejects on error. */
|
|
57294
57362
|
connectSse() {
|
|
57295
|
-
return new Promise((
|
|
57363
|
+
return new Promise((resolve12, reject) => {
|
|
57296
57364
|
if (!this.state) {
|
|
57297
57365
|
reject(new Error("No state"));
|
|
57298
57366
|
return;
|
|
@@ -57308,7 +57376,7 @@ var SseTransport = class {
|
|
|
57308
57376
|
clearTimeout(timeout);
|
|
57309
57377
|
this.state.connected = true;
|
|
57310
57378
|
this.state.reconnectAttempts = 0;
|
|
57311
|
-
|
|
57379
|
+
resolve12();
|
|
57312
57380
|
});
|
|
57313
57381
|
es.addEventListener("message", (event) => {
|
|
57314
57382
|
this.handleSseMessage(event);
|
|
@@ -58290,16 +58358,16 @@ function collectTransitiveDependents(taskId, dependentsMap) {
|
|
|
58290
58358
|
return visited;
|
|
58291
58359
|
}
|
|
58292
58360
|
function countBlockedWork(taskId, transitiveDependents, taskMap) {
|
|
58293
|
-
let
|
|
58361
|
+
let count3 = 0;
|
|
58294
58362
|
for (const depId of transitiveDependents) {
|
|
58295
58363
|
if (depId === taskId) continue;
|
|
58296
58364
|
const task = taskMap.get(depId);
|
|
58297
58365
|
if (!task) continue;
|
|
58298
58366
|
if (task.status !== "done" && task.status !== "cancelled") {
|
|
58299
|
-
|
|
58367
|
+
count3++;
|
|
58300
58368
|
}
|
|
58301
58369
|
}
|
|
58302
|
-
return
|
|
58370
|
+
return count3;
|
|
58303
58371
|
}
|
|
58304
58372
|
function findAffectedPipelines(taskId, transitiveDependents, tasks2) {
|
|
58305
58373
|
const affectedEpicIds = /* @__PURE__ */ new Set();
|
|
@@ -58908,19 +58976,19 @@ async function extractWorkflowPatterns(accessor, minFrequency) {
|
|
|
58908
58976
|
depTargetCounts.set(dep, (depTargetCounts.get(dep) || 0) + 1);
|
|
58909
58977
|
}
|
|
58910
58978
|
}
|
|
58911
|
-
for (const [taskId,
|
|
58912
|
-
if (
|
|
58979
|
+
for (const [taskId, count3] of depTargetCounts) {
|
|
58980
|
+
if (count3 >= minFrequency) {
|
|
58913
58981
|
const hubTask = allTasks.find((t) => t.id === taskId);
|
|
58914
58982
|
const title = hubTask?.title ?? taskId;
|
|
58915
58983
|
patterns.push({
|
|
58916
58984
|
type: "workflow",
|
|
58917
|
-
pattern: `Task "${title}" (${taskId}) is a dependency hub with ${
|
|
58985
|
+
pattern: `Task "${title}" (${taskId}) is a dependency hub with ${count3} dependents`,
|
|
58918
58986
|
context: "Dependency graph analysis \u2014 hub tasks are critical path candidates",
|
|
58919
|
-
frequency:
|
|
58987
|
+
frequency: count3,
|
|
58920
58988
|
successRate: hubTask?.status === "done" ? 1 : null,
|
|
58921
|
-
impact:
|
|
58922
|
-
antiPattern:
|
|
58923
|
-
mitigation:
|
|
58989
|
+
impact: count3 >= 5 ? "high" : "medium",
|
|
58990
|
+
antiPattern: count3 >= 8 ? `Task ${taskId} may be an overly-centralized bottleneck` : null,
|
|
58991
|
+
mitigation: count3 >= 8 ? "Consider decomposing this task to reduce coupling" : null,
|
|
58924
58992
|
examples: allTasks.filter((t) => t.depends?.includes(taskId)).slice(0, 10).map((t) => t.id),
|
|
58925
58993
|
confidence: 0.7
|
|
58926
58994
|
});
|
|
@@ -58962,18 +59030,18 @@ async function extractObservationPatterns(brainAccessor, minFrequency) {
|
|
|
58962
59030
|
for (const obs of observations) {
|
|
58963
59031
|
typeCounts.set(obs.type, (typeCounts.get(obs.type) || 0) + 1);
|
|
58964
59032
|
}
|
|
58965
|
-
for (const [type,
|
|
58966
|
-
if (
|
|
59033
|
+
for (const [type, count3] of typeCounts) {
|
|
59034
|
+
if (count3 >= minFrequency) {
|
|
58967
59035
|
const patternType = observationTypeToPatternType(type);
|
|
58968
59036
|
patterns.push({
|
|
58969
59037
|
type: patternType,
|
|
58970
|
-
pattern: `${
|
|
59038
|
+
pattern: `${count3} "${type}" observations recorded`,
|
|
58971
59039
|
context: "Brain observation frequency analysis",
|
|
58972
|
-
frequency:
|
|
59040
|
+
frequency: count3,
|
|
58973
59041
|
successRate: type === "feature" || type === "refactor" ? 0.8 : null,
|
|
58974
|
-
impact:
|
|
58975
|
-
antiPattern: type === "bugfix" &&
|
|
58976
|
-
mitigation: type === "bugfix" &&
|
|
59042
|
+
impact: count3 >= 10 ? "high" : count3 >= 5 ? "medium" : "low",
|
|
59043
|
+
antiPattern: type === "bugfix" && count3 >= 5 ? "High number of bugfix observations may indicate quality issues" : null,
|
|
59044
|
+
mitigation: type === "bugfix" && count3 >= 5 ? "Consider adding more automated tests and code review" : null,
|
|
58977
59045
|
examples: observations.filter((o) => o.type === type).slice(0, 5).map((o) => o.id),
|
|
58978
59046
|
confidence: 0.5
|
|
58979
59047
|
});
|
|
@@ -58985,13 +59053,13 @@ async function extractObservationPatterns(brainAccessor, minFrequency) {
|
|
|
58985
59053
|
projectCounts.set(obs.project, (projectCounts.get(obs.project) || 0) + 1);
|
|
58986
59054
|
}
|
|
58987
59055
|
}
|
|
58988
|
-
for (const [project,
|
|
58989
|
-
if (
|
|
59056
|
+
for (const [project, count3] of projectCounts) {
|
|
59057
|
+
if (count3 >= minFrequency * 2) {
|
|
58990
59058
|
patterns.push({
|
|
58991
59059
|
type: "workflow",
|
|
58992
|
-
pattern: `Project "${project}" has ${
|
|
59060
|
+
pattern: `Project "${project}" has ${count3} observations \u2014 high activity area`,
|
|
58993
59061
|
context: "Cross-project observation density analysis",
|
|
58994
|
-
frequency:
|
|
59062
|
+
frequency: count3,
|
|
58995
59063
|
successRate: null,
|
|
58996
59064
|
impact: "medium",
|
|
58997
59065
|
antiPattern: null,
|
|
@@ -59505,7 +59573,7 @@ function augmentError(err, context) {
|
|
|
59505
59573
|
}
|
|
59506
59574
|
}
|
|
59507
59575
|
function sleep2(ms) {
|
|
59508
|
-
return new Promise((
|
|
59576
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
59509
59577
|
}
|
|
59510
59578
|
|
|
59511
59579
|
// packages/core/src/lib/index.ts
|
|
@@ -64969,6 +65037,7 @@ __export(nexus_exports, {
|
|
|
64969
65037
|
nexusSync: () => nexusSync,
|
|
64970
65038
|
nexusSyncAll: () => nexusSyncAll,
|
|
64971
65039
|
nexusUnregister: () => nexusUnregister,
|
|
65040
|
+
nexusUpdateIndexStats: () => nexusUpdateIndexStats,
|
|
64972
65041
|
orphanDetection: () => orphanDetection,
|
|
64973
65042
|
parseDirective: () => parseDirective,
|
|
64974
65043
|
parseQuery: () => parseQuery,
|
|
@@ -65118,8 +65187,8 @@ async function resolveProjectPath2(projectName) {
|
|
|
65118
65187
|
if (projectName === ".") {
|
|
65119
65188
|
try {
|
|
65120
65189
|
const accessor = await getAccessor(process.cwd());
|
|
65121
|
-
const
|
|
65122
|
-
if (
|
|
65190
|
+
const count3 = await accessor.countTasks();
|
|
65191
|
+
if (count3 >= 0) return process.cwd();
|
|
65123
65192
|
throw new Error("No task data");
|
|
65124
65193
|
} catch {
|
|
65125
65194
|
throw new CleoError(
|
|
@@ -69887,17 +69956,17 @@ async function generateReleaseChangelog(version2, loadTasksFn, cwd) {
|
|
|
69887
69956
|
function buildEntry(task) {
|
|
69888
69957
|
const cleanTitle = capitalize(stripConventionalPrefix(task.title));
|
|
69889
69958
|
const safeDesc = task.description?.replace(/\r?\n/g, " ").replace(/\s{2,}/g, " ").trim();
|
|
69890
|
-
const
|
|
69959
|
+
const desc6 = safeDesc;
|
|
69891
69960
|
const shouldIncludeDesc = (() => {
|
|
69892
|
-
if (!
|
|
69961
|
+
if (!desc6 || desc6.length === 0) return false;
|
|
69893
69962
|
const titleNorm = cleanTitle.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim();
|
|
69894
|
-
const descNorm =
|
|
69963
|
+
const descNorm = desc6.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim();
|
|
69895
69964
|
if (titleNorm === descNorm) return false;
|
|
69896
69965
|
if (descNorm.startsWith(titleNorm) && descNorm.length < titleNorm.length * 1.3) return false;
|
|
69897
|
-
return
|
|
69966
|
+
return desc6.length >= 20;
|
|
69898
69967
|
})();
|
|
69899
69968
|
if (shouldIncludeDesc) {
|
|
69900
|
-
const descDisplay =
|
|
69969
|
+
const descDisplay = desc6.length > 150 ? desc6.slice(0, 147) + "..." : desc6;
|
|
69901
69970
|
return `- **${cleanTitle}**: ${descDisplay} (${task.id})`;
|
|
69902
69971
|
}
|
|
69903
69972
|
return `- ${cleanTitle} (${task.id})`;
|
|
@@ -70463,11 +70532,11 @@ __export(remote_exports, {
|
|
|
70463
70532
|
init_paths();
|
|
70464
70533
|
init_git_checkpoint();
|
|
70465
70534
|
import { execFile as execFile5 } from "node:child_process";
|
|
70466
|
-
import { resolve as
|
|
70535
|
+
import { resolve as resolve8 } from "node:path";
|
|
70467
70536
|
import { promisify as promisify5 } from "node:util";
|
|
70468
70537
|
var execFileAsync5 = promisify5(execFile5);
|
|
70469
70538
|
async function cleoGitExec(args, cleoDir) {
|
|
70470
|
-
const abs =
|
|
70539
|
+
const abs = resolve8(cleoDir);
|
|
70471
70540
|
const result = await execFileAsync5("git", args, {
|
|
70472
70541
|
cwd: abs,
|
|
70473
70542
|
env: makeCleoGitEnv(cleoDir),
|
|
@@ -72334,7 +72403,7 @@ __export(security_exports, {
|
|
|
72334
72403
|
// packages/core/src/security/input-sanitization.ts
|
|
72335
72404
|
init_src();
|
|
72336
72405
|
init_tasks_schema();
|
|
72337
|
-
import { isAbsolute as isAbsolute2, normalize, relative as relative6, resolve as
|
|
72406
|
+
import { isAbsolute as isAbsolute2, normalize, relative as relative6, resolve as resolve9 } from "path";
|
|
72338
72407
|
|
|
72339
72408
|
// packages/core/src/tasks/id-generator.ts
|
|
72340
72409
|
function normalizeTaskId(input) {
|
|
@@ -72396,12 +72465,12 @@ function sanitizePath(path4, projectRoot) {
|
|
|
72396
72465
|
if (trimmedPath.includes("\0")) {
|
|
72397
72466
|
throw new SecurityError("Path contains null bytes", "E_PATH_TRAVERSAL", "path");
|
|
72398
72467
|
}
|
|
72399
|
-
const normalizedRoot =
|
|
72468
|
+
const normalizedRoot = resolve9(projectRoot);
|
|
72400
72469
|
let resolvedPath;
|
|
72401
72470
|
if (isAbsolute2(trimmedPath)) {
|
|
72402
72471
|
resolvedPath = normalize(trimmedPath);
|
|
72403
72472
|
} else {
|
|
72404
|
-
resolvedPath =
|
|
72473
|
+
resolvedPath = resolve9(normalizedRoot, trimmedPath);
|
|
72405
72474
|
}
|
|
72406
72475
|
const relativePath = relative6(normalizedRoot, resolvedPath);
|
|
72407
72476
|
if (relativePath.startsWith("..") || isAbsolute2(relativePath)) {
|
|
@@ -74289,7 +74358,7 @@ async function validateOrchestratorCompliance(epicId, cwd) {
|
|
|
74289
74358
|
|
|
74290
74359
|
// packages/core/src/skills/skill-paths.ts
|
|
74291
74360
|
import { existsSync as existsSync80, lstatSync, readlinkSync as readlinkSync2, realpathSync } from "node:fs";
|
|
74292
|
-
import { delimiter, join as join81, resolve as
|
|
74361
|
+
import { delimiter, join as join81, resolve as resolve10 } from "node:path";
|
|
74293
74362
|
import { getCanonicalSkillsDir as getCanonicalSkillsDir2 } from "@cleocode/caamp";
|
|
74294
74363
|
function getCaampCanonical() {
|
|
74295
74364
|
return getCanonicalSkillsDir2();
|
|
@@ -74406,7 +74475,7 @@ function getSkillSourceType(skillDir, projectRoot) {
|
|
|
74406
74475
|
}
|
|
74407
74476
|
} catch {
|
|
74408
74477
|
}
|
|
74409
|
-
if (normalizedDir.startsWith(
|
|
74478
|
+
if (normalizedDir.startsWith(resolve10(embeddedDir)) || normalizedDir.startsWith(join81(root, "skills"))) {
|
|
74410
74479
|
return "embedded";
|
|
74411
74480
|
}
|
|
74412
74481
|
if (normalizedDir.startsWith(caampDir)) {
|
|
@@ -74937,8 +75006,8 @@ async function initializeSpawnAdapters(manifests) {
|
|
|
74937
75006
|
if (!manifest.capabilities?.supportsSpawn) continue;
|
|
74938
75007
|
if (spawnRegistry.hasAdapterForProvider(manifest.provider)) continue;
|
|
74939
75008
|
try {
|
|
74940
|
-
const { join:
|
|
74941
|
-
const modulePath =
|
|
75009
|
+
const { join: join109 } = await import("node:path");
|
|
75010
|
+
const modulePath = join109(manifest.packagePath, manifest.entryPoint);
|
|
74942
75011
|
const adapterModule = await import(modulePath);
|
|
74943
75012
|
let SpawnProviderClass;
|
|
74944
75013
|
for (const [exportName, exportValue] of Object.entries(adapterModule)) {
|
|
@@ -75040,7 +75109,7 @@ async function queryTasks(cwd, since) {
|
|
|
75040
75109
|
try {
|
|
75041
75110
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
75042
75111
|
const { tasks: tasks2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
75043
|
-
const { and:
|
|
75112
|
+
const { and: and11, gte: gte3 } = await import("drizzle-orm");
|
|
75044
75113
|
const db = await getDb3(cwd);
|
|
75045
75114
|
const conditions = [];
|
|
75046
75115
|
if (since) {
|
|
@@ -75054,7 +75123,7 @@ async function queryTasks(cwd, since) {
|
|
|
75054
75123
|
sessionId: tasks2.sessionId,
|
|
75055
75124
|
completedAt: tasks2.completedAt,
|
|
75056
75125
|
createdAt: tasks2.createdAt
|
|
75057
|
-
}).from(tasks2).where(conditions.length > 0 ?
|
|
75126
|
+
}).from(tasks2).where(conditions.length > 0 ? and11(...conditions) : void 0).all();
|
|
75058
75127
|
return rows;
|
|
75059
75128
|
} catch (err) {
|
|
75060
75129
|
log9.warn({ err }, "Failed to query tasks for workflow telemetry");
|
|
@@ -75065,7 +75134,7 @@ async function queryCompletionAuditRows(cwd, since) {
|
|
|
75065
75134
|
try {
|
|
75066
75135
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
75067
75136
|
const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
75068
|
-
const { and:
|
|
75137
|
+
const { and: and11, gte: gte3 } = await import("drizzle-orm");
|
|
75069
75138
|
const db = await getDb3(cwd);
|
|
75070
75139
|
const conditions = [];
|
|
75071
75140
|
if (since) conditions.push(gte3(auditLog2.timestamp, since));
|
|
@@ -75077,7 +75146,7 @@ async function queryCompletionAuditRows(cwd, since) {
|
|
|
75077
75146
|
afterJson: auditLog2.afterJson,
|
|
75078
75147
|
operation: auditLog2.operation,
|
|
75079
75148
|
domain: auditLog2.domain
|
|
75080
|
-
}).from(auditLog2).where(conditions.length > 0 ?
|
|
75149
|
+
}).from(auditLog2).where(conditions.length > 0 ? and11(...conditions) : void 0).orderBy(auditLog2.timestamp).all();
|
|
75081
75150
|
return allRows.filter((row) => {
|
|
75082
75151
|
const isComplete = row.action === "task_completed" || row.action === "complete" || row.operation === "complete" && row.domain === "tasks";
|
|
75083
75152
|
if (!isComplete && row.afterJson) {
|
|
@@ -75532,7 +75601,7 @@ async function getDashboard(opts, accessor) {
|
|
|
75532
75601
|
labelMap[label] = (labelMap[label] ?? 0) + 1;
|
|
75533
75602
|
}
|
|
75534
75603
|
}
|
|
75535
|
-
const topLabels = Object.entries(labelMap).map(([label,
|
|
75604
|
+
const topLabels = Object.entries(labelMap).map(([label, count3]) => ({ label, count: count3 })).sort((a, b) => b.count - a.count).slice(0, 8);
|
|
75536
75605
|
return {
|
|
75537
75606
|
project,
|
|
75538
75607
|
currentPhase,
|
|
@@ -75570,7 +75639,7 @@ async function getCompletionHistory(opts) {
|
|
|
75570
75639
|
const date6 = c.timestamp.split("T")[0];
|
|
75571
75640
|
byDate[date6] = (byDate[date6] ?? 0) + 1;
|
|
75572
75641
|
}
|
|
75573
|
-
const dailyCounts = Object.entries(byDate).sort(([a], [b]) => a.localeCompare(b)).map(([date6,
|
|
75642
|
+
const dailyCounts = Object.entries(byDate).sort(([a], [b]) => a.localeCompare(b)).map(([date6, count3]) => ({ date: date6, count: count3 }));
|
|
75574
75643
|
const totalCompletions = completions.length;
|
|
75575
75644
|
const avgPerDay = days > 0 ? Math.round(totalCompletions / days * 100) / 100 : 0;
|
|
75576
75645
|
const peakDay = dailyCounts.reduce((max, d) => d.count > max.count ? d : max, {
|
|
@@ -76067,7 +76136,7 @@ function byLabelReport(tasks2) {
|
|
|
76067
76136
|
counts[label] = (counts[label] ?? 0) + 1;
|
|
76068
76137
|
}
|
|
76069
76138
|
}
|
|
76070
|
-
return Object.entries(counts).map(([label,
|
|
76139
|
+
return Object.entries(counts).map(([label, count3]) => ({ label, count: count3 })).sort((a, b) => b.count - a.count);
|
|
76071
76140
|
}
|
|
76072
76141
|
function byPriorityReport(tasks2) {
|
|
76073
76142
|
const PRIO_ORDER = ["critical", "high", "medium", "low", "unset"];
|
|
@@ -76127,15 +76196,15 @@ function trendsReport(tasks2) {
|
|
|
76127
76196
|
const date6 = t.archive.archivedAt.slice(0, 10);
|
|
76128
76197
|
byDay[date6] = (byDay[date6] ?? 0) + 1;
|
|
76129
76198
|
}
|
|
76130
|
-
const dailyEntries = Object.entries(byDay).map(([date6,
|
|
76199
|
+
const dailyEntries = Object.entries(byDay).map(([date6, count3]) => ({ date: date6, count: count3 })).sort((a, b) => a.date.localeCompare(b.date));
|
|
76131
76200
|
const byMonth = {};
|
|
76132
|
-
for (const { date: date6, count:
|
|
76201
|
+
for (const { date: date6, count: count3 } of dailyEntries) {
|
|
76133
76202
|
const month = date6.slice(0, 7);
|
|
76134
|
-
byMonth[month] = (byMonth[month] ?? 0) +
|
|
76203
|
+
byMonth[month] = (byMonth[month] ?? 0) + count3;
|
|
76135
76204
|
}
|
|
76136
|
-
const monthlyEntries = Object.entries(byMonth).map(([month,
|
|
76205
|
+
const monthlyEntries = Object.entries(byMonth).map(([month, count3]) => ({
|
|
76137
76206
|
month,
|
|
76138
|
-
count:
|
|
76207
|
+
count: count3
|
|
76139
76208
|
}));
|
|
76140
76209
|
const totalPeriod = dailyEntries.reduce((sum, d) => sum + d.count, 0);
|
|
76141
76210
|
return {
|
|
@@ -79078,6 +79147,304 @@ async function showTask(taskId, cwd, accessor) {
|
|
|
79078
79147
|
// packages/core/src/tasks/index.ts
|
|
79079
79148
|
init_update2();
|
|
79080
79149
|
|
|
79150
|
+
// packages/core/src/telemetry/index.ts
|
|
79151
|
+
var telemetry_exports = {};
|
|
79152
|
+
__export(telemetry_exports, {
|
|
79153
|
+
buildDiagnosticsReport: () => buildDiagnosticsReport,
|
|
79154
|
+
disableTelemetry: () => disableTelemetry,
|
|
79155
|
+
enableTelemetry: () => enableTelemetry,
|
|
79156
|
+
exportTelemetryEvents: () => exportTelemetryEvents,
|
|
79157
|
+
getTelemetryConfigPath: () => getTelemetryConfigPath,
|
|
79158
|
+
getTelemetryDb: () => getTelemetryDb,
|
|
79159
|
+
getTelemetryDbPath: () => getTelemetryDbPath,
|
|
79160
|
+
isTelemetryEnabled: () => isTelemetryEnabled,
|
|
79161
|
+
loadTelemetryConfig: () => loadTelemetryConfig,
|
|
79162
|
+
recordTelemetryEvent: () => recordTelemetryEvent,
|
|
79163
|
+
saveTelemetryConfig: () => saveTelemetryConfig,
|
|
79164
|
+
telemetryEvents: () => telemetryEvents,
|
|
79165
|
+
telemetrySchemaMeta: () => telemetrySchemaMeta
|
|
79166
|
+
});
|
|
79167
|
+
init_paths();
|
|
79168
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
79169
|
+
import { existsSync as existsSync96, mkdirSync as mkdirSync24, readFileSync as readFileSync68, writeFileSync as writeFileSync16 } from "node:fs";
|
|
79170
|
+
import { join as join99 } from "node:path";
|
|
79171
|
+
import { and as and10, count as count2, desc as desc5, gt as gt2, sql as sql13 } from "drizzle-orm";
|
|
79172
|
+
|
|
79173
|
+
// packages/core/src/telemetry/schema.ts
|
|
79174
|
+
var schema_exports = {};
|
|
79175
|
+
__export(schema_exports, {
|
|
79176
|
+
telemetryEvents: () => telemetryEvents,
|
|
79177
|
+
telemetrySchemaMeta: () => telemetrySchemaMeta
|
|
79178
|
+
});
|
|
79179
|
+
init_sqlite_core();
|
|
79180
|
+
import { sql as sql12 } from "drizzle-orm";
|
|
79181
|
+
var telemetryEvents = sqliteTable(
|
|
79182
|
+
"telemetry_events",
|
|
79183
|
+
{
|
|
79184
|
+
/** UUID primary key. */
|
|
79185
|
+
id: text("id").primaryKey(),
|
|
79186
|
+
/** Anonymous install identifier (UUIDv4, generated once on first enable). */
|
|
79187
|
+
anonymousId: text("anonymous_id").notNull(),
|
|
79188
|
+
/** Canonical domain (e.g. "tasks", "session", "memory", "admin"). */
|
|
79189
|
+
domain: text("domain").notNull(),
|
|
79190
|
+
/** CQRS gateway ("query" or "mutate"). */
|
|
79191
|
+
gateway: text("gateway").notNull(),
|
|
79192
|
+
/** Operation name (e.g. "show", "add", "complete"). */
|
|
79193
|
+
operation: text("operation").notNull(),
|
|
79194
|
+
/** Composed command string "{domain}.{operation}" for easy grouping. */
|
|
79195
|
+
command: text("command").notNull(),
|
|
79196
|
+
/** LAFS exit code (0 = success, non-zero = failure). */
|
|
79197
|
+
exitCode: integer("exit_code").notNull().default(0),
|
|
79198
|
+
/** Wall-clock duration in milliseconds. */
|
|
79199
|
+
durationMs: integer("duration_ms").notNull(),
|
|
79200
|
+
/** Machine-readable error code when exit_code != 0. NULL on success. */
|
|
79201
|
+
errorCode: text("error_code"),
|
|
79202
|
+
/** ISO-8601 timestamp of the invocation. */
|
|
79203
|
+
timestamp: text("timestamp").notNull().default(sql12`(datetime('now'))`)
|
|
79204
|
+
},
|
|
79205
|
+
(table) => [
|
|
79206
|
+
index("idx_telemetry_command").on(table.command),
|
|
79207
|
+
index("idx_telemetry_domain").on(table.domain),
|
|
79208
|
+
index("idx_telemetry_exit_code").on(table.exitCode),
|
|
79209
|
+
index("idx_telemetry_timestamp").on(table.timestamp),
|
|
79210
|
+
index("idx_telemetry_duration").on(table.durationMs)
|
|
79211
|
+
]
|
|
79212
|
+
);
|
|
79213
|
+
var telemetrySchemaMeta = sqliteTable("telemetry_schema_meta", {
|
|
79214
|
+
/** Config key. */
|
|
79215
|
+
key: text("key").primaryKey(),
|
|
79216
|
+
/** Config value. */
|
|
79217
|
+
value: text("value").notNull()
|
|
79218
|
+
});
|
|
79219
|
+
|
|
79220
|
+
// packages/core/src/telemetry/sqlite.ts
|
|
79221
|
+
init_node_sqlite();
|
|
79222
|
+
init_paths();
|
|
79223
|
+
init_migration_manager();
|
|
79224
|
+
init_sqlite2();
|
|
79225
|
+
import { mkdirSync as mkdirSync23 } from "node:fs";
|
|
79226
|
+
import { dirname as dirname20, join as join98 } from "node:path";
|
|
79227
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
79228
|
+
var DB_FILENAME4 = "telemetry.db";
|
|
79229
|
+
var TELEMETRY_SCHEMA_VERSION = "1.0.0";
|
|
79230
|
+
var _db3 = null;
|
|
79231
|
+
var _nativeDb3 = null;
|
|
79232
|
+
var _dbPath3 = null;
|
|
79233
|
+
var _initPromise3 = null;
|
|
79234
|
+
function getTelemetryDbPath() {
|
|
79235
|
+
return join98(getCleoHome(), DB_FILENAME4);
|
|
79236
|
+
}
|
|
79237
|
+
function resolveTelemetryMigrationsFolder() {
|
|
79238
|
+
const __filename = fileURLToPath6(import.meta.url);
|
|
79239
|
+
const __dir = dirname20(__filename);
|
|
79240
|
+
const isBundled = __dir.endsWith("/dist") || __dir.endsWith("\\dist");
|
|
79241
|
+
const pkgRoot = isBundled ? join98(__dir, "..") : join98(__dir, "..", "..");
|
|
79242
|
+
return join98(pkgRoot, "migrations", "drizzle-telemetry");
|
|
79243
|
+
}
|
|
79244
|
+
function runTelemetryMigrations(nativeDb, db) {
|
|
79245
|
+
const migrationsFolder = resolveTelemetryMigrationsFolder();
|
|
79246
|
+
reconcileJournal(nativeDb, migrationsFolder, "telemetry_events", "telemetry");
|
|
79247
|
+
migrateWithRetry(db, migrationsFolder, nativeDb, "telemetry_events", "telemetry");
|
|
79248
|
+
ensureColumns(
|
|
79249
|
+
nativeDb,
|
|
79250
|
+
"telemetry_events",
|
|
79251
|
+
[
|
|
79252
|
+
{ name: "anonymous_id", ddl: "text NOT NULL DEFAULT ''" },
|
|
79253
|
+
{ name: "domain", ddl: "text NOT NULL DEFAULT ''" },
|
|
79254
|
+
{ name: "gateway", ddl: "text NOT NULL DEFAULT 'query'" },
|
|
79255
|
+
{ name: "operation", ddl: "text NOT NULL DEFAULT ''" },
|
|
79256
|
+
{ name: "command", ddl: "text NOT NULL DEFAULT ''" },
|
|
79257
|
+
{ name: "exit_code", ddl: "integer NOT NULL DEFAULT 0" },
|
|
79258
|
+
{ name: "duration_ms", ddl: "integer NOT NULL DEFAULT 0" },
|
|
79259
|
+
{ name: "error_code", ddl: "text" }
|
|
79260
|
+
],
|
|
79261
|
+
"telemetry"
|
|
79262
|
+
);
|
|
79263
|
+
}
|
|
79264
|
+
function resetTelemetryDbState() {
|
|
79265
|
+
try {
|
|
79266
|
+
_nativeDb3?.close();
|
|
79267
|
+
} catch {
|
|
79268
|
+
}
|
|
79269
|
+
_db3 = null;
|
|
79270
|
+
_nativeDb3 = null;
|
|
79271
|
+
_dbPath3 = null;
|
|
79272
|
+
_initPromise3 = null;
|
|
79273
|
+
}
|
|
79274
|
+
async function getTelemetryDb() {
|
|
79275
|
+
const requestedPath = getTelemetryDbPath();
|
|
79276
|
+
if (_db3 && _dbPath3 !== requestedPath) {
|
|
79277
|
+
resetTelemetryDbState();
|
|
79278
|
+
}
|
|
79279
|
+
if (_db3) return _db3;
|
|
79280
|
+
if (_initPromise3) return _initPromise3;
|
|
79281
|
+
_initPromise3 = (async () => {
|
|
79282
|
+
const dbPath = requestedPath;
|
|
79283
|
+
_dbPath3 = dbPath;
|
|
79284
|
+
mkdirSync23(dirname20(dbPath), { recursive: true });
|
|
79285
|
+
const nativeDb = openNativeDatabase(dbPath);
|
|
79286
|
+
_nativeDb3 = nativeDb;
|
|
79287
|
+
const db = drizzle({ client: nativeDb, schema: schema_exports });
|
|
79288
|
+
runTelemetryMigrations(nativeDb, db);
|
|
79289
|
+
nativeDb.prepare(
|
|
79290
|
+
`INSERT OR IGNORE INTO telemetry_schema_meta (key, value) VALUES ('schemaVersion', '${TELEMETRY_SCHEMA_VERSION}')`
|
|
79291
|
+
).run();
|
|
79292
|
+
_db3 = db;
|
|
79293
|
+
return db;
|
|
79294
|
+
})();
|
|
79295
|
+
return _initPromise3;
|
|
79296
|
+
}
|
|
79297
|
+
|
|
79298
|
+
// packages/core/src/telemetry/index.ts
|
|
79299
|
+
var TELEMETRY_CONFIG_FILENAME = "telemetry-config.json";
|
|
79300
|
+
function getTelemetryConfigPath() {
|
|
79301
|
+
return join99(getCleoHome(), TELEMETRY_CONFIG_FILENAME);
|
|
79302
|
+
}
|
|
79303
|
+
function loadTelemetryConfig() {
|
|
79304
|
+
const path4 = getTelemetryConfigPath();
|
|
79305
|
+
if (!existsSync96(path4)) {
|
|
79306
|
+
return { enabled: false, anonymousId: "" };
|
|
79307
|
+
}
|
|
79308
|
+
try {
|
|
79309
|
+
return JSON.parse(readFileSync68(path4, "utf-8"));
|
|
79310
|
+
} catch {
|
|
79311
|
+
return { enabled: false, anonymousId: "" };
|
|
79312
|
+
}
|
|
79313
|
+
}
|
|
79314
|
+
function saveTelemetryConfig(config2) {
|
|
79315
|
+
const path4 = getTelemetryConfigPath();
|
|
79316
|
+
mkdirSync24(join99(path4, ".."), { recursive: true });
|
|
79317
|
+
writeFileSync16(path4, JSON.stringify(config2, null, 2), "utf-8");
|
|
79318
|
+
}
|
|
79319
|
+
function isTelemetryEnabled() {
|
|
79320
|
+
return loadTelemetryConfig().enabled;
|
|
79321
|
+
}
|
|
79322
|
+
function enableTelemetry() {
|
|
79323
|
+
const existing = loadTelemetryConfig();
|
|
79324
|
+
const config2 = {
|
|
79325
|
+
enabled: true,
|
|
79326
|
+
anonymousId: existing.anonymousId || randomUUID7()
|
|
79327
|
+
};
|
|
79328
|
+
saveTelemetryConfig(config2);
|
|
79329
|
+
return config2;
|
|
79330
|
+
}
|
|
79331
|
+
function disableTelemetry() {
|
|
79332
|
+
const existing = loadTelemetryConfig();
|
|
79333
|
+
const config2 = { ...existing, enabled: false };
|
|
79334
|
+
saveTelemetryConfig(config2);
|
|
79335
|
+
return config2;
|
|
79336
|
+
}
|
|
79337
|
+
async function recordTelemetryEvent(event) {
|
|
79338
|
+
const config2 = loadTelemetryConfig();
|
|
79339
|
+
if (!config2.enabled || !config2.anonymousId) return;
|
|
79340
|
+
try {
|
|
79341
|
+
const db = await getTelemetryDb();
|
|
79342
|
+
const command = `${event.domain}.${event.operation}`;
|
|
79343
|
+
await db.insert(telemetryEvents).values({
|
|
79344
|
+
id: randomUUID7(),
|
|
79345
|
+
anonymousId: config2.anonymousId,
|
|
79346
|
+
domain: event.domain,
|
|
79347
|
+
gateway: event.gateway,
|
|
79348
|
+
operation: event.operation,
|
|
79349
|
+
command,
|
|
79350
|
+
exitCode: event.exitCode,
|
|
79351
|
+
durationMs: event.durationMs,
|
|
79352
|
+
errorCode: event.errorCode ?? null,
|
|
79353
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
79354
|
+
}).run();
|
|
79355
|
+
} catch {
|
|
79356
|
+
}
|
|
79357
|
+
}
|
|
79358
|
+
function daysAgo(n) {
|
|
79359
|
+
const d = /* @__PURE__ */ new Date();
|
|
79360
|
+
d.setDate(d.getDate() - n);
|
|
79361
|
+
return d.toISOString();
|
|
79362
|
+
}
|
|
79363
|
+
async function buildDiagnosticsReport(days = 30) {
|
|
79364
|
+
const config2 = loadTelemetryConfig();
|
|
79365
|
+
if (!config2.enabled) return null;
|
|
79366
|
+
const db = await getTelemetryDb();
|
|
79367
|
+
const from = daysAgo(days);
|
|
79368
|
+
const to = (/* @__PURE__ */ new Date()).toISOString();
|
|
79369
|
+
const [totalRow] = await db.select({ n: count2(telemetryEvents.id) }).from(telemetryEvents).where(gt2(telemetryEvents.timestamp, from)).all();
|
|
79370
|
+
const totalEvents = totalRow?.n ?? 0;
|
|
79371
|
+
if (totalEvents === 0)
|
|
79372
|
+
return {
|
|
79373
|
+
period: { from, to },
|
|
79374
|
+
totalEvents: 0,
|
|
79375
|
+
topFailing: [],
|
|
79376
|
+
topSlow: [],
|
|
79377
|
+
rareCommands: [],
|
|
79378
|
+
observations: []
|
|
79379
|
+
};
|
|
79380
|
+
const rows = await db.select({
|
|
79381
|
+
command: telemetryEvents.command,
|
|
79382
|
+
total: count2(telemetryEvents.id),
|
|
79383
|
+
failures: sql13`SUM(CASE WHEN ${telemetryEvents.exitCode} != 0 THEN 1 ELSE 0 END)`,
|
|
79384
|
+
avgMs: sql13`AVG(${telemetryEvents.durationMs})`,
|
|
79385
|
+
maxMs: sql13`MAX(${telemetryEvents.durationMs})`
|
|
79386
|
+
}).from(telemetryEvents).where(gt2(telemetryEvents.timestamp, from)).groupBy(telemetryEvents.command).all();
|
|
79387
|
+
const errorCodeRows = await db.select({
|
|
79388
|
+
command: telemetryEvents.command,
|
|
79389
|
+
errorCode: telemetryEvents.errorCode,
|
|
79390
|
+
n: count2(telemetryEvents.id)
|
|
79391
|
+
}).from(telemetryEvents).where(and10(gt2(telemetryEvents.timestamp, from), sql13`${telemetryEvents.errorCode} IS NOT NULL`)).groupBy(telemetryEvents.command, telemetryEvents.errorCode).orderBy(desc5(count2(telemetryEvents.id))).all();
|
|
79392
|
+
const topErrorMap = /* @__PURE__ */ new Map();
|
|
79393
|
+
for (const r of errorCodeRows) {
|
|
79394
|
+
if (!topErrorMap.has(r.command)) {
|
|
79395
|
+
topErrorMap.set(r.command, r.errorCode ?? "");
|
|
79396
|
+
}
|
|
79397
|
+
}
|
|
79398
|
+
const stats2 = rows.map((r) => {
|
|
79399
|
+
const failures = Number(r.failures) || 0;
|
|
79400
|
+
const total = Number(r.total) || 0;
|
|
79401
|
+
return {
|
|
79402
|
+
command: r.command,
|
|
79403
|
+
count: total,
|
|
79404
|
+
failureCount: failures,
|
|
79405
|
+
failureRate: total > 0 ? failures / total : 0,
|
|
79406
|
+
avgDurationMs: Math.round(Number(r.avgMs) || 0),
|
|
79407
|
+
maxDurationMs: Math.round(Number(r.maxMs) || 0),
|
|
79408
|
+
topErrorCode: topErrorMap.get(r.command) ?? null
|
|
79409
|
+
};
|
|
79410
|
+
});
|
|
79411
|
+
const topFailing = stats2.filter((s) => s.count >= 5 && s.failureRate > 0).sort((a, b) => b.failureRate - a.failureRate).slice(0, 10);
|
|
79412
|
+
const topSlow = [...stats2].sort((a, b) => b.avgDurationMs - a.avgDurationMs).slice(0, 10);
|
|
79413
|
+
const rareCommands = stats2.filter((s) => s.count === 1).map((s) => s.command);
|
|
79414
|
+
const observations = [];
|
|
79415
|
+
for (const s of topFailing.slice(0, 5)) {
|
|
79416
|
+
const pct = Math.round(s.failureRate * 100);
|
|
79417
|
+
const errPart = s.topErrorCode ? ` (most common error: ${s.topErrorCode})` : "";
|
|
79418
|
+
observations.push(
|
|
79419
|
+
`Command '${s.command}' fails ${pct}% of the time across ${s.count} invocations${errPart}. Investigate root cause.`
|
|
79420
|
+
);
|
|
79421
|
+
}
|
|
79422
|
+
const sortedAvg = stats2.map((s) => s.avgDurationMs).sort((a, b) => a - b);
|
|
79423
|
+
const median = sortedAvg[Math.floor(sortedAvg.length / 2)] ?? 0;
|
|
79424
|
+
for (const s of topSlow.slice(0, 5)) {
|
|
79425
|
+
if (median > 0 && s.avgDurationMs > median * 2) {
|
|
79426
|
+
observations.push(
|
|
79427
|
+
`Command '${s.command}' averages ${s.avgDurationMs}ms \u2014 ${Math.round(s.avgDurationMs / median)}x slower than the ${median}ms median. Profile for performance improvement.`
|
|
79428
|
+
);
|
|
79429
|
+
}
|
|
79430
|
+
}
|
|
79431
|
+
return { period: { from, to }, totalEvents, topFailing, topSlow, rareCommands, observations };
|
|
79432
|
+
}
|
|
79433
|
+
async function exportTelemetryEvents(days) {
|
|
79434
|
+
const config2 = loadTelemetryConfig();
|
|
79435
|
+
if (!config2.enabled) return [];
|
|
79436
|
+
const db = await getTelemetryDb();
|
|
79437
|
+
const rows = days ? await db.select().from(telemetryEvents).where(gt2(telemetryEvents.timestamp, daysAgo(days))).orderBy(desc5(telemetryEvents.timestamp)).all() : await db.select().from(telemetryEvents).orderBy(desc5(telemetryEvents.timestamp)).all();
|
|
79438
|
+
return rows.map((r) => ({
|
|
79439
|
+
domain: r.domain,
|
|
79440
|
+
gateway: r.gateway,
|
|
79441
|
+
operation: r.operation,
|
|
79442
|
+
durationMs: r.durationMs,
|
|
79443
|
+
exitCode: r.exitCode,
|
|
79444
|
+
errorCode: r.errorCode
|
|
79445
|
+
}));
|
|
79446
|
+
}
|
|
79447
|
+
|
|
79081
79448
|
// packages/core/src/templates/index.ts
|
|
79082
79449
|
var templates_exports = {};
|
|
79083
79450
|
__export(templates_exports, {
|
|
@@ -79089,8 +79456,8 @@ __export(templates_exports, {
|
|
|
79089
79456
|
|
|
79090
79457
|
// packages/core/src/templates/parser.ts
|
|
79091
79458
|
init_platform();
|
|
79092
|
-
import { existsSync as
|
|
79093
|
-
import { join as
|
|
79459
|
+
import { existsSync as existsSync97, readdirSync as readdirSync30, readFileSync as readFileSync69 } from "fs";
|
|
79460
|
+
import { join as join100 } from "path";
|
|
79094
79461
|
import { parse as parseYaml } from "yaml";
|
|
79095
79462
|
var SUFFIX_PATTERNS = ["_report", "_request", "_question"];
|
|
79096
79463
|
function deriveSubcommand(filename) {
|
|
@@ -79105,8 +79472,8 @@ function deriveSubcommand(filename) {
|
|
|
79105
79472
|
return firstWord.toLowerCase();
|
|
79106
79473
|
}
|
|
79107
79474
|
function parseTemplateFile2(templateDir, filename) {
|
|
79108
|
-
const filePath =
|
|
79109
|
-
const raw =
|
|
79475
|
+
const filePath = join100(templateDir, filename);
|
|
79476
|
+
const raw = readFileSync69(filePath, "utf-8");
|
|
79110
79477
|
const parsed = parseYaml(raw);
|
|
79111
79478
|
const name2 = typeof parsed.name === "string" ? parsed.name : filename;
|
|
79112
79479
|
const titlePrefix = typeof parsed.title === "string" ? parsed.title : "";
|
|
@@ -79155,8 +79522,8 @@ function parseTemplateFile2(templateDir, filename) {
|
|
|
79155
79522
|
};
|
|
79156
79523
|
}
|
|
79157
79524
|
function parseIssueTemplates2(projectRoot) {
|
|
79158
|
-
const templateDir =
|
|
79159
|
-
if (!
|
|
79525
|
+
const templateDir = join100(projectRoot, ".github", "ISSUE_TEMPLATE");
|
|
79526
|
+
if (!existsSync97(templateDir)) {
|
|
79160
79527
|
return {
|
|
79161
79528
|
success: false,
|
|
79162
79529
|
error: { code: "E_NOT_FOUND", message: `Issue template directory not found: ${templateDir}` }
|
|
@@ -79303,9 +79670,9 @@ __export(ui_exports, {
|
|
|
79303
79670
|
});
|
|
79304
79671
|
|
|
79305
79672
|
// packages/core/src/ui/aliases.ts
|
|
79306
|
-
import { existsSync as
|
|
79673
|
+
import { existsSync as existsSync98, readFileSync as readFileSync70, writeFileSync as writeFileSync17 } from "node:fs";
|
|
79307
79674
|
import { homedir as homedir6, platform as platform3 } from "node:os";
|
|
79308
|
-
import { join as
|
|
79675
|
+
import { join as join101 } from "node:path";
|
|
79309
79676
|
var MARKER_START = "# CLEO-CLAUDE-ALIASES:START";
|
|
79310
79677
|
var MARKER_END = "# CLEO-CLAUDE-ALIASES:END";
|
|
79311
79678
|
var ALIASES_VERSION = "1.0.0";
|
|
@@ -79327,22 +79694,22 @@ function getRcFilePath(shell) {
|
|
|
79327
79694
|
const sh = shell ?? getCurrentShell();
|
|
79328
79695
|
switch (sh) {
|
|
79329
79696
|
case "bash":
|
|
79330
|
-
return
|
|
79697
|
+
return join101(home, ".bashrc");
|
|
79331
79698
|
case "zsh":
|
|
79332
|
-
return
|
|
79699
|
+
return join101(home, ".zshrc");
|
|
79333
79700
|
case "powershell":
|
|
79334
|
-
return
|
|
79701
|
+
return join101(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
79335
79702
|
case "cmd":
|
|
79336
79703
|
return "";
|
|
79337
79704
|
// CMD doesn't have a standard RC
|
|
79338
79705
|
default:
|
|
79339
|
-
return
|
|
79706
|
+
return join101(home, ".bashrc");
|
|
79340
79707
|
}
|
|
79341
79708
|
}
|
|
79342
79709
|
function detectAvailableShells() {
|
|
79343
79710
|
const shells = [];
|
|
79344
|
-
if (
|
|
79345
|
-
if (
|
|
79711
|
+
if (existsSync98(getRcFilePath("bash")) || existsSync98("/bin/bash")) shells.push("bash");
|
|
79712
|
+
if (existsSync98(getRcFilePath("zsh")) || existsSync98("/bin/zsh")) shells.push("zsh");
|
|
79346
79713
|
if (platform3() === "win32") shells.push("powershell");
|
|
79347
79714
|
return shells;
|
|
79348
79715
|
}
|
|
@@ -79374,47 +79741,47 @@ function generatePowershellAliases(cleoPath) {
|
|
|
79374
79741
|
].join("\n");
|
|
79375
79742
|
}
|
|
79376
79743
|
function hasAliasBlock(filePath) {
|
|
79377
|
-
if (!
|
|
79378
|
-
const content =
|
|
79744
|
+
if (!existsSync98(filePath)) return false;
|
|
79745
|
+
const content = readFileSync70(filePath, "utf-8");
|
|
79379
79746
|
return content.includes(MARKER_START) && content.includes(MARKER_END);
|
|
79380
79747
|
}
|
|
79381
79748
|
function getInstalledVersion(filePath) {
|
|
79382
|
-
if (!
|
|
79383
|
-
const content =
|
|
79749
|
+
if (!existsSync98(filePath)) return null;
|
|
79750
|
+
const content = readFileSync70(filePath, "utf-8");
|
|
79384
79751
|
const match = content.match(/CLEO CLI aliases \(v([^)]+)\)/);
|
|
79385
79752
|
return match?.[1] ?? null;
|
|
79386
79753
|
}
|
|
79387
79754
|
function injectAliases(filePath, shell = "bash", cleoPath) {
|
|
79388
79755
|
const content = shell === "powershell" ? generatePowershellAliases(cleoPath) : generateBashAliases(cleoPath);
|
|
79389
|
-
if (!
|
|
79390
|
-
|
|
79756
|
+
if (!existsSync98(filePath)) {
|
|
79757
|
+
writeFileSync17(filePath, content + "\n", "utf-8");
|
|
79391
79758
|
return { action: "created", version: ALIASES_VERSION };
|
|
79392
79759
|
}
|
|
79393
|
-
const existing =
|
|
79760
|
+
const existing = readFileSync70(filePath, "utf-8");
|
|
79394
79761
|
if (hasAliasBlock(filePath)) {
|
|
79395
79762
|
const startIdx = existing.indexOf(MARKER_START);
|
|
79396
79763
|
const endIdx = existing.indexOf(MARKER_END) + MARKER_END.length;
|
|
79397
79764
|
const updated = existing.slice(0, startIdx) + content + existing.slice(endIdx);
|
|
79398
|
-
|
|
79765
|
+
writeFileSync17(filePath, updated, "utf-8");
|
|
79399
79766
|
return { action: "updated", version: ALIASES_VERSION };
|
|
79400
79767
|
}
|
|
79401
|
-
|
|
79768
|
+
writeFileSync17(filePath, existing + "\n" + content + "\n", "utf-8");
|
|
79402
79769
|
return { action: "added", version: ALIASES_VERSION };
|
|
79403
79770
|
}
|
|
79404
79771
|
function removeAliases(filePath) {
|
|
79405
|
-
if (!
|
|
79406
|
-
const existing =
|
|
79772
|
+
if (!existsSync98(filePath) || !hasAliasBlock(filePath)) return false;
|
|
79773
|
+
const existing = readFileSync70(filePath, "utf-8");
|
|
79407
79774
|
const startIdx = existing.indexOf(MARKER_START);
|
|
79408
79775
|
const endIdx = existing.indexOf(MARKER_END) + MARKER_END.length;
|
|
79409
79776
|
const before = existing.slice(0, startIdx).replace(/\n+$/, "\n");
|
|
79410
79777
|
const after = existing.slice(endIdx).replace(/^\n+/, "\n");
|
|
79411
|
-
|
|
79778
|
+
writeFileSync17(filePath, before + after, "utf-8");
|
|
79412
79779
|
return true;
|
|
79413
79780
|
}
|
|
79414
79781
|
function checkAliasesStatus(shell) {
|
|
79415
79782
|
const sh = shell ?? getCurrentShell();
|
|
79416
79783
|
const rcFile = getRcFilePath(sh);
|
|
79417
|
-
if (!rcFile || !
|
|
79784
|
+
if (!rcFile || !existsSync98(rcFile)) {
|
|
79418
79785
|
return { shell: sh, rcFile, installed: false, version: null, needsUpdate: false };
|
|
79419
79786
|
}
|
|
79420
79787
|
const installed = hasAliasBlock(rcFile);
|
|
@@ -79425,7 +79792,7 @@ function checkAliasesStatus(shell) {
|
|
|
79425
79792
|
|
|
79426
79793
|
// packages/core/src/ui/changelog.ts
|
|
79427
79794
|
init_data_accessor();
|
|
79428
|
-
import { appendFileSync as appendFileSync9, existsSync as
|
|
79795
|
+
import { appendFileSync as appendFileSync9, existsSync as existsSync99, readFileSync as readFileSync71, writeFileSync as writeFileSync18 } from "node:fs";
|
|
79429
79796
|
var LABEL_CATEGORIES = {
|
|
79430
79797
|
feature: "Features",
|
|
79431
79798
|
feat: "Features",
|
|
@@ -79526,21 +79893,21 @@ function formatChangelogJson(version2, date6, sections) {
|
|
|
79526
79893
|
};
|
|
79527
79894
|
}
|
|
79528
79895
|
function writeChangelogFile(filePath, content) {
|
|
79529
|
-
|
|
79896
|
+
writeFileSync18(filePath, content, "utf-8");
|
|
79530
79897
|
}
|
|
79531
79898
|
function appendToChangelog(filePath, newContent) {
|
|
79532
|
-
if (!
|
|
79533
|
-
|
|
79899
|
+
if (!existsSync99(filePath)) {
|
|
79900
|
+
writeFileSync18(filePath, `# Changelog
|
|
79534
79901
|
|
|
79535
79902
|
${newContent}`, "utf-8");
|
|
79536
79903
|
return;
|
|
79537
79904
|
}
|
|
79538
|
-
const existing =
|
|
79905
|
+
const existing = readFileSync71(filePath, "utf-8");
|
|
79539
79906
|
const headerMatch = existing.match(/^# .+\n/m);
|
|
79540
79907
|
if (headerMatch) {
|
|
79541
79908
|
const insertPos = (headerMatch.index ?? 0) + headerMatch[0].length;
|
|
79542
79909
|
const updated = existing.slice(0, insertPos) + "\n" + newContent + existing.slice(insertPos);
|
|
79543
|
-
|
|
79910
|
+
writeFileSync18(filePath, updated, "utf-8");
|
|
79544
79911
|
} else {
|
|
79545
79912
|
appendFileSync9(filePath, "\n" + newContent);
|
|
79546
79913
|
}
|
|
@@ -79575,13 +79942,13 @@ ${markdown}`);
|
|
|
79575
79942
|
}
|
|
79576
79943
|
|
|
79577
79944
|
// packages/core/src/ui/command-registry.ts
|
|
79578
|
-
import { existsSync as
|
|
79579
|
-
import { basename as basename16, join as
|
|
79945
|
+
import { existsSync as existsSync100, readdirSync as readdirSync31, readFileSync as readFileSync72 } from "node:fs";
|
|
79946
|
+
import { basename as basename16, join as join102 } from "node:path";
|
|
79580
79947
|
var CLEO_HEADER_START = "###CLEO";
|
|
79581
79948
|
var CLEO_HEADER_END = "###END";
|
|
79582
79949
|
function parseCommandHeader(scriptPath) {
|
|
79583
|
-
if (!
|
|
79584
|
-
const content =
|
|
79950
|
+
if (!existsSync100(scriptPath)) return null;
|
|
79951
|
+
const content = readFileSync72(scriptPath, "utf-8");
|
|
79585
79952
|
const lines = content.split("\n");
|
|
79586
79953
|
let inHeader = false;
|
|
79587
79954
|
const headerLines = [];
|
|
@@ -79659,10 +80026,10 @@ function parseCommandHeader(scriptPath) {
|
|
|
79659
80026
|
}
|
|
79660
80027
|
function scanAllCommands(scriptsDir) {
|
|
79661
80028
|
const registry2 = /* @__PURE__ */ new Map();
|
|
79662
|
-
if (!
|
|
80029
|
+
if (!existsSync100(scriptsDir)) return registry2;
|
|
79663
80030
|
for (const file2 of readdirSync31(scriptsDir)) {
|
|
79664
80031
|
if (!file2.endsWith(".sh") && !file2.endsWith(".ts")) continue;
|
|
79665
|
-
const meta3 = parseCommandHeader(
|
|
80032
|
+
const meta3 = parseCommandHeader(join102(scriptsDir, file2));
|
|
79666
80033
|
if (meta3) {
|
|
79667
80034
|
registry2.set(meta3.command, meta3);
|
|
79668
80035
|
}
|
|
@@ -80605,10 +80972,10 @@ function calculateOrchestrationOverhead(orchestratorTokens, totalSubagentTokens,
|
|
|
80605
80972
|
}
|
|
80606
80973
|
|
|
80607
80974
|
// packages/core/src/validation/docs-sync.ts
|
|
80608
|
-
import { existsSync as
|
|
80609
|
-
import { join as
|
|
80975
|
+
import { existsSync as existsSync101, readdirSync as readdirSync32, readFileSync as readFileSync73 } from "node:fs";
|
|
80976
|
+
import { join as join103 } from "node:path";
|
|
80610
80977
|
function getScriptCommands(scriptsDir) {
|
|
80611
|
-
if (!
|
|
80978
|
+
if (!existsSync101(scriptsDir)) return [];
|
|
80612
80979
|
try {
|
|
80613
80980
|
return readdirSync32(scriptsDir).filter((f) => f.endsWith(".sh")).map((f) => f.replace(/\.sh$/, "")).sort();
|
|
80614
80981
|
} catch {
|
|
@@ -80616,9 +80983,9 @@ function getScriptCommands(scriptsDir) {
|
|
|
80616
80983
|
}
|
|
80617
80984
|
}
|
|
80618
80985
|
function getIndexScripts(indexPath) {
|
|
80619
|
-
if (!
|
|
80986
|
+
if (!existsSync101(indexPath)) return [];
|
|
80620
80987
|
try {
|
|
80621
|
-
const content =
|
|
80988
|
+
const content = readFileSync73(indexPath, "utf-8");
|
|
80622
80989
|
const index2 = JSON.parse(content);
|
|
80623
80990
|
return index2.commands.map((cmd) => cmd.script ?? "").filter((s) => s).map((s) => s.replace(/\.sh$/, "")).sort();
|
|
80624
80991
|
} catch {
|
|
@@ -80626,9 +80993,9 @@ function getIndexScripts(indexPath) {
|
|
|
80626
80993
|
}
|
|
80627
80994
|
}
|
|
80628
80995
|
function getIndexCommands(indexPath) {
|
|
80629
|
-
if (!
|
|
80996
|
+
if (!existsSync101(indexPath)) return [];
|
|
80630
80997
|
try {
|
|
80631
|
-
const content =
|
|
80998
|
+
const content = readFileSync73(indexPath, "utf-8");
|
|
80632
80999
|
const index2 = JSON.parse(content);
|
|
80633
81000
|
return index2.commands.map((cmd) => cmd.name).sort();
|
|
80634
81001
|
} catch {
|
|
@@ -80662,11 +81029,11 @@ function checkCommandsSync(scriptsDir, indexPath) {
|
|
|
80662
81029
|
return issues;
|
|
80663
81030
|
}
|
|
80664
81031
|
function checkWrapperSync(wrapperPath, indexPath) {
|
|
80665
|
-
if (!
|
|
81032
|
+
if (!existsSync101(wrapperPath) || !existsSync101(indexPath)) return [];
|
|
80666
81033
|
const issues = [];
|
|
80667
81034
|
try {
|
|
80668
|
-
const wrapperContent =
|
|
80669
|
-
const indexContent =
|
|
81035
|
+
const wrapperContent = readFileSync73(wrapperPath, "utf-8");
|
|
81036
|
+
const indexContent = readFileSync73(indexPath, "utf-8");
|
|
80670
81037
|
const index2 = JSON.parse(indexContent);
|
|
80671
81038
|
const match = wrapperContent.match(/_get_all_commands\(\)\s*\{[^}]*echo\s+"([^"]+)"/);
|
|
80672
81039
|
const wrapperCmds = new Set(match ? match[1].split(/\s+/).filter(Boolean) : []);
|
|
@@ -80699,16 +81066,16 @@ var CRITICAL_COMMANDS = [
|
|
|
80699
81066
|
];
|
|
80700
81067
|
function detectDrift(mode = "full", projectRoot = ".") {
|
|
80701
81068
|
const issues = [];
|
|
80702
|
-
const scriptsDir =
|
|
80703
|
-
const indexPath =
|
|
81069
|
+
const scriptsDir = join103(projectRoot, "scripts");
|
|
81070
|
+
const indexPath = join103(projectRoot, "docs/commands/COMMANDS-INDEX.json");
|
|
80704
81071
|
issues.push(...checkCommandsSync(scriptsDir, indexPath));
|
|
80705
|
-
const wrapperPath =
|
|
81072
|
+
const wrapperPath = join103(projectRoot, "installer/lib/link.sh");
|
|
80706
81073
|
issues.push(...checkWrapperSync(wrapperPath, indexPath));
|
|
80707
81074
|
if (mode === "full") {
|
|
80708
|
-
const readmePath =
|
|
80709
|
-
if (
|
|
81075
|
+
const readmePath = join103(projectRoot, "README.md");
|
|
81076
|
+
if (existsSync101(readmePath)) {
|
|
80710
81077
|
try {
|
|
80711
|
-
const readme =
|
|
81078
|
+
const readme = readFileSync73(readmePath, "utf-8");
|
|
80712
81079
|
const readmeCmds = new Set(
|
|
80713
81080
|
(readme.match(/cleo [a-z-]+/g) ?? []).map((m) => m.replace("cleo ", ""))
|
|
80714
81081
|
);
|
|
@@ -80742,14 +81109,14 @@ function shouldRunDriftDetection(enabled = true, autoCheck = false, command, cri
|
|
|
80742
81109
|
// packages/core/src/validation/doctor/project-cache.ts
|
|
80743
81110
|
init_paths();
|
|
80744
81111
|
import { createHash as createHash12 } from "node:crypto";
|
|
80745
|
-
import { existsSync as
|
|
80746
|
-
import { dirname as
|
|
81112
|
+
import { existsSync as existsSync102, mkdirSync as mkdirSync25, readFileSync as readFileSync74, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19 } from "node:fs";
|
|
81113
|
+
import { dirname as dirname21, join as join104 } from "node:path";
|
|
80747
81114
|
var CACHE_VERSION = "1.0.0";
|
|
80748
81115
|
var CACHE_TTL_SECONDS = 300;
|
|
80749
81116
|
var CACHE_FILE2 = "doctor-project-cache.json";
|
|
80750
81117
|
function getCacheFilePath(cleoHome) {
|
|
80751
81118
|
const home = cleoHome ?? getCleoHome();
|
|
80752
|
-
return
|
|
81119
|
+
return join104(home, CACHE_FILE2);
|
|
80753
81120
|
}
|
|
80754
81121
|
function initCacheFile(cacheFile) {
|
|
80755
81122
|
const cache = {
|
|
@@ -80757,26 +81124,26 @@ function initCacheFile(cacheFile) {
|
|
|
80757
81124
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
80758
81125
|
projects: {}
|
|
80759
81126
|
};
|
|
80760
|
-
const dir =
|
|
80761
|
-
if (!
|
|
80762
|
-
|
|
81127
|
+
const dir = dirname21(cacheFile);
|
|
81128
|
+
if (!existsSync102(dir)) {
|
|
81129
|
+
mkdirSync25(dir, { recursive: true });
|
|
80763
81130
|
}
|
|
80764
|
-
|
|
81131
|
+
writeFileSync19(cacheFile, JSON.stringify(cache, null, 2));
|
|
80765
81132
|
return cache;
|
|
80766
81133
|
}
|
|
80767
81134
|
function loadCache(cacheFile) {
|
|
80768
|
-
if (!
|
|
81135
|
+
if (!existsSync102(cacheFile)) return null;
|
|
80769
81136
|
try {
|
|
80770
|
-
const content =
|
|
81137
|
+
const content = readFileSync74(cacheFile, "utf-8");
|
|
80771
81138
|
return JSON.parse(content);
|
|
80772
81139
|
} catch {
|
|
80773
81140
|
return null;
|
|
80774
81141
|
}
|
|
80775
81142
|
}
|
|
80776
81143
|
function getFileHash(filePath) {
|
|
80777
|
-
if (!
|
|
81144
|
+
if (!existsSync102(filePath)) return "";
|
|
80778
81145
|
try {
|
|
80779
|
-
const content =
|
|
81146
|
+
const content = readFileSync74(filePath);
|
|
80780
81147
|
return createHash12("sha256").update(content).digest("hex");
|
|
80781
81148
|
} catch {
|
|
80782
81149
|
return "";
|
|
@@ -80793,8 +81160,8 @@ function getCachedValidation(projectHash, projectPath, cacheFile) {
|
|
|
80793
81160
|
const now = Date.now();
|
|
80794
81161
|
const age = (now - lastValidated) / 1e3;
|
|
80795
81162
|
if (age > (entry.ttl || CACHE_TTL_SECONDS)) return null;
|
|
80796
|
-
const currentTasksDbHash = getFileHash(
|
|
80797
|
-
const currentConfigHash = getFileHash(
|
|
81163
|
+
const currentTasksDbHash = getFileHash(join104(projectPath, ".cleo", "tasks.db"));
|
|
81164
|
+
const currentConfigHash = getFileHash(join104(projectPath, ".cleo", "config.json"));
|
|
80798
81165
|
if (currentTasksDbHash !== (entry.fileHashes["tasks.db"] ?? "")) return null;
|
|
80799
81166
|
if (currentConfigHash !== (entry.fileHashes["config.json"] ?? "")) return null;
|
|
80800
81167
|
return entry;
|
|
@@ -80805,8 +81172,8 @@ function cacheValidationResult(projectHash, projectPath, validationStatus, issue
|
|
|
80805
81172
|
if (!cache) {
|
|
80806
81173
|
cache = initCacheFile(cachePath);
|
|
80807
81174
|
}
|
|
80808
|
-
const tasksDbHash = getFileHash(
|
|
80809
|
-
const configHash = getFileHash(
|
|
81175
|
+
const tasksDbHash = getFileHash(join104(projectPath, ".cleo", "tasks.db"));
|
|
81176
|
+
const configHash = getFileHash(join104(projectPath, ".cleo", "config.json"));
|
|
80810
81177
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
80811
81178
|
cache.projects[projectHash] = {
|
|
80812
81179
|
path: projectPath,
|
|
@@ -80821,18 +81188,18 @@ function cacheValidationResult(projectHash, projectPath, validationStatus, issue
|
|
|
80821
81188
|
ttl: CACHE_TTL_SECONDS
|
|
80822
81189
|
};
|
|
80823
81190
|
cache.lastUpdated = timestamp2;
|
|
80824
|
-
|
|
81191
|
+
writeFileSync19(cachePath, JSON.stringify(cache, null, 2));
|
|
80825
81192
|
}
|
|
80826
81193
|
function clearProjectCache(projectHash, cacheFile) {
|
|
80827
81194
|
const cachePath = cacheFile ?? getCacheFilePath();
|
|
80828
81195
|
const cache = loadCache(cachePath);
|
|
80829
81196
|
if (!cache) return;
|
|
80830
81197
|
delete cache.projects[projectHash];
|
|
80831
|
-
|
|
81198
|
+
writeFileSync19(cachePath, JSON.stringify(cache, null, 2));
|
|
80832
81199
|
}
|
|
80833
81200
|
function clearEntireCache(cacheFile) {
|
|
80834
81201
|
const cachePath = cacheFile ?? getCacheFilePath();
|
|
80835
|
-
if (
|
|
81202
|
+
if (existsSync102(cachePath)) {
|
|
80836
81203
|
unlinkSync8(cachePath);
|
|
80837
81204
|
}
|
|
80838
81205
|
initCacheFile(cachePath);
|
|
@@ -81101,15 +81468,15 @@ function validateTitle2(title) {
|
|
|
81101
81468
|
}
|
|
81102
81469
|
return { valid: errors.length === 0, errors, warnings };
|
|
81103
81470
|
}
|
|
81104
|
-
function validateDescription(
|
|
81105
|
-
if (!
|
|
81106
|
-
if (
|
|
81471
|
+
function validateDescription(desc6) {
|
|
81472
|
+
if (!desc6) return { valid: true, errors: [], warnings: [] };
|
|
81473
|
+
if (desc6.length > FIELD_LIMITS.MAX_DESCRIPTION_LENGTH) {
|
|
81107
81474
|
return {
|
|
81108
81475
|
valid: false,
|
|
81109
81476
|
errors: [
|
|
81110
81477
|
{
|
|
81111
81478
|
field: "description",
|
|
81112
|
-
message: `Description exceeds ${FIELD_LIMITS.MAX_DESCRIPTION_LENGTH} characters (${
|
|
81479
|
+
message: `Description exceeds ${FIELD_LIMITS.MAX_DESCRIPTION_LENGTH} characters (${desc6.length} provided)`,
|
|
81113
81480
|
severity: "error"
|
|
81114
81481
|
}
|
|
81115
81482
|
],
|
|
@@ -81818,9 +82185,9 @@ function formatGapReport(report) {
|
|
|
81818
82185
|
|
|
81819
82186
|
// packages/core/src/validation/manifest.ts
|
|
81820
82187
|
init_paths();
|
|
81821
|
-
import { existsSync as
|
|
82188
|
+
import { existsSync as existsSync103 } from "node:fs";
|
|
81822
82189
|
import { appendFile as appendFile3, mkdir as mkdir15, readFile as readFile18 } from "node:fs/promises";
|
|
81823
|
-
import { dirname as
|
|
82190
|
+
import { dirname as dirname22 } from "node:path";
|
|
81824
82191
|
var DEFAULT_MANIFEST_PATH = ".cleo/agent-outputs/MANIFEST.jsonl";
|
|
81825
82192
|
var DEFAULT_COMPLIANCE_PATH = ".cleo/metrics/COMPLIANCE.jsonl";
|
|
81826
82193
|
async function findManifestEntry(taskId, manifestPath) {
|
|
@@ -81831,7 +82198,7 @@ async function findManifestEntry(taskId, manifestPath) {
|
|
|
81831
82198
|
manifestPath = DEFAULT_MANIFEST_PATH;
|
|
81832
82199
|
}
|
|
81833
82200
|
}
|
|
81834
|
-
if (!
|
|
82201
|
+
if (!existsSync103(manifestPath)) return null;
|
|
81835
82202
|
const content = await readFile18(manifestPath, "utf-8");
|
|
81836
82203
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
81837
82204
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -81943,7 +82310,7 @@ async function validateManifestEntry(taskId, manifestEntry, manifestPath = DEFAU
|
|
|
81943
82310
|
};
|
|
81944
82311
|
}
|
|
81945
82312
|
async function logRealCompliance(taskId, validationResult, agentType = "unknown", compliancePath = DEFAULT_COMPLIANCE_PATH) {
|
|
81946
|
-
const metricsDir =
|
|
82313
|
+
const metricsDir = dirname22(compliancePath);
|
|
81947
82314
|
await mkdir15(metricsDir, { recursive: true });
|
|
81948
82315
|
const { score, pass, violations } = validationResult;
|
|
81949
82316
|
const violationCount = violations.length;
|
|
@@ -82003,9 +82370,9 @@ async function validateAndLog(taskId, manifestPath = DEFAULT_MANIFEST_PATH, comp
|
|
|
82003
82370
|
|
|
82004
82371
|
// packages/core/src/validation/protocol-common.ts
|
|
82005
82372
|
init_src();
|
|
82006
|
-
import { existsSync as
|
|
82373
|
+
import { existsSync as existsSync104, readdirSync as readdirSync33, readFileSync as readFileSync75 } from "node:fs";
|
|
82007
82374
|
function checkOutputFileExists(taskId, expectedDir, pattern) {
|
|
82008
|
-
if (!
|
|
82375
|
+
if (!existsSync104(expectedDir)) return false;
|
|
82009
82376
|
const filePattern = pattern ?? `${taskId}`;
|
|
82010
82377
|
try {
|
|
82011
82378
|
const files = readdirSync33(expectedDir);
|
|
@@ -82015,9 +82382,9 @@ function checkOutputFileExists(taskId, expectedDir, pattern) {
|
|
|
82015
82382
|
}
|
|
82016
82383
|
}
|
|
82017
82384
|
function checkDocumentationSections(filePath, sections) {
|
|
82018
|
-
if (!
|
|
82385
|
+
if (!existsSync104(filePath)) return false;
|
|
82019
82386
|
try {
|
|
82020
|
-
const content =
|
|
82387
|
+
const content = readFileSync75(filePath, "utf-8");
|
|
82021
82388
|
return sections.every((section) => {
|
|
82022
82389
|
const regex = new RegExp(`^#+ .*${escapeRegex3(section)}`, "m");
|
|
82023
82390
|
return regex.test(content);
|
|
@@ -82110,9 +82477,9 @@ function checkLinkedTasksPresent(entry, requiredIds) {
|
|
|
82110
82477
|
return requiredIds.every((id) => linkedTasks.includes(id));
|
|
82111
82478
|
}
|
|
82112
82479
|
function checkProvenanceTags(filePath, taskId) {
|
|
82113
|
-
if (!
|
|
82480
|
+
if (!existsSync104(filePath)) return false;
|
|
82114
82481
|
try {
|
|
82115
|
-
const content =
|
|
82482
|
+
const content = readFileSync75(filePath, "utf-8");
|
|
82116
82483
|
if (taskId) {
|
|
82117
82484
|
return content.includes(`@task ${taskId}`);
|
|
82118
82485
|
}
|
|
@@ -82771,17 +83138,17 @@ init_logger();
|
|
|
82771
83138
|
|
|
82772
83139
|
// packages/core/src/output.ts
|
|
82773
83140
|
init_errors3();
|
|
82774
|
-
import { randomUUID as
|
|
83141
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
82775
83142
|
|
|
82776
83143
|
// packages/core/src/sessions/context-alert.ts
|
|
82777
83144
|
init_paths();
|
|
82778
|
-
import { existsSync as
|
|
82779
|
-
import { join as
|
|
83145
|
+
import { existsSync as existsSync107, readFileSync as readFileSync77, writeFileSync as writeFileSync20 } from "node:fs";
|
|
83146
|
+
import { join as join107 } from "node:path";
|
|
82780
83147
|
function getCurrentSessionId(cwd) {
|
|
82781
83148
|
if (process.env.CLEO_SESSION) return process.env.CLEO_SESSION;
|
|
82782
|
-
const sessionFile =
|
|
82783
|
-
if (
|
|
82784
|
-
return
|
|
83149
|
+
const sessionFile = join107(getCleoDir(cwd), ".current-session");
|
|
83150
|
+
if (existsSync107(sessionFile)) {
|
|
83151
|
+
return readFileSync77(sessionFile, "utf-8").trim() || null;
|
|
82785
83152
|
}
|
|
82786
83153
|
return null;
|
|
82787
83154
|
}
|
|
@@ -82801,7 +83168,7 @@ function createCliMeta(operation, duration_ms = 0) {
|
|
|
82801
83168
|
const warnings = drainWarnings();
|
|
82802
83169
|
const meta3 = {
|
|
82803
83170
|
operation,
|
|
82804
|
-
requestId:
|
|
83171
|
+
requestId: randomUUID8(),
|
|
82805
83172
|
duration_ms,
|
|
82806
83173
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
82807
83174
|
};
|
|
@@ -82864,10 +83231,10 @@ init_adapters();
|
|
|
82864
83231
|
// packages/core/src/bootstrap.ts
|
|
82865
83232
|
init_paths();
|
|
82866
83233
|
init_scaffold();
|
|
82867
|
-
import { existsSync as
|
|
83234
|
+
import { existsSync as existsSync108, readFileSync as readFileSync78 } from "node:fs";
|
|
82868
83235
|
import { mkdir as mkdir17, readFile as readFile20, writeFile as writeFile12 } from "node:fs/promises";
|
|
82869
83236
|
import { homedir as homedir7 } from "node:os";
|
|
82870
|
-
import { join as
|
|
83237
|
+
import { join as join108 } from "node:path";
|
|
82871
83238
|
async function bootstrapGlobalCleo(options) {
|
|
82872
83239
|
const ctx = {
|
|
82873
83240
|
created: [],
|
|
@@ -82888,8 +83255,8 @@ async function bootstrapGlobalCleo(options) {
|
|
|
82888
83255
|
}
|
|
82889
83256
|
async function writeTemplateTo(content, destPath, isDryRun) {
|
|
82890
83257
|
if (isDryRun) return false;
|
|
82891
|
-
const { dirname:
|
|
82892
|
-
await mkdir17(
|
|
83258
|
+
const { dirname: dirname24 } = await import("node:path");
|
|
83259
|
+
await mkdir17(dirname24(destPath), { recursive: true });
|
|
82893
83260
|
await writeFile12(destPath, content);
|
|
82894
83261
|
return true;
|
|
82895
83262
|
}
|
|
@@ -82901,9 +83268,9 @@ async function ensureGlobalTemplatesBootstrap(ctx, packageRootOverride) {
|
|
|
82901
83268
|
let templateContent = null;
|
|
82902
83269
|
try {
|
|
82903
83270
|
const pkgRoot = packageRootOverride ?? getPackageRoot();
|
|
82904
|
-
const templatePath =
|
|
82905
|
-
if (
|
|
82906
|
-
templateContent =
|
|
83271
|
+
const templatePath = join108(pkgRoot, "templates", "CLEO-INJECTION.md");
|
|
83272
|
+
if (existsSync108(templatePath)) {
|
|
83273
|
+
templateContent = readFileSync78(templatePath, "utf-8");
|
|
82907
83274
|
}
|
|
82908
83275
|
} catch {
|
|
82909
83276
|
}
|
|
@@ -82920,15 +83287,15 @@ async function ensureGlobalTemplatesBootstrap(ctx, packageRootOverride) {
|
|
|
82920
83287
|
ctx.warnings.push("Could not refresh CLEO-INJECTION.md template");
|
|
82921
83288
|
return;
|
|
82922
83289
|
}
|
|
82923
|
-
const xdgDest =
|
|
83290
|
+
const xdgDest = join108(globalTemplatesDir, "CLEO-INJECTION.md");
|
|
82924
83291
|
const xdgWritten = await writeTemplateTo(templateContent, xdgDest, ctx.isDryRun);
|
|
82925
83292
|
ctx.created.push(
|
|
82926
83293
|
`${getCleoTemplatesTildePath()}/CLEO-INJECTION.md (${xdgWritten ? "refreshed" : "would refresh"})`
|
|
82927
83294
|
);
|
|
82928
83295
|
const home = homedir7();
|
|
82929
|
-
const legacyTemplatesDir =
|
|
82930
|
-
if (legacyTemplatesDir !== globalTemplatesDir &&
|
|
82931
|
-
const legacyDest =
|
|
83296
|
+
const legacyTemplatesDir = join108(home, ".cleo", "templates");
|
|
83297
|
+
if (legacyTemplatesDir !== globalTemplatesDir && existsSync108(join108(home, ".cleo"))) {
|
|
83298
|
+
const legacyDest = join108(legacyTemplatesDir, "CLEO-INJECTION.md");
|
|
82932
83299
|
const legacyWritten = await writeTemplateTo(templateContent, legacyDest, ctx.isDryRun);
|
|
82933
83300
|
if (legacyWritten) {
|
|
82934
83301
|
ctx.created.push("~/.cleo/templates/CLEO-INJECTION.md (legacy sync)");
|
|
@@ -82947,12 +83314,12 @@ function sanitizeCaampFile(content) {
|
|
|
82947
83314
|
}
|
|
82948
83315
|
async function injectAgentsHub(ctx) {
|
|
82949
83316
|
const globalAgentsDir = getAgentsHome();
|
|
82950
|
-
const globalAgentsMd =
|
|
83317
|
+
const globalAgentsMd = join108(globalAgentsDir, "AGENTS.md");
|
|
82951
83318
|
try {
|
|
82952
83319
|
const { inject: inject2, getInstalledProviders: getInstalledProviders3, injectAll: injectAll2, buildInjectionContent } = await import("@cleocode/caamp");
|
|
82953
83320
|
if (!ctx.isDryRun) {
|
|
82954
83321
|
await mkdir17(globalAgentsDir, { recursive: true });
|
|
82955
|
-
if (
|
|
83322
|
+
if (existsSync108(globalAgentsMd)) {
|
|
82956
83323
|
const content = await readFile20(globalAgentsMd, "utf8");
|
|
82957
83324
|
const stripped = content.replace(
|
|
82958
83325
|
/\n?<!-- CLEO:START[^>]*-->[\s\S]*?<!-- CLEO:END -->\n?/g,
|
|
@@ -82987,8 +83354,8 @@ async function injectAgentsHub(ctx) {
|
|
|
82987
83354
|
});
|
|
82988
83355
|
if (!ctx.isDryRun) {
|
|
82989
83356
|
for (const provider of providers) {
|
|
82990
|
-
const instructFilePath =
|
|
82991
|
-
if (
|
|
83357
|
+
const instructFilePath = join108(provider.pathGlobal, provider.instructFile);
|
|
83358
|
+
if (existsSync108(instructFilePath)) {
|
|
82992
83359
|
const fileContent = await readFile20(instructFilePath, "utf8");
|
|
82993
83360
|
const stripped = fileContent.replace(
|
|
82994
83361
|
/\n?<!-- CLEO:START[^>]*-->[\s\S]*?<!-- CLEO:END -->\n?/g,
|
|
@@ -83006,7 +83373,7 @@ async function injectAgentsHub(ctx) {
|
|
|
83006
83373
|
}
|
|
83007
83374
|
} else {
|
|
83008
83375
|
for (const p of providers) {
|
|
83009
|
-
const displayPath =
|
|
83376
|
+
const displayPath = join108(p.pathGlobal, p.instructFile).replace(homedir7(), "~");
|
|
83010
83377
|
ctx.created.push(`${displayPath} (would update CAAMP block)`);
|
|
83011
83378
|
}
|
|
83012
83379
|
}
|
|
@@ -83080,17 +83447,17 @@ async function installProviderAdapters(ctx, packageRootOverride) {
|
|
|
83080
83447
|
async function verifyBootstrapHealth(ctx) {
|
|
83081
83448
|
if (ctx.isDryRun) return;
|
|
83082
83449
|
try {
|
|
83083
|
-
const xdgTemplatePath =
|
|
83084
|
-
const agentsMd =
|
|
83085
|
-
if (!
|
|
83450
|
+
const xdgTemplatePath = join108(getCleoTemplatesDir(), "CLEO-INJECTION.md");
|
|
83451
|
+
const agentsMd = join108(getAgentsHome(), "AGENTS.md");
|
|
83452
|
+
if (!existsSync108(xdgTemplatePath)) {
|
|
83086
83453
|
ctx.warnings.push("Health: XDG template missing after bootstrap");
|
|
83087
83454
|
return;
|
|
83088
83455
|
}
|
|
83089
83456
|
const xdgContent = await readFile20(xdgTemplatePath, "utf8");
|
|
83090
83457
|
const xdgVersion = xdgContent.match(/^Version:\s*(.+)$/m)?.[1]?.trim();
|
|
83091
83458
|
const home = homedir7();
|
|
83092
|
-
const legacyTemplatePath =
|
|
83093
|
-
if (
|
|
83459
|
+
const legacyTemplatePath = join108(home, ".cleo", "templates", "CLEO-INJECTION.md");
|
|
83460
|
+
if (existsSync108(legacyTemplatePath)) {
|
|
83094
83461
|
const legacyContent = await readFile20(legacyTemplatePath, "utf8");
|
|
83095
83462
|
const legacyVersion = legacyContent.match(/^Version:\s*(.+)$/m)?.[1]?.trim();
|
|
83096
83463
|
if (legacyVersion !== xdgVersion) {
|
|
@@ -83099,7 +83466,7 @@ async function verifyBootstrapHealth(ctx) {
|
|
|
83099
83466
|
);
|
|
83100
83467
|
}
|
|
83101
83468
|
}
|
|
83102
|
-
if (
|
|
83469
|
+
if (existsSync108(agentsMd)) {
|
|
83103
83470
|
const agentsContent = await readFile20(agentsMd, "utf8");
|
|
83104
83471
|
const expectedRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
|
|
83105
83472
|
if (!agentsContent.includes(expectedRef)) {
|
|
@@ -83183,13 +83550,13 @@ async function serializeSession(projectRoot, options = {}, accessor) {
|
|
|
83183
83550
|
const { tasks: tasks2 } = await acc.queryTasks({});
|
|
83184
83551
|
const task = tasks2.find((t) => t.id === session.taskWork?.taskId);
|
|
83185
83552
|
if (task) {
|
|
83186
|
-
const
|
|
83553
|
+
const desc6 = task.description ?? "";
|
|
83187
83554
|
activeTask = {
|
|
83188
83555
|
taskId: task.id,
|
|
83189
83556
|
title: task.title,
|
|
83190
83557
|
status: task.status,
|
|
83191
83558
|
priority: task.priority ?? "medium",
|
|
83192
|
-
description:
|
|
83559
|
+
description: desc6.length > maxDescLen ? desc6.slice(0, maxDescLen) + "..." : desc6,
|
|
83193
83560
|
acceptance: Array.isArray(task.acceptance) ? task.acceptance.join("\n") : task.acceptance ?? void 0
|
|
83194
83561
|
};
|
|
83195
83562
|
}
|
|
@@ -83820,6 +84187,7 @@ export {
|
|
|
83820
84187
|
taskTypeSchema,
|
|
83821
84188
|
task_work_exports as taskWork,
|
|
83822
84189
|
tasks_exports as tasks,
|
|
84190
|
+
telemetry_exports as telemetry,
|
|
83823
84191
|
templates_exports as templates,
|
|
83824
84192
|
timelineBrain,
|
|
83825
84193
|
tokenUsageConfidenceSchema,
|