Sync adabot changes on top of origin/main

Includes:
- memory-neo4j: four-phase sleep cycle (dedup, decay, extraction, cleanup)
- memory-neo4j: full plugin implementation with hybrid search
- memory-lancedb: updates and benchmarks
- OpenSpec workflow skills and commands
- Session memory hooks
- Various CLI and config improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Tarun Sukhani
2026-02-04 15:14:46 +00:00
parent 7cfd0aed5f
commit e65d1deedd
59 changed files with 7326 additions and 310 deletions

View File

@@ -368,6 +368,9 @@ export function normalizeCronJobInput(
stripLegacyTopLevelFields(next);
if (options.applyDefaults) {
if (typeof next.enabled !== "boolean") {
next.enabled = true;
}
if (!next.wakeMode) {
next.wakeMode = "now";
}

View File

@@ -202,11 +202,21 @@ export async function run(state: CronServiceState, id: string, mode?: "due" | "f
return { ok: true, ran: false, reason: "already-running" as const };
}
const now = state.deps.nowMs();
const due = isJobDue(job, now, { forced: mode === "force" });
const forced = mode === "force";
const due = isJobDue(job, now, { forced });
if (!due) {
return { ok: true, ran: false, reason: "not-due" as const };
}
await executeJob(state, job, now, { forced: mode === "force" });
if (forced) {
// Fire-and-forget: don't block the caller waiting for job completion
void executeJob(state, job, now, { forced }).then(() => {
recomputeNextRuns(state);
persist(state).catch(() => {});
armTimer(state);
});
return { ok: true, ran: true } as const;
}
await executeJob(state, job, now, { forced });
recomputeNextRuns(state);
await persist(state);
armTimer(state);