@cleocode/cleo 2026.4.60 → 2026.4.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1424 -305
- package/dist/cli/index.js.map +4 -4
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -1931,7 +1931,7 @@ var init_sql = __esm({
|
|
|
1931
1931
|
return new SQL([new StringChunk(str)]);
|
|
1932
1932
|
}
|
|
1933
1933
|
_sql.raw = raw;
|
|
1934
|
-
function
|
|
1934
|
+
function join136(chunks, separator) {
|
|
1935
1935
|
const result = [];
|
|
1936
1936
|
for (const [i, chunk] of chunks.entries()) {
|
|
1937
1937
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -1939,7 +1939,7 @@ var init_sql = __esm({
|
|
|
1939
1939
|
}
|
|
1940
1940
|
return new SQL(result);
|
|
1941
1941
|
}
|
|
1942
|
-
_sql.join =
|
|
1942
|
+
_sql.join = join136;
|
|
1943
1943
|
function identifier(value) {
|
|
1944
1944
|
return new Name(value);
|
|
1945
1945
|
}
|
|
@@ -6713,7 +6713,7 @@ var init_select2 = __esm({
|
|
|
6713
6713
|
const baseTableName = this.tableName;
|
|
6714
6714
|
const tableName = getTableLikeName(table);
|
|
6715
6715
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
6716
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
6716
|
+
if (typeof tableName === "string" && this.config.joins?.some((join136) => join136.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
6717
6717
|
if (!this.isPartialSelect) {
|
|
6718
6718
|
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
|
|
6719
6719
|
if (typeof tableName === "string" && !is(table, SQL)) {
|
|
@@ -7998,7 +7998,7 @@ var init_dialect = __esm({
|
|
|
7998
7998
|
if (!joins2) return;
|
|
7999
7999
|
const withEntries = Object.entries(joins2).filter(([_2, v2]) => v2);
|
|
8000
8000
|
if (!withEntries.length) return;
|
|
8001
|
-
return sql.join(withEntries.map(([k2,
|
|
8001
|
+
return sql.join(withEntries.map(([k2, join136]) => {
|
|
8002
8002
|
const relation = tableConfig.relations[k2];
|
|
8003
8003
|
const isSingle2 = is(relation, One3);
|
|
8004
8004
|
const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
|
|
@@ -8009,7 +8009,7 @@ var init_dialect = __esm({
|
|
|
8009
8009
|
table: targetTable,
|
|
8010
8010
|
mode: isSingle2 ? "first" : "many",
|
|
8011
8011
|
schema,
|
|
8012
|
-
queryConfig:
|
|
8012
|
+
queryConfig: join136,
|
|
8013
8013
|
tableConfig: schema[relation.targetTableName],
|
|
8014
8014
|
relationWhere: filter,
|
|
8015
8015
|
isNested: true,
|
|
@@ -8023,7 +8023,7 @@ var init_dialect = __esm({
|
|
|
8023
8023
|
key: k2,
|
|
8024
8024
|
selection: innerQuery.selection,
|
|
8025
8025
|
isArray: !isSingle2,
|
|
8026
|
-
isOptional: (relation.optional ?? false) ||
|
|
8026
|
+
isOptional: (relation.optional ?? false) || join136 !== true && !!join136.where
|
|
8027
8027
|
});
|
|
8028
8028
|
const jsonColumns = sql.join(innerQuery.selection.map((s3) => {
|
|
8029
8029
|
return sql`${sql.raw(this.escapeString(s3.key))}, ${s3.selection ? sql`${jsonb2}(${sql.identifier(s3.key)})` : sql.identifier(s3.key)}`;
|
|
@@ -8422,7 +8422,7 @@ var init_update = __esm({
|
|
|
8422
8422
|
createJoin(joinType) {
|
|
8423
8423
|
return ((table, on) => {
|
|
8424
8424
|
const tableName = getTableLikeName(table);
|
|
8425
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
8425
|
+
if (typeof tableName === "string" && this.config.joins.some((join136) => join136.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
8426
8426
|
if (typeof on === "function") {
|
|
8427
8427
|
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;
|
|
8428
8428
|
on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
|
|
@@ -15271,48 +15271,6 @@ function runBrainMigrations(nativeDb, db) {
|
|
|
15271
15271
|
}
|
|
15272
15272
|
reconcileJournal(nativeDb, migrationsFolder, "brain_decisions", "brain");
|
|
15273
15273
|
migrateWithRetry(db, migrationsFolder, nativeDb, "brain_decisions", "brain");
|
|
15274
|
-
ensureColumns(
|
|
15275
|
-
nativeDb,
|
|
15276
|
-
"brain_page_nodes",
|
|
15277
|
-
[
|
|
15278
|
-
{ name: "quality_score", ddl: "real DEFAULT 0.5" },
|
|
15279
|
-
{ name: "content_hash", ddl: "text" },
|
|
15280
|
-
{ name: "last_activity_at", ddl: "text" },
|
|
15281
|
-
{ name: "updated_at", ddl: "text" }
|
|
15282
|
-
],
|
|
15283
|
-
"brain"
|
|
15284
|
-
);
|
|
15285
|
-
for (const table of [
|
|
15286
|
-
"brain_decisions",
|
|
15287
|
-
"brain_patterns",
|
|
15288
|
-
"brain_learnings",
|
|
15289
|
-
"brain_observations"
|
|
15290
|
-
]) {
|
|
15291
|
-
ensureColumns(nativeDb, table, [{ name: "quality_score", ddl: "real" }], "brain");
|
|
15292
|
-
}
|
|
15293
|
-
for (const table of [
|
|
15294
|
-
"brain_decisions",
|
|
15295
|
-
"brain_patterns",
|
|
15296
|
-
"brain_learnings",
|
|
15297
|
-
"brain_observations"
|
|
15298
|
-
]) {
|
|
15299
|
-
ensureColumns(
|
|
15300
|
-
nativeDb,
|
|
15301
|
-
table,
|
|
15302
|
-
[
|
|
15303
|
-
{ name: "memory_tier", ddl: "text DEFAULT 'short'" },
|
|
15304
|
-
{ name: "memory_type", ddl: "text DEFAULT 'episodic'" },
|
|
15305
|
-
{ name: "verified", ddl: "integer NOT NULL DEFAULT 0" },
|
|
15306
|
-
// valid_at uses nullable text (no datetime('now') default) because
|
|
15307
|
-
// ALTER TABLE ADD COLUMN with non-constant defaults fails on non-empty tables.
|
|
15308
|
-
{ name: "valid_at", ddl: "text" },
|
|
15309
|
-
{ name: "invalid_at", ddl: "text" },
|
|
15310
|
-
{ name: "source_confidence", ddl: "text DEFAULT 'agent'" },
|
|
15311
|
-
{ name: "citation_count", ddl: "integer NOT NULL DEFAULT 0" }
|
|
15312
|
-
],
|
|
15313
|
-
"brain"
|
|
15314
|
-
);
|
|
15315
|
-
}
|
|
15316
15274
|
if (tableExists(nativeDb, "brain_page_edges")) {
|
|
15317
15275
|
nativeDb.prepare(
|
|
15318
15276
|
`UPDATE brain_page_edges
|
|
@@ -16567,7 +16525,8 @@ async function createSqliteDataAccessor(cwd) {
|
|
|
16567
16525
|
["createdBy", "createdBy"],
|
|
16568
16526
|
["modifiedBy", "modifiedBy"],
|
|
16569
16527
|
["sessionId", "sessionId"],
|
|
16570
|
-
["assignee", "assignee"]
|
|
16528
|
+
["assignee", "assignee"],
|
|
16529
|
+
["pipelineStage", "pipelineStage"]
|
|
16571
16530
|
];
|
|
16572
16531
|
for (const [key, col] of fieldMap) {
|
|
16573
16532
|
if (fields[key] !== void 0) {
|
|
@@ -46914,13 +46873,147 @@ var init_graph_memory_bridge = __esm({
|
|
|
46914
46873
|
}
|
|
46915
46874
|
});
|
|
46916
46875
|
|
|
46876
|
+
// packages/core/src/memory/brain-plasticity-class.ts
|
|
46877
|
+
function upgradePlasticityClass(currentClass, event) {
|
|
46878
|
+
const current = currentClass ?? "static";
|
|
46879
|
+
if (current === "stdp") return "stdp";
|
|
46880
|
+
if (event === "stdp") return "stdp";
|
|
46881
|
+
if (event === "hebbian") {
|
|
46882
|
+
return current === "static" ? "hebbian" : current;
|
|
46883
|
+
}
|
|
46884
|
+
return current;
|
|
46885
|
+
}
|
|
46886
|
+
function computeStabilityScore(reinforcementCount, lastReinforcedAt, now2 = Date.now()) {
|
|
46887
|
+
if (!reinforcementCount || reinforcementCount <= 0) return null;
|
|
46888
|
+
if (!lastReinforcedAt) return null;
|
|
46889
|
+
const rcTerm = Math.tanh(reinforcementCount / 10);
|
|
46890
|
+
const lastReinforcedMs = new Date(lastReinforcedAt).getTime();
|
|
46891
|
+
const ageMs = now2 - lastReinforcedMs;
|
|
46892
|
+
const ageDays = ageMs / (24 * 60 * 60 * 1e3);
|
|
46893
|
+
const decayTerm = Math.exp(-ageDays / 30);
|
|
46894
|
+
const stability = rcTerm * decayTerm;
|
|
46895
|
+
return Math.max(0, Math.min(1, stability));
|
|
46896
|
+
}
|
|
46897
|
+
var init_brain_plasticity_class = __esm({
|
|
46898
|
+
"packages/core/src/memory/brain-plasticity-class.ts"() {
|
|
46899
|
+
"use strict";
|
|
46900
|
+
}
|
|
46901
|
+
});
|
|
46902
|
+
|
|
46917
46903
|
// packages/core/src/memory/brain-stdp.ts
|
|
46918
46904
|
var brain_stdp_exports = {};
|
|
46919
46905
|
__export(brain_stdp_exports, {
|
|
46906
|
+
applyHomeostaticDecay: () => applyHomeostaticDecay,
|
|
46920
46907
|
applyStdpPlasticity: () => applyStdpPlasticity,
|
|
46921
|
-
|
|
46922
|
-
|
|
46923
|
-
|
|
46908
|
+
backfillRewardSignals: () => backfillRewardSignals,
|
|
46909
|
+
computeTau: () => computeTau,
|
|
46910
|
+
getPlasticityStats: () => getPlasticityStats,
|
|
46911
|
+
shouldRunPlasticity: () => shouldRunPlasticity
|
|
46912
|
+
});
|
|
46913
|
+
function computeTau(deltaT) {
|
|
46914
|
+
if (deltaT <= TAU_NEAR_THRESHOLD_MS) return TAU_NEAR_MS;
|
|
46915
|
+
if (deltaT <= TAU_SESSION_THRESHOLD_MS) return TAU_SESSION_MS;
|
|
46916
|
+
return TAU_EPISODIC_MS;
|
|
46917
|
+
}
|
|
46918
|
+
function isPlasticityEventDuplicate(nativeDb, sourceNode, targetNode, kind, sessionId, withinHours = 1) {
|
|
46919
|
+
try {
|
|
46920
|
+
const cutoffIso = new Date(Date.now() - withinHours * 60 * 60 * 1e3).toISOString().replace("T", " ").slice(0, 19);
|
|
46921
|
+
const db = nativeDb;
|
|
46922
|
+
const stmt = db.prepare(
|
|
46923
|
+
`SELECT 1 FROM brain_plasticity_events
|
|
46924
|
+
WHERE source_node = ? AND target_node = ? AND kind = ?
|
|
46925
|
+
AND session_id = ?
|
|
46926
|
+
AND timestamp > ?
|
|
46927
|
+
LIMIT 1`
|
|
46928
|
+
);
|
|
46929
|
+
const result = stmt.get(sourceNode, targetNode, kind, sessionId, cutoffIso);
|
|
46930
|
+
return result !== void 0;
|
|
46931
|
+
} catch {
|
|
46932
|
+
return false;
|
|
46933
|
+
}
|
|
46934
|
+
}
|
|
46935
|
+
function hasMinimumRetrievalsSinceLastPlasticity(nativeDb, minCount = 2, sessionId = null) {
|
|
46936
|
+
try {
|
|
46937
|
+
const db = nativeDb;
|
|
46938
|
+
const lastPlasticityStmt = db.prepare(
|
|
46939
|
+
`SELECT MAX(timestamp) as last_time FROM brain_plasticity_events
|
|
46940
|
+
WHERE session_id = ?`
|
|
46941
|
+
);
|
|
46942
|
+
const lastPlasticityRow = lastPlasticityStmt.get(sessionId);
|
|
46943
|
+
const lastTime = lastPlasticityRow?.last_time ?? null;
|
|
46944
|
+
let newRetrievalCount;
|
|
46945
|
+
if (lastTime === null) {
|
|
46946
|
+
const countRow = db.prepare(
|
|
46947
|
+
`SELECT COUNT(*) as cnt FROM brain_retrieval_log
|
|
46948
|
+
WHERE session_id = ?`
|
|
46949
|
+
).get(sessionId);
|
|
46950
|
+
newRetrievalCount = countRow?.cnt ?? 0;
|
|
46951
|
+
} else {
|
|
46952
|
+
const countRow = db.prepare(
|
|
46953
|
+
`SELECT COUNT(*) as cnt FROM brain_retrieval_log
|
|
46954
|
+
WHERE session_id = ? AND created_at > ?`
|
|
46955
|
+
).get(sessionId, lastTime);
|
|
46956
|
+
newRetrievalCount = countRow?.cnt ?? 0;
|
|
46957
|
+
}
|
|
46958
|
+
return newRetrievalCount >= minCount;
|
|
46959
|
+
} catch {
|
|
46960
|
+
return true;
|
|
46961
|
+
}
|
|
46962
|
+
}
|
|
46963
|
+
async function shouldRunPlasticity(projectRoot, sessionId = null, minRetrievalsForPlasticity = 2) {
|
|
46964
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
46965
|
+
await getBrainDb2(projectRoot);
|
|
46966
|
+
const nativeDb = getBrainNativeDb2();
|
|
46967
|
+
if (!nativeDb) return true;
|
|
46968
|
+
const hasMinimum = hasMinimumRetrievalsSinceLastPlasticity(
|
|
46969
|
+
nativeDb,
|
|
46970
|
+
minRetrievalsForPlasticity,
|
|
46971
|
+
sessionId
|
|
46972
|
+
);
|
|
46973
|
+
if (!hasMinimum) {
|
|
46974
|
+
const count5 = (() => {
|
|
46975
|
+
try {
|
|
46976
|
+
const db = nativeDb;
|
|
46977
|
+
const lastPlasticityStmt = db.prepare(
|
|
46978
|
+
`SELECT MAX(timestamp) as last_time FROM brain_plasticity_events WHERE session_id = ?`
|
|
46979
|
+
);
|
|
46980
|
+
const lastPlasticityRow = lastPlasticityStmt.get(sessionId);
|
|
46981
|
+
const lastTime = lastPlasticityRow?.last_time ?? null;
|
|
46982
|
+
if (lastTime === null) {
|
|
46983
|
+
const countStmt = db.prepare(
|
|
46984
|
+
`SELECT COUNT(*) as cnt FROM brain_retrieval_log WHERE session_id = ?`
|
|
46985
|
+
);
|
|
46986
|
+
const countRow = countStmt.get(sessionId);
|
|
46987
|
+
return countRow?.cnt ?? 0;
|
|
46988
|
+
} else {
|
|
46989
|
+
const countStmt = db.prepare(
|
|
46990
|
+
`SELECT COUNT(*) as cnt FROM brain_retrieval_log WHERE session_id = ? AND created_at > ?`
|
|
46991
|
+
);
|
|
46992
|
+
const countRow = countStmt.get(sessionId, lastTime);
|
|
46993
|
+
return countRow?.cnt ?? 0;
|
|
46994
|
+
}
|
|
46995
|
+
} catch {
|
|
46996
|
+
return 0;
|
|
46997
|
+
}
|
|
46998
|
+
})();
|
|
46999
|
+
console.warn(
|
|
47000
|
+
`[plasticity] Minimum-pair gate: skipped STDP Step 9b (${count5} retrievals, need >=${minRetrievalsForPlasticity})`
|
|
47001
|
+
);
|
|
47002
|
+
}
|
|
47003
|
+
return hasMinimum;
|
|
47004
|
+
}
|
|
47005
|
+
async function applyStdpPlasticity(projectRoot, options) {
|
|
47006
|
+
let lookbackDays = DEFAULT_LOOKBACK_DAYS;
|
|
47007
|
+
let pairingWindowMs = DEFAULT_PAIRING_WINDOW_MS;
|
|
47008
|
+
if (typeof options === "number") {
|
|
47009
|
+
console.warn(
|
|
47010
|
+
"[brain-stdp] Deprecated: passing sessionWindowMs as a number. Use StdpPlasticityOptions { lookbackDays, pairingWindowMs } instead. (T679)"
|
|
47011
|
+
);
|
|
47012
|
+
pairingWindowMs = options;
|
|
47013
|
+
} else if (options !== void 0) {
|
|
47014
|
+
lookbackDays = options.lookbackDays ?? DEFAULT_LOOKBACK_DAYS;
|
|
47015
|
+
pairingWindowMs = options.pairingWindowMs ?? DEFAULT_PAIRING_WINDOW_MS;
|
|
47016
|
+
}
|
|
46924
47017
|
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
46925
47018
|
await getBrainDb2(projectRoot);
|
|
46926
47019
|
const nativeDb = getBrainNativeDb2();
|
|
@@ -46928,7 +47021,8 @@ async function applyStdpPlasticity(projectRoot, sessionWindowMs = 5 * 60 * 1e3)
|
|
|
46928
47021
|
ltpEvents: 0,
|
|
46929
47022
|
ltdEvents: 0,
|
|
46930
47023
|
edgesCreated: 0,
|
|
46931
|
-
pairsExamined: 0
|
|
47024
|
+
pairsExamined: 0,
|
|
47025
|
+
rewardModulatedEvents: 0
|
|
46932
47026
|
};
|
|
46933
47027
|
if (!nativeDb) return result;
|
|
46934
47028
|
try {
|
|
@@ -46942,14 +47036,14 @@ async function applyStdpPlasticity(projectRoot, sessionWindowMs = 5 * 60 * 1e3)
|
|
|
46942
47036
|
return result;
|
|
46943
47037
|
}
|
|
46944
47038
|
const now2 = Date.now();
|
|
46945
|
-
const cutoffMs = now2 -
|
|
47039
|
+
const cutoffMs = now2 - lookbackDays * 24 * 60 * 60 * 1e3;
|
|
46946
47040
|
const cutoffIso = new Date(cutoffMs).toISOString().replace("T", " ").slice(0, 19);
|
|
46947
47041
|
const nowIso = new Date(now2).toISOString().replace("T", " ").slice(0, 19);
|
|
46948
47042
|
let logRows = [];
|
|
46949
47043
|
try {
|
|
46950
47044
|
logRows = typedAll(
|
|
46951
47045
|
nativeDb.prepare(
|
|
46952
|
-
`SELECT id, entry_ids, created_at, retrieval_order, delta_ms
|
|
47046
|
+
`SELECT id, entry_ids, created_at, retrieval_order, delta_ms, session_id, reward_signal
|
|
46953
47047
|
FROM brain_retrieval_log
|
|
46954
47048
|
WHERE created_at >= ?
|
|
46955
47049
|
ORDER BY created_at ASC, id ASC
|
|
@@ -46970,68 +47064,318 @@ async function applyStdpPlasticity(projectRoot, sessionWindowMs = 5 * 60 * 1e3)
|
|
|
46970
47064
|
} catch {
|
|
46971
47065
|
continue;
|
|
46972
47066
|
}
|
|
47067
|
+
if (!Array.isArray(ids)) continue;
|
|
46973
47068
|
const rowTime = (/* @__PURE__ */ new Date(row.created_at.replace(" ", "T") + "Z")).getTime();
|
|
46974
47069
|
for (const rawId of ids) {
|
|
47070
|
+
if (typeof rawId !== "string" || rawId.length === 0) continue;
|
|
46975
47071
|
const entryId = rawId.includes(":") ? rawId : `observation:${rawId}`;
|
|
46976
47072
|
spikes.push({
|
|
46977
47073
|
entryId,
|
|
46978
47074
|
rowId: row.id,
|
|
46979
47075
|
retrievedAt: rowTime,
|
|
46980
|
-
order: row.retrieval_order ?? globalOrder
|
|
47076
|
+
order: row.retrieval_order ?? globalOrder,
|
|
47077
|
+
sessionId: row.session_id ?? null,
|
|
47078
|
+
rewardSignal: row.reward_signal ?? null
|
|
46981
47079
|
});
|
|
46982
47080
|
globalOrder++;
|
|
46983
47081
|
}
|
|
46984
47082
|
}
|
|
47083
|
+
if (spikes.length < 2) return result;
|
|
46985
47084
|
spikes.sort((a, b2) => a.retrievedAt - b2.retrievedAt || a.order - b2.order);
|
|
47085
|
+
const MAX_PAIRS_PER_SESSION = 50;
|
|
47086
|
+
const sessionBucketMap = /* @__PURE__ */ new Map();
|
|
47087
|
+
for (const spike of spikes) {
|
|
47088
|
+
const key = spike.sessionId ?? "null";
|
|
47089
|
+
const bucket = sessionBucketMap.get(key);
|
|
47090
|
+
if (bucket !== void 0) {
|
|
47091
|
+
bucket.push(spike);
|
|
47092
|
+
} else {
|
|
47093
|
+
sessionBucketMap.set(key, [spike]);
|
|
47094
|
+
}
|
|
47095
|
+
}
|
|
47096
|
+
const orderedBuckets = Array.from(sessionBucketMap.entries()).sort(
|
|
47097
|
+
([, a], [, b2]) => (a[0]?.retrievedAt ?? 0) - (b2[0]?.retrievedAt ?? 0)
|
|
47098
|
+
);
|
|
47099
|
+
const workingSpikes = [];
|
|
47100
|
+
for (let bi2 = 0; bi2 < orderedBuckets.length; bi2++) {
|
|
47101
|
+
const [, bucketSpikes] = orderedBuckets[bi2];
|
|
47102
|
+
workingSpikes.push(...bucketSpikes);
|
|
47103
|
+
}
|
|
47104
|
+
const withinSessionIndex = /* @__PURE__ */ new Map();
|
|
47105
|
+
const sessionSizeMap = /* @__PURE__ */ new Map();
|
|
47106
|
+
for (const [, bucketSpikes] of orderedBuckets) {
|
|
47107
|
+
for (let idx = 0; idx < bucketSpikes.length; idx++) {
|
|
47108
|
+
const spike = bucketSpikes[idx];
|
|
47109
|
+
withinSessionIndex.set(spike, idx);
|
|
47110
|
+
sessionSizeMap.set(spike.sessionId ?? "null", bucketSpikes.length);
|
|
47111
|
+
}
|
|
47112
|
+
}
|
|
46986
47113
|
const prepareGetEdge = nativeDb.prepare(
|
|
46987
|
-
`SELECT weight
|
|
47114
|
+
`SELECT weight, reinforcement_count, last_reinforced_at, plasticity_class, depression_count, last_depressed_at
|
|
47115
|
+
FROM brain_page_edges
|
|
47116
|
+
WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
|
|
47117
|
+
);
|
|
47118
|
+
const prepareUpdateEdgeLtp = nativeDb.prepare(
|
|
47119
|
+
`UPDATE brain_page_edges
|
|
47120
|
+
SET weight = MAX(?, MIN(?, weight + ?)),
|
|
47121
|
+
reinforcement_count = reinforcement_count + 1,
|
|
47122
|
+
last_reinforced_at = ?,
|
|
47123
|
+
plasticity_class = ?,
|
|
47124
|
+
stability_score = ?
|
|
46988
47125
|
WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
|
|
46989
47126
|
);
|
|
46990
|
-
const
|
|
47127
|
+
const prepareUpdateEdgeLtd = nativeDb.prepare(
|
|
46991
47128
|
`UPDATE brain_page_edges
|
|
46992
|
-
SET weight = MAX(?, MIN(?, weight + ?))
|
|
47129
|
+
SET weight = MAX(?, MIN(?, weight + ?)),
|
|
47130
|
+
depression_count = depression_count + 1,
|
|
47131
|
+
last_depressed_at = ?,
|
|
47132
|
+
plasticity_class = ?,
|
|
47133
|
+
stability_score = ?
|
|
46993
47134
|
WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
|
|
46994
47135
|
);
|
|
46995
47136
|
const prepareInsertEdge = nativeDb.prepare(
|
|
46996
47137
|
`INSERT OR IGNORE INTO brain_page_edges
|
|
46997
|
-
(from_id, to_id, edge_type, weight, provenance, created_at)
|
|
46998
|
-
VALUES (?, ?, 'co_retrieved', ?, 'plasticity:stdp-ltp', ?)`
|
|
47138
|
+
(from_id, to_id, edge_type, weight, provenance, reinforcement_count, last_reinforced_at, plasticity_class, stability_score, created_at)
|
|
47139
|
+
VALUES (?, ?, 'co_retrieved', ?, 'plasticity:stdp-ltp', 1, ?, 'stdp', ?, ?)`
|
|
46999
47140
|
);
|
|
47000
47141
|
const prepareLogEvent = nativeDb.prepare(
|
|
47001
47142
|
`INSERT INTO brain_plasticity_events
|
|
47002
|
-
(source_node, target_node, delta_w, kind, timestamp
|
|
47003
|
-
|
|
47143
|
+
(source_node, target_node, delta_w, kind, timestamp,
|
|
47144
|
+
session_id, retrieval_log_id, weight_before, weight_after, delta_t_ms)
|
|
47145
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
47004
47146
|
);
|
|
47005
|
-
|
|
47006
|
-
|
|
47007
|
-
|
|
47008
|
-
|
|
47147
|
+
let prepareLogWeightHistory = null;
|
|
47148
|
+
try {
|
|
47149
|
+
nativeDb.prepare("SELECT 1 FROM brain_weight_history LIMIT 1").get();
|
|
47150
|
+
prepareLogWeightHistory = nativeDb.prepare(
|
|
47151
|
+
`INSERT INTO brain_weight_history
|
|
47152
|
+
(edge_from_id, edge_to_id, edge_type, weight_before, weight_after,
|
|
47153
|
+
delta_weight, event_kind, source_plasticity_event_id, retrieval_log_id,
|
|
47154
|
+
reward_signal, changed_at)
|
|
47155
|
+
VALUES (?, ?, 'co_retrieved', ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
47156
|
+
);
|
|
47157
|
+
} catch {
|
|
47158
|
+
}
|
|
47159
|
+
for (let i = 0; i < workingSpikes.length; i++) {
|
|
47160
|
+
const spikeA = workingSpikes[i];
|
|
47161
|
+
const sessionKeyA = spikeA.sessionId ?? "null";
|
|
47162
|
+
const sessionSizeA = sessionSizeMap.get(sessionKeyA) ?? 1;
|
|
47163
|
+
const posInSessionA = withinSessionIndex.get(spikeA) ?? 0;
|
|
47164
|
+
const canCrossSession = posInSessionA >= sessionSizeA - MAX_PAIRS_PER_SESSION;
|
|
47165
|
+
for (let j2 = i + 1; j2 < workingSpikes.length; j2++) {
|
|
47166
|
+
const spikeB = workingSpikes[j2];
|
|
47009
47167
|
const deltaT = spikeB.retrievedAt - spikeA.retrievedAt;
|
|
47010
|
-
if (deltaT >
|
|
47168
|
+
if (deltaT > pairingWindowMs) break;
|
|
47011
47169
|
if (spikeA.entryId === spikeB.entryId) continue;
|
|
47170
|
+
const sessionKeyB = spikeB.sessionId ?? "null";
|
|
47171
|
+
if (sessionKeyA !== sessionKeyB && !canCrossSession) {
|
|
47172
|
+
continue;
|
|
47173
|
+
}
|
|
47012
47174
|
result.pairsExamined++;
|
|
47013
|
-
const
|
|
47175
|
+
const tau = computeTau(deltaT);
|
|
47176
|
+
let deltaW = A_PRE * Math.exp(-deltaT / tau);
|
|
47014
47177
|
if (deltaW < 1e-6) continue;
|
|
47178
|
+
const eventSessionId = spikeA.sessionId ?? null;
|
|
47179
|
+
const eventRewardSignal = spikeA.rewardSignal ?? null;
|
|
47180
|
+
let wasRewardModulated = false;
|
|
47181
|
+
if (eventRewardSignal !== null) {
|
|
47182
|
+
const r = eventRewardSignal;
|
|
47183
|
+
deltaW = Math.min(deltaW * (1 + r), 2 * A_PRE);
|
|
47184
|
+
deltaW = Math.max(deltaW, 0);
|
|
47185
|
+
wasRewardModulated = true;
|
|
47186
|
+
}
|
|
47187
|
+
if (deltaW < 1e-6) {
|
|
47188
|
+
if (wasRewardModulated) result.rewardModulatedEvents++;
|
|
47189
|
+
continue;
|
|
47190
|
+
}
|
|
47015
47191
|
const existingEdge = prepareGetEdge.get(spikeA.entryId, spikeB.entryId);
|
|
47192
|
+
let ltpEventId = null;
|
|
47016
47193
|
try {
|
|
47017
47194
|
if (existingEdge !== void 0) {
|
|
47018
|
-
|
|
47195
|
+
const currentWeight = existingEdge.weight;
|
|
47196
|
+
const newWeight = Math.max(WEIGHT_MIN, Math.min(WEIGHT_MAX, currentWeight + deltaW));
|
|
47197
|
+
const upgradedClass = upgradePlasticityClass(existingEdge.plasticity_class, "stdp");
|
|
47198
|
+
const newRcCount = (existingEdge.reinforcement_count ?? 0) + 1;
|
|
47199
|
+
const stability = computeStabilityScore(newRcCount, nowIso, now2);
|
|
47200
|
+
prepareUpdateEdgeLtp.run(
|
|
47201
|
+
WEIGHT_MIN,
|
|
47202
|
+
WEIGHT_MAX,
|
|
47203
|
+
deltaW,
|
|
47204
|
+
nowIso,
|
|
47205
|
+
// last_reinforced_at
|
|
47206
|
+
upgradedClass,
|
|
47207
|
+
stability,
|
|
47208
|
+
spikeA.entryId,
|
|
47209
|
+
spikeB.entryId
|
|
47210
|
+
);
|
|
47211
|
+
const isDuplicate = isPlasticityEventDuplicate(
|
|
47212
|
+
nativeDb,
|
|
47213
|
+
spikeA.entryId,
|
|
47214
|
+
spikeB.entryId,
|
|
47215
|
+
"ltp",
|
|
47216
|
+
eventSessionId,
|
|
47217
|
+
1
|
|
47218
|
+
// within 1 hour
|
|
47219
|
+
);
|
|
47220
|
+
if (isDuplicate) {
|
|
47221
|
+
result.ltpEvents++;
|
|
47222
|
+
if (wasRewardModulated) result.rewardModulatedEvents++;
|
|
47223
|
+
continue;
|
|
47224
|
+
}
|
|
47225
|
+
const evtStmt = prepareLogEvent.run(
|
|
47226
|
+
spikeA.entryId,
|
|
47227
|
+
spikeB.entryId,
|
|
47228
|
+
deltaW,
|
|
47229
|
+
"ltp",
|
|
47230
|
+
nowIso,
|
|
47231
|
+
eventSessionId,
|
|
47232
|
+
spikeA.rowId,
|
|
47233
|
+
currentWeight,
|
|
47234
|
+
newWeight,
|
|
47235
|
+
deltaT
|
|
47236
|
+
);
|
|
47237
|
+
ltpEventId = evtStmt.lastInsertRowid != null ? Number(evtStmt.lastInsertRowid) : null;
|
|
47238
|
+
if (prepareLogWeightHistory) {
|
|
47239
|
+
prepareLogWeightHistory.run(
|
|
47240
|
+
spikeA.entryId,
|
|
47241
|
+
spikeB.entryId,
|
|
47242
|
+
currentWeight,
|
|
47243
|
+
newWeight,
|
|
47244
|
+
deltaW,
|
|
47245
|
+
"ltp",
|
|
47246
|
+
ltpEventId,
|
|
47247
|
+
spikeA.rowId,
|
|
47248
|
+
eventRewardSignal,
|
|
47249
|
+
nowIso
|
|
47250
|
+
);
|
|
47251
|
+
}
|
|
47019
47252
|
} else {
|
|
47020
|
-
const
|
|
47021
|
-
|
|
47253
|
+
const noveltyBoostedWeight = deltaW * K_NOVELTY;
|
|
47254
|
+
const initialWeight = Math.min(
|
|
47255
|
+
WEIGHT_MAX,
|
|
47256
|
+
Math.min(A_PRE * K_NOVELTY, noveltyBoostedWeight)
|
|
47257
|
+
);
|
|
47258
|
+
const stability = computeStabilityScore(1, nowIso, now2);
|
|
47259
|
+
prepareInsertEdge.run(
|
|
47260
|
+
spikeA.entryId,
|
|
47261
|
+
spikeB.entryId,
|
|
47262
|
+
initialWeight,
|
|
47263
|
+
nowIso,
|
|
47264
|
+
// last_reinforced_at
|
|
47265
|
+
stability,
|
|
47266
|
+
nowIso
|
|
47267
|
+
);
|
|
47022
47268
|
result.edgesCreated++;
|
|
47269
|
+
const evtStmt = prepareLogEvent.run(
|
|
47270
|
+
spikeA.entryId,
|
|
47271
|
+
spikeB.entryId,
|
|
47272
|
+
initialWeight,
|
|
47273
|
+
"ltp",
|
|
47274
|
+
nowIso,
|
|
47275
|
+
eventSessionId,
|
|
47276
|
+
spikeA.rowId,
|
|
47277
|
+
null,
|
|
47278
|
+
initialWeight,
|
|
47279
|
+
deltaT
|
|
47280
|
+
);
|
|
47281
|
+
ltpEventId = evtStmt.lastInsertRowid != null ? Number(evtStmt.lastInsertRowid) : null;
|
|
47282
|
+
if (prepareLogWeightHistory) {
|
|
47283
|
+
prepareLogWeightHistory.run(
|
|
47284
|
+
spikeA.entryId,
|
|
47285
|
+
spikeB.entryId,
|
|
47286
|
+
null,
|
|
47287
|
+
initialWeight,
|
|
47288
|
+
initialWeight,
|
|
47289
|
+
"ltp",
|
|
47290
|
+
ltpEventId,
|
|
47291
|
+
spikeA.rowId,
|
|
47292
|
+
eventRewardSignal,
|
|
47293
|
+
nowIso
|
|
47294
|
+
);
|
|
47295
|
+
}
|
|
47023
47296
|
}
|
|
47024
|
-
prepareLogEvent.run(spikeA.entryId, spikeB.entryId, deltaW, "ltp", nowIso);
|
|
47025
47297
|
result.ltpEvents++;
|
|
47298
|
+
if (wasRewardModulated) result.rewardModulatedEvents++;
|
|
47026
47299
|
} catch {
|
|
47027
47300
|
}
|
|
47028
|
-
|
|
47301
|
+
let deltaWNeg = -(A_POST * Math.exp(-deltaT / tau));
|
|
47302
|
+
let ltdWasRewardModulated = false;
|
|
47303
|
+
if (eventRewardSignal !== null) {
|
|
47304
|
+
const r = eventRewardSignal;
|
|
47305
|
+
deltaWNeg = Math.max(deltaWNeg * (1 - r), -2 * A_POST);
|
|
47306
|
+
ltdWasRewardModulated = true;
|
|
47307
|
+
}
|
|
47029
47308
|
const existingReverseEdge = prepareGetEdge.get(spikeB.entryId, spikeA.entryId);
|
|
47030
47309
|
if (existingReverseEdge !== void 0 && Math.abs(deltaWNeg) >= 1e-6) {
|
|
47031
47310
|
try {
|
|
47032
|
-
|
|
47033
|
-
|
|
47311
|
+
const currentReverseWeight = existingReverseEdge.weight;
|
|
47312
|
+
const newReverseWeight = Math.max(
|
|
47313
|
+
WEIGHT_MIN,
|
|
47314
|
+
Math.min(WEIGHT_MAX, currentReverseWeight + deltaWNeg)
|
|
47315
|
+
);
|
|
47316
|
+
const upgradedClass = upgradePlasticityClass(
|
|
47317
|
+
existingReverseEdge.plasticity_class,
|
|
47318
|
+
"stdp"
|
|
47319
|
+
);
|
|
47320
|
+
const stability = computeStabilityScore(
|
|
47321
|
+
existingReverseEdge.reinforcement_count,
|
|
47322
|
+
existingReverseEdge.last_reinforced_at,
|
|
47323
|
+
now2
|
|
47324
|
+
);
|
|
47325
|
+
prepareUpdateEdgeLtd.run(
|
|
47326
|
+
WEIGHT_MIN,
|
|
47327
|
+
WEIGHT_MAX,
|
|
47328
|
+
deltaWNeg,
|
|
47329
|
+
nowIso,
|
|
47330
|
+
// last_depressed_at
|
|
47331
|
+
upgradedClass,
|
|
47332
|
+
stability,
|
|
47333
|
+
spikeB.entryId,
|
|
47334
|
+
spikeA.entryId
|
|
47335
|
+
);
|
|
47336
|
+
const isLtdDuplicate = isPlasticityEventDuplicate(
|
|
47337
|
+
nativeDb,
|
|
47338
|
+
spikeB.entryId,
|
|
47339
|
+
spikeA.entryId,
|
|
47340
|
+
"ltd",
|
|
47341
|
+
eventSessionId,
|
|
47342
|
+
1
|
|
47343
|
+
// within 1 hour
|
|
47344
|
+
);
|
|
47345
|
+
if (isLtdDuplicate) {
|
|
47346
|
+
result.ltdEvents++;
|
|
47347
|
+
if (ltdWasRewardModulated) result.rewardModulatedEvents++;
|
|
47348
|
+
continue;
|
|
47349
|
+
}
|
|
47350
|
+
const ltdEvtStmt = prepareLogEvent.run(
|
|
47351
|
+
spikeB.entryId,
|
|
47352
|
+
spikeA.entryId,
|
|
47353
|
+
deltaWNeg,
|
|
47354
|
+
"ltd",
|
|
47355
|
+
nowIso,
|
|
47356
|
+
eventSessionId,
|
|
47357
|
+
spikeB.rowId,
|
|
47358
|
+
currentReverseWeight,
|
|
47359
|
+
newReverseWeight,
|
|
47360
|
+
deltaT
|
|
47361
|
+
);
|
|
47362
|
+
const ltdEventId = ltdEvtStmt.lastInsertRowid != null ? Number(ltdEvtStmt.lastInsertRowid) : null;
|
|
47363
|
+
if (prepareLogWeightHistory) {
|
|
47364
|
+
prepareLogWeightHistory.run(
|
|
47365
|
+
spikeB.entryId,
|
|
47366
|
+
spikeA.entryId,
|
|
47367
|
+
currentReverseWeight,
|
|
47368
|
+
newReverseWeight,
|
|
47369
|
+
deltaWNeg,
|
|
47370
|
+
"ltd",
|
|
47371
|
+
ltdEventId,
|
|
47372
|
+
spikeB.rowId,
|
|
47373
|
+
eventRewardSignal,
|
|
47374
|
+
nowIso
|
|
47375
|
+
);
|
|
47376
|
+
}
|
|
47034
47377
|
result.ltdEvents++;
|
|
47378
|
+
if (ltdWasRewardModulated) result.rewardModulatedEvents++;
|
|
47035
47379
|
} catch {
|
|
47036
47380
|
}
|
|
47037
47381
|
}
|
|
@@ -47101,15 +47445,240 @@ async function getPlasticityStats(projectRoot, limit = 20) {
|
|
|
47101
47445
|
}))
|
|
47102
47446
|
};
|
|
47103
47447
|
}
|
|
47104
|
-
|
|
47448
|
+
async function backfillRewardSignals(projectRoot, sessionId, lookbackDays = 30) {
|
|
47449
|
+
const result = { rowsLabeled: 0, rowsSkipped: 0 };
|
|
47450
|
+
if (!sessionId) {
|
|
47451
|
+
return result;
|
|
47452
|
+
}
|
|
47453
|
+
if (sessionId.startsWith("ses_backfill_")) {
|
|
47454
|
+
return result;
|
|
47455
|
+
}
|
|
47456
|
+
let taskRows = [];
|
|
47457
|
+
try {
|
|
47458
|
+
const { getDb: getDb4 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
47459
|
+
const tasksDb = await getDb4(projectRoot);
|
|
47460
|
+
const { tasks: tasks2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
47461
|
+
const { and: and15, eq: eq18, inArray: inArray8, gte: gte4, or: or7, isNotNull: isNotNull3 } = await import("drizzle-orm");
|
|
47462
|
+
const cutoffTs = new Date(Date.now() - lookbackDays * 24 * 60 * 60 * 1e3).toISOString().replace("T", " ").slice(0, 19);
|
|
47463
|
+
const rawRows = await tasksDb.select({
|
|
47464
|
+
id: tasks2.id,
|
|
47465
|
+
status: tasks2.status,
|
|
47466
|
+
verificationJson: tasks2.verificationJson,
|
|
47467
|
+
completedAt: tasks2.completedAt,
|
|
47468
|
+
cancelledAt: tasks2.cancelledAt
|
|
47469
|
+
}).from(tasks2).where(
|
|
47470
|
+
and15(
|
|
47471
|
+
eq18(tasks2.sessionId, sessionId),
|
|
47472
|
+
inArray8(tasks2.status, ["done", "cancelled"]),
|
|
47473
|
+
or7(
|
|
47474
|
+
and15(isNotNull3(tasks2.completedAt), gte4(tasks2.completedAt, cutoffTs)),
|
|
47475
|
+
and15(isNotNull3(tasks2.cancelledAt), gte4(tasks2.cancelledAt, cutoffTs))
|
|
47476
|
+
)
|
|
47477
|
+
)
|
|
47478
|
+
).all();
|
|
47479
|
+
taskRows = rawRows.map((r) => ({
|
|
47480
|
+
id: r.id,
|
|
47481
|
+
status: r.status,
|
|
47482
|
+
verificationJson: r.verificationJson ?? null,
|
|
47483
|
+
completedAt: r.completedAt ?? null,
|
|
47484
|
+
cancelledAt: r.cancelledAt ?? null
|
|
47485
|
+
}));
|
|
47486
|
+
} catch {
|
|
47487
|
+
return result;
|
|
47488
|
+
}
|
|
47489
|
+
if (taskRows.length === 0) {
|
|
47490
|
+
return result;
|
|
47491
|
+
}
|
|
47492
|
+
let sessionReward = null;
|
|
47493
|
+
function deriveTaskReward(task) {
|
|
47494
|
+
if (task.status === "cancelled") {
|
|
47495
|
+
return -0.5;
|
|
47496
|
+
}
|
|
47497
|
+
let verificationPassed = false;
|
|
47498
|
+
if (task.verificationJson) {
|
|
47499
|
+
try {
|
|
47500
|
+
const v2 = JSON.parse(task.verificationJson);
|
|
47501
|
+
verificationPassed = v2.passed === true;
|
|
47502
|
+
} catch {
|
|
47503
|
+
}
|
|
47504
|
+
}
|
|
47505
|
+
return verificationPassed ? 1 : 0.5;
|
|
47506
|
+
}
|
|
47507
|
+
for (const task of taskRows) {
|
|
47508
|
+
const taskReward = deriveTaskReward(task);
|
|
47509
|
+
if (sessionReward === null || taskReward > sessionReward) {
|
|
47510
|
+
sessionReward = taskReward;
|
|
47511
|
+
}
|
|
47512
|
+
}
|
|
47513
|
+
if (sessionReward === null) {
|
|
47514
|
+
return result;
|
|
47515
|
+
}
|
|
47516
|
+
try {
|
|
47517
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47518
|
+
await getBrainDb2(projectRoot);
|
|
47519
|
+
const nativeDb = getBrainNativeDb2();
|
|
47520
|
+
if (!nativeDb) return result;
|
|
47521
|
+
try {
|
|
47522
|
+
nativeDb.prepare("SELECT 1 FROM brain_retrieval_log LIMIT 1").get();
|
|
47523
|
+
} catch {
|
|
47524
|
+
return result;
|
|
47525
|
+
}
|
|
47526
|
+
const updateResult = nativeDb.prepare(
|
|
47527
|
+
`UPDATE brain_retrieval_log
|
|
47528
|
+
SET reward_signal = ?
|
|
47529
|
+
WHERE session_id = ?
|
|
47530
|
+
AND reward_signal IS NULL`
|
|
47531
|
+
).run(sessionReward, sessionId);
|
|
47532
|
+
const updatedCount = typeof updateResult.changes === "number" ? updateResult.changes : 0;
|
|
47533
|
+
result.rowsLabeled = updatedCount;
|
|
47534
|
+
const skipRow = nativeDb.prepare(
|
|
47535
|
+
`SELECT COUNT(*) AS cnt FROM brain_retrieval_log
|
|
47536
|
+
WHERE session_id = ? AND reward_signal IS NOT NULL`
|
|
47537
|
+
).get(sessionId);
|
|
47538
|
+
result.rowsSkipped = skipRow?.cnt ?? 0;
|
|
47539
|
+
let modulatorsExist = false;
|
|
47540
|
+
try {
|
|
47541
|
+
nativeDb.prepare("SELECT 1 FROM brain_modulators LIMIT 1").get();
|
|
47542
|
+
modulatorsExist = true;
|
|
47543
|
+
} catch {
|
|
47544
|
+
}
|
|
47545
|
+
if (modulatorsExist && updatedCount > 0) {
|
|
47546
|
+
const insertModulator = nativeDb.prepare(
|
|
47547
|
+
`INSERT INTO brain_modulators
|
|
47548
|
+
(modulator_type, valence, magnitude, source_event_id, session_id, description)
|
|
47549
|
+
VALUES (?, ?, 1.0, ?, ?, ?)`
|
|
47550
|
+
);
|
|
47551
|
+
for (const task of taskRows) {
|
|
47552
|
+
const taskReward = deriveTaskReward(task);
|
|
47553
|
+
let modulatorType;
|
|
47554
|
+
let description;
|
|
47555
|
+
if (task.status === "cancelled") {
|
|
47556
|
+
modulatorType = "task_cancelled";
|
|
47557
|
+
description = `Task ${task.id} cancelled`;
|
|
47558
|
+
} else if (taskReward >= 1) {
|
|
47559
|
+
modulatorType = "task_verified";
|
|
47560
|
+
description = `Task ${task.id} completed and verified`;
|
|
47561
|
+
} else {
|
|
47562
|
+
modulatorType = "task_completed";
|
|
47563
|
+
description = `Task ${task.id} completed (unverified)`;
|
|
47564
|
+
}
|
|
47565
|
+
try {
|
|
47566
|
+
insertModulator.run(modulatorType, taskReward, task.id, sessionId, description);
|
|
47567
|
+
} catch {
|
|
47568
|
+
}
|
|
47569
|
+
}
|
|
47570
|
+
}
|
|
47571
|
+
} catch {
|
|
47572
|
+
}
|
|
47573
|
+
return result;
|
|
47574
|
+
}
|
|
47575
|
+
async function applyHomeostaticDecay(projectRoot, options) {
|
|
47576
|
+
const decayRatePerDay = options?.decayRatePerDay ?? 0.02;
|
|
47577
|
+
const gracePeriodDays = options?.gracePeriodDays ?? 7;
|
|
47578
|
+
const pruneThreshold = options?.pruneThreshold ?? 0.05;
|
|
47579
|
+
const result = { edgesDecayed: 0, edgesPruned: 0 };
|
|
47580
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47581
|
+
await getBrainDb2(projectRoot);
|
|
47582
|
+
const nativeDb = getBrainNativeDb2();
|
|
47583
|
+
if (!nativeDb) return result;
|
|
47584
|
+
try {
|
|
47585
|
+
nativeDb.prepare("SELECT 1 FROM brain_page_edges LIMIT 1").get();
|
|
47586
|
+
} catch {
|
|
47587
|
+
return result;
|
|
47588
|
+
}
|
|
47589
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
47590
|
+
let weightHistoryExists = false;
|
|
47591
|
+
try {
|
|
47592
|
+
nativeDb.prepare("SELECT 1 FROM brain_weight_history LIMIT 1").get();
|
|
47593
|
+
weightHistoryExists = true;
|
|
47594
|
+
} catch {
|
|
47595
|
+
}
|
|
47596
|
+
let candidates = [];
|
|
47597
|
+
try {
|
|
47598
|
+
candidates = typedAll(
|
|
47599
|
+
nativeDb.prepare(
|
|
47600
|
+
`SELECT from_id, to_id, edge_type, weight, plasticity_class, last_reinforced_at
|
|
47601
|
+
FROM brain_page_edges
|
|
47602
|
+
WHERE plasticity_class IN ('hebbian', 'stdp')
|
|
47603
|
+
AND last_reinforced_at IS NOT NULL
|
|
47604
|
+
AND (julianday('now') - julianday(last_reinforced_at)) > ?`
|
|
47605
|
+
),
|
|
47606
|
+
gracePeriodDays
|
|
47607
|
+
);
|
|
47608
|
+
} catch {
|
|
47609
|
+
return result;
|
|
47610
|
+
}
|
|
47611
|
+
if (candidates.length === 0) return result;
|
|
47612
|
+
const prepareUpdateWeight = nativeDb.prepare(
|
|
47613
|
+
`UPDATE brain_page_edges
|
|
47614
|
+
SET weight = ?
|
|
47615
|
+
WHERE from_id = ? AND to_id = ? AND edge_type = ?`
|
|
47616
|
+
);
|
|
47617
|
+
const prepareDeleteEdge = nativeDb.prepare(
|
|
47618
|
+
`DELETE FROM brain_page_edges
|
|
47619
|
+
WHERE from_id = ? AND to_id = ? AND edge_type = ?`
|
|
47620
|
+
);
|
|
47621
|
+
let prepareInsertHistory = null;
|
|
47622
|
+
if (weightHistoryExists) {
|
|
47623
|
+
try {
|
|
47624
|
+
prepareInsertHistory = nativeDb.prepare(
|
|
47625
|
+
`INSERT INTO brain_weight_history
|
|
47626
|
+
(edge_from_id, edge_to_id, edge_type, weight_before, weight_after,
|
|
47627
|
+
delta_weight, event_kind, changed_at)
|
|
47628
|
+
VALUES (?, ?, ?, ?, 0.0, ?, 'prune', ?)`
|
|
47629
|
+
);
|
|
47630
|
+
} catch {
|
|
47631
|
+
}
|
|
47632
|
+
}
|
|
47633
|
+
const nowMs = Date.now();
|
|
47634
|
+
for (const edge of candidates) {
|
|
47635
|
+
try {
|
|
47636
|
+
const lastReinforced = (/* @__PURE__ */ new Date(edge.last_reinforced_at.replace(" ", "T") + "Z")).getTime();
|
|
47637
|
+
const daysIdle = (nowMs - lastReinforced) / (24 * 60 * 60 * 1e3);
|
|
47638
|
+
const decayDays = Math.max(0, daysIdle - gracePeriodDays);
|
|
47639
|
+
const newWeight = edge.weight * (1 - decayRatePerDay) ** decayDays;
|
|
47640
|
+
if (newWeight < pruneThreshold) {
|
|
47641
|
+
prepareDeleteEdge.run(edge.from_id, edge.to_id, edge.edge_type);
|
|
47642
|
+
result.edgesPruned++;
|
|
47643
|
+
if (prepareInsertHistory) {
|
|
47644
|
+
const deltaW = -edge.weight;
|
|
47645
|
+
try {
|
|
47646
|
+
prepareInsertHistory.run(
|
|
47647
|
+
edge.from_id,
|
|
47648
|
+
edge.to_id,
|
|
47649
|
+
edge.edge_type,
|
|
47650
|
+
edge.weight,
|
|
47651
|
+
deltaW,
|
|
47652
|
+
nowIso
|
|
47653
|
+
);
|
|
47654
|
+
} catch {
|
|
47655
|
+
}
|
|
47656
|
+
}
|
|
47657
|
+
} else {
|
|
47658
|
+
prepareUpdateWeight.run(newWeight, edge.from_id, edge.to_id, edge.edge_type);
|
|
47659
|
+
result.edgesDecayed++;
|
|
47660
|
+
}
|
|
47661
|
+
} catch {
|
|
47662
|
+
}
|
|
47663
|
+
}
|
|
47664
|
+
return result;
|
|
47665
|
+
}
|
|
47666
|
+
var DEFAULT_LOOKBACK_DAYS, DEFAULT_PAIRING_WINDOW_MS, TAU_NEAR_MS, TAU_SESSION_MS, TAU_EPISODIC_MS, TAU_NEAR_THRESHOLD_MS, TAU_SESSION_THRESHOLD_MS, A_PRE, A_POST, K_NOVELTY, WEIGHT_MIN, WEIGHT_MAX;
|
|
47105
47667
|
var init_brain_stdp = __esm({
|
|
47106
47668
|
"packages/core/src/memory/brain-stdp.ts"() {
|
|
47107
47669
|
"use strict";
|
|
47108
47670
|
init_typed_query();
|
|
47109
|
-
|
|
47110
|
-
|
|
47671
|
+
init_brain_plasticity_class();
|
|
47672
|
+
DEFAULT_LOOKBACK_DAYS = 30;
|
|
47673
|
+
DEFAULT_PAIRING_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
47674
|
+
TAU_NEAR_MS = 2e4;
|
|
47675
|
+
TAU_SESSION_MS = 30 * 60 * 1e3;
|
|
47676
|
+
TAU_EPISODIC_MS = 12 * 60 * 60 * 1e3;
|
|
47677
|
+
TAU_NEAR_THRESHOLD_MS = 3e4;
|
|
47678
|
+
TAU_SESSION_THRESHOLD_MS = 2 * 60 * 60 * 1e3;
|
|
47111
47679
|
A_PRE = 0.05;
|
|
47112
47680
|
A_POST = 0.06;
|
|
47681
|
+
K_NOVELTY = 1.5;
|
|
47113
47682
|
WEIGHT_MIN = 0;
|
|
47114
47683
|
WEIGHT_MAX = 1;
|
|
47115
47684
|
}
|
|
@@ -47358,7 +47927,8 @@ async function runTierPromotion(projectRoot) {
|
|
|
47358
47927
|
}
|
|
47359
47928
|
return { promoted, evicted };
|
|
47360
47929
|
}
|
|
47361
|
-
async function runConsolidation(projectRoot) {
|
|
47930
|
+
async function runConsolidation(projectRoot, sessionId, trigger = "session_end") {
|
|
47931
|
+
const consolidationStartMs = Date.now();
|
|
47362
47932
|
const result = {
|
|
47363
47933
|
deduplicated: 0,
|
|
47364
47934
|
qualityRecomputed: 0,
|
|
@@ -47421,11 +47991,59 @@ async function runConsolidation(projectRoot) {
|
|
|
47421
47991
|
console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
|
|
47422
47992
|
}
|
|
47423
47993
|
try {
|
|
47424
|
-
const {
|
|
47425
|
-
const
|
|
47426
|
-
result.
|
|
47994
|
+
const { backfillRewardSignals: backfillRewardSignals2 } = await Promise.resolve().then(() => (init_brain_stdp(), brain_stdp_exports));
|
|
47995
|
+
const rewardResult = await backfillRewardSignals2(projectRoot, sessionId ?? null);
|
|
47996
|
+
result.rewardBackfilled = rewardResult;
|
|
47997
|
+
} catch (err) {
|
|
47998
|
+
console.warn("[consolidation] Step 9a reward backfill failed:", err);
|
|
47999
|
+
}
|
|
48000
|
+
try {
|
|
48001
|
+
const { applyStdpPlasticity: applyStdpPlasticity2, shouldRunPlasticity: shouldRunPlasticity2 } = await Promise.resolve().then(() => (init_brain_stdp(), brain_stdp_exports));
|
|
48002
|
+
const shouldRun = await shouldRunPlasticity2(projectRoot, sessionId ?? null, 2);
|
|
48003
|
+
if (shouldRun) {
|
|
48004
|
+
const stdpResult = await applyStdpPlasticity2(projectRoot);
|
|
48005
|
+
result.stdpPlasticity = stdpResult;
|
|
48006
|
+
} else {
|
|
48007
|
+
result.stdpPlasticity = {
|
|
48008
|
+
ltpEvents: 0,
|
|
48009
|
+
ltdEvents: 0,
|
|
48010
|
+
edgesCreated: 0,
|
|
48011
|
+
pairsExamined: 0
|
|
48012
|
+
};
|
|
48013
|
+
}
|
|
48014
|
+
} catch (err) {
|
|
48015
|
+
console.warn("[consolidation] Step 9b STDP plasticity failed:", err);
|
|
48016
|
+
}
|
|
48017
|
+
try {
|
|
48018
|
+
const { applyHomeostaticDecay: applyHomeostaticDecay2 } = await Promise.resolve().then(() => (init_brain_stdp(), brain_stdp_exports));
|
|
48019
|
+
const decayResult = await applyHomeostaticDecay2(projectRoot);
|
|
48020
|
+
result.homeostaticDecay = decayResult;
|
|
48021
|
+
} catch (err) {
|
|
48022
|
+
console.warn("[consolidation] Step 9c homeostatic decay failed:", err);
|
|
48023
|
+
}
|
|
48024
|
+
try {
|
|
48025
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
48026
|
+
await getBrainDb2(projectRoot);
|
|
48027
|
+
const nativeDb = getBrainNativeDb2();
|
|
48028
|
+
if (nativeDb) {
|
|
48029
|
+
let consolidationEventsExist = false;
|
|
48030
|
+
try {
|
|
48031
|
+
nativeDb.prepare("SELECT 1 FROM brain_consolidation_events LIMIT 1").get();
|
|
48032
|
+
consolidationEventsExist = true;
|
|
48033
|
+
} catch {
|
|
48034
|
+
}
|
|
48035
|
+
if (consolidationEventsExist) {
|
|
48036
|
+
const durationMs = Date.now() - consolidationStartMs;
|
|
48037
|
+
const stepResultsJson = JSON.stringify(result);
|
|
48038
|
+
nativeDb.prepare(
|
|
48039
|
+
`INSERT INTO brain_consolidation_events
|
|
48040
|
+
(trigger, session_id, step_results_json, duration_ms, succeeded)
|
|
48041
|
+
VALUES (?, ?, ?, ?, 1)`
|
|
48042
|
+
).run(trigger, sessionId ?? null, stepResultsJson, durationMs);
|
|
48043
|
+
}
|
|
48044
|
+
}
|
|
47427
48045
|
} catch (err) {
|
|
47428
|
-
console.warn("[consolidation] Step
|
|
48046
|
+
console.warn("[consolidation] Step 9e consolidation event log failed:", err);
|
|
47429
48047
|
}
|
|
47430
48048
|
return result;
|
|
47431
48049
|
}
|
|
@@ -47587,7 +48205,8 @@ async function strengthenCoRetrievedEdges(projectRoot) {
|
|
|
47587
48205
|
try {
|
|
47588
48206
|
const updateStmt = nativeDb.prepare(`
|
|
47589
48207
|
UPDATE brain_page_edges
|
|
47590
|
-
SET weight = MIN(1.0, weight + 0.1)
|
|
48208
|
+
SET weight = MIN(1.0, weight + 0.1),
|
|
48209
|
+
plasticity_class = 'hebbian'
|
|
47591
48210
|
WHERE from_id = ? AND to_id = ? AND edge_type = ?
|
|
47592
48211
|
`);
|
|
47593
48212
|
const updateResult = updateStmt.run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED);
|
|
@@ -47595,8 +48214,8 @@ async function strengthenCoRetrievedEdges(projectRoot) {
|
|
|
47595
48214
|
if (changes === 0) {
|
|
47596
48215
|
nativeDb.prepare(`
|
|
47597
48216
|
INSERT OR IGNORE INTO brain_page_edges
|
|
47598
|
-
(from_id, to_id, edge_type, weight, provenance, created_at)
|
|
47599
|
-
VALUES (?, ?, ?, 0.3, 'consolidation:co-retrieval', ?)
|
|
48217
|
+
(from_id, to_id, edge_type, weight, provenance, plasticity_class, created_at)
|
|
48218
|
+
VALUES (?, ?, ?, 0.3, 'consolidation:co-retrieval', 'hebbian', ?)
|
|
47600
48219
|
`).run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED, now2);
|
|
47601
48220
|
}
|
|
47602
48221
|
strengthened++;
|
|
@@ -57185,8 +57804,8 @@ async function ensureGlobalHome() {
|
|
|
57185
57804
|
await writeFile6(globalConfigPath, resolved);
|
|
57186
57805
|
}
|
|
57187
57806
|
}
|
|
57188
|
-
const
|
|
57189
|
-
const legacyCleoHome = join42(
|
|
57807
|
+
const homedir9 = (await import("node:os")).homedir();
|
|
57808
|
+
const legacyCleoHome = join42(homedir9, ".cleo");
|
|
57190
57809
|
const cleanupPaths = [cleoHome];
|
|
57191
57810
|
if (legacyCleoHome !== cleoHome && existsSync40(legacyCleoHome)) {
|
|
57192
57811
|
cleanupPaths.push(legacyCleoHome);
|
|
@@ -65289,10 +65908,10 @@ async function readProjectMeta(projectPath) {
|
|
|
65289
65908
|
}
|
|
65290
65909
|
async function readProjectId(projectPath) {
|
|
65291
65910
|
try {
|
|
65292
|
-
const { readFileSync:
|
|
65911
|
+
const { readFileSync: readFileSync108, existsSync: existsSync136 } = await import("node:fs");
|
|
65293
65912
|
const infoPath = join64(projectPath, ".cleo", "project-info.json");
|
|
65294
|
-
if (!
|
|
65295
|
-
const data = JSON.parse(
|
|
65913
|
+
if (!existsSync136(infoPath)) return "";
|
|
65914
|
+
const data = JSON.parse(readFileSync108(infoPath, "utf-8"));
|
|
65296
65915
|
return typeof data.projectId === "string" ? data.projectId : "";
|
|
65297
65916
|
} catch {
|
|
65298
65917
|
return "";
|
|
@@ -66996,6 +67615,10 @@ async function startTask(taskId, cwd, accessor) {
|
|
|
66996
67615
|
}
|
|
66997
67616
|
);
|
|
66998
67617
|
}
|
|
67618
|
+
const currentStage = task.pipelineStage;
|
|
67619
|
+
if (currentStage && isValidPipelineStage(currentStage) && PLANNING_STAGES2.has(currentStage)) {
|
|
67620
|
+
await acc.updateTaskFields(taskId, { pipelineStage: "implementation" });
|
|
67621
|
+
}
|
|
66999
67622
|
const focus = await acc.getMetaValue("focus_state") ?? {};
|
|
67000
67623
|
const previousTask = focus.currentTask ?? null;
|
|
67001
67624
|
focus.currentTask = taskId;
|
|
@@ -67083,16 +67706,24 @@ async function getWorkHistory(cwd, accessor) {
|
|
|
67083
67706
|
}
|
|
67084
67707
|
return history.reverse();
|
|
67085
67708
|
}
|
|
67086
|
-
var getTaskHistory;
|
|
67709
|
+
var PLANNING_STAGES2, getTaskHistory;
|
|
67087
67710
|
var init_task_work = __esm({
|
|
67088
67711
|
"packages/core/src/task-work/index.ts"() {
|
|
67089
67712
|
"use strict";
|
|
67713
|
+
init_handlers();
|
|
67090
67714
|
init_src();
|
|
67091
67715
|
init_errors3();
|
|
67092
67716
|
init_data_accessor();
|
|
67093
67717
|
init_add();
|
|
67094
67718
|
init_dependency_check();
|
|
67095
|
-
|
|
67719
|
+
init_pipeline_stage();
|
|
67720
|
+
PLANNING_STAGES2 = /* @__PURE__ */ new Set([
|
|
67721
|
+
"research",
|
|
67722
|
+
"consensus",
|
|
67723
|
+
"architecture_decision",
|
|
67724
|
+
"specification",
|
|
67725
|
+
"decomposition"
|
|
67726
|
+
]);
|
|
67096
67727
|
getTaskHistory = getWorkHistory;
|
|
67097
67728
|
}
|
|
67098
67729
|
});
|
|
@@ -67214,6 +67845,10 @@ async function completeTask(options, cwd, accessor) {
|
|
|
67214
67845
|
}
|
|
67215
67846
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
67216
67847
|
const before = { ...task };
|
|
67848
|
+
const completionStage = task.pipelineStage;
|
|
67849
|
+
if (completionStage && isValidPipelineStage(completionStage) && EXECUTION_STAGES_FOR_RELEASE.has(completionStage)) {
|
|
67850
|
+
task.pipelineStage = "release";
|
|
67851
|
+
}
|
|
67217
67852
|
task.status = "done";
|
|
67218
67853
|
task.completedAt = now2;
|
|
67219
67854
|
task.updatedAt = now2;
|
|
@@ -67326,7 +67961,7 @@ async function completeTask(options, cwd, accessor) {
|
|
|
67326
67961
|
...unblockedTasks.length > 0 && { unblockedTasks }
|
|
67327
67962
|
};
|
|
67328
67963
|
}
|
|
67329
|
-
var DEFAULT_VERIFICATION_REQUIRED_GATES, VERIFICATION_GATES;
|
|
67964
|
+
var EXECUTION_STAGES_FOR_RELEASE, DEFAULT_VERIFICATION_REQUIRED_GATES, VERIFICATION_GATES;
|
|
67330
67965
|
var init_complete = __esm({
|
|
67331
67966
|
"packages/core/src/tasks/complete.ts"() {
|
|
67332
67967
|
"use strict";
|
|
@@ -67336,6 +67971,8 @@ var init_complete = __esm({
|
|
|
67336
67971
|
init_session_enforcement();
|
|
67337
67972
|
init_data_accessor();
|
|
67338
67973
|
init_enforcement();
|
|
67974
|
+
init_pipeline_stage();
|
|
67975
|
+
EXECUTION_STAGES_FOR_RELEASE = /* @__PURE__ */ new Set(["implementation", "validation", "testing"]);
|
|
67339
67976
|
DEFAULT_VERIFICATION_REQUIRED_GATES = [
|
|
67340
67977
|
"implemented",
|
|
67341
67978
|
"testsPassed",
|
|
@@ -76910,8 +77547,8 @@ async function initializeSpawnAdapters(manifests) {
|
|
|
76910
77547
|
if (!manifest.capabilities?.supportsSpawn) continue;
|
|
76911
77548
|
if (spawnRegistry.hasAdapterForProvider(manifest.provider)) continue;
|
|
76912
77549
|
try {
|
|
76913
|
-
const { join:
|
|
76914
|
-
const modulePath =
|
|
77550
|
+
const { join: join136 } = await import("node:path");
|
|
77551
|
+
const modulePath = join136(manifest.packagePath, manifest.entryPoint);
|
|
76915
77552
|
const adapterModule = await import(modulePath);
|
|
76916
77553
|
let SpawnProviderClass;
|
|
76917
77554
|
for (const [exportName, exportValue] of Object.entries(adapterModule)) {
|
|
@@ -80878,6 +81515,46 @@ async function getSystemHealth(projectRoot, opts) {
|
|
|
80878
81515
|
if (existsSync92(dbPath)) {
|
|
80879
81516
|
checks.push(checkAuditLogAvailability(dbPath));
|
|
80880
81517
|
}
|
|
81518
|
+
if (existsSync92(dbPath) && databaseSyncCtor) {
|
|
81519
|
+
try {
|
|
81520
|
+
const tasksDb = new databaseSyncCtor(dbPath, { readOnly: true });
|
|
81521
|
+
let taskCount = 0;
|
|
81522
|
+
try {
|
|
81523
|
+
const tableExists3 = tasksDb.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks'").get();
|
|
81524
|
+
if (tableExists3?.name) {
|
|
81525
|
+
const countRow = tasksDb.prepare("SELECT COUNT(*) as cnt FROM tasks").get();
|
|
81526
|
+
taskCount = countRow?.cnt ?? 0;
|
|
81527
|
+
}
|
|
81528
|
+
} finally {
|
|
81529
|
+
tasksDb.close();
|
|
81530
|
+
}
|
|
81531
|
+
if (taskCount === 0) {
|
|
81532
|
+
const { listSqliteBackups: listSqliteBackups2 } = await Promise.resolve().then(() => (init_sqlite_backup(), sqlite_backup_exports));
|
|
81533
|
+
const backups = listSqliteBackups2(projectRoot);
|
|
81534
|
+
if (backups.length > 0) {
|
|
81535
|
+
const latestBackup = backups[0];
|
|
81536
|
+
checks.push({
|
|
81537
|
+
name: "tasks_wipe_guard",
|
|
81538
|
+
status: "fail",
|
|
81539
|
+
message: `WIPE ALERT: tasks.db has 0 tasks but ${backups.length} backup(s) exist. Latest: ${latestBackup?.name ?? "unknown"} (${new Date(latestBackup?.mtimeMs ?? 0).toISOString()}). Probable data loss \u2014 restore via: cleo restore backup --file tasks.db. See docs/RECOVERY.md for the full procedure. (T724)`
|
|
81540
|
+
});
|
|
81541
|
+
} else {
|
|
81542
|
+
checks.push({
|
|
81543
|
+
name: "tasks_wipe_guard",
|
|
81544
|
+
status: "warn",
|
|
81545
|
+
message: "tasks.db has 0 tasks and no backups exist (fresh install or data loss without backup recovery)."
|
|
81546
|
+
});
|
|
81547
|
+
}
|
|
81548
|
+
} else {
|
|
81549
|
+
checks.push({
|
|
81550
|
+
name: "tasks_wipe_guard",
|
|
81551
|
+
status: "pass",
|
|
81552
|
+
message: `tasks.db integrity: ${taskCount} task(s) present`
|
|
81553
|
+
});
|
|
81554
|
+
}
|
|
81555
|
+
} catch {
|
|
81556
|
+
}
|
|
81557
|
+
}
|
|
80881
81558
|
const sdDbPath = join94(cleoDir, "signaldock.db");
|
|
80882
81559
|
if (existsSync92(sdDbPath)) {
|
|
80883
81560
|
try {
|
|
@@ -88706,6 +89383,7 @@ var init_cleo = __esm({
|
|
|
88706
89383
|
// packages/core/src/index.ts
|
|
88707
89384
|
var init_src3 = __esm({
|
|
88708
89385
|
"packages/core/src/index.ts"() {
|
|
89386
|
+
"use strict";
|
|
88709
89387
|
init_src();
|
|
88710
89388
|
init_adapters();
|
|
88711
89389
|
init_admin();
|
|
@@ -92175,6 +92853,197 @@ var init_claude_mem_migration = __esm({
|
|
|
92175
92853
|
}
|
|
92176
92854
|
});
|
|
92177
92855
|
|
|
92856
|
+
// packages/core/src/memory/dream-cycle.ts
|
|
92857
|
+
function countNewObservations(afterTimestamp) {
|
|
92858
|
+
const db = getBrainNativeDb();
|
|
92859
|
+
if (!db) return 0;
|
|
92860
|
+
try {
|
|
92861
|
+
const row = db.prepare(
|
|
92862
|
+
`SELECT COUNT(*) AS cnt FROM brain_observations
|
|
92863
|
+
WHERE created_at > ? AND invalid_at IS NULL`
|
|
92864
|
+
).get(afterTimestamp);
|
|
92865
|
+
return row?.cnt ?? 0;
|
|
92866
|
+
} catch {
|
|
92867
|
+
return 0;
|
|
92868
|
+
}
|
|
92869
|
+
}
|
|
92870
|
+
function getLastConsolidationTimestamp() {
|
|
92871
|
+
const db = getBrainNativeDb();
|
|
92872
|
+
if (!db) return null;
|
|
92873
|
+
try {
|
|
92874
|
+
const row = db.prepare(
|
|
92875
|
+
`SELECT started_at FROM brain_consolidation_events
|
|
92876
|
+
ORDER BY started_at DESC LIMIT 1`
|
|
92877
|
+
).get();
|
|
92878
|
+
return row?.started_at ?? null;
|
|
92879
|
+
} catch {
|
|
92880
|
+
return null;
|
|
92881
|
+
}
|
|
92882
|
+
}
|
|
92883
|
+
function getLastRetrievalTimestamp() {
|
|
92884
|
+
const db = getBrainNativeDb();
|
|
92885
|
+
if (!db) return null;
|
|
92886
|
+
try {
|
|
92887
|
+
const row = db.prepare(`SELECT created_at FROM brain_retrieval_log ORDER BY created_at DESC LIMIT 1`).get();
|
|
92888
|
+
return row?.created_at ?? null;
|
|
92889
|
+
} catch {
|
|
92890
|
+
return null;
|
|
92891
|
+
}
|
|
92892
|
+
}
|
|
92893
|
+
function minutesSince(isoTimestamp2) {
|
|
92894
|
+
if (!isoTimestamp2) return Infinity;
|
|
92895
|
+
const normalised = isoTimestamp2.includes("T") ? isoTimestamp2 : isoTimestamp2.replace(" ", "T") + "Z";
|
|
92896
|
+
const ms2 = Date.now() - new Date(normalised).getTime();
|
|
92897
|
+
return ms2 / 6e4;
|
|
92898
|
+
}
|
|
92899
|
+
function checkVolumeTrigger(threshold) {
|
|
92900
|
+
const lastConsolidated = getLastConsolidationTimestamp();
|
|
92901
|
+
const after = lastConsolidated ?? "1970-01-01 00:00:00";
|
|
92902
|
+
const newObservationCount = countNewObservations(after);
|
|
92903
|
+
return {
|
|
92904
|
+
shouldTrigger: newObservationCount >= threshold,
|
|
92905
|
+
newObservationCount
|
|
92906
|
+
};
|
|
92907
|
+
}
|
|
92908
|
+
function checkIdleTrigger(idleThresholdMinutes) {
|
|
92909
|
+
const lastRetrievalTs = getLastRetrievalTimestamp();
|
|
92910
|
+
if (lastRetrievalTs === null) {
|
|
92911
|
+
return { shouldTrigger: false, idleMinutes: 0 };
|
|
92912
|
+
}
|
|
92913
|
+
const idleMinutes = minutesSince(lastRetrievalTs);
|
|
92914
|
+
return {
|
|
92915
|
+
shouldTrigger: idleMinutes >= idleThresholdMinutes,
|
|
92916
|
+
idleMinutes
|
|
92917
|
+
};
|
|
92918
|
+
}
|
|
92919
|
+
async function dispatchDream(projectRoot, sessionId, inline = false) {
|
|
92920
|
+
if (dreamInFlight) return;
|
|
92921
|
+
dreamInFlight = true;
|
|
92922
|
+
lastDreamAt = Date.now();
|
|
92923
|
+
const run = async () => {
|
|
92924
|
+
try {
|
|
92925
|
+
const { runConsolidation: runConsolidation2 } = await Promise.resolve().then(() => (init_brain_lifecycle(), brain_lifecycle_exports));
|
|
92926
|
+
await runConsolidation2(projectRoot, sessionId ?? null, "scheduled");
|
|
92927
|
+
} catch (err) {
|
|
92928
|
+
console.warn("[dream-cycle] Consolidation failed:", err);
|
|
92929
|
+
} finally {
|
|
92930
|
+
dreamInFlight = false;
|
|
92931
|
+
}
|
|
92932
|
+
};
|
|
92933
|
+
if (inline) {
|
|
92934
|
+
await run();
|
|
92935
|
+
} else {
|
|
92936
|
+
setImmediate(run);
|
|
92937
|
+
}
|
|
92938
|
+
}
|
|
92939
|
+
async function checkAndDream(projectRoot, opts = {}) {
|
|
92940
|
+
const volumeThreshold = opts.volumeThreshold ?? VOLUME_THRESHOLD_DEFAULT;
|
|
92941
|
+
const idleThresholdMinutes = opts.idleThresholdMinutes ?? IDLE_MINUTES_DEFAULT;
|
|
92942
|
+
try {
|
|
92943
|
+
await getBrainDb(projectRoot);
|
|
92944
|
+
} catch {
|
|
92945
|
+
return {
|
|
92946
|
+
triggered: false,
|
|
92947
|
+
tier: null,
|
|
92948
|
+
skippedReason: "brain.db unavailable"
|
|
92949
|
+
};
|
|
92950
|
+
}
|
|
92951
|
+
const msSinceLastDream = Date.now() - lastDreamAt;
|
|
92952
|
+
if (msSinceLastDream < DREAM_COOLDOWN_MS) {
|
|
92953
|
+
return {
|
|
92954
|
+
triggered: false,
|
|
92955
|
+
tier: null,
|
|
92956
|
+
skippedReason: `dream cooldown active (${Math.round(msSinceLastDream / 1e3)}s since last dream)`
|
|
92957
|
+
};
|
|
92958
|
+
}
|
|
92959
|
+
if (dreamInFlight) {
|
|
92960
|
+
return {
|
|
92961
|
+
triggered: false,
|
|
92962
|
+
tier: null,
|
|
92963
|
+
skippedReason: "dream already in flight"
|
|
92964
|
+
};
|
|
92965
|
+
}
|
|
92966
|
+
const volumeCheck = checkVolumeTrigger(volumeThreshold);
|
|
92967
|
+
if (volumeCheck.shouldTrigger) {
|
|
92968
|
+
await dispatchDream(projectRoot, opts.sessionId, opts.inline);
|
|
92969
|
+
return {
|
|
92970
|
+
triggered: true,
|
|
92971
|
+
tier: "volume",
|
|
92972
|
+
newObservationCount: volumeCheck.newObservationCount
|
|
92973
|
+
};
|
|
92974
|
+
}
|
|
92975
|
+
const idleCheck = checkIdleTrigger(idleThresholdMinutes);
|
|
92976
|
+
if (idleCheck.shouldTrigger) {
|
|
92977
|
+
await dispatchDream(projectRoot, opts.sessionId, opts.inline);
|
|
92978
|
+
return {
|
|
92979
|
+
triggered: true,
|
|
92980
|
+
tier: "idle",
|
|
92981
|
+
idleMinutes: idleCheck.idleMinutes
|
|
92982
|
+
};
|
|
92983
|
+
}
|
|
92984
|
+
return {
|
|
92985
|
+
triggered: false,
|
|
92986
|
+
tier: null,
|
|
92987
|
+
skippedReason: `volume below threshold (${volumeCheck.newObservationCount}/${volumeThreshold}); idle below threshold (${Math.round(idleCheck.idleMinutes)}/${idleThresholdMinutes} min)`,
|
|
92988
|
+
newObservationCount: volumeCheck.newObservationCount,
|
|
92989
|
+
idleMinutes: idleCheck.idleMinutes
|
|
92990
|
+
};
|
|
92991
|
+
}
|
|
92992
|
+
async function triggerManualDream(projectRoot, sessionId) {
|
|
92993
|
+
const { runConsolidation: runConsolidation2 } = await Promise.resolve().then(() => (init_brain_lifecycle(), brain_lifecycle_exports));
|
|
92994
|
+
const result = await runConsolidation2(projectRoot, sessionId ?? null, "manual");
|
|
92995
|
+
lastDreamAt = Date.now();
|
|
92996
|
+
return result;
|
|
92997
|
+
}
|
|
92998
|
+
function startDreamScheduler(projectRoot, hourUTC = NIGHTLY_HOUR_DEFAULT) {
|
|
92999
|
+
if (nightlyTimer !== null) return false;
|
|
93000
|
+
const msUntilNextFire = () => {
|
|
93001
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
93002
|
+
const next = new Date(now2);
|
|
93003
|
+
next.setUTCHours(hourUTC, 0, 0, 0);
|
|
93004
|
+
if (next.getTime() <= now2.getTime()) {
|
|
93005
|
+
next.setUTCDate(next.getUTCDate() + 1);
|
|
93006
|
+
}
|
|
93007
|
+
return next.getTime() - now2.getTime();
|
|
93008
|
+
};
|
|
93009
|
+
const scheduleNext = () => {
|
|
93010
|
+
nightlyTimer = setTimeout(() => {
|
|
93011
|
+
nightlyTimer = null;
|
|
93012
|
+
checkAndDream(projectRoot, { inline: false }).catch((err) => {
|
|
93013
|
+
console.warn("[dream-cycle] Nightly cron failed:", err);
|
|
93014
|
+
});
|
|
93015
|
+
scheduleNext();
|
|
93016
|
+
}, msUntilNextFire());
|
|
93017
|
+
};
|
|
93018
|
+
scheduleNext();
|
|
93019
|
+
return true;
|
|
93020
|
+
}
|
|
93021
|
+
function stopDreamScheduler() {
|
|
93022
|
+
if (nightlyTimer === null) return false;
|
|
93023
|
+
clearTimeout(nightlyTimer);
|
|
93024
|
+
nightlyTimer = null;
|
|
93025
|
+
return true;
|
|
93026
|
+
}
|
|
93027
|
+
function _resetDreamState() {
|
|
93028
|
+
lastDreamAt = 0;
|
|
93029
|
+
dreamInFlight = false;
|
|
93030
|
+
stopDreamScheduler();
|
|
93031
|
+
}
|
|
93032
|
+
var VOLUME_THRESHOLD_DEFAULT, IDLE_MINUTES_DEFAULT, DREAM_COOLDOWN_MS, NIGHTLY_HOUR_DEFAULT, lastDreamAt, dreamInFlight, nightlyTimer;
|
|
93033
|
+
var init_dream_cycle = __esm({
|
|
93034
|
+
"packages/core/src/memory/dream-cycle.ts"() {
|
|
93035
|
+
"use strict";
|
|
93036
|
+
init_brain_sqlite();
|
|
93037
|
+
VOLUME_THRESHOLD_DEFAULT = 10;
|
|
93038
|
+
IDLE_MINUTES_DEFAULT = 30;
|
|
93039
|
+
DREAM_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
93040
|
+
NIGHTLY_HOUR_DEFAULT = 4;
|
|
93041
|
+
lastDreamAt = 0;
|
|
93042
|
+
dreamInFlight = false;
|
|
93043
|
+
nightlyTimer = null;
|
|
93044
|
+
}
|
|
93045
|
+
});
|
|
93046
|
+
|
|
92178
93047
|
// packages/core/src/memory/mental-model-queue.ts
|
|
92179
93048
|
async function drainQueue() {
|
|
92180
93049
|
if (_queue.length === 0) return 0;
|
|
@@ -101333,9 +102202,9 @@ async function runUpgrade(options = {}) {
|
|
|
101333
102202
|
mkdirSync29(backupDir, { recursive: true });
|
|
101334
102203
|
}
|
|
101335
102204
|
copyFileSync9(dbPath2, dbBackupPath);
|
|
101336
|
-
const { createHash:
|
|
101337
|
-
const origChecksum =
|
|
101338
|
-
const backupChecksum =
|
|
102205
|
+
const { createHash: createHash18 } = await import("node:crypto");
|
|
102206
|
+
const origChecksum = createHash18("sha256").update(readFileSync87(dbPath2)).digest("hex");
|
|
102207
|
+
const backupChecksum = createHash18("sha256").update(readFileSync87(dbBackupPath)).digest("hex");
|
|
101339
102208
|
if (origChecksum !== backupChecksum) {
|
|
101340
102209
|
throw new Error(
|
|
101341
102210
|
`Backup verification failed: checksum mismatch. Aborting migration to prevent data loss.`
|
|
@@ -113993,6 +114862,7 @@ __export(internal_exports, {
|
|
|
113993
114862
|
WORKFLOW_GATE_SEQUENCE: () => WORKFLOW_GATE_SEQUENCE,
|
|
113994
114863
|
WorkflowGateName: () => WorkflowGateName,
|
|
113995
114864
|
WorkflowGateTracker: () => WorkflowGateTracker,
|
|
114865
|
+
_resetDreamState: () => _resetDreamState,
|
|
113996
114866
|
_resetGlobalSignaldockDb_TESTING_ONLY: () => _resetGlobalSignaldockDb_TESTING_ONLY,
|
|
113997
114867
|
adapters: () => adapters_exports,
|
|
113998
114868
|
addChain: () => addChain,
|
|
@@ -114065,6 +114935,7 @@ __export(internal_exports, {
|
|
|
114065
114935
|
channelToDistTag: () => channelToDistTag,
|
|
114066
114936
|
checkAgentHealth: () => checkAgentHealth2,
|
|
114067
114937
|
checkAllDependencies: () => checkAllDependencies,
|
|
114938
|
+
checkAndDream: () => checkAndDream,
|
|
114068
114939
|
checkArchitectureDecisionManifest: () => checkArchitectureDecisionManifest,
|
|
114069
114940
|
checkArtifactPublishManifest: () => checkArtifactPublishManifest,
|
|
114070
114941
|
checkConduitDbHealth: () => checkConduitDbHealth,
|
|
@@ -114076,6 +114947,7 @@ __export(internal_exports, {
|
|
|
114076
114947
|
checkEpicCompleteness: () => checkEpicCompleteness,
|
|
114077
114948
|
checkGate: () => checkGate,
|
|
114078
114949
|
checkGlobalSignaldockDbHealth: () => checkGlobalSignaldockDbHealth,
|
|
114950
|
+
checkIdleTrigger: () => checkIdleTrigger,
|
|
114079
114951
|
checkImplementationManifest: () => checkImplementationManifest,
|
|
114080
114952
|
checkProvenanceManifest: () => checkProvenanceManifest,
|
|
114081
114953
|
checkReleaseManifest: () => checkReleaseManifest,
|
|
@@ -114089,6 +114961,7 @@ __export(internal_exports, {
|
|
|
114089
114961
|
checkStorageMigration: () => checkStorageMigration,
|
|
114090
114962
|
checkTestingManifest: () => checkTestingManifest,
|
|
114091
114963
|
checkValidationManifest: () => checkValidationManifest,
|
|
114964
|
+
checkVolumeTrigger: () => checkVolumeTrigger,
|
|
114092
114965
|
classifyError: () => classifyError,
|
|
114093
114966
|
classifyProject: () => classifyProject,
|
|
114094
114967
|
cleanupSessions: () => cleanupSessions,
|
|
@@ -114685,6 +115558,7 @@ __export(internal_exports, {
|
|
|
114685
115558
|
snapshot: () => snapshot_exports,
|
|
114686
115559
|
spawn: () => spawn_exports,
|
|
114687
115560
|
spawnRegistry: () => spawnRegistry,
|
|
115561
|
+
startDreamScheduler: () => startDreamScheduler,
|
|
114688
115562
|
startParallelExecution: () => startParallelExecution,
|
|
114689
115563
|
startPhase: () => startPhase,
|
|
114690
115564
|
startSession: () => startSession,
|
|
@@ -114692,6 +115566,7 @@ __export(internal_exports, {
|
|
|
114692
115566
|
startupHealthCheck: () => startupHealthCheck,
|
|
114693
115567
|
stats: () => stats_exports,
|
|
114694
115568
|
sticky: () => sticky_exports,
|
|
115569
|
+
stopDreamScheduler: () => stopDreamScheduler,
|
|
114695
115570
|
stopTask: () => stopTask,
|
|
114696
115571
|
storeDetectedPattern: () => storeDetectedPattern,
|
|
114697
115572
|
storeHealingStrategy: () => storeHealingStrategy,
|
|
@@ -114726,6 +115601,7 @@ __export(internal_exports, {
|
|
|
114726
115601
|
tokenUsageTransportSchema: () => tokenUsageTransportSchema,
|
|
114727
115602
|
touchLink: () => touchLink,
|
|
114728
115603
|
trackMemoryUsage: () => trackMemoryUsage,
|
|
115604
|
+
triggerManualDream: () => triggerManualDream,
|
|
114729
115605
|
ui: () => ui_exports,
|
|
114730
115606
|
uncancelTask: () => uncancelTask,
|
|
114731
115607
|
unpackBundle: () => unpackBundle,
|
|
@@ -114813,6 +115689,7 @@ var init_internal = __esm({
|
|
|
114813
115689
|
init_brain_retrieval();
|
|
114814
115690
|
init_brain_stdp();
|
|
114815
115691
|
init_claude_mem_migration();
|
|
115692
|
+
init_dream_cycle();
|
|
114816
115693
|
init_engine_compat();
|
|
114817
115694
|
init_pipeline_manifest_sqlite();
|
|
114818
115695
|
init_quality_feedback();
|
|
@@ -122185,7 +123062,7 @@ async function systemStats(projectRoot, params) {
|
|
|
122185
123062
|
}
|
|
122186
123063
|
const byPhase = {};
|
|
122187
123064
|
for (const t of activeTasks) {
|
|
122188
|
-
const phase = t.
|
|
123065
|
+
const phase = t.pipelineStage || "unassigned";
|
|
122189
123066
|
byPhase[phase] = (byPhase[phase] ?? 0) + 1;
|
|
122190
123067
|
}
|
|
122191
123068
|
const completedTasks = tasks2.filter((t) => t.status === "done" && t.completedAt && t.createdAt);
|
|
@@ -122271,10 +123148,10 @@ async function systemLog(projectRoot, filters) {
|
|
|
122271
123148
|
}
|
|
122272
123149
|
async function queryAuditLogSqlite(projectRoot, filters) {
|
|
122273
123150
|
try {
|
|
122274
|
-
const { join:
|
|
122275
|
-
const { existsSync:
|
|
122276
|
-
const dbPath =
|
|
122277
|
-
if (!
|
|
123151
|
+
const { join: join136 } = await import("node:path");
|
|
123152
|
+
const { existsSync: existsSync136 } = await import("node:fs");
|
|
123153
|
+
const dbPath = join136(projectRoot, ".cleo", "tasks.db");
|
|
123154
|
+
if (!existsSync136(dbPath)) {
|
|
122278
123155
|
const offset = filters?.offset ?? 0;
|
|
122279
123156
|
const limit = filters?.limit ?? 20;
|
|
122280
123157
|
return {
|
|
@@ -127880,16 +128757,16 @@ var init_nexus2 = __esm({
|
|
|
127880
128757
|
async function orchestrateClassify(request, context, projectRoot) {
|
|
127881
128758
|
try {
|
|
127882
128759
|
const { getCleoCantWorkflowsDir: getCleoCantWorkflowsDir2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
127883
|
-
const { readFileSync:
|
|
127884
|
-
const { join:
|
|
128760
|
+
const { readFileSync: readFileSync108, readdirSync: readdirSync43, existsSync: existsSync136 } = await import("node:fs");
|
|
128761
|
+
const { join: join136 } = await import("node:path");
|
|
127885
128762
|
const workflowsDir = getCleoCantWorkflowsDir2();
|
|
127886
128763
|
const combined = `${request} ${context ?? ""}`.toLowerCase();
|
|
127887
128764
|
const matches = [];
|
|
127888
|
-
if (
|
|
127889
|
-
const files =
|
|
128765
|
+
if (existsSync136(workflowsDir)) {
|
|
128766
|
+
const files = readdirSync43(workflowsDir).filter((f2) => f2.endsWith(".cant"));
|
|
127890
128767
|
for (const file2 of files) {
|
|
127891
128768
|
try {
|
|
127892
|
-
const src =
|
|
128769
|
+
const src = readFileSync108(join136(workflowsDir, file2), "utf-8");
|
|
127893
128770
|
const teamMatch = /^team\s+(\S+):/m.exec(src);
|
|
127894
128771
|
if (!teamMatch) continue;
|
|
127895
128772
|
const teamName = teamMatch[1];
|
|
@@ -127904,12 +128781,12 @@ async function orchestrateClassify(request, context, projectRoot) {
|
|
|
127904
128781
|
}
|
|
127905
128782
|
}
|
|
127906
128783
|
}
|
|
127907
|
-
const localCantDir =
|
|
127908
|
-
if (
|
|
127909
|
-
const files =
|
|
128784
|
+
const localCantDir = join136(projectRoot, ".cleo", "workflows");
|
|
128785
|
+
if (existsSync136(localCantDir)) {
|
|
128786
|
+
const files = readdirSync43(localCantDir).filter((f2) => f2.endsWith(".cant"));
|
|
127910
128787
|
for (const file2 of files) {
|
|
127911
128788
|
try {
|
|
127912
|
-
const src =
|
|
128789
|
+
const src = readFileSync108(join136(localCantDir, file2), "utf-8");
|
|
127913
128790
|
const teamMatch = /^team\s+(\S+):/m.exec(src);
|
|
127914
128791
|
if (!teamMatch) continue;
|
|
127915
128792
|
const teamName = teamMatch[1];
|
|
@@ -132554,8 +133431,8 @@ var init_cli = __esm({
|
|
|
132554
133431
|
|
|
132555
133432
|
// packages/cleo/src/cli/index.ts
|
|
132556
133433
|
init_internal();
|
|
132557
|
-
import { readFileSync as
|
|
132558
|
-
import { dirname as dirname31, join as
|
|
133434
|
+
import { readFileSync as readFileSync107 } from "node:fs";
|
|
133435
|
+
import { dirname as dirname31, join as join135 } from "node:path";
|
|
132559
133436
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
132560
133437
|
|
|
132561
133438
|
// node_modules/.pnpm/citty@0.2.1/node_modules/citty/dist/_chunks/libs/scule.mjs
|
|
@@ -134057,13 +134934,13 @@ function registerAgentCommand(program) {
|
|
|
134057
134934
|
transportConfig: {},
|
|
134058
134935
|
isActive: true
|
|
134059
134936
|
});
|
|
134060
|
-
const { existsSync:
|
|
134061
|
-
const { join:
|
|
134062
|
-
const cantDir =
|
|
134063
|
-
const cantPath =
|
|
134937
|
+
const { existsSync: existsSync136, mkdirSync: mkdirSync36, writeFileSync: writeFileSync27 } = await import("node:fs");
|
|
134938
|
+
const { join: join136 } = await import("node:path");
|
|
134939
|
+
const cantDir = join136(".cleo", "agents");
|
|
134940
|
+
const cantPath = join136(cantDir, `${agentId}.cant`);
|
|
134064
134941
|
let cantScaffolded = false;
|
|
134065
|
-
if (!
|
|
134066
|
-
|
|
134942
|
+
if (!existsSync136(cantPath)) {
|
|
134943
|
+
mkdirSync36(cantDir, { recursive: true });
|
|
134067
134944
|
const role = classification ?? "specialist";
|
|
134068
134945
|
const cantContent = `---
|
|
134069
134946
|
kind: agent
|
|
@@ -134113,7 +134990,7 @@ agent ${agentId}:
|
|
|
134113
134990
|
enforcement:
|
|
134114
134991
|
1: TODO \u2014 what does this agent push back on?
|
|
134115
134992
|
`;
|
|
134116
|
-
|
|
134993
|
+
writeFileSync27(cantPath, cantContent, "utf-8");
|
|
134117
134994
|
cantScaffolded = true;
|
|
134118
134995
|
}
|
|
134119
134996
|
cliOutput(
|
|
@@ -134122,7 +134999,7 @@ agent ${agentId}:
|
|
|
134122
134999
|
data: {
|
|
134123
135000
|
agentId: credential.agentId,
|
|
134124
135001
|
displayName: credential.displayName,
|
|
134125
|
-
cantFile: cantScaffolded ? cantPath :
|
|
135002
|
+
cantFile: cantScaffolded ? cantPath : existsSync136(cantPath) ? cantPath : null,
|
|
134126
135003
|
cantScaffolded
|
|
134127
135004
|
}
|
|
134128
135005
|
},
|
|
@@ -134202,8 +135079,8 @@ agent ${agentId}:
|
|
|
134202
135079
|
try {
|
|
134203
135080
|
const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
134204
135081
|
const { createRuntime } = await import("@cleocode/runtime");
|
|
134205
|
-
const { existsSync:
|
|
134206
|
-
const { join:
|
|
135082
|
+
const { existsSync: existsSync136, readFileSync: readFileSync108 } = await import("node:fs");
|
|
135083
|
+
const { join: join136 } = await import("node:path");
|
|
134207
135084
|
await getDb4();
|
|
134208
135085
|
const registry2 = new AgentRegistryAccessor2(process.cwd());
|
|
134209
135086
|
const credential = await registry2.get(agentId);
|
|
@@ -134223,9 +135100,9 @@ agent ${agentId}:
|
|
|
134223
135100
|
}
|
|
134224
135101
|
let profile = null;
|
|
134225
135102
|
let cantValidation = null;
|
|
134226
|
-
const cantPath = opts["cant"] ??
|
|
134227
|
-
if (
|
|
134228
|
-
profile =
|
|
135103
|
+
const cantPath = opts["cant"] ?? join136(".cleo", "agents", `${agentId}.cant`);
|
|
135104
|
+
if (existsSync136(cantPath)) {
|
|
135105
|
+
profile = readFileSync108(cantPath, "utf-8");
|
|
134229
135106
|
try {
|
|
134230
135107
|
const cantModule = await import("@cleocode/cant");
|
|
134231
135108
|
const validate = "validate" in cantModule ? cantModule.validate : null;
|
|
@@ -134620,8 +135497,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
134620
135497
|
try {
|
|
134621
135498
|
const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
134622
135499
|
const { createRuntime } = await import("@cleocode/runtime");
|
|
134623
|
-
const { existsSync:
|
|
134624
|
-
const { join:
|
|
135500
|
+
const { existsSync: existsSync136 } = await import("node:fs");
|
|
135501
|
+
const { join: join136 } = await import("node:path");
|
|
134625
135502
|
const { execFile: execFile8 } = await import("node:child_process");
|
|
134626
135503
|
const { promisify: promisify8 } = await import("node:util");
|
|
134627
135504
|
const execFileAsync6 = promisify8(execFile8);
|
|
@@ -134641,8 +135518,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
134641
135518
|
}
|
|
134642
135519
|
await registry2.update(agentId, { isActive: true });
|
|
134643
135520
|
await registry2.markUsed(agentId);
|
|
134644
|
-
const cantPath =
|
|
134645
|
-
const hasProfile =
|
|
135521
|
+
const cantPath = join136(".cleo", "agents", `${agentId}.cant`);
|
|
135522
|
+
const hasProfile = existsSync136(cantPath);
|
|
134646
135523
|
const runtime = await createRuntime(registry2, {
|
|
134647
135524
|
agentId,
|
|
134648
135525
|
pollIntervalMs: 5e3,
|
|
@@ -135265,12 +136142,12 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135265
136142
|
});
|
|
135266
136143
|
agent.command("install <path>").description("Install an agent from a .cantz archive or agent directory").option("--global", "Install to global tier (~/.local/share/cleo/cant/agents/)").action(async (sourcePath, opts) => {
|
|
135267
136144
|
try {
|
|
135268
|
-
const { existsSync:
|
|
135269
|
-
const { join:
|
|
135270
|
-
const { homedir:
|
|
136145
|
+
const { existsSync: existsSync136, mkdirSync: mkdirSync36, cpSync, readFileSync: readFileSync108, rmSync: rmSync2, statSync: statSync22 } = await import("node:fs");
|
|
136146
|
+
const { join: join136, basename: basename19, resolve: resolve17 } = await import("node:path");
|
|
136147
|
+
const { homedir: homedir9 } = await import("node:os");
|
|
135271
136148
|
const { tmpdir: tmpdir2 } = await import("node:os");
|
|
135272
136149
|
const resolvedPath = resolve17(sourcePath);
|
|
135273
|
-
if (!
|
|
136150
|
+
if (!existsSync136(resolvedPath)) {
|
|
135274
136151
|
cliOutput(
|
|
135275
136152
|
{
|
|
135276
136153
|
success: false,
|
|
@@ -135290,8 +136167,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135290
136167
|
const isCantzArchive = resolvedPath.endsWith(".cantz") && statSync22(resolvedPath).isFile();
|
|
135291
136168
|
if (isCantzArchive) {
|
|
135292
136169
|
const { execFileSync: execFileSync19 } = await import("node:child_process");
|
|
135293
|
-
tempDir =
|
|
135294
|
-
|
|
136170
|
+
tempDir = join136(tmpdir2(), `cleo-agent-install-${Date.now()}`);
|
|
136171
|
+
mkdirSync36(tempDir, { recursive: true });
|
|
135295
136172
|
try {
|
|
135296
136173
|
execFileSync19("unzip", ["-o", "-q", resolvedPath, "-d", tempDir], {
|
|
135297
136174
|
encoding: "utf-8",
|
|
@@ -135312,9 +136189,9 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135312
136189
|
process.exitCode = 6;
|
|
135313
136190
|
return;
|
|
135314
136191
|
}
|
|
135315
|
-
const { readdirSync:
|
|
135316
|
-
const topLevel =
|
|
135317
|
-
const entryPath =
|
|
136192
|
+
const { readdirSync: readdirSync43 } = await import("node:fs");
|
|
136193
|
+
const topLevel = readdirSync43(tempDir).filter((entry) => {
|
|
136194
|
+
const entryPath = join136(tempDir, entry);
|
|
135318
136195
|
return statSync22(entryPath).isDirectory();
|
|
135319
136196
|
});
|
|
135320
136197
|
if (topLevel.length !== 1) {
|
|
@@ -135333,7 +136210,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135333
136210
|
return;
|
|
135334
136211
|
}
|
|
135335
136212
|
agentName = topLevel[0];
|
|
135336
|
-
agentDir =
|
|
136213
|
+
agentDir = join136(tempDir, agentName);
|
|
135337
136214
|
} else if (statSync22(resolvedPath).isDirectory()) {
|
|
135338
136215
|
agentDir = resolvedPath;
|
|
135339
136216
|
agentName = basename19(resolvedPath);
|
|
@@ -135351,8 +136228,8 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135351
136228
|
process.exitCode = 6;
|
|
135352
136229
|
return;
|
|
135353
136230
|
}
|
|
135354
|
-
const personaPath =
|
|
135355
|
-
if (!
|
|
136231
|
+
const personaPath = join136(agentDir, "persona.cant");
|
|
136232
|
+
if (!existsSync136(personaPath)) {
|
|
135356
136233
|
if (tempDir) rmSync2(tempDir, { recursive: true, force: true });
|
|
135357
136234
|
cliOutput(
|
|
135358
136235
|
{
|
|
@@ -135370,21 +136247,21 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135370
136247
|
const isGlobal = opts["global"] === true;
|
|
135371
136248
|
let targetRoot;
|
|
135372
136249
|
if (isGlobal) {
|
|
135373
|
-
const home =
|
|
135374
|
-
const xdgData = process.env["XDG_DATA_HOME"] ??
|
|
135375
|
-
targetRoot =
|
|
136250
|
+
const home = homedir9();
|
|
136251
|
+
const xdgData = process.env["XDG_DATA_HOME"] ?? join136(home, ".local", "share");
|
|
136252
|
+
targetRoot = join136(xdgData, "cleo", "cant", "agents");
|
|
135376
136253
|
} else {
|
|
135377
|
-
targetRoot =
|
|
136254
|
+
targetRoot = join136(process.cwd(), ".cleo", "cant", "agents");
|
|
135378
136255
|
}
|
|
135379
|
-
const targetDir =
|
|
135380
|
-
|
|
136256
|
+
const targetDir = join136(targetRoot, agentName);
|
|
136257
|
+
mkdirSync36(targetRoot, { recursive: true });
|
|
135381
136258
|
cpSync(agentDir, targetDir, { recursive: true, force: true });
|
|
135382
136259
|
if (tempDir) {
|
|
135383
136260
|
rmSync2(tempDir, { recursive: true, force: true });
|
|
135384
136261
|
}
|
|
135385
136262
|
let registered = false;
|
|
135386
136263
|
try {
|
|
135387
|
-
const persona =
|
|
136264
|
+
const persona = readFileSync108(join136(targetDir, "persona.cant"), "utf-8");
|
|
135388
136265
|
const descMatch = persona.match(/description:\s*"([^"]+)"/);
|
|
135389
136266
|
const displayName = descMatch?.[1] ?? agentName;
|
|
135390
136267
|
const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
@@ -135431,11 +136308,11 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135431
136308
|
});
|
|
135432
136309
|
agent.command("pack <dir>").description("Package an agent directory as a .cantz archive").action(async (dir) => {
|
|
135433
136310
|
try {
|
|
135434
|
-
const { existsSync:
|
|
136311
|
+
const { existsSync: existsSync136, statSync: statSync22 } = await import("node:fs");
|
|
135435
136312
|
const { resolve: resolve17, basename: basename19, dirname: dirname32 } = await import("node:path");
|
|
135436
136313
|
const { execFileSync: execFileSync19 } = await import("node:child_process");
|
|
135437
136314
|
const resolvedDir = resolve17(dir);
|
|
135438
|
-
if (!
|
|
136315
|
+
if (!existsSync136(resolvedDir) || !statSync22(resolvedDir).isDirectory()) {
|
|
135439
136316
|
cliOutput(
|
|
135440
136317
|
{
|
|
135441
136318
|
success: false,
|
|
@@ -135449,9 +136326,9 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135449
136326
|
process.exitCode = 4;
|
|
135450
136327
|
return;
|
|
135451
136328
|
}
|
|
135452
|
-
const { join:
|
|
135453
|
-
const personaPath =
|
|
135454
|
-
if (!
|
|
136329
|
+
const { join: join136 } = await import("node:path");
|
|
136330
|
+
const personaPath = join136(resolvedDir, "persona.cant");
|
|
136331
|
+
if (!existsSync136(personaPath)) {
|
|
135455
136332
|
cliOutput(
|
|
135456
136333
|
{
|
|
135457
136334
|
success: false,
|
|
@@ -135490,15 +136367,15 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135490
136367
|
return;
|
|
135491
136368
|
}
|
|
135492
136369
|
const archiveStats = statSync22(archivePath);
|
|
135493
|
-
const { readdirSync:
|
|
136370
|
+
const { readdirSync: readdirSync43 } = await import("node:fs");
|
|
135494
136371
|
let fileCount = 0;
|
|
135495
136372
|
const countFiles2 = (dirPath) => {
|
|
135496
|
-
const entries =
|
|
136373
|
+
const entries = readdirSync43(dirPath, { withFileTypes: true });
|
|
135497
136374
|
for (const entry of entries) {
|
|
135498
136375
|
if (entry.isFile()) {
|
|
135499
136376
|
fileCount++;
|
|
135500
136377
|
} else if (entry.isDirectory()) {
|
|
135501
|
-
countFiles2(
|
|
136378
|
+
countFiles2(join136(dirPath, entry.name));
|
|
135502
136379
|
}
|
|
135503
136380
|
}
|
|
135504
136381
|
};
|
|
@@ -135525,9 +136402,9 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135525
136402
|
});
|
|
135526
136403
|
agent.command("create").description("Scaffold a new agent package with persona.cant and manifest.json").requiredOption("--name <name>", "Agent name (kebab-case)").requiredOption("--role <role>", "Agent role: orchestrator, lead, worker, or docs-worker").option("--tier <tier>", "Agent tier: low, mid, or high (defaults based on role)").option("--team <teamName>", "Team this agent belongs to").option("--domain <description>", "Domain description for file permissions and context").option("--global", "Create in global tier (~/.local/share/cleo/cant/agents/)").option("--seed-brain", "Create expertise/mental-model-seed.md and seed a BRAIN observation").option("--parent <parentAgent>", "Parent agent name in the hierarchy").action(async (opts) => {
|
|
135527
136404
|
try {
|
|
135528
|
-
const { existsSync:
|
|
135529
|
-
const { join:
|
|
135530
|
-
const { homedir:
|
|
136405
|
+
const { existsSync: existsSync136, mkdirSync: mkdirSync36, writeFileSync: writeFileSync27 } = await import("node:fs");
|
|
136406
|
+
const { join: join136 } = await import("node:path");
|
|
136407
|
+
const { homedir: homedir9 } = await import("node:os");
|
|
135531
136408
|
const name2 = opts["name"];
|
|
135532
136409
|
const role = opts["role"];
|
|
135533
136410
|
const tier = opts["tier"] ?? inferTierFromRole(role);
|
|
@@ -135585,14 +136462,14 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135585
136462
|
}
|
|
135586
136463
|
let targetRoot;
|
|
135587
136464
|
if (isGlobal) {
|
|
135588
|
-
const home =
|
|
135589
|
-
const xdgData = process.env["XDG_DATA_HOME"] ??
|
|
135590
|
-
targetRoot =
|
|
136465
|
+
const home = homedir9();
|
|
136466
|
+
const xdgData = process.env["XDG_DATA_HOME"] ?? join136(home, ".local", "share");
|
|
136467
|
+
targetRoot = join136(xdgData, "cleo", "cant", "agents");
|
|
135591
136468
|
} else {
|
|
135592
|
-
targetRoot =
|
|
136469
|
+
targetRoot = join136(process.cwd(), ".cleo", "cant", "agents");
|
|
135593
136470
|
}
|
|
135594
|
-
const agentDir =
|
|
135595
|
-
if (
|
|
136471
|
+
const agentDir = join136(targetRoot, name2);
|
|
136472
|
+
if (existsSync136(agentDir)) {
|
|
135596
136473
|
cliOutput(
|
|
135597
136474
|
{
|
|
135598
136475
|
success: false,
|
|
@@ -135607,7 +136484,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135607
136484
|
process.exitCode = 6;
|
|
135608
136485
|
return;
|
|
135609
136486
|
}
|
|
135610
|
-
|
|
136487
|
+
mkdirSync36(agentDir, { recursive: true });
|
|
135611
136488
|
const personaContent = generatePersonaCant({
|
|
135612
136489
|
name: name2,
|
|
135613
136490
|
role,
|
|
@@ -135616,29 +136493,29 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
135616
136493
|
domain: domain2,
|
|
135617
136494
|
parent
|
|
135618
136495
|
});
|
|
135619
|
-
|
|
136496
|
+
writeFileSync27(join136(agentDir, "persona.cant"), personaContent, "utf-8");
|
|
135620
136497
|
const manifest = generateManifest2({ name: name2, role, tier, domain: domain2 });
|
|
135621
|
-
|
|
135622
|
-
|
|
136498
|
+
writeFileSync27(
|
|
136499
|
+
join136(agentDir, "manifest.json"),
|
|
135623
136500
|
`${JSON.stringify(manifest, null, 2)}
|
|
135624
136501
|
`,
|
|
135625
136502
|
"utf-8"
|
|
135626
136503
|
);
|
|
135627
136504
|
const createdFiles = [
|
|
135628
|
-
|
|
135629
|
-
|
|
136505
|
+
join136(agentDir, "persona.cant"),
|
|
136506
|
+
join136(agentDir, "manifest.json")
|
|
135630
136507
|
];
|
|
135631
136508
|
if (team) {
|
|
135632
136509
|
const teamConfigContent = generateTeamConfig(name2, role, team);
|
|
135633
|
-
|
|
135634
|
-
createdFiles.push(
|
|
136510
|
+
writeFileSync27(join136(agentDir, "team-config.cant"), teamConfigContent, "utf-8");
|
|
136511
|
+
createdFiles.push(join136(agentDir, "team-config.cant"));
|
|
135635
136512
|
}
|
|
135636
136513
|
if (seedBrain) {
|
|
135637
|
-
const expertiseDir =
|
|
135638
|
-
|
|
136514
|
+
const expertiseDir = join136(agentDir, "expertise");
|
|
136515
|
+
mkdirSync36(expertiseDir, { recursive: true });
|
|
135639
136516
|
const seedContent = generateMentalModelSeed(name2, role, domain2);
|
|
135640
|
-
|
|
135641
|
-
createdFiles.push(
|
|
136517
|
+
writeFileSync27(join136(expertiseDir, "mental-model-seed.md"), seedContent, "utf-8");
|
|
136518
|
+
createdFiles.push(join136(expertiseDir, "mental-model-seed.md"));
|
|
135642
136519
|
try {
|
|
135643
136520
|
const { execFile: execFile8 } = await import("node:child_process");
|
|
135644
136521
|
const { promisify: promisify8 } = await import("node:util");
|
|
@@ -137509,10 +138386,10 @@ function registerCheckCommand(program) {
|
|
|
137509
138386
|
);
|
|
137510
138387
|
});
|
|
137511
138388
|
check2.command("chain-validate <file>").description("Validate a WarpChain definition from a JSON file").action(async (file2) => {
|
|
137512
|
-
const { readFileSync:
|
|
138389
|
+
const { readFileSync: readFileSync108 } = await import("node:fs");
|
|
137513
138390
|
let chain;
|
|
137514
138391
|
try {
|
|
137515
|
-
chain = JSON.parse(
|
|
138392
|
+
chain = JSON.parse(readFileSync108(file2, "utf8"));
|
|
137516
138393
|
} catch (err) {
|
|
137517
138394
|
const message = err instanceof Error ? err.message : String(err);
|
|
137518
138395
|
console.error(`Failed to read or parse chain file: ${message}`);
|
|
@@ -139956,6 +140833,55 @@ function registerMapCommand(program) {
|
|
|
139956
140833
|
init_internal();
|
|
139957
140834
|
init_cli();
|
|
139958
140835
|
init_renderers();
|
|
140836
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
140837
|
+
import { existsSync as existsSync135, mkdirSync as mkdirSync35, readdirSync as readdirSync42, readFileSync as readFileSync105, writeFileSync as writeFileSync26 } from "node:fs";
|
|
140838
|
+
import { homedir as homedir8 } from "node:os";
|
|
140839
|
+
import { join as join132 } from "node:path";
|
|
140840
|
+
function parseMemoryFileFrontmatter(raw) {
|
|
140841
|
+
const lines = raw.split("\n");
|
|
140842
|
+
if (!lines[0]?.trim().startsWith("---")) {
|
|
140843
|
+
return { body: raw.trim() };
|
|
140844
|
+
}
|
|
140845
|
+
const endIdx = lines.slice(1).findIndex((l) => /^---\s*$/.test(l));
|
|
140846
|
+
if (endIdx === -1) {
|
|
140847
|
+
return { body: raw.trim() };
|
|
140848
|
+
}
|
|
140849
|
+
const fmLines = lines.slice(1, endIdx + 1);
|
|
140850
|
+
const body = lines.slice(endIdx + 2).join("\n").trim();
|
|
140851
|
+
const fm = {};
|
|
140852
|
+
for (const line2 of fmLines) {
|
|
140853
|
+
const colonIdx = line2.indexOf(":");
|
|
140854
|
+
if (colonIdx === -1) continue;
|
|
140855
|
+
const key = line2.slice(0, colonIdx).trim();
|
|
140856
|
+
const value = line2.slice(colonIdx + 1).trim();
|
|
140857
|
+
if (key && value) fm[key] = value;
|
|
140858
|
+
}
|
|
140859
|
+
return {
|
|
140860
|
+
name: fm["name"],
|
|
140861
|
+
description: fm["description"],
|
|
140862
|
+
type: fm["type"],
|
|
140863
|
+
body
|
|
140864
|
+
};
|
|
140865
|
+
}
|
|
140866
|
+
function memoryContentHash(title, body) {
|
|
140867
|
+
return createHash17("sha256").update(`${title}
|
|
140868
|
+
${body}`).digest("hex").slice(0, 16);
|
|
140869
|
+
}
|
|
140870
|
+
function loadImportHashes(stateFile) {
|
|
140871
|
+
try {
|
|
140872
|
+
if (!existsSync135(stateFile)) return /* @__PURE__ */ new Set();
|
|
140873
|
+
const raw = readFileSync105(stateFile, "utf-8");
|
|
140874
|
+
const parsed = JSON.parse(raw);
|
|
140875
|
+
return new Set(parsed.hashes);
|
|
140876
|
+
} catch {
|
|
140877
|
+
return /* @__PURE__ */ new Set();
|
|
140878
|
+
}
|
|
140879
|
+
}
|
|
140880
|
+
function saveImportHashes(stateFile, hashes) {
|
|
140881
|
+
const dir = stateFile.slice(0, stateFile.lastIndexOf("/"));
|
|
140882
|
+
if (!existsSync135(dir)) mkdirSync35(dir, { recursive: true });
|
|
140883
|
+
writeFileSync26(stateFile, JSON.stringify({ hashes: [...hashes] }, null, 2), "utf-8");
|
|
140884
|
+
}
|
|
139959
140885
|
function registerMemoryBrainCommand(program) {
|
|
139960
140886
|
const memory = program.command("memory").description("BRAIN memory operations (patterns, learnings)");
|
|
139961
140887
|
memory.command("store").description("Store a pattern or learning to BRAIN memory").requiredOption("--type <type>", "Memory type: pattern or learning").requiredOption("--content <text>", "Content of the memory entry").option("--context <text>", "Context in which the pattern/learning was observed").option("--source <text>", "Source of the learning").option(
|
|
@@ -140371,6 +141297,206 @@ function registerMemoryBrainCommand(program) {
|
|
|
140371
141297
|
process.exit(1);
|
|
140372
141298
|
}
|
|
140373
141299
|
});
|
|
141300
|
+
memory.command("dream").description(
|
|
141301
|
+
"Manually trigger the full auto-dream cycle: consolidation pipeline including R-STDP reward backfill (Step 9a), STDP plasticity (Step 9b), and homeostatic decay (Step 9c). Equivalent to autonomous autonomous nightly consolidation but triggered on demand. Idempotent \u2014 safe to run multiple times."
|
|
141302
|
+
).option("--json", "Output results as JSON").action(async (opts) => {
|
|
141303
|
+
const root = getProjectRoot();
|
|
141304
|
+
const isJson = !!opts.json;
|
|
141305
|
+
if (!isJson) {
|
|
141306
|
+
console.log("Triggering dream cycle (full consolidation including STDP plasticity)...");
|
|
141307
|
+
}
|
|
141308
|
+
try {
|
|
141309
|
+
const result = await triggerManualDream(root);
|
|
141310
|
+
if (isJson) {
|
|
141311
|
+
console.log(
|
|
141312
|
+
JSON.stringify(
|
|
141313
|
+
{
|
|
141314
|
+
success: true,
|
|
141315
|
+
data: result,
|
|
141316
|
+
meta: {
|
|
141317
|
+
operation: "memory.dream",
|
|
141318
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
141319
|
+
}
|
|
141320
|
+
},
|
|
141321
|
+
null,
|
|
141322
|
+
2
|
|
141323
|
+
)
|
|
141324
|
+
);
|
|
141325
|
+
return;
|
|
141326
|
+
}
|
|
141327
|
+
console.log("\nDream cycle complete.");
|
|
141328
|
+
console.log(` Deduplicated: ${result.deduplicated}`);
|
|
141329
|
+
console.log(` Quality recomp: ${result.qualityRecomputed}`);
|
|
141330
|
+
console.log(` Tier promoted: ${result.tierPromotions.promoted.length} entries promoted`);
|
|
141331
|
+
console.log(` Tier evicted: ${result.tierPromotions.evicted.length} entries evicted`);
|
|
141332
|
+
console.log(` Contradictions: ${result.contradictions}`);
|
|
141333
|
+
console.log(` Soft evicted: ${result.softEvicted}`);
|
|
141334
|
+
console.log(` Edges strength: ${result.edgesStrengthened}`);
|
|
141335
|
+
console.log(` Summaries gen: ${result.summariesGenerated}`);
|
|
141336
|
+
if (result.graphLinksCreated !== void 0) {
|
|
141337
|
+
console.log(` Graph links: ${result.graphLinksCreated}`);
|
|
141338
|
+
}
|
|
141339
|
+
if (result.rewardBackfilled !== void 0) {
|
|
141340
|
+
console.log(
|
|
141341
|
+
` Reward backfill: ${result.rewardBackfilled.rowsLabeled} labeled, ${result.rewardBackfilled.rowsSkipped} skipped`
|
|
141342
|
+
);
|
|
141343
|
+
}
|
|
141344
|
+
if (result.stdpPlasticity !== void 0) {
|
|
141345
|
+
console.log(
|
|
141346
|
+
` STDP plasticity: ${result.stdpPlasticity.ltpEvents} LTP, ${result.stdpPlasticity.ltdEvents} LTD, ${result.stdpPlasticity.edgesCreated} edges created`
|
|
141347
|
+
);
|
|
141348
|
+
}
|
|
141349
|
+
if (result.homeostaticDecay !== void 0) {
|
|
141350
|
+
console.log(
|
|
141351
|
+
` Decay/pruning: ${result.homeostaticDecay.edgesDecayed} decayed, ${result.homeostaticDecay.edgesPruned} pruned`
|
|
141352
|
+
);
|
|
141353
|
+
}
|
|
141354
|
+
} catch (err) {
|
|
141355
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
141356
|
+
if (isJson) {
|
|
141357
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
141358
|
+
} else {
|
|
141359
|
+
console.error(`Dream cycle failed: ${message}`);
|
|
141360
|
+
}
|
|
141361
|
+
process.exit(1);
|
|
141362
|
+
}
|
|
141363
|
+
});
|
|
141364
|
+
memory.command("import").description(
|
|
141365
|
+
"Import memory files from a provider-specific directory (e.g. ~/.claude/projects/*/memory/) into brain.db. Enables provider-agnostic memory via CLEO CLI instead of Claude Code MEMORY.md."
|
|
141366
|
+
).option(
|
|
141367
|
+
"--from <dir>",
|
|
141368
|
+
"Source directory containing *.md memory files (default: ~/.claude/projects/-mnt-projects-cleocode/memory)"
|
|
141369
|
+
).option("--dry-run", "Print what would be imported without writing to brain.db").option("--json", "Output results as JSON").action(async (opts) => {
|
|
141370
|
+
const sourceDir = opts.from ?? join132(homedir8(), ".claude", "projects", "-mnt-projects-cleocode", "memory");
|
|
141371
|
+
const isDryRun = !!opts.dryRun;
|
|
141372
|
+
const isJson = !!opts.json;
|
|
141373
|
+
const projectRoot = getProjectRoot();
|
|
141374
|
+
const stateFile = join132(projectRoot, ".cleo", "migrate-memory-hashes.json");
|
|
141375
|
+
if (!existsSync135(sourceDir)) {
|
|
141376
|
+
const msg = `Source directory not found: ${sourceDir}`;
|
|
141377
|
+
if (isJson) {
|
|
141378
|
+
console.log(JSON.stringify({ success: false, error: msg }));
|
|
141379
|
+
} else {
|
|
141380
|
+
console.error(msg);
|
|
141381
|
+
}
|
|
141382
|
+
process.exit(1);
|
|
141383
|
+
}
|
|
141384
|
+
const files = readdirSync42(sourceDir).filter((f2) => f2.endsWith(".md") && f2 !== "MEMORY.md").map((f2) => join132(sourceDir, f2));
|
|
141385
|
+
const importedHashes = isDryRun ? /* @__PURE__ */ new Set() : loadImportHashes(stateFile);
|
|
141386
|
+
const stats2 = { total: files.length, imported: 0, skipped: 0, errors: 0 };
|
|
141387
|
+
const importedEntries = [];
|
|
141388
|
+
const skippedEntries = [];
|
|
141389
|
+
const errorEntries = [];
|
|
141390
|
+
if (!isJson) {
|
|
141391
|
+
console.log(`Importing memory from: ${sourceDir}`);
|
|
141392
|
+
console.log(`Files found: ${files.length}`);
|
|
141393
|
+
if (isDryRun) console.log("Mode: DRY RUN");
|
|
141394
|
+
console.log("");
|
|
141395
|
+
}
|
|
141396
|
+
for (const filePath of files) {
|
|
141397
|
+
const fileName = filePath.split("/").pop() ?? filePath;
|
|
141398
|
+
try {
|
|
141399
|
+
const raw = readFileSync105(filePath, "utf-8");
|
|
141400
|
+
if (!raw.trim()) {
|
|
141401
|
+
stats2.skipped++;
|
|
141402
|
+
skippedEntries.push({ file: fileName, reason: "empty file" });
|
|
141403
|
+
continue;
|
|
141404
|
+
}
|
|
141405
|
+
const { name: name2, description, type, body } = parseMemoryFileFrontmatter(raw);
|
|
141406
|
+
const title = name2 ?? fileName.replace(/\.md$/, "").replace(/-/g, " ");
|
|
141407
|
+
const bodyParts = [description, body].filter(Boolean);
|
|
141408
|
+
const fullText = bodyParts.join("\n\n").trim();
|
|
141409
|
+
if (!fullText) {
|
|
141410
|
+
stats2.skipped++;
|
|
141411
|
+
skippedEntries.push({ file: fileName, reason: "empty body" });
|
|
141412
|
+
continue;
|
|
141413
|
+
}
|
|
141414
|
+
const hash2 = memoryContentHash(title, fullText);
|
|
141415
|
+
if (!isDryRun && importedHashes.has(hash2)) {
|
|
141416
|
+
stats2.skipped++;
|
|
141417
|
+
skippedEntries.push({ file: fileName, reason: `already imported (hash: ${hash2})` });
|
|
141418
|
+
if (!isJson) console.log(` [SKIP] ${fileName}`);
|
|
141419
|
+
continue;
|
|
141420
|
+
}
|
|
141421
|
+
const entryType = type ?? "project";
|
|
141422
|
+
if (!isJson) {
|
|
141423
|
+
const prefix = isDryRun ? "[DRY-RUN]" : "[IMPORT]";
|
|
141424
|
+
console.log(` ${prefix} ${fileName} (type: ${entryType})`);
|
|
141425
|
+
}
|
|
141426
|
+
if (!isDryRun) {
|
|
141427
|
+
if (entryType === "feedback") {
|
|
141428
|
+
await dispatchFromCli(
|
|
141429
|
+
"mutate",
|
|
141430
|
+
"memory",
|
|
141431
|
+
"learning.store",
|
|
141432
|
+
{
|
|
141433
|
+
insight: `[MIGRATED] ${title}: ${fullText}`,
|
|
141434
|
+
source: "manual",
|
|
141435
|
+
confidence: 0.8,
|
|
141436
|
+
actionable: false
|
|
141437
|
+
},
|
|
141438
|
+
{ command: "memory", operation: "memory.learning.store" }
|
|
141439
|
+
);
|
|
141440
|
+
} else {
|
|
141441
|
+
const observeType = entryType === "project" ? "feature" : entryType === "reference" ? "discovery" : entryType === "user" ? "change" : "discovery";
|
|
141442
|
+
await dispatchFromCli(
|
|
141443
|
+
"mutate",
|
|
141444
|
+
"memory",
|
|
141445
|
+
"observe",
|
|
141446
|
+
{
|
|
141447
|
+
text: `[MIGRATED] ${title}: ${fullText}`,
|
|
141448
|
+
title: `[MIGRATED] ${title}`,
|
|
141449
|
+
type: observeType,
|
|
141450
|
+
sourceType: "manual"
|
|
141451
|
+
},
|
|
141452
|
+
{ command: "memory", operation: "memory.observe" }
|
|
141453
|
+
);
|
|
141454
|
+
}
|
|
141455
|
+
importedHashes.add(hash2);
|
|
141456
|
+
}
|
|
141457
|
+
stats2.imported++;
|
|
141458
|
+
importedEntries.push({ file: fileName, type: entryType, title });
|
|
141459
|
+
} catch (err) {
|
|
141460
|
+
stats2.errors++;
|
|
141461
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
141462
|
+
errorEntries.push({ file: fileName, error: message });
|
|
141463
|
+
if (!isJson) console.error(` [ERROR] ${fileName}: ${message}`);
|
|
141464
|
+
}
|
|
141465
|
+
}
|
|
141466
|
+
if (!isDryRun) {
|
|
141467
|
+
saveImportHashes(stateFile, importedHashes);
|
|
141468
|
+
}
|
|
141469
|
+
if (isJson) {
|
|
141470
|
+
console.log(
|
|
141471
|
+
JSON.stringify(
|
|
141472
|
+
{
|
|
141473
|
+
success: stats2.errors === 0,
|
|
141474
|
+
data: {
|
|
141475
|
+
...stats2,
|
|
141476
|
+
dryRun: isDryRun,
|
|
141477
|
+
imported: importedEntries,
|
|
141478
|
+
skipped: skippedEntries,
|
|
141479
|
+
errors: errorEntries
|
|
141480
|
+
},
|
|
141481
|
+
meta: {
|
|
141482
|
+
operation: "memory.import",
|
|
141483
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
141484
|
+
}
|
|
141485
|
+
},
|
|
141486
|
+
null,
|
|
141487
|
+
2
|
|
141488
|
+
)
|
|
141489
|
+
);
|
|
141490
|
+
} else {
|
|
141491
|
+
console.log("");
|
|
141492
|
+
console.log("=== Import Complete ===");
|
|
141493
|
+
console.log(`Total: ${stats2.total}`);
|
|
141494
|
+
console.log(`Imported: ${stats2.imported}`);
|
|
141495
|
+
console.log(`Skipped: ${stats2.skipped}`);
|
|
141496
|
+
console.log(`Errors: ${stats2.errors}`);
|
|
141497
|
+
}
|
|
141498
|
+
if (stats2.errors > 0) process.exit(1);
|
|
141499
|
+
});
|
|
140374
141500
|
}
|
|
140375
141501
|
|
|
140376
141502
|
// packages/cleo/src/cli/commands/migrate-claude-mem.ts
|
|
@@ -141828,17 +142954,17 @@ function registerNexusCommand(program) {
|
|
|
141828
142954
|
const autoRegister = !!opts["autoRegister"];
|
|
141829
142955
|
const includeExisting = !!opts["includeExisting"];
|
|
141830
142956
|
const maxDepth = Math.max(1, Math.min(opts["maxDepth"] ?? 4, 20));
|
|
141831
|
-
const { homedir:
|
|
141832
|
-
const home =
|
|
142957
|
+
const { homedir: homedir9 } = await import("node:os");
|
|
142958
|
+
const home = homedir9();
|
|
141833
142959
|
const defaultRoots = [path10.join(home, "code"), path10.join(home, "projects"), "/mnt/projects"];
|
|
141834
142960
|
const rawRoots = typeof opts["roots"] === "string" && opts["roots"].trim().length > 0 ? opts["roots"].split(",").map((r) => r.trim()).filter((r) => r.length > 0).map(
|
|
141835
142961
|
(r) => r.startsWith("~") ? path10.join(home, r.slice(1)) : path10.resolve(r)
|
|
141836
142962
|
) : defaultRoots;
|
|
141837
|
-
const { existsSync:
|
|
142963
|
+
const { existsSync: existsSync136, readdirSync: readdirSync43, statSync: statSync22 } = await import("node:fs");
|
|
141838
142964
|
const { Dirent } = await import("node:fs");
|
|
141839
142965
|
const roots = rawRoots.filter((r) => {
|
|
141840
142966
|
try {
|
|
141841
|
-
return
|
|
142967
|
+
return existsSync136(r) && statSync22(r).isDirectory();
|
|
141842
142968
|
} catch {
|
|
141843
142969
|
return false;
|
|
141844
142970
|
}
|
|
@@ -141879,7 +143005,7 @@ function registerNexusCommand(program) {
|
|
|
141879
143005
|
if (depth > maxDepth) return [];
|
|
141880
143006
|
let entries;
|
|
141881
143007
|
try {
|
|
141882
|
-
entries =
|
|
143008
|
+
entries = readdirSync43(dir, { withFileTypes: true });
|
|
141883
143009
|
} catch {
|
|
141884
143010
|
return [];
|
|
141885
143011
|
}
|
|
@@ -142422,8 +143548,8 @@ function registerNexusCommand(program) {
|
|
|
142422
143548
|
return;
|
|
142423
143549
|
}
|
|
142424
143550
|
if (outputFile) {
|
|
142425
|
-
const { writeFileSync:
|
|
142426
|
-
|
|
143551
|
+
const { writeFileSync: writeFileSync27 } = await import("node:fs");
|
|
143552
|
+
writeFileSync27(outputFile, output, "utf-8");
|
|
142427
143553
|
process.stdout.write(
|
|
142428
143554
|
`[nexus] Exported to ${outputFile} (${nodes.length} nodes, ${relations.length} edges)
|
|
142429
143555
|
`
|
|
@@ -144255,7 +145381,7 @@ init_src();
|
|
|
144255
145381
|
init_internal();
|
|
144256
145382
|
import { execFile as execFile7 } from "node:child_process";
|
|
144257
145383
|
import { readFile as readFile23 } from "node:fs/promises";
|
|
144258
|
-
import { join as
|
|
145384
|
+
import { join as join133 } from "node:path";
|
|
144259
145385
|
import * as readline2 from "node:readline";
|
|
144260
145386
|
import { promisify as promisify7 } from "node:util";
|
|
144261
145387
|
init_renderers();
|
|
@@ -144264,7 +145390,7 @@ var GITHUB_REPO = BUILD_CONFIG.repository.fullName;
|
|
|
144264
145390
|
async function getCurrentVersion() {
|
|
144265
145391
|
const cleoHome = getCleoHome();
|
|
144266
145392
|
try {
|
|
144267
|
-
const content = await readFile23(
|
|
145393
|
+
const content = await readFile23(join133(cleoHome, "VERSION"), "utf-8");
|
|
144268
145394
|
return (content.split("\n")[0] ?? "unknown").trim();
|
|
144269
145395
|
} catch {
|
|
144270
145396
|
return "unknown";
|
|
@@ -144318,7 +145444,7 @@ async function writeRuntimeVersionMetadata(mode, source, version2) {
|
|
|
144318
145444
|
];
|
|
144319
145445
|
await import("node:fs/promises").then(
|
|
144320
145446
|
({ writeFile: writeFile15, mkdir: mkdir20 }) => mkdir20(cleoHome, { recursive: true }).then(
|
|
144321
|
-
() => writeFile15(
|
|
145447
|
+
() => writeFile15(join133(cleoHome, "VERSION"), `${lines.join("\n")}
|
|
144322
145448
|
`, "utf-8")
|
|
144323
145449
|
)
|
|
144324
145450
|
);
|
|
@@ -145371,10 +146497,10 @@ function registerSyncCommand(program) {
|
|
|
145371
146497
|
"How to resolve conflicts: keep-cleo, keep-external, or newest (default: keep-cleo)",
|
|
145372
146498
|
"keep-cleo"
|
|
145373
146499
|
).action(async (file2, opts) => {
|
|
145374
|
-
const { readFileSync:
|
|
146500
|
+
const { readFileSync: readFileSync108 } = await import("node:fs");
|
|
145375
146501
|
let externalTasks;
|
|
145376
146502
|
try {
|
|
145377
|
-
externalTasks = JSON.parse(
|
|
146503
|
+
externalTasks = JSON.parse(readFileSync108(file2, "utf8"));
|
|
145378
146504
|
} catch (err) {
|
|
145379
146505
|
const message = err instanceof Error ? err.message : String(err);
|
|
145380
146506
|
console.error(`Failed to read or parse external tasks file: ${message}`);
|
|
@@ -145470,11 +146596,11 @@ function registerTestingCommand(program) {
|
|
|
145470
146596
|
init_internal();
|
|
145471
146597
|
init_cli();
|
|
145472
146598
|
init_renderers();
|
|
145473
|
-
import { readFileSync as
|
|
146599
|
+
import { readFileSync as readFileSync106 } from "node:fs";
|
|
145474
146600
|
function readPayload(opts, textKey, fileKey) {
|
|
145475
146601
|
const text3 = opts[textKey];
|
|
145476
146602
|
const file2 = opts[fileKey];
|
|
145477
|
-
if (file2) return
|
|
146603
|
+
if (file2) return readFileSync106(file2, "utf-8");
|
|
145478
146604
|
return text3;
|
|
145479
146605
|
}
|
|
145480
146606
|
function registerTokenCommand(program) {
|
|
@@ -145724,16 +146850,16 @@ init_src3();
|
|
|
145724
146850
|
init_renderers();
|
|
145725
146851
|
import { execFileSync as execFileSync18, spawn as spawn2 } from "node:child_process";
|
|
145726
146852
|
import { mkdir as mkdir19, open, readFile as readFile24, rm as rm3, stat as stat3, writeFile as writeFile14 } from "node:fs/promises";
|
|
145727
|
-
import { join as
|
|
146853
|
+
import { join as join134 } from "node:path";
|
|
145728
146854
|
var DEFAULT_PORT = 3456;
|
|
145729
146855
|
var DEFAULT_HOST = "127.0.0.1";
|
|
145730
146856
|
function getWebPaths() {
|
|
145731
146857
|
const cleoHome = getCleoHome();
|
|
145732
146858
|
return {
|
|
145733
|
-
pidFile:
|
|
145734
|
-
configFile:
|
|
145735
|
-
logDir:
|
|
145736
|
-
logFile:
|
|
146859
|
+
pidFile: join134(cleoHome, "web-server.pid"),
|
|
146860
|
+
configFile: join134(cleoHome, "web-server.json"),
|
|
146861
|
+
logDir: join134(cleoHome, "logs"),
|
|
146862
|
+
logFile: join134(cleoHome, "logs", "web-server.log")
|
|
145737
146863
|
};
|
|
145738
146864
|
}
|
|
145739
146865
|
function isProcessRunning(pid) {
|
|
@@ -145765,99 +146891,99 @@ async function getStatus() {
|
|
|
145765
146891
|
return { running: false, pid: null, port: null, host: null, url: null };
|
|
145766
146892
|
}
|
|
145767
146893
|
}
|
|
146894
|
+
async function startWebServer(port, host) {
|
|
146895
|
+
const { pidFile, configFile, logFile, logDir } = getWebPaths();
|
|
146896
|
+
const status = await getStatus();
|
|
146897
|
+
if (status.running) {
|
|
146898
|
+
throw new CleoError(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
|
|
146899
|
+
}
|
|
146900
|
+
const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
|
|
146901
|
+
const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join134(projectRoot, "packages", "studio", "build");
|
|
146902
|
+
await mkdir19(logDir, { recursive: true });
|
|
146903
|
+
await writeFile14(
|
|
146904
|
+
configFile,
|
|
146905
|
+
JSON.stringify({
|
|
146906
|
+
port,
|
|
146907
|
+
host,
|
|
146908
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
146909
|
+
})
|
|
146910
|
+
);
|
|
146911
|
+
const webIndexPath = join134(studioDir, "index.js");
|
|
146912
|
+
try {
|
|
146913
|
+
await stat3(webIndexPath);
|
|
146914
|
+
} catch {
|
|
146915
|
+
try {
|
|
146916
|
+
execFileSync18("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
|
|
146917
|
+
cwd: projectRoot,
|
|
146918
|
+
stdio: "ignore"
|
|
146919
|
+
});
|
|
146920
|
+
} catch {
|
|
146921
|
+
throw new CleoError(
|
|
146922
|
+
1 /* GENERAL_ERROR */,
|
|
146923
|
+
`Studio build failed. Run: pnpm --filter @cleocode/studio run build
|
|
146924
|
+
Logs: ${logFile}`
|
|
146925
|
+
);
|
|
146926
|
+
}
|
|
146927
|
+
}
|
|
146928
|
+
const logFileHandle = await open(logFile, "a");
|
|
146929
|
+
const serverProcess = spawn2("node", [webIndexPath], {
|
|
146930
|
+
cwd: studioDir,
|
|
146931
|
+
env: {
|
|
146932
|
+
...process.env,
|
|
146933
|
+
HOST: host,
|
|
146934
|
+
PORT: String(port),
|
|
146935
|
+
// Pass CLEO paths through to the studio server
|
|
146936
|
+
CLEO_ROOT: projectRoot
|
|
146937
|
+
},
|
|
146938
|
+
detached: true,
|
|
146939
|
+
stdio: ["ignore", logFileHandle.fd, logFileHandle.fd]
|
|
146940
|
+
});
|
|
146941
|
+
serverProcess.unref();
|
|
146942
|
+
const pidFileTmp = `${pidFile}.tmp`;
|
|
146943
|
+
await writeFile14(pidFileTmp, String(serverProcess.pid));
|
|
146944
|
+
await rm3(pidFile, { force: true });
|
|
146945
|
+
await writeFile14(pidFile, String(serverProcess.pid));
|
|
146946
|
+
await rm3(pidFileTmp, { force: true });
|
|
146947
|
+
await logFileHandle.close();
|
|
146948
|
+
const maxAttempts = 30;
|
|
146949
|
+
let started = false;
|
|
146950
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
146951
|
+
try {
|
|
146952
|
+
const response = await fetch(`http://${host}:${port}/api/health`);
|
|
146953
|
+
if (response.ok) {
|
|
146954
|
+
started = true;
|
|
146955
|
+
break;
|
|
146956
|
+
}
|
|
146957
|
+
} catch {
|
|
146958
|
+
}
|
|
146959
|
+
await new Promise((resolve17) => setTimeout(resolve17, 500));
|
|
146960
|
+
}
|
|
146961
|
+
if (!started) {
|
|
146962
|
+
try {
|
|
146963
|
+
process.kill(serverProcess.pid);
|
|
146964
|
+
} catch {
|
|
146965
|
+
}
|
|
146966
|
+
await rm3(pidFile, { force: true });
|
|
146967
|
+
throw new CleoError(1 /* GENERAL_ERROR */, "Server failed to start within 15 seconds");
|
|
146968
|
+
}
|
|
146969
|
+
cliOutput(
|
|
146970
|
+
{
|
|
146971
|
+
pid: serverProcess.pid,
|
|
146972
|
+
port,
|
|
146973
|
+
host,
|
|
146974
|
+
url: `http://${host}:${port}`,
|
|
146975
|
+
logFile
|
|
146976
|
+
},
|
|
146977
|
+
{ command: "web", message: `CLEO Web UI running on port ${port}` }
|
|
146978
|
+
);
|
|
146979
|
+
}
|
|
145768
146980
|
function registerWebCommand(program) {
|
|
145769
146981
|
const webCmd = program.command("web").description("Manage CLEO Web UI server");
|
|
145770
146982
|
webCmd.command("start").description("Start the web server").option("--port <port>", "Server port", String(DEFAULT_PORT)).option("--host <host>", "Server host", DEFAULT_HOST).action(async (opts) => {
|
|
145771
146983
|
try {
|
|
145772
146984
|
const port = parseInt(opts["port"], 10);
|
|
145773
146985
|
const host = opts["host"];
|
|
145774
|
-
|
|
145775
|
-
const status = await getStatus();
|
|
145776
|
-
if (status.running) {
|
|
145777
|
-
throw new CleoError(
|
|
145778
|
-
1 /* GENERAL_ERROR */,
|
|
145779
|
-
`Server already running (PID: ${status.pid})`
|
|
145780
|
-
);
|
|
145781
|
-
}
|
|
145782
|
-
const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
|
|
145783
|
-
const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join133(projectRoot, "packages", "studio", "build");
|
|
145784
|
-
await mkdir19(logDir, { recursive: true });
|
|
145785
|
-
await writeFile14(
|
|
145786
|
-
configFile,
|
|
145787
|
-
JSON.stringify({
|
|
145788
|
-
port,
|
|
145789
|
-
host,
|
|
145790
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
145791
|
-
})
|
|
145792
|
-
);
|
|
145793
|
-
const webIndexPath = join133(studioDir, "index.js");
|
|
145794
|
-
try {
|
|
145795
|
-
await stat3(webIndexPath);
|
|
145796
|
-
} catch {
|
|
145797
|
-
try {
|
|
145798
|
-
execFileSync18("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
|
|
145799
|
-
cwd: projectRoot,
|
|
145800
|
-
stdio: "ignore"
|
|
145801
|
-
});
|
|
145802
|
-
} catch {
|
|
145803
|
-
throw new CleoError(
|
|
145804
|
-
1 /* GENERAL_ERROR */,
|
|
145805
|
-
`Studio build failed. Run: pnpm --filter @cleocode/studio run build
|
|
145806
|
-
Logs: ${logFile}`
|
|
145807
|
-
);
|
|
145808
|
-
}
|
|
145809
|
-
}
|
|
145810
|
-
const logFileHandle = await open(logFile, "a");
|
|
145811
|
-
const serverProcess = spawn2("node", [webIndexPath], {
|
|
145812
|
-
cwd: studioDir,
|
|
145813
|
-
env: {
|
|
145814
|
-
...process.env,
|
|
145815
|
-
HOST: host,
|
|
145816
|
-
PORT: String(port),
|
|
145817
|
-
// Pass CLEO paths through to the studio server
|
|
145818
|
-
CLEO_ROOT: projectRoot
|
|
145819
|
-
},
|
|
145820
|
-
detached: true,
|
|
145821
|
-
stdio: ["ignore", logFileHandle.fd, logFileHandle.fd]
|
|
145822
|
-
});
|
|
145823
|
-
serverProcess.unref();
|
|
145824
|
-
const pidFileTmp = `${pidFile}.tmp`;
|
|
145825
|
-
await writeFile14(pidFileTmp, String(serverProcess.pid));
|
|
145826
|
-
await rm3(pidFile, { force: true });
|
|
145827
|
-
await writeFile14(pidFile, String(serverProcess.pid));
|
|
145828
|
-
await rm3(pidFileTmp, { force: true });
|
|
145829
|
-
await logFileHandle.close();
|
|
145830
|
-
const maxAttempts = 30;
|
|
145831
|
-
let started = false;
|
|
145832
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
145833
|
-
try {
|
|
145834
|
-
const response = await fetch(`http://${host}:${port}/api/health`);
|
|
145835
|
-
if (response.ok) {
|
|
145836
|
-
started = true;
|
|
145837
|
-
break;
|
|
145838
|
-
}
|
|
145839
|
-
} catch {
|
|
145840
|
-
}
|
|
145841
|
-
await new Promise((resolve17) => setTimeout(resolve17, 500));
|
|
145842
|
-
}
|
|
145843
|
-
if (!started) {
|
|
145844
|
-
try {
|
|
145845
|
-
process.kill(serverProcess.pid);
|
|
145846
|
-
} catch {
|
|
145847
|
-
}
|
|
145848
|
-
await rm3(pidFile, { force: true });
|
|
145849
|
-
throw new CleoError(1 /* GENERAL_ERROR */, "Server failed to start within 15 seconds");
|
|
145850
|
-
}
|
|
145851
|
-
cliOutput(
|
|
145852
|
-
{
|
|
145853
|
-
pid: serverProcess.pid,
|
|
145854
|
-
port,
|
|
145855
|
-
host,
|
|
145856
|
-
url: `http://${host}:${port}`,
|
|
145857
|
-
logFile
|
|
145858
|
-
},
|
|
145859
|
-
{ command: "web", message: `CLEO Web UI running on port ${port}` }
|
|
145860
|
-
);
|
|
146986
|
+
await startWebServer(port, host);
|
|
145861
146987
|
} catch (err) {
|
|
145862
146988
|
if (err instanceof CleoError) {
|
|
145863
146989
|
console.error(formatError3(err));
|
|
@@ -145936,16 +147062,9 @@ Logs: ${logFile}`
|
|
|
145936
147062
|
}
|
|
145937
147063
|
await rm3(pidFile, { force: true });
|
|
145938
147064
|
}
|
|
145939
|
-
const port = opts["port"] ?? String(DEFAULT_PORT);
|
|
147065
|
+
const port = parseInt(opts["port"] ?? String(DEFAULT_PORT), 10);
|
|
145940
147066
|
const host = opts["host"] ?? DEFAULT_HOST;
|
|
145941
|
-
|
|
145942
|
-
const startCmd = webCmd.commands.find((c) => c.name() === "start");
|
|
145943
|
-
const startAction = startCmd?.action;
|
|
145944
|
-
if (startAction) {
|
|
145945
|
-
await startAction(startOpts);
|
|
145946
|
-
} else {
|
|
145947
|
-
throw new CleoError(1 /* GENERAL_ERROR */, "Could not restart server");
|
|
145948
|
-
}
|
|
147067
|
+
await startWebServer(port, host);
|
|
145949
147068
|
} catch (err) {
|
|
145950
147069
|
if (err instanceof CleoError) {
|
|
145951
147070
|
console.error(formatError3(err));
|
|
@@ -146019,9 +147138,9 @@ var codeCommand = defineCommand({
|
|
|
146019
147138
|
async run({ args }) {
|
|
146020
147139
|
await requireTreeSitter();
|
|
146021
147140
|
const { smartOutline: smartOutline2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
146022
|
-
const { join:
|
|
147141
|
+
const { join: join136 } = await import("node:path");
|
|
146023
147142
|
const root = process.cwd();
|
|
146024
|
-
const absPath = args.file.startsWith("/") ? args.file :
|
|
147143
|
+
const absPath = args.file.startsWith("/") ? args.file : join136(root, args.file);
|
|
146025
147144
|
const result = smartOutline2(absPath, root);
|
|
146026
147145
|
if (result.errors.length > 0 && result.symbols.length === 0) {
|
|
146027
147146
|
console.error(`Error: ${result.errors.join(", ")}`);
|
|
@@ -146087,9 +147206,9 @@ var codeCommand = defineCommand({
|
|
|
146087
147206
|
async run({ args }) {
|
|
146088
147207
|
await requireTreeSitter();
|
|
146089
147208
|
const { smartUnfold: smartUnfold2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
146090
|
-
const { join:
|
|
147209
|
+
const { join: join136 } = await import("node:path");
|
|
146091
147210
|
const root = process.cwd();
|
|
146092
|
-
const absPath = args.file.startsWith("/") ? args.file :
|
|
147211
|
+
const absPath = args.file.startsWith("/") ? args.file : join136(root, args.file);
|
|
146093
147212
|
const result = smartUnfold2(absPath, args.symbol, root);
|
|
146094
147213
|
if (!result.found) {
|
|
146095
147214
|
console.error(`Symbol "${args.symbol}" not found in ${args.file}`);
|
|
@@ -146108,8 +147227,8 @@ var codeCommand = defineCommand({
|
|
|
146108
147227
|
|
|
146109
147228
|
// packages/cleo/src/cli/index.ts
|
|
146110
147229
|
function getPackageVersion() {
|
|
146111
|
-
const pkgPath =
|
|
146112
|
-
const pkg = JSON.parse(
|
|
147230
|
+
const pkgPath = join135(dirname31(fileURLToPath8(import.meta.url)), "../../package.json");
|
|
147231
|
+
const pkg = JSON.parse(readFileSync107(pkgPath, "utf-8"));
|
|
146113
147232
|
return pkg.version;
|
|
146114
147233
|
}
|
|
146115
147234
|
var CLI_VERSION = getPackageVersion();
|