@cortexkit/pi-magic-context 0.34.0 → 0.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-0k3j1tc3.js → index-ekzg3w5y.js} +149 -41
- package/dist/index.js +535 -319
- package/dist/subagent-entry.js +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -200,6 +200,7 @@ import {
|
|
|
200
200
|
hasMeaningfulUserText,
|
|
201
201
|
hasMemoryClassifiedAtColumn,
|
|
202
202
|
hasMemoryShareableColumn,
|
|
203
|
+
hasMuralCueColumns,
|
|
203
204
|
hasPiFallbackMessageTags,
|
|
204
205
|
hasPiFallbackToolOwnerTags,
|
|
205
206
|
incrementHistorianFailure,
|
|
@@ -361,7 +362,7 @@ import {
|
|
|
361
362
|
withMigrationLanguageDirective,
|
|
362
363
|
withRawMessageProvider,
|
|
363
364
|
withRawSessionMessageCache
|
|
364
|
-
} from "./index-
|
|
365
|
+
} from "./index-ekzg3w5y.js";
|
|
365
366
|
import {
|
|
366
367
|
pushNotification
|
|
367
368
|
} from "./index-hw34xmzk.js";
|
|
@@ -443,6 +444,16 @@ var CANONICAL_DREAM_TASKS = [
|
|
|
443
444
|
"promote-primers",
|
|
444
445
|
"refresh-primers"
|
|
445
446
|
];
|
|
447
|
+
function formatDreamTaskBacklogs(backlogs, tasks = CANONICAL_DREAM_TASKS) {
|
|
448
|
+
return tasks.filter((task) => backlogs[task] !== undefined).map((task) => {
|
|
449
|
+
const backlog = backlogs[task];
|
|
450
|
+
return `- ${task}: ${backlog?.pending ?? 0} pending / ${backlog?.total ?? 0} total`;
|
|
451
|
+
}).join(`
|
|
452
|
+
`);
|
|
453
|
+
}
|
|
454
|
+
function processedDreamTaskItems(startPending, endPending) {
|
|
455
|
+
return Math.max(0, startPending - endPending);
|
|
456
|
+
}
|
|
446
457
|
var MEMORY_DOMAIN_TASKS = [
|
|
447
458
|
"map-memories",
|
|
448
459
|
"verify",
|
|
@@ -580,7 +591,7 @@ function formatFailClosedBlockingMessage(reason) {
|
|
|
580
591
|
}
|
|
581
592
|
if (reason.kind === "schema_fence") {
|
|
582
593
|
return [
|
|
583
|
-
`Magic Context cannot operate: this Magic Context build is older than the database; upgrade/restart this harness (
|
|
594
|
+
`Magic Context cannot operate: this Magic Context build is older than the database; upgrade/restart this harness (upstream migration lane v${reason.persistedVersion}, build supports through v${reason.supportedVersion}).`,
|
|
584
595
|
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
585
596
|
].join(" ");
|
|
586
597
|
}
|
|
@@ -3072,6 +3083,394 @@ ${sidekickText}
|
|
|
3072
3083
|
});
|
|
3073
3084
|
}
|
|
3074
3085
|
|
|
3086
|
+
// ../plugin/src/features/magic-context/smart-notes/types.ts
|
|
3087
|
+
var SMART_NOTE_CHECK_POLICY_VERSION = 1;
|
|
3088
|
+
var SMART_NOTE_CHECK_FLOOR_MS = 5 * 60 * 1000;
|
|
3089
|
+
var SMART_NOTE_CHECK_CEILING_MS = 24 * 60 * 60 * 1000;
|
|
3090
|
+
var SMART_NOTE_CHECK_DEFAULT_INTERVAL_MS = 60 * 60 * 1000;
|
|
3091
|
+
var SMART_NOTE_CHECK_MAX_STALENESS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
3092
|
+
var SMART_NOTE_CHECK_LIVENESS_RECHECK_MS = 24 * 60 * 60 * 1000;
|
|
3093
|
+
|
|
3094
|
+
class SmartNoteNetworkError extends Error {
|
|
3095
|
+
isSmartNoteNetworkError = true;
|
|
3096
|
+
terminal;
|
|
3097
|
+
constructor(message, options = {}) {
|
|
3098
|
+
super(message);
|
|
3099
|
+
this.name = "SmartNoteNetworkError";
|
|
3100
|
+
this.terminal = options.terminal ?? false;
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
|
|
3104
|
+
class SmartNoteSecurityError extends Error {
|
|
3105
|
+
isSmartNoteSecurityError = true;
|
|
3106
|
+
constructor(message) {
|
|
3107
|
+
super(message);
|
|
3108
|
+
this.name = "SmartNoteSecurityError";
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
function isSmartNoteNetworkError(error) {
|
|
3112
|
+
return error instanceof SmartNoteNetworkError || error instanceof Error && (error.name === "SmartNoteNetworkError" || error.message.includes("SmartNoteNetworkError") || error.message.includes("SMART_NOTE_NETWORK"));
|
|
3113
|
+
}
|
|
3114
|
+
function isTerminalSmartNoteNetworkError(error) {
|
|
3115
|
+
return error instanceof SmartNoteNetworkError && error.terminal;
|
|
3116
|
+
}
|
|
3117
|
+
function parseSmartNoteManifest(json) {
|
|
3118
|
+
if (!json)
|
|
3119
|
+
return { capabilities: [] };
|
|
3120
|
+
try {
|
|
3121
|
+
const parsed = JSON.parse(json);
|
|
3122
|
+
const capabilities = Array.isArray(parsed.capabilities) ? parsed.capabilities.filter((c) => ["readFile", "gitHeadSha", "gitTag", "gitLog", "httpGet"].includes(String(c))) : [];
|
|
3123
|
+
return {
|
|
3124
|
+
capabilities,
|
|
3125
|
+
readFiles: stringArray(parsed.readFiles),
|
|
3126
|
+
hosts: stringArray(parsed.hosts),
|
|
3127
|
+
urls: stringArray(parsed.urls),
|
|
3128
|
+
signals: stringArray(parsed.signals),
|
|
3129
|
+
summary: typeof parsed.summary === "string" ? parsed.summary : undefined
|
|
3130
|
+
};
|
|
3131
|
+
} catch {
|
|
3132
|
+
return { capabilities: [] };
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
function stringArray(value) {
|
|
3136
|
+
if (!Array.isArray(value))
|
|
3137
|
+
return;
|
|
3138
|
+
const arr = value.filter((item) => typeof item === "string");
|
|
3139
|
+
return arr.length > 0 ? arr : undefined;
|
|
3140
|
+
}
|
|
3141
|
+
|
|
3142
|
+
// ../plugin/src/features/magic-context/smart-notes/storage.ts
|
|
3143
|
+
function toSmartNote(note) {
|
|
3144
|
+
return {
|
|
3145
|
+
...note,
|
|
3146
|
+
checkStatus: note.checkStatus ?? "uncompiled",
|
|
3147
|
+
checkFailureCount: note.checkFailureCount ?? 0,
|
|
3148
|
+
checkNetworkFailureCount: note.checkNetworkFailureCount ?? 0,
|
|
3149
|
+
policyVersion: note.policyVersion ?? 0
|
|
3150
|
+
};
|
|
3151
|
+
}
|
|
3152
|
+
function commitSmartNoteState(db, args) {
|
|
3153
|
+
db.exec("BEGIN IMMEDIATE");
|
|
3154
|
+
let leaseLost = false;
|
|
3155
|
+
let committed = false;
|
|
3156
|
+
try {
|
|
3157
|
+
if (args.leaseHeld && !args.leaseHeld()) {
|
|
3158
|
+
leaseLost = true;
|
|
3159
|
+
} else if (claimExpectedState(db, args.expected)) {
|
|
3160
|
+
args.write();
|
|
3161
|
+
committed = true;
|
|
3162
|
+
}
|
|
3163
|
+
db.exec("COMMIT");
|
|
3164
|
+
} catch (error) {
|
|
3165
|
+
try {
|
|
3166
|
+
db.exec("ROLLBACK");
|
|
3167
|
+
} catch {}
|
|
3168
|
+
throw error;
|
|
3169
|
+
}
|
|
3170
|
+
if (leaseLost) {
|
|
3171
|
+
throw new Error(`Dream lease lost during smart-note ${args.phase} commit`);
|
|
3172
|
+
}
|
|
3173
|
+
if (!committed) {
|
|
3174
|
+
log(`[debug] smart note #${args.expected.noteId}: discarded stale ${args.phase} result`);
|
|
3175
|
+
}
|
|
3176
|
+
return committed;
|
|
3177
|
+
}
|
|
3178
|
+
function claimExpectedState(db, expected) {
|
|
3179
|
+
if (expected.kind === "compiled-check") {
|
|
3180
|
+
return db.prepare(`UPDATE notes SET id = id
|
|
3181
|
+
WHERE id = ? AND type = 'smart' AND status = 'pending'
|
|
3182
|
+
AND check_status = 'compiled' AND compiled_check = ?
|
|
3183
|
+
AND check_hash IS ? AND check_compiled_at IS ?`).run(expected.noteId, expected.compiledCheck, expected.checkHash, expected.checkCompiledAt).changes > 0;
|
|
3184
|
+
}
|
|
3185
|
+
const statusClause = expected.checkStatus ? " AND check_status = ?" : "";
|
|
3186
|
+
const params = [
|
|
3187
|
+
expected.noteId,
|
|
3188
|
+
expected.content,
|
|
3189
|
+
expected.surfaceCondition,
|
|
3190
|
+
expected.updatedAt
|
|
3191
|
+
];
|
|
3192
|
+
if (expected.checkStatus)
|
|
3193
|
+
params.push(expected.checkStatus);
|
|
3194
|
+
return db.prepare(`UPDATE notes SET id = id
|
|
3195
|
+
WHERE id = ? AND type = 'smart' AND status = 'pending'
|
|
3196
|
+
AND content = ? AND surface_condition IS ? AND updated_at = ?${statusClause}`).run(...params).changes > 0;
|
|
3197
|
+
}
|
|
3198
|
+
function getDueCompiledSmartNoteChecks(db, projectPath, now, limit) {
|
|
3199
|
+
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
3200
|
+
}
|
|
3201
|
+
function getSmartNotesNeedingCompilation(db, projectPath, now, limit) {
|
|
3202
|
+
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
|
|
3203
|
+
}
|
|
3204
|
+
function getStaleCompiledSmartNotes(db, projectPath, now, limit) {
|
|
3205
|
+
const staleBefore = now - SMART_NOTE_CHECK_MAX_STALENESS_MS;
|
|
3206
|
+
const livenessBefore = now - SMART_NOTE_CHECK_LIVENESS_RECHECK_MS;
|
|
3207
|
+
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
3208
|
+
}
|
|
3209
|
+
function storeCompiledSmartNoteCheck(db, args) {
|
|
3210
|
+
db.prepare(`UPDATE notes
|
|
3211
|
+
SET compiled_check = ?,
|
|
3212
|
+
manifest_json = ?,
|
|
3213
|
+
check_hash = ?,
|
|
3214
|
+
check_cron = ?,
|
|
3215
|
+
check_version = 1,
|
|
3216
|
+
check_status = 'compiled',
|
|
3217
|
+
check_failure_count = 0,
|
|
3218
|
+
check_network_failure_count = 0,
|
|
3219
|
+
check_quarantined_until = NULL,
|
|
3220
|
+
check_next_due_at = ?,
|
|
3221
|
+
check_compiled_at = ?,
|
|
3222
|
+
check_false_since_at = COALESCE(check_false_since_at, ?),
|
|
3223
|
+
check_last_liveness_at = NULL,
|
|
3224
|
+
policy_version = ?,
|
|
3225
|
+
updated_at = ?
|
|
3226
|
+
WHERE id = ? AND type = 'smart'`).run(args.compiledCheck, JSON.stringify(args.manifest), args.checkHash, args.checkCron, args.nextDueAt, args.now, args.now, SMART_NOTE_CHECK_POLICY_VERSION, args.now, args.noteId);
|
|
3227
|
+
}
|
|
3228
|
+
function markCompiledCheckFalse(db, noteId, nextDueAt, now) {
|
|
3229
|
+
db.prepare(`UPDATE notes
|
|
3230
|
+
SET last_checked_at = ?,
|
|
3231
|
+
updated_at = ?,
|
|
3232
|
+
check_next_due_at = ?,
|
|
3233
|
+
check_failure_count = 0,
|
|
3234
|
+
check_network_failure_count = 0,
|
|
3235
|
+
check_false_since_at = COALESCE(check_false_since_at, ?)
|
|
3236
|
+
WHERE id = ? AND type = 'smart'`).run(now, now, nextDueAt, now, noteId);
|
|
3237
|
+
}
|
|
3238
|
+
function markCompiledCheckLogicFailure(db, noteId, now, maxFailures) {
|
|
3239
|
+
const failureCount = readFailureCount(db, noteId, "check_failure_count") + 1;
|
|
3240
|
+
const status = failureCount >= maxFailures ? "failing" : "compiled";
|
|
3241
|
+
db.prepare(`UPDATE notes
|
|
3242
|
+
SET check_failure_count = ?,
|
|
3243
|
+
check_status = ?,
|
|
3244
|
+
check_next_due_at = ?,
|
|
3245
|
+
updated_at = ?
|
|
3246
|
+
WHERE id = ? AND type = 'smart'`).run(failureCount, status, now + backoffMs(failureCount), now, noteId);
|
|
3247
|
+
}
|
|
3248
|
+
function markCompiledCheckNetworkFailure(db, noteId, now, maxFailures) {
|
|
3249
|
+
const failureCount = readFailureCount(db, noteId, "check_network_failure_count") + 1;
|
|
3250
|
+
const quarantinedUntil = now + backoffMs(failureCount);
|
|
3251
|
+
const status = failureCount >= maxFailures ? "failing" : "compiled";
|
|
3252
|
+
db.prepare(`UPDATE notes
|
|
3253
|
+
SET check_network_failure_count = ?,
|
|
3254
|
+
check_status = ?,
|
|
3255
|
+
check_next_due_at = ?,
|
|
3256
|
+
check_quarantined_until = ?,
|
|
3257
|
+
updated_at = ?
|
|
3258
|
+
WHERE id = ? AND type = 'smart'`).run(failureCount, status, quarantinedUntil, quarantinedUntil, now, noteId);
|
|
3259
|
+
}
|
|
3260
|
+
function markSmartNoteLivenessChecked(db, noteId, now) {
|
|
3261
|
+
db.prepare(`UPDATE notes
|
|
3262
|
+
SET check_last_liveness_at = ?, updated_at = ?
|
|
3263
|
+
WHERE id = ? AND type = 'smart'`).run(now, now, noteId);
|
|
3264
|
+
}
|
|
3265
|
+
function markSmartNoteCheckStatus(db, noteId, status, now) {
|
|
3266
|
+
db.prepare(`UPDATE notes SET check_status = ?, updated_at = ? WHERE id = ? AND type = 'smart'`).run(status, now, noteId);
|
|
3267
|
+
}
|
|
3268
|
+
function markSmartNoteCompilationFailure(db, noteId, now, maxFailures) {
|
|
3269
|
+
const failureCount = readFailureCount(db, noteId, "check_failure_count") + 1;
|
|
3270
|
+
const status = failureCount >= maxFailures ? "fallback" : "uncompiled";
|
|
3271
|
+
db.prepare(`UPDATE notes
|
|
3272
|
+
SET check_failure_count = ?,
|
|
3273
|
+
check_status = ?,
|
|
3274
|
+
check_next_due_at = ?,
|
|
3275
|
+
updated_at = ?
|
|
3276
|
+
WHERE id = ? AND type = 'smart'`).run(failureCount, status, now + backoffMs(failureCount), now, noteId);
|
|
3277
|
+
}
|
|
3278
|
+
function readFailureCount(db, noteId, column) {
|
|
3279
|
+
if (column !== "check_failure_count" && column !== "check_network_failure_count")
|
|
3280
|
+
return 0;
|
|
3281
|
+
const row = db.prepare(`SELECT ${column} AS count FROM notes WHERE id = ?`).get(noteId);
|
|
3282
|
+
return row?.count ?? 0;
|
|
3283
|
+
}
|
|
3284
|
+
function backoffMs(failureCount) {
|
|
3285
|
+
const minutes = Math.min(24 * 60, 5 * 2 ** Math.max(0, failureCount - 1));
|
|
3286
|
+
return minutes * 60 * 1000;
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3289
|
+
// ../plugin/src/features/magic-context/dreamer/task-gates.ts
|
|
3290
|
+
function countActiveMemories(db, projectPath) {
|
|
3291
|
+
const row = db.prepare("SELECT COUNT(*) AS cnt FROM memories WHERE project_path = ? AND status IN ('active','permanent')").get(projectPath);
|
|
3292
|
+
return row?.cnt ?? 0;
|
|
3293
|
+
}
|
|
3294
|
+
function countUnmappedActiveMemories(db, projectPath) {
|
|
3295
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
3296
|
+
FROM memories m
|
|
3297
|
+
WHERE m.project_path = ?
|
|
3298
|
+
AND m.status IN ('active','permanent')
|
|
3299
|
+
AND NOT EXISTS (
|
|
3300
|
+
SELECT 1 FROM memory_verifications v WHERE v.memory_id = m.id
|
|
3301
|
+
)`).get(projectPath);
|
|
3302
|
+
return row?.cnt ?? 0;
|
|
3303
|
+
}
|
|
3304
|
+
function countCompartmentsSince(db, projectPath, since) {
|
|
3305
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
3306
|
+
FROM compartments c
|
|
3307
|
+
JOIN session_projects sp ON sp.session_id = c.session_id
|
|
3308
|
+
WHERE sp.project_path = ? AND c.created_at > ?`).get(projectPath, since);
|
|
3309
|
+
return row?.cnt ?? 0;
|
|
3310
|
+
}
|
|
3311
|
+
function countProjectSessionsSince(db, projectPath, since) {
|
|
3312
|
+
const row = since === null ? db.prepare("SELECT COUNT(*) AS cnt FROM session_projects WHERE project_path = ?").get(projectPath) : db.prepare("SELECT COUNT(*) AS cnt FROM session_projects WHERE project_path = ? AND updated_at > ?").get(projectPath, since);
|
|
3313
|
+
return row?.cnt ?? 0;
|
|
3314
|
+
}
|
|
3315
|
+
function countMappedMemories(db, projectPath) {
|
|
3316
|
+
const row = db.prepare(`SELECT COUNT(DISTINCT m.id) AS cnt
|
|
3317
|
+
FROM memories m
|
|
3318
|
+
JOIN memory_verifications v ON v.memory_id = m.id
|
|
3319
|
+
WHERE m.project_path = ?
|
|
3320
|
+
AND m.status IN ('active','permanent')
|
|
3321
|
+
AND v.file_path <> ''`).get(projectPath);
|
|
3322
|
+
return row?.cnt ?? 0;
|
|
3323
|
+
}
|
|
3324
|
+
function countUnverifiedMappedMemories(db, projectPath) {
|
|
3325
|
+
const row = db.prepare(`SELECT COUNT(DISTINCT m.id) AS cnt
|
|
3326
|
+
FROM memories m
|
|
3327
|
+
JOIN memory_verifications v ON v.memory_id = m.id
|
|
3328
|
+
WHERE m.project_path = ?
|
|
3329
|
+
AND m.status IN ('active','permanent')
|
|
3330
|
+
AND v.file_path <> ''
|
|
3331
|
+
AND v.verified_at = 0`).get(projectPath);
|
|
3332
|
+
return row?.cnt ?? 0;
|
|
3333
|
+
}
|
|
3334
|
+
function countCueCandidates(db, projectPath) {
|
|
3335
|
+
if (!hasMuralCueColumns(db))
|
|
3336
|
+
return countActiveMemories(db, projectPath);
|
|
3337
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
3338
|
+
FROM memories
|
|
3339
|
+
WHERE project_path = ?
|
|
3340
|
+
AND status IN ('active','permanent')
|
|
3341
|
+
AND (mural_cue IS NULL OR mural_cue_hash IS NULL OR updated_at > mural_cue_at)`).get(projectPath);
|
|
3342
|
+
return row?.cnt ?? 0;
|
|
3343
|
+
}
|
|
3344
|
+
function countStalePrimers(db, projectPath) {
|
|
3345
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
3346
|
+
FROM primers
|
|
3347
|
+
WHERE project_path = ?
|
|
3348
|
+
AND status = 'active'
|
|
3349
|
+
AND (answer IS NULL OR TRIM(answer) = '' OR answer_refreshed_at IS NULL
|
|
3350
|
+
OR last_observed_at > answer_refreshed_at)`).get(projectPath);
|
|
3351
|
+
return row?.cnt ?? 0;
|
|
3352
|
+
}
|
|
3353
|
+
function countUnclassifiedActiveMemories(db, projectPath) {
|
|
3354
|
+
if (!hasMemoryClassifiedAtColumn(db))
|
|
3355
|
+
return countActiveMemories(db, projectPath);
|
|
3356
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
3357
|
+
FROM memories
|
|
3358
|
+
WHERE project_path = ?
|
|
3359
|
+
AND status IN ('active','permanent')
|
|
3360
|
+
AND classified_at IS NULL`).get(projectPath);
|
|
3361
|
+
return row?.cnt ?? 0;
|
|
3362
|
+
}
|
|
3363
|
+
function countPendingSmartNotes(db, projectPath) {
|
|
3364
|
+
const row = db.prepare("SELECT COUNT(*) AS cnt FROM notes WHERE project_path = ? AND type = 'smart' AND status = 'pending'").get(projectPath);
|
|
3365
|
+
return row?.cnt ?? 0;
|
|
3366
|
+
}
|
|
3367
|
+
function countUserMemoryCandidates(db) {
|
|
3368
|
+
const row = db.prepare("SELECT COUNT(*) AS cnt FROM user_memory_candidates").get();
|
|
3369
|
+
return row?.cnt ?? 0;
|
|
3370
|
+
}
|
|
3371
|
+
function countActivePrimers(db, projectPath) {
|
|
3372
|
+
const row = db.prepare("SELECT COUNT(*) AS cnt FROM primers WHERE project_path = ? AND status = 'active'").get(projectPath);
|
|
3373
|
+
return row?.cnt ?? 0;
|
|
3374
|
+
}
|
|
3375
|
+
function getDreamTaskBacklog(db, projectPath, task, options = {}) {
|
|
3376
|
+
switch (task) {
|
|
3377
|
+
case "map-memories": {
|
|
3378
|
+
const total = countActiveMemories(db, projectPath);
|
|
3379
|
+
return { pending: countUnmappedActiveMemories(db, projectPath), total };
|
|
3380
|
+
}
|
|
3381
|
+
case "verify": {
|
|
3382
|
+
return {
|
|
3383
|
+
pending: countUnverifiedMappedMemories(db, projectPath),
|
|
3384
|
+
total: countMappedMemories(db, projectPath)
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3387
|
+
case "verify-broad": {
|
|
3388
|
+
const total = countMappedMemories(db, projectPath);
|
|
3389
|
+
return { pending: total, total };
|
|
3390
|
+
}
|
|
3391
|
+
case "curate": {
|
|
3392
|
+
const total = countActiveMemories(db, projectPath);
|
|
3393
|
+
return { pending: total, total };
|
|
3394
|
+
}
|
|
3395
|
+
case "compress-cues": {
|
|
3396
|
+
const total = countActiveMemories(db, projectPath);
|
|
3397
|
+
return { pending: countCueCandidates(db, projectPath), total };
|
|
3398
|
+
}
|
|
3399
|
+
case "classify-memories": {
|
|
3400
|
+
const total = countActiveMemories(db, projectPath);
|
|
3401
|
+
return { pending: countUnclassifiedActiveMemories(db, projectPath), total };
|
|
3402
|
+
}
|
|
3403
|
+
case "retrospective": {
|
|
3404
|
+
const pending = countProjectSessionsSince(db, projectPath, options.retrospectiveWatermarkMs ?? null);
|
|
3405
|
+
return { pending, total: pending };
|
|
3406
|
+
}
|
|
3407
|
+
case "maintain-docs": {
|
|
3408
|
+
const total = countCompartmentsSince(db, projectPath, 0);
|
|
3409
|
+
const pending = countCompartmentsSince(db, projectPath, options.lastRunAt ?? 0);
|
|
3410
|
+
return { pending, total };
|
|
3411
|
+
}
|
|
3412
|
+
case "evaluate-smart-notes": {
|
|
3413
|
+
const pending = countPendingSmartNotes(db, projectPath);
|
|
3414
|
+
return { pending, total: pending };
|
|
3415
|
+
}
|
|
3416
|
+
case "review-user-memories": {
|
|
3417
|
+
const pending = countUserMemoryCandidates(db);
|
|
3418
|
+
return { pending, total: pending };
|
|
3419
|
+
}
|
|
3420
|
+
case "promote-primers": {
|
|
3421
|
+
const pending = countPrimerCandidatesForProject(db, projectPath);
|
|
3422
|
+
return { pending, total: pending };
|
|
3423
|
+
}
|
|
3424
|
+
case "refresh-primers": {
|
|
3425
|
+
const total = countActivePrimers(db, projectPath);
|
|
3426
|
+
return { pending: countStalePrimers(db, projectPath), total };
|
|
3427
|
+
}
|
|
3428
|
+
default: {
|
|
3429
|
+
const _exhaustive = task;
|
|
3430
|
+
return _exhaustive;
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
function getDreamTaskBacklogs(db, projectPath, tasks = CANONICAL_DREAM_TASKS, options = {}) {
|
|
3435
|
+
const result = {};
|
|
3436
|
+
for (const task of tasks)
|
|
3437
|
+
result[task] = getDreamTaskBacklog(db, projectPath, task, options);
|
|
3438
|
+
return result;
|
|
3439
|
+
}
|
|
3440
|
+
function evaluateTaskGate(task, ctx) {
|
|
3441
|
+
const { db, projectIdentity: project, lastRunAt } = ctx;
|
|
3442
|
+
switch (task) {
|
|
3443
|
+
case "map-memories":
|
|
3444
|
+
return countUnmappedActiveMemories(db, project) > 0;
|
|
3445
|
+
case "verify":
|
|
3446
|
+
return countActiveMemories(db, project) > 0;
|
|
3447
|
+
case "verify-broad":
|
|
3448
|
+
return countActiveMemories(db, project) > 0;
|
|
3449
|
+
case "curate":
|
|
3450
|
+
return countActiveMemories(db, project) > 0;
|
|
3451
|
+
case "compress-cues":
|
|
3452
|
+
return countActiveMemories(db, project) > 0;
|
|
3453
|
+
case "classify-memories":
|
|
3454
|
+
return countActiveMemories(db, project) > 0;
|
|
3455
|
+
case "retrospective":
|
|
3456
|
+
return countProjectSessionsSince(db, project, ctx.retrospectiveWatermarkMs ?? null) > 0;
|
|
3457
|
+
case "maintain-docs":
|
|
3458
|
+
return countCompartmentsSince(db, project, lastRunAt ?? 0) > 0;
|
|
3459
|
+
case "evaluate-smart-notes":
|
|
3460
|
+
return getSmartNotesNeedingCompilation(db, project, Date.now(), 1).length > 0 || getStaleCompiledSmartNotes(db, project, Date.now(), 1).length > 0 || getPendingSmartNotes(db, project).some((note) => note.checkStatus === "fallback");
|
|
3461
|
+
case "review-user-memories":
|
|
3462
|
+
return getUserMemoryCandidates(db).length >= ctx.promotionThreshold;
|
|
3463
|
+
case "promote-primers":
|
|
3464
|
+
return countPrimerCandidatesForProject(db, project) >= (ctx.promotionThreshold ?? 2);
|
|
3465
|
+
case "refresh-primers":
|
|
3466
|
+
return getActivePrimers(db, project).some((primer) => !primer.answer.trim() || primer.answerRefreshedAt == null || (primer.lastObservedAt ?? 0) > primer.answerRefreshedAt);
|
|
3467
|
+
default: {
|
|
3468
|
+
const _exhaustive = task;
|
|
3469
|
+
return Boolean(_exhaustive);
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
|
|
3075
3474
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
3076
3475
|
import { existsSync as existsSync4 } from "node:fs";
|
|
3077
3476
|
function openOpenCodeDb() {
|
|
@@ -4059,6 +4458,7 @@ async function runCompressCues(args) {
|
|
|
4059
4458
|
result.skipped += outcome.skipped;
|
|
4060
4459
|
result.remaining -= outcome.compressed;
|
|
4061
4460
|
result.chunks += 1;
|
|
4461
|
+
args.onProgress?.(result.compressed + result.skipped);
|
|
4062
4462
|
if (outcome.failure?.class === "timeout") {
|
|
4063
4463
|
consecutiveTimeouts += 1;
|
|
4064
4464
|
timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
|
|
@@ -5154,6 +5554,7 @@ async function runClassify(args) {
|
|
|
5154
5554
|
result.changed += counts.changed;
|
|
5155
5555
|
result.remaining -= counts.classified;
|
|
5156
5556
|
result.chunks += 1;
|
|
5557
|
+
args.onProgress?.(result.classified);
|
|
5157
5558
|
}
|
|
5158
5559
|
result.complete = result.remaining === 0;
|
|
5159
5560
|
log(`[dreamer] classify: stage=${stage} classified=${result.classified} changed=${result.changed} chunks=${result.chunks} remaining=${result.remaining} complete=${result.complete}`);
|
|
@@ -5383,95 +5784,37 @@ function applyClassifications(args, chunk, manifestText) {
|
|
|
5383
5784
|
});
|
|
5384
5785
|
return { classified, changed };
|
|
5385
5786
|
}
|
|
5386
|
-
function recordInvocation(args, startedAt, params) {
|
|
5387
|
-
if (!args.parentSessionId)
|
|
5388
|
-
return;
|
|
5389
|
-
recordChildInvocation({
|
|
5390
|
-
db: args.db,
|
|
5391
|
-
parentSessionId: args.parentSessionId,
|
|
5392
|
-
harness: "opencode",
|
|
5393
|
-
subagent: "dreamer",
|
|
5394
|
-
task: "classify-memories",
|
|
5395
|
-
startedAt,
|
|
5396
|
-
status: params.status,
|
|
5397
|
-
messages: params.messages,
|
|
5398
|
-
error: params.error
|
|
5399
|
-
});
|
|
5400
|
-
}
|
|
5401
|
-
|
|
5402
|
-
// ../plugin/src/agents/smart-note-compiler.ts
|
|
5403
|
-
var SMART_NOTE_COMPILER_AGENT = "smart-note-compiler";
|
|
5404
|
-
|
|
5405
|
-
// ../plugin/src/features/magic-context/smart-notes/capabilities.ts
|
|
5406
|
-
import { execFile } from "node:child_process";
|
|
5407
|
-
import { constants as fsConstants } from "node:fs";
|
|
5408
|
-
import { lstat, open, realpath } from "node:fs/promises";
|
|
5409
|
-
import path3 from "node:path";
|
|
5410
|
-
import { promisify } from "node:util";
|
|
5411
|
-
|
|
5412
|
-
// ../plugin/src/features/magic-context/smart-notes/ssrf-guard.ts
|
|
5413
|
-
import { lookup as dnsLookup } from "node:dns/promises";
|
|
5414
|
-
import * as https from "node:https";
|
|
5415
|
-
import { isIP } from "node:net";
|
|
5416
|
-
import { domainToASCII } from "node:url";
|
|
5417
|
-
|
|
5418
|
-
// ../plugin/src/features/magic-context/smart-notes/types.ts
|
|
5419
|
-
var SMART_NOTE_CHECK_POLICY_VERSION = 1;
|
|
5420
|
-
var SMART_NOTE_CHECK_FLOOR_MS = 5 * 60 * 1000;
|
|
5421
|
-
var SMART_NOTE_CHECK_CEILING_MS = 24 * 60 * 60 * 1000;
|
|
5422
|
-
var SMART_NOTE_CHECK_DEFAULT_INTERVAL_MS = 60 * 60 * 1000;
|
|
5423
|
-
var SMART_NOTE_CHECK_MAX_STALENESS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
5424
|
-
var SMART_NOTE_CHECK_LIVENESS_RECHECK_MS = 24 * 60 * 60 * 1000;
|
|
5425
|
-
|
|
5426
|
-
class SmartNoteNetworkError extends Error {
|
|
5427
|
-
isSmartNoteNetworkError = true;
|
|
5428
|
-
terminal;
|
|
5429
|
-
constructor(message, options = {}) {
|
|
5430
|
-
super(message);
|
|
5431
|
-
this.name = "SmartNoteNetworkError";
|
|
5432
|
-
this.terminal = options.terminal ?? false;
|
|
5433
|
-
}
|
|
5434
|
-
}
|
|
5435
|
-
|
|
5436
|
-
class SmartNoteSecurityError extends Error {
|
|
5437
|
-
isSmartNoteSecurityError = true;
|
|
5438
|
-
constructor(message) {
|
|
5439
|
-
super(message);
|
|
5440
|
-
this.name = "SmartNoteSecurityError";
|
|
5441
|
-
}
|
|
5442
|
-
}
|
|
5443
|
-
function isSmartNoteNetworkError(error) {
|
|
5444
|
-
return error instanceof SmartNoteNetworkError || error instanceof Error && (error.name === "SmartNoteNetworkError" || error.message.includes("SmartNoteNetworkError") || error.message.includes("SMART_NOTE_NETWORK"));
|
|
5445
|
-
}
|
|
5446
|
-
function isTerminalSmartNoteNetworkError(error) {
|
|
5447
|
-
return error instanceof SmartNoteNetworkError && error.terminal;
|
|
5448
|
-
}
|
|
5449
|
-
function parseSmartNoteManifest(json) {
|
|
5450
|
-
if (!json)
|
|
5451
|
-
return { capabilities: [] };
|
|
5452
|
-
try {
|
|
5453
|
-
const parsed = JSON.parse(json);
|
|
5454
|
-
const capabilities = Array.isArray(parsed.capabilities) ? parsed.capabilities.filter((c) => ["readFile", "gitHeadSha", "gitTag", "gitLog", "httpGet"].includes(String(c))) : [];
|
|
5455
|
-
return {
|
|
5456
|
-
capabilities,
|
|
5457
|
-
readFiles: stringArray(parsed.readFiles),
|
|
5458
|
-
hosts: stringArray(parsed.hosts),
|
|
5459
|
-
urls: stringArray(parsed.urls),
|
|
5460
|
-
signals: stringArray(parsed.signals),
|
|
5461
|
-
summary: typeof parsed.summary === "string" ? parsed.summary : undefined
|
|
5462
|
-
};
|
|
5463
|
-
} catch {
|
|
5464
|
-
return { capabilities: [] };
|
|
5465
|
-
}
|
|
5466
|
-
}
|
|
5467
|
-
function stringArray(value) {
|
|
5468
|
-
if (!Array.isArray(value))
|
|
5787
|
+
function recordInvocation(args, startedAt, params) {
|
|
5788
|
+
if (!args.parentSessionId)
|
|
5469
5789
|
return;
|
|
5470
|
-
|
|
5471
|
-
|
|
5790
|
+
recordChildInvocation({
|
|
5791
|
+
db: args.db,
|
|
5792
|
+
parentSessionId: args.parentSessionId,
|
|
5793
|
+
harness: "opencode",
|
|
5794
|
+
subagent: "dreamer",
|
|
5795
|
+
task: "classify-memories",
|
|
5796
|
+
startedAt,
|
|
5797
|
+
status: params.status,
|
|
5798
|
+
messages: params.messages,
|
|
5799
|
+
error: params.error
|
|
5800
|
+
});
|
|
5472
5801
|
}
|
|
5473
5802
|
|
|
5803
|
+
// ../plugin/src/agents/smart-note-compiler.ts
|
|
5804
|
+
var SMART_NOTE_COMPILER_AGENT = "smart-note-compiler";
|
|
5805
|
+
|
|
5806
|
+
// ../plugin/src/features/magic-context/smart-notes/capabilities.ts
|
|
5807
|
+
import { execFile } from "node:child_process";
|
|
5808
|
+
import { constants as fsConstants } from "node:fs";
|
|
5809
|
+
import { lstat, open, realpath } from "node:fs/promises";
|
|
5810
|
+
import path3 from "node:path";
|
|
5811
|
+
import { promisify } from "node:util";
|
|
5812
|
+
|
|
5474
5813
|
// ../plugin/src/features/magic-context/smart-notes/ssrf-guard.ts
|
|
5814
|
+
import { lookup as dnsLookup } from "node:dns/promises";
|
|
5815
|
+
import * as https from "node:https";
|
|
5816
|
+
import { isIP } from "node:net";
|
|
5817
|
+
import { domainToASCII } from "node:url";
|
|
5475
5818
|
var DNS_TIMEOUT_MS = 3000;
|
|
5476
5819
|
var DEFAULT_HTTP_TIMEOUT_MS = 5000;
|
|
5477
5820
|
var DEFAULT_HTTP_BODY_LIMIT_BYTES = 64 * 1024;
|
|
@@ -6457,153 +6800,6 @@ function deterministicJitterMs(intervalMs, noteId, hash) {
|
|
|
6457
6800
|
return unsigned % (max * 2 + 1) - max;
|
|
6458
6801
|
}
|
|
6459
6802
|
|
|
6460
|
-
// ../plugin/src/features/magic-context/smart-notes/storage.ts
|
|
6461
|
-
function toSmartNote(note) {
|
|
6462
|
-
return {
|
|
6463
|
-
...note,
|
|
6464
|
-
checkStatus: note.checkStatus ?? "uncompiled",
|
|
6465
|
-
checkFailureCount: note.checkFailureCount ?? 0,
|
|
6466
|
-
checkNetworkFailureCount: note.checkNetworkFailureCount ?? 0,
|
|
6467
|
-
policyVersion: note.policyVersion ?? 0
|
|
6468
|
-
};
|
|
6469
|
-
}
|
|
6470
|
-
function commitSmartNoteState(db, args) {
|
|
6471
|
-
db.exec("BEGIN IMMEDIATE");
|
|
6472
|
-
let leaseLost = false;
|
|
6473
|
-
let committed = false;
|
|
6474
|
-
try {
|
|
6475
|
-
if (args.leaseHeld && !args.leaseHeld()) {
|
|
6476
|
-
leaseLost = true;
|
|
6477
|
-
} else if (claimExpectedState(db, args.expected)) {
|
|
6478
|
-
args.write();
|
|
6479
|
-
committed = true;
|
|
6480
|
-
}
|
|
6481
|
-
db.exec("COMMIT");
|
|
6482
|
-
} catch (error) {
|
|
6483
|
-
try {
|
|
6484
|
-
db.exec("ROLLBACK");
|
|
6485
|
-
} catch {}
|
|
6486
|
-
throw error;
|
|
6487
|
-
}
|
|
6488
|
-
if (leaseLost) {
|
|
6489
|
-
throw new Error(`Dream lease lost during smart-note ${args.phase} commit`);
|
|
6490
|
-
}
|
|
6491
|
-
if (!committed) {
|
|
6492
|
-
log(`[debug] smart note #${args.expected.noteId}: discarded stale ${args.phase} result`);
|
|
6493
|
-
}
|
|
6494
|
-
return committed;
|
|
6495
|
-
}
|
|
6496
|
-
function claimExpectedState(db, expected) {
|
|
6497
|
-
if (expected.kind === "compiled-check") {
|
|
6498
|
-
return db.prepare(`UPDATE notes SET id = id
|
|
6499
|
-
WHERE id = ? AND type = 'smart' AND status = 'pending'
|
|
6500
|
-
AND check_status = 'compiled' AND compiled_check = ?
|
|
6501
|
-
AND check_hash IS ? AND check_compiled_at IS ?`).run(expected.noteId, expected.compiledCheck, expected.checkHash, expected.checkCompiledAt).changes > 0;
|
|
6502
|
-
}
|
|
6503
|
-
const statusClause = expected.checkStatus ? " AND check_status = ?" : "";
|
|
6504
|
-
const params = [
|
|
6505
|
-
expected.noteId,
|
|
6506
|
-
expected.content,
|
|
6507
|
-
expected.surfaceCondition,
|
|
6508
|
-
expected.updatedAt
|
|
6509
|
-
];
|
|
6510
|
-
if (expected.checkStatus)
|
|
6511
|
-
params.push(expected.checkStatus);
|
|
6512
|
-
return db.prepare(`UPDATE notes SET id = id
|
|
6513
|
-
WHERE id = ? AND type = 'smart' AND status = 'pending'
|
|
6514
|
-
AND content = ? AND surface_condition IS ? AND updated_at = ?${statusClause}`).run(...params).changes > 0;
|
|
6515
|
-
}
|
|
6516
|
-
function getDueCompiledSmartNoteChecks(db, projectPath, now, limit) {
|
|
6517
|
-
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
6518
|
-
}
|
|
6519
|
-
function getSmartNotesNeedingCompilation(db, projectPath, now, limit) {
|
|
6520
|
-
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
|
|
6521
|
-
}
|
|
6522
|
-
function getStaleCompiledSmartNotes(db, projectPath, now, limit) {
|
|
6523
|
-
const staleBefore = now - SMART_NOTE_CHECK_MAX_STALENESS_MS;
|
|
6524
|
-
const livenessBefore = now - SMART_NOTE_CHECK_LIVENESS_RECHECK_MS;
|
|
6525
|
-
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
6526
|
-
}
|
|
6527
|
-
function storeCompiledSmartNoteCheck(db, args) {
|
|
6528
|
-
db.prepare(`UPDATE notes
|
|
6529
|
-
SET compiled_check = ?,
|
|
6530
|
-
manifest_json = ?,
|
|
6531
|
-
check_hash = ?,
|
|
6532
|
-
check_cron = ?,
|
|
6533
|
-
check_version = 1,
|
|
6534
|
-
check_status = 'compiled',
|
|
6535
|
-
check_failure_count = 0,
|
|
6536
|
-
check_network_failure_count = 0,
|
|
6537
|
-
check_quarantined_until = NULL,
|
|
6538
|
-
check_next_due_at = ?,
|
|
6539
|
-
check_compiled_at = ?,
|
|
6540
|
-
check_false_since_at = COALESCE(check_false_since_at, ?),
|
|
6541
|
-
check_last_liveness_at = NULL,
|
|
6542
|
-
policy_version = ?,
|
|
6543
|
-
updated_at = ?
|
|
6544
|
-
WHERE id = ? AND type = 'smart'`).run(args.compiledCheck, JSON.stringify(args.manifest), args.checkHash, args.checkCron, args.nextDueAt, args.now, args.now, SMART_NOTE_CHECK_POLICY_VERSION, args.now, args.noteId);
|
|
6545
|
-
}
|
|
6546
|
-
function markCompiledCheckFalse(db, noteId, nextDueAt, now) {
|
|
6547
|
-
db.prepare(`UPDATE notes
|
|
6548
|
-
SET last_checked_at = ?,
|
|
6549
|
-
updated_at = ?,
|
|
6550
|
-
check_next_due_at = ?,
|
|
6551
|
-
check_failure_count = 0,
|
|
6552
|
-
check_network_failure_count = 0,
|
|
6553
|
-
check_false_since_at = COALESCE(check_false_since_at, ?)
|
|
6554
|
-
WHERE id = ? AND type = 'smart'`).run(now, now, nextDueAt, now, noteId);
|
|
6555
|
-
}
|
|
6556
|
-
function markCompiledCheckLogicFailure(db, noteId, now, maxFailures) {
|
|
6557
|
-
const failureCount = readFailureCount(db, noteId, "check_failure_count") + 1;
|
|
6558
|
-
const status = failureCount >= maxFailures ? "failing" : "compiled";
|
|
6559
|
-
db.prepare(`UPDATE notes
|
|
6560
|
-
SET check_failure_count = ?,
|
|
6561
|
-
check_status = ?,
|
|
6562
|
-
check_next_due_at = ?,
|
|
6563
|
-
updated_at = ?
|
|
6564
|
-
WHERE id = ? AND type = 'smart'`).run(failureCount, status, now + backoffMs(failureCount), now, noteId);
|
|
6565
|
-
}
|
|
6566
|
-
function markCompiledCheckNetworkFailure(db, noteId, now, maxFailures) {
|
|
6567
|
-
const failureCount = readFailureCount(db, noteId, "check_network_failure_count") + 1;
|
|
6568
|
-
const quarantinedUntil = now + backoffMs(failureCount);
|
|
6569
|
-
const status = failureCount >= maxFailures ? "failing" : "compiled";
|
|
6570
|
-
db.prepare(`UPDATE notes
|
|
6571
|
-
SET check_network_failure_count = ?,
|
|
6572
|
-
check_status = ?,
|
|
6573
|
-
check_next_due_at = ?,
|
|
6574
|
-
check_quarantined_until = ?,
|
|
6575
|
-
updated_at = ?
|
|
6576
|
-
WHERE id = ? AND type = 'smart'`).run(failureCount, status, quarantinedUntil, quarantinedUntil, now, noteId);
|
|
6577
|
-
}
|
|
6578
|
-
function markSmartNoteLivenessChecked(db, noteId, now) {
|
|
6579
|
-
db.prepare(`UPDATE notes
|
|
6580
|
-
SET check_last_liveness_at = ?, updated_at = ?
|
|
6581
|
-
WHERE id = ? AND type = 'smart'`).run(now, now, noteId);
|
|
6582
|
-
}
|
|
6583
|
-
function markSmartNoteCheckStatus(db, noteId, status, now) {
|
|
6584
|
-
db.prepare(`UPDATE notes SET check_status = ?, updated_at = ? WHERE id = ? AND type = 'smart'`).run(status, now, noteId);
|
|
6585
|
-
}
|
|
6586
|
-
function markSmartNoteCompilationFailure(db, noteId, now, maxFailures) {
|
|
6587
|
-
const failureCount = readFailureCount(db, noteId, "check_failure_count") + 1;
|
|
6588
|
-
const status = failureCount >= maxFailures ? "fallback" : "uncompiled";
|
|
6589
|
-
db.prepare(`UPDATE notes
|
|
6590
|
-
SET check_failure_count = ?,
|
|
6591
|
-
check_status = ?,
|
|
6592
|
-
check_next_due_at = ?,
|
|
6593
|
-
updated_at = ?
|
|
6594
|
-
WHERE id = ? AND type = 'smart'`).run(failureCount, status, now + backoffMs(failureCount), now, noteId);
|
|
6595
|
-
}
|
|
6596
|
-
function readFailureCount(db, noteId, column) {
|
|
6597
|
-
if (column !== "check_failure_count" && column !== "check_network_failure_count")
|
|
6598
|
-
return 0;
|
|
6599
|
-
const row = db.prepare(`SELECT ${column} AS count FROM notes WHERE id = ?`).get(noteId);
|
|
6600
|
-
return row?.count ?? 0;
|
|
6601
|
-
}
|
|
6602
|
-
function backoffMs(failureCount) {
|
|
6603
|
-
const minutes = Math.min(24 * 60, 5 * 2 ** Math.max(0, failureCount - 1));
|
|
6604
|
-
return minutes * 60 * 1000;
|
|
6605
|
-
}
|
|
6606
|
-
|
|
6607
6803
|
// ../plugin/src/features/magic-context/smart-notes/runner.ts
|
|
6608
6804
|
function inferEvaluateSmartNotesLeaseHeld(db, projectIdentity) {
|
|
6609
6805
|
const leaseKey = leaseKeyFor("evaluate-smart-notes", projectIdentity);
|
|
@@ -7337,6 +7533,7 @@ async function mapMemories(args) {
|
|
|
7337
7533
|
result.independent += counts.independent;
|
|
7338
7534
|
result.remaining -= counts.mapped + counts.independent;
|
|
7339
7535
|
result.batches += 1;
|
|
7536
|
+
args.onProgress?.(result.mapped + result.independent);
|
|
7340
7537
|
}
|
|
7341
7538
|
result.complete = result.remaining === 0;
|
|
7342
7539
|
log(`[dreamer] map-memories: mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}`);
|
|
@@ -7938,6 +8135,7 @@ async function refreshPrimers(args) {
|
|
|
7938
8135
|
result.refreshed += 1;
|
|
7939
8136
|
else
|
|
7940
8137
|
result.skipped += 1;
|
|
8138
|
+
args.onProgress?.(result.refreshed + result.skipped);
|
|
7941
8139
|
}
|
|
7942
8140
|
log(`[dreamer] refresh-primers: refreshed=${result.refreshed} skipped=${result.skipped}`);
|
|
7943
8141
|
return result;
|
|
@@ -8785,6 +8983,7 @@ async function runVerify(args) {
|
|
|
8785
8983
|
result.archived += counts.archived;
|
|
8786
8984
|
result.remaining -= counts.verified + counts.updated + counts.archived;
|
|
8787
8985
|
result.batches += 1;
|
|
8986
|
+
args.onProgress?.(result.verified + result.updated + result.archived);
|
|
8788
8987
|
}
|
|
8789
8988
|
result.complete = result.remaining === 0;
|
|
8790
8989
|
log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: verified=${result.verified} updated=${result.updated} archived=${result.archived} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}`);
|
|
@@ -9076,6 +9275,20 @@ function createDreamTaskExecutor(deps) {
|
|
|
9076
9275
|
const { db, projectIdentity, holderId, leaseKey } = ctx;
|
|
9077
9276
|
const startedAt = Date.now();
|
|
9078
9277
|
const deadline = startedAt + config.timeoutMinutes * 60 * 1000;
|
|
9278
|
+
const backlogAtStart = getDreamTaskBacklog(db, projectIdentity, config.task);
|
|
9279
|
+
const reportProgress = (processed) => {
|
|
9280
|
+
deps.onProgress?.({
|
|
9281
|
+
task: config.task,
|
|
9282
|
+
processed: Math.max(0, processed),
|
|
9283
|
+
total: backlogAtStart.pending,
|
|
9284
|
+
startedAt
|
|
9285
|
+
});
|
|
9286
|
+
};
|
|
9287
|
+
reportProgress(0);
|
|
9288
|
+
const incompleteMessage = (remaining) => {
|
|
9289
|
+
const processed = processedDreamTaskItems(backlogAtStart.pending, remaining);
|
|
9290
|
+
return `${config.task} incomplete: ${remaining} remain (was ${backlogAtStart.pending} at run start; processed ${processed} this run)`;
|
|
9291
|
+
};
|
|
9079
9292
|
const parent = await resolveParentSessionId();
|
|
9080
9293
|
let moduleRoute;
|
|
9081
9294
|
if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
|
|
@@ -9104,7 +9317,19 @@ function createDreamTaskExecutor(deps) {
|
|
|
9104
9317
|
name: config.task,
|
|
9105
9318
|
durationMs: Date.now() - startedAt,
|
|
9106
9319
|
resultChars: 0,
|
|
9107
|
-
...error ? { error } : {}
|
|
9320
|
+
...error ? { error } : {},
|
|
9321
|
+
backlog: (() => {
|
|
9322
|
+
const end = getDreamTaskBacklog(db, projectIdentity, config.task);
|
|
9323
|
+
const processed = processedDreamTaskItems(backlogAtStart.pending, end.pending);
|
|
9324
|
+
const value = {
|
|
9325
|
+
pendingAtStart: backlogAtStart.pending,
|
|
9326
|
+
totalAtStart: backlogAtStart.total,
|
|
9327
|
+
pendingAtEnd: end.pending,
|
|
9328
|
+
totalAtEnd: end.total,
|
|
9329
|
+
processed
|
|
9330
|
+
};
|
|
9331
|
+
return value;
|
|
9332
|
+
})()
|
|
9108
9333
|
}
|
|
9109
9334
|
],
|
|
9110
9335
|
tasksSucceeded: status === "completed" ? 1 : 0,
|
|
@@ -9138,8 +9363,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
9138
9363
|
}
|
|
9139
9364
|
try {
|
|
9140
9365
|
if (config.task === "compress-cues") {
|
|
9141
|
-
if (deps.
|
|
9142
|
-
log("[dreamer] compress-cues: skipped (
|
|
9366
|
+
if (deps.mural?.enabled !== true) {
|
|
9367
|
+
log("[dreamer] compress-cues: skipped (mural is not enabled)");
|
|
9143
9368
|
recordRun("completed", null);
|
|
9144
9369
|
return { status: "completed" };
|
|
9145
9370
|
}
|
|
@@ -9158,12 +9383,13 @@ function createDreamTaskExecutor(deps) {
|
|
|
9158
9383
|
holderId,
|
|
9159
9384
|
leaseKey,
|
|
9160
9385
|
deadline,
|
|
9161
|
-
model: config.model ?? deps.
|
|
9162
|
-
fallbackModels: config.fallbackModels
|
|
9386
|
+
model: config.model ?? deps.mural.model ?? deps.dreamerModel,
|
|
9387
|
+
fallbackModels: config.fallbackModels,
|
|
9388
|
+
onProgress: (processed) => reportProgress(processed)
|
|
9163
9389
|
});
|
|
9164
9390
|
log(`[dreamer] compress-cues: compressed=${result.compressed} skipped=${result.skipped} chunks=${result.chunks} remaining=${result.remaining}`);
|
|
9165
9391
|
if (!result.complete) {
|
|
9166
|
-
const error =
|
|
9392
|
+
const error = incompleteMessage(result.remaining);
|
|
9167
9393
|
recordRun("failed", error);
|
|
9168
9394
|
return { status: "failed", transient: true, error };
|
|
9169
9395
|
}
|
|
@@ -9200,11 +9426,12 @@ function createDreamTaskExecutor(deps) {
|
|
|
9200
9426
|
deadline,
|
|
9201
9427
|
model: config.model,
|
|
9202
9428
|
fallbackModels: config.fallbackModels,
|
|
9203
|
-
moduleRoute
|
|
9429
|
+
moduleRoute,
|
|
9430
|
+
onProgress: (processed) => reportProgress(processed)
|
|
9204
9431
|
});
|
|
9205
9432
|
log(`[dreamer] map-memories: mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining}`);
|
|
9206
9433
|
if (!result.complete) {
|
|
9207
|
-
const error =
|
|
9434
|
+
const error = incompleteMessage(result.remaining);
|
|
9208
9435
|
recordRun("failed", error);
|
|
9209
9436
|
return { status: "failed", transient: true, error };
|
|
9210
9437
|
}
|
|
@@ -9226,10 +9453,11 @@ function createDreamTaskExecutor(deps) {
|
|
|
9226
9453
|
model: config.model,
|
|
9227
9454
|
fallbackModels: config.fallbackModels,
|
|
9228
9455
|
language: config.language ?? deps.language,
|
|
9229
|
-
moduleRoute
|
|
9456
|
+
moduleRoute,
|
|
9457
|
+
onProgress: (processed) => reportProgress(processed)
|
|
9230
9458
|
});
|
|
9231
9459
|
if (!result.complete) {
|
|
9232
|
-
const error =
|
|
9460
|
+
const error = incompleteMessage(result.remaining);
|
|
9233
9461
|
recordRun("failed", error, {
|
|
9234
9462
|
memoryChanges: computeMemoryDelta(memoryBefore)
|
|
9235
9463
|
});
|
|
@@ -9288,11 +9516,12 @@ function createDreamTaskExecutor(deps) {
|
|
|
9288
9516
|
deadline,
|
|
9289
9517
|
model: config.model,
|
|
9290
9518
|
fallbackModels: config.fallbackModels,
|
|
9291
|
-
...moduleArgs
|
|
9519
|
+
...moduleArgs,
|
|
9520
|
+
onProgress: (processed) => reportProgress(processed)
|
|
9292
9521
|
});
|
|
9293
9522
|
log(`[dreamer] classify-memories: stage=${result.stage} classified=${result.classified} changed=${result.changed} chunks=${result.chunks} remaining=${result.remaining}`);
|
|
9294
9523
|
if (!result.complete) {
|
|
9295
|
-
const error =
|
|
9524
|
+
const error = incompleteMessage(result.remaining);
|
|
9296
9525
|
recordRun("failed", error);
|
|
9297
9526
|
return { status: "failed", transient: true, error };
|
|
9298
9527
|
}
|
|
@@ -9328,7 +9557,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
9328
9557
|
model: config.model,
|
|
9329
9558
|
fallbackModels: config.fallbackModels,
|
|
9330
9559
|
language: config.language ?? deps.language,
|
|
9331
|
-
rawProviderFactory: deps.primerRawProviderFactory
|
|
9560
|
+
rawProviderFactory: deps.primerRawProviderFactory,
|
|
9561
|
+
onProgress: (processed) => reportProgress(processed)
|
|
9332
9562
|
});
|
|
9333
9563
|
recordRun("completed", null);
|
|
9334
9564
|
log(`[dreamer] refresh-primers: refreshed=${result.refreshed} skipped=${result.skipped}`);
|
|
@@ -9382,6 +9612,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
9382
9612
|
recordRun("failed", brief);
|
|
9383
9613
|
log(`[dreamer] task ${config.task} failed (transient=${transient}): ${brief}`);
|
|
9384
9614
|
return { status: "failed", transient, error: brief };
|
|
9615
|
+
} finally {
|
|
9616
|
+
deps.onProgress?.(null, config.task);
|
|
9385
9617
|
}
|
|
9386
9618
|
};
|
|
9387
9619
|
}
|
|
@@ -9757,66 +9989,6 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9757
9989
|
}
|
|
9758
9990
|
}
|
|
9759
9991
|
|
|
9760
|
-
// ../plugin/src/features/magic-context/dreamer/task-gates.ts
|
|
9761
|
-
function countActiveMemories(db, projectPath) {
|
|
9762
|
-
const row = db.prepare("SELECT COUNT(*) AS cnt FROM memories WHERE project_path = ? AND status IN ('active','permanent')").get(projectPath);
|
|
9763
|
-
return row?.cnt ?? 0;
|
|
9764
|
-
}
|
|
9765
|
-
function countUnmappedActiveMemories(db, projectPath) {
|
|
9766
|
-
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
9767
|
-
FROM memories m
|
|
9768
|
-
WHERE m.project_path = ?
|
|
9769
|
-
AND m.status IN ('active','permanent')
|
|
9770
|
-
AND NOT EXISTS (
|
|
9771
|
-
SELECT 1 FROM memory_verifications v WHERE v.memory_id = m.id
|
|
9772
|
-
)`).get(projectPath);
|
|
9773
|
-
return row?.cnt ?? 0;
|
|
9774
|
-
}
|
|
9775
|
-
function countCompartmentsSince(db, projectPath, since) {
|
|
9776
|
-
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
9777
|
-
FROM compartments c
|
|
9778
|
-
JOIN session_projects sp ON sp.session_id = c.session_id
|
|
9779
|
-
WHERE sp.project_path = ? AND c.created_at > ?`).get(projectPath, since);
|
|
9780
|
-
return row?.cnt ?? 0;
|
|
9781
|
-
}
|
|
9782
|
-
function countProjectSessionsSince(db, projectPath, since) {
|
|
9783
|
-
const row = since === null ? db.prepare("SELECT COUNT(*) AS cnt FROM session_projects WHERE project_path = ?").get(projectPath) : db.prepare("SELECT COUNT(*) AS cnt FROM session_projects WHERE project_path = ? AND updated_at > ?").get(projectPath, since);
|
|
9784
|
-
return row?.cnt ?? 0;
|
|
9785
|
-
}
|
|
9786
|
-
function evaluateTaskGate(task, ctx) {
|
|
9787
|
-
const { db, projectIdentity: project, lastRunAt } = ctx;
|
|
9788
|
-
switch (task) {
|
|
9789
|
-
case "map-memories":
|
|
9790
|
-
return countUnmappedActiveMemories(db, project) > 0;
|
|
9791
|
-
case "verify":
|
|
9792
|
-
return countActiveMemories(db, project) > 0;
|
|
9793
|
-
case "verify-broad":
|
|
9794
|
-
return countActiveMemories(db, project) > 0;
|
|
9795
|
-
case "curate":
|
|
9796
|
-
return countActiveMemories(db, project) > 0;
|
|
9797
|
-
case "compress-cues":
|
|
9798
|
-
return countActiveMemories(db, project) > 0;
|
|
9799
|
-
case "classify-memories":
|
|
9800
|
-
return countActiveMemories(db, project) > 0;
|
|
9801
|
-
case "retrospective":
|
|
9802
|
-
return countProjectSessionsSince(db, project, ctx.retrospectiveWatermarkMs ?? null) > 0;
|
|
9803
|
-
case "maintain-docs":
|
|
9804
|
-
return countCompartmentsSince(db, project, lastRunAt ?? 0) > 0;
|
|
9805
|
-
case "evaluate-smart-notes":
|
|
9806
|
-
return getSmartNotesNeedingCompilation(db, project, Date.now(), 1).length > 0 || getStaleCompiledSmartNotes(db, project, Date.now(), 1).length > 0 || getPendingSmartNotes(db, project).some((note) => note.checkStatus === "fallback");
|
|
9807
|
-
case "review-user-memories":
|
|
9808
|
-
return getUserMemoryCandidates(db).length >= ctx.promotionThreshold;
|
|
9809
|
-
case "promote-primers":
|
|
9810
|
-
return countPrimerCandidatesForProject(db, project) >= (ctx.promotionThreshold ?? 2);
|
|
9811
|
-
case "refresh-primers":
|
|
9812
|
-
return getActivePrimers(db, project).some((primer) => !primer.answer.trim() || primer.answerRefreshedAt == null || (primer.lastObservedAt ?? 0) > primer.answerRefreshedAt);
|
|
9813
|
-
default: {
|
|
9814
|
-
const _exhaustive = task;
|
|
9815
|
-
return Boolean(_exhaustive);
|
|
9816
|
-
}
|
|
9817
|
-
}
|
|
9818
|
-
}
|
|
9819
|
-
|
|
9820
9992
|
// ../plugin/src/features/magic-context/dreamer/task-scheduler.ts
|
|
9821
9993
|
var MAX_TASK_RETRIES = 3;
|
|
9822
9994
|
function ensureSeeded(db, projectIdentity, config, now) {
|
|
@@ -9964,10 +10136,10 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
9964
10136
|
cb?.onRan?.(due.config.task);
|
|
9965
10137
|
} else if (outcome.transient) {
|
|
9966
10138
|
recordTransientFailure(db, projectIdentity, due, finishedAt, outcome.error ?? null);
|
|
9967
|
-
cb?.onFailed?.(due.config.task);
|
|
10139
|
+
cb?.onFailed?.(due.config.task, outcome.error);
|
|
9968
10140
|
} else {
|
|
9969
10141
|
advanceAfterRun(db, projectIdentity, due, finishedAt, "failed", outcome.error ?? null);
|
|
9970
|
-
cb?.onFailed?.(due.config.task);
|
|
10142
|
+
cb?.onFailed?.(due.config.task, outcome.error);
|
|
9971
10143
|
}
|
|
9972
10144
|
}
|
|
9973
10145
|
} finally {
|
|
@@ -9976,7 +10148,15 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
9976
10148
|
}
|
|
9977
10149
|
async function runManualDream(deps) {
|
|
9978
10150
|
const now = Date.now();
|
|
9979
|
-
const result = {
|
|
10151
|
+
const result = {
|
|
10152
|
+
ran: [],
|
|
10153
|
+
skippedNoWork: [],
|
|
10154
|
+
deferredBusy: [],
|
|
10155
|
+
failed: [],
|
|
10156
|
+
failureDetails: [],
|
|
10157
|
+
backlogBefore: {},
|
|
10158
|
+
backlogAfter: {}
|
|
10159
|
+
};
|
|
9980
10160
|
let selected;
|
|
9981
10161
|
let forceGate = false;
|
|
9982
10162
|
if (deps.task) {
|
|
@@ -9990,6 +10170,9 @@ async function runManualDream(deps) {
|
|
|
9990
10170
|
}
|
|
9991
10171
|
if (selected.length === 0)
|
|
9992
10172
|
return result;
|
|
10173
|
+
const selectedTaskNames = selected.map((config) => config.task);
|
|
10174
|
+
result.backlogBefore = getDreamTaskBacklogs(deps.db, deps.projectIdentity, selectedTaskNames);
|
|
10175
|
+
result.backlogAfter = { ...result.backlogBefore };
|
|
9993
10176
|
for (const cfg of selected)
|
|
9994
10177
|
ensureSeeded(deps.db, deps.projectIdentity, cfg, now);
|
|
9995
10178
|
const dueAll = selected.map((config) => ({ config, scheduledAt: now }));
|
|
@@ -10011,8 +10194,10 @@ async function runManualDream(deps) {
|
|
|
10011
10194
|
else
|
|
10012
10195
|
result.skippedNoWork.push(d.config.task);
|
|
10013
10196
|
}
|
|
10014
|
-
if (gated.length === 0)
|
|
10197
|
+
if (gated.length === 0) {
|
|
10198
|
+
result.backlogAfter = getDreamTaskBacklogs(deps.db, deps.projectIdentity, selectedTaskNames);
|
|
10015
10199
|
return result;
|
|
10200
|
+
}
|
|
10016
10201
|
const groups = new Map;
|
|
10017
10202
|
for (const d of gated) {
|
|
10018
10203
|
const kind = leaseKindFor(d.config.task);
|
|
@@ -10024,9 +10209,14 @@ async function runManualDream(deps) {
|
|
|
10024
10209
|
forceGate,
|
|
10025
10210
|
leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
|
|
10026
10211
|
onRan: (t) => result.ran.push(t),
|
|
10027
|
-
onFailed: (
|
|
10212
|
+
onFailed: (task, error) => {
|
|
10213
|
+
result.failed.push(task);
|
|
10214
|
+
if (error)
|
|
10215
|
+
result.failureDetails?.push(`${task}: ${error}`);
|
|
10216
|
+
},
|
|
10028
10217
|
onBusy: (t) => result.deferredBusy.push(t)
|
|
10029
10218
|
})));
|
|
10219
|
+
result.backlogAfter = getDreamTaskBacklogs(deps.db, deps.projectIdentity, selectedTaskNames);
|
|
10030
10220
|
return result;
|
|
10031
10221
|
}
|
|
10032
10222
|
async function runDueTasksForProject(deps) {
|
|
@@ -10341,10 +10531,11 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
10341
10531
|
ensureProjectRegistered: reg.ensureRegistered,
|
|
10342
10532
|
language: reg.language,
|
|
10343
10533
|
dreamerModel: dreamerConfig.model,
|
|
10344
|
-
|
|
10534
|
+
mural: reg.mural,
|
|
10345
10535
|
memoryInjectionBudgetTokens: reg.memoryInjectionBudgetTokens,
|
|
10346
10536
|
transformMode: reg.transformMode,
|
|
10347
|
-
moduleClient: reg.moduleClient
|
|
10537
|
+
moduleClient: reg.moduleClient,
|
|
10538
|
+
onProgress: (progress, completedTask) => reg.onDreamerProgress?.(progress, completedTask)
|
|
10348
10539
|
});
|
|
10349
10540
|
const ran = await runDueTasksForProject({
|
|
10350
10541
|
db,
|
|
@@ -11014,13 +11205,18 @@ Unknown task "${requested}".`,
|
|
|
11014
11205
|
});
|
|
11015
11206
|
return;
|
|
11016
11207
|
}
|
|
11208
|
+
const backlogTasks = task ? [task] : CANONICAL_DREAM_TASKS;
|
|
11209
|
+
const backlogBefore = getDreamTaskBacklogs(deps.db, project.projectIdentity, backlogTasks);
|
|
11017
11210
|
sendCtxStatusMessage(pi, {
|
|
11018
11211
|
title: "/ctx-dream",
|
|
11019
11212
|
text: [
|
|
11020
11213
|
"## /ctx-dream",
|
|
11021
11214
|
"",
|
|
11022
11215
|
task ? `Running dream task "${task}" for ${project.projectIdentity}…` : `Starting dream run for ${project.projectIdentity}…`,
|
|
11023
|
-
`Project directory: ${project.projectDir}
|
|
11216
|
+
`Project directory: ${project.projectDir}`,
|
|
11217
|
+
"",
|
|
11218
|
+
"Backlog before starting:",
|
|
11219
|
+
formatDreamTaskBacklogs(backlogBefore, backlogTasks)
|
|
11024
11220
|
].join(`
|
|
11025
11221
|
`),
|
|
11026
11222
|
level: "info"
|
|
@@ -11035,10 +11231,16 @@ Unknown task "${requested}".`,
|
|
|
11035
11231
|
lines.push(`Ran: ${result.ran.join(", ")}`);
|
|
11036
11232
|
if (result.failed.length > 0)
|
|
11037
11233
|
lines.push(`Failed: ${result.failed.join(", ")}`);
|
|
11234
|
+
if ((result.failureDetails?.length ?? 0) > 0) {
|
|
11235
|
+
lines.push("Failure details:", ...(result.failureDetails ?? []).map((detail) => `- ${detail}`));
|
|
11236
|
+
}
|
|
11038
11237
|
if (result.skippedNoWork.length > 0)
|
|
11039
11238
|
lines.push(`Skipped (no work): ${result.skippedNoWork.join(", ")}`);
|
|
11040
11239
|
if (result.deferredBusy.length > 0)
|
|
11041
11240
|
lines.push(`Busy: ${result.deferredBusy.join(", ")} — another dream task holds this domain's lease; retry in a minute`);
|
|
11241
|
+
if (Object.keys(result.backlogAfter ?? {}).length > 0) {
|
|
11242
|
+
lines.push("", "Backlog at run end:", formatDreamTaskBacklogs(result.backlogAfter));
|
|
11243
|
+
}
|
|
11042
11244
|
if (lines.length === 0)
|
|
11043
11245
|
lines.push("No enabled dream tasks to run.");
|
|
11044
11246
|
sendCtxStatusMessage(pi, {
|
|
@@ -27175,7 +27377,7 @@ function formatExecuteThreshold(detail, contextLimit) {
|
|
|
27175
27377
|
}
|
|
27176
27378
|
return `${percentage}%${clampNote}`;
|
|
27177
27379
|
}
|
|
27178
|
-
function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit) {
|
|
27380
|
+
function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit, dreamer) {
|
|
27179
27381
|
const thresholdDetail = resolveExecuteThresholdDetail(executeThresholdPercentageConfig, liveModelKey, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, {
|
|
27180
27382
|
tokensConfig: executeThresholdTokens,
|
|
27181
27383
|
contextLimit,
|
|
@@ -27230,6 +27432,11 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
|
|
|
27230
27432
|
`**Protected tags:** ${protectedTags}`,
|
|
27231
27433
|
`**Subagent session:** ${meta.isSubagent}`
|
|
27232
27434
|
];
|
|
27435
|
+
if (dreamer?.backlog && Object.keys(dreamer.backlog).length > 0) {
|
|
27436
|
+
lines.push("", "### Dreamer", ...dreamer.progress ? [
|
|
27437
|
+
`- Running: ${dreamer.progress.task} — ${dreamer.progress.processed}/${dreamer.progress.total} processed`
|
|
27438
|
+
] : [], ...formatDreamTaskBacklogs(dreamer.backlog).split("\\n"));
|
|
27439
|
+
}
|
|
27233
27440
|
if (meta.lastContextPercentage > 0 || meta.lastInputTokens > 0) {
|
|
27234
27441
|
lines.push("", "### Context Usage", `- Last percentage: ${meta.lastContextPercentage.toFixed(1)}%`, `- Last input tokens: ${meta.lastInputTokens.toLocaleString()}`, `- Resolved context limit: ${displayContextLimit > 0 ? displayContextLimit.toLocaleString() : "unknown"}`, `- Proactive compartment evaluation: ${proactiveCompartmentTrigger}%`, `- Post-drop target for historian: ${(executeThresholdPercentage * POST_DROP_TARGET_RATIO).toFixed(0)}% (${executeThresholdPercentage}% * ${POST_DROP_TARGET_RATIO})`, `- Commit cluster trigger: ${commitClusterTrigger?.enabled !== false ? `enabled (min ${commitClusterTrigger?.min_clusters ?? 3} clusters)` : "disabled"}, tail-size trigger: > 3x compartment budget`);
|
|
27235
27442
|
}
|
|
@@ -27252,6 +27459,12 @@ ${c.content}
|
|
|
27252
27459
|
lines.push(`- §${op.tagId}§ → ${op.operation}`);
|
|
27253
27460
|
}
|
|
27254
27461
|
}
|
|
27462
|
+
if (dreamer?.backlog && Object.keys(dreamer.backlog).length > 0) {
|
|
27463
|
+
lines.push("", "### Dreamer Backlog", formatDreamTaskBacklogs(dreamer.backlog));
|
|
27464
|
+
}
|
|
27465
|
+
if (dreamer?.progress) {
|
|
27466
|
+
lines.push("", "### Dreamer Progress", `- ${dreamer.progress.task}: ${dreamer.progress.processed}/${dreamer.progress.total} processed this run`);
|
|
27467
|
+
}
|
|
27255
27468
|
return lines.join(`
|
|
27256
27469
|
`);
|
|
27257
27470
|
} catch (error) {
|
|
@@ -27326,7 +27539,7 @@ ${c.content}
|
|
|
27326
27539
|
// package.json
|
|
27327
27540
|
var package_default = {
|
|
27328
27541
|
name: "@cortexkit/pi-magic-context",
|
|
27329
|
-
version: "0.34.
|
|
27542
|
+
version: "0.34.1",
|
|
27330
27543
|
type: "module",
|
|
27331
27544
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
27332
27545
|
main: "dist/index.js",
|
|
@@ -27834,7 +28047,9 @@ No active Pi session is available.`,
|
|
|
27834
28047
|
model: ctx.model,
|
|
27835
28048
|
detectedContextLimit
|
|
27836
28049
|
});
|
|
27837
|
-
const statusText = executeStatus(currentDeps.db, sessionId, currentDeps.protectedTags ?? 20, currentDeps.executeThresholdPercentage, modelKey, currentDeps.historyBudgetPercentage, currentDeps.commitClusterTrigger, currentDeps.executeThresholdTokens, usableContextLimit
|
|
28050
|
+
const statusText = executeStatus(currentDeps.db, sessionId, currentDeps.protectedTags ?? 20, currentDeps.executeThresholdPercentage, modelKey, currentDeps.historyBudgetPercentage, currentDeps.commitClusterTrigger, currentDeps.executeThresholdTokens, usableContextLimit, {
|
|
28051
|
+
backlog: getDreamTaskBacklogs(currentDeps.db, currentDeps.projectIdentity, CANONICAL_DREAM_TASKS)
|
|
28052
|
+
});
|
|
27838
28053
|
const details = buildStatusDetails(currentDeps, sessionId);
|
|
27839
28054
|
sendCtxStatusMessage(pi, { title: "/ctx-status", text: statusText, level: "info" }, details);
|
|
27840
28055
|
} catch (error) {
|
|
@@ -27876,6 +28091,7 @@ function buildStatusDetails(deps, sessionId) {
|
|
|
27876
28091
|
dreamer: {
|
|
27877
28092
|
enabled: deps.dreamer?.runnable === true,
|
|
27878
28093
|
scheduleSummary: deps.dreamer?.scheduleSummary ?? null,
|
|
28094
|
+
backlog: getDreamTaskBacklogs(deps.db, deps.projectIdentity, CANONICAL_DREAM_TASKS),
|
|
27879
28095
|
lastRunAt: getMostRecentTaskRunAt(deps.db, deps.projectIdentity)
|
|
27880
28096
|
},
|
|
27881
28097
|
historian: readHistorianState(deps.db, sessionId, meta)
|
|
@@ -28838,7 +29054,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28838
29054
|
injectDocs: cfg.dreamer?.inject_docs !== false,
|
|
28839
29055
|
injectionBudgetTokens: cfg.memory.injection_budget_tokens,
|
|
28840
29056
|
temporalAwareness: cfg.temporal_awareness === true,
|
|
28841
|
-
muralEnabled: cfg.
|
|
29057
|
+
muralEnabled: cfg.mural.enabled === true
|
|
28842
29058
|
},
|
|
28843
29059
|
scheduler: {
|
|
28844
29060
|
executeThresholdPercentage: cfg.execute_threshold_percentage,
|