cipher-security 5.0.0

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.
Files changed (75) hide show
  1. package/bin/cipher.js +465 -0
  2. package/lib/api/billing.js +321 -0
  3. package/lib/api/compliance.js +693 -0
  4. package/lib/api/controls.js +1401 -0
  5. package/lib/api/index.js +49 -0
  6. package/lib/api/marketplace.js +467 -0
  7. package/lib/api/openai-proxy.js +383 -0
  8. package/lib/api/server.js +685 -0
  9. package/lib/autonomous/feedback-loop.js +554 -0
  10. package/lib/autonomous/framework.js +512 -0
  11. package/lib/autonomous/index.js +97 -0
  12. package/lib/autonomous/leaderboard.js +594 -0
  13. package/lib/autonomous/modes/architect.js +412 -0
  14. package/lib/autonomous/modes/blue.js +386 -0
  15. package/lib/autonomous/modes/incident.js +684 -0
  16. package/lib/autonomous/modes/privacy.js +369 -0
  17. package/lib/autonomous/modes/purple.js +294 -0
  18. package/lib/autonomous/modes/recon.js +250 -0
  19. package/lib/autonomous/parallel.js +587 -0
  20. package/lib/autonomous/researcher.js +583 -0
  21. package/lib/autonomous/runner.js +955 -0
  22. package/lib/autonomous/scheduler.js +615 -0
  23. package/lib/autonomous/task-parser.js +127 -0
  24. package/lib/autonomous/validators/forensic.js +266 -0
  25. package/lib/autonomous/validators/osint.js +216 -0
  26. package/lib/autonomous/validators/privacy.js +296 -0
  27. package/lib/autonomous/validators/purple.js +298 -0
  28. package/lib/autonomous/validators/sigma.js +248 -0
  29. package/lib/autonomous/validators/threat-model.js +363 -0
  30. package/lib/benchmark/agent.js +119 -0
  31. package/lib/benchmark/baselines.js +43 -0
  32. package/lib/benchmark/builder.js +143 -0
  33. package/lib/benchmark/config.js +35 -0
  34. package/lib/benchmark/coordinator.js +91 -0
  35. package/lib/benchmark/index.js +20 -0
  36. package/lib/benchmark/llm.js +58 -0
  37. package/lib/benchmark/models.js +137 -0
  38. package/lib/benchmark/reporter.js +103 -0
  39. package/lib/benchmark/runner.js +103 -0
  40. package/lib/benchmark/sandbox.js +96 -0
  41. package/lib/benchmark/scorer.js +32 -0
  42. package/lib/benchmark/solver.js +166 -0
  43. package/lib/benchmark/tools.js +62 -0
  44. package/lib/bot/bot.js +130 -0
  45. package/lib/commands.js +99 -0
  46. package/lib/complexity.js +377 -0
  47. package/lib/config.js +213 -0
  48. package/lib/gateway/client.js +309 -0
  49. package/lib/gateway/commands.js +830 -0
  50. package/lib/gateway/config-validate.js +109 -0
  51. package/lib/gateway/gateway.js +367 -0
  52. package/lib/gateway/index.js +62 -0
  53. package/lib/gateway/mode.js +309 -0
  54. package/lib/gateway/plugins.js +222 -0
  55. package/lib/gateway/prompt.js +214 -0
  56. package/lib/mcp/server.js +262 -0
  57. package/lib/memory/compressor.js +425 -0
  58. package/lib/memory/engine.js +763 -0
  59. package/lib/memory/evolution.js +668 -0
  60. package/lib/memory/index.js +58 -0
  61. package/lib/memory/orchestrator.js +506 -0
  62. package/lib/memory/retriever.js +515 -0
  63. package/lib/memory/synthesizer.js +333 -0
  64. package/lib/pipeline/async-scanner.js +510 -0
  65. package/lib/pipeline/binary-analysis.js +1043 -0
  66. package/lib/pipeline/dom-xss-scanner.js +435 -0
  67. package/lib/pipeline/github-actions.js +792 -0
  68. package/lib/pipeline/index.js +124 -0
  69. package/lib/pipeline/osint.js +498 -0
  70. package/lib/pipeline/sarif.js +373 -0
  71. package/lib/pipeline/scanner.js +880 -0
  72. package/lib/pipeline/template-manager.js +525 -0
  73. package/lib/pipeline/xss-scanner.js +353 -0
  74. package/lib/setup-wizard.js +229 -0
  75. package/package.json +30 -0
@@ -0,0 +1,615 @@
1
+ // Copyright (c) 2026 defconxt. All rights reserved.
2
+ // Licensed under AGPL-3.0 — see LICENSE file for details.
3
+ // CIPHER is a trademark of defconxt.
4
+
5
+ /**
6
+ * CIPHER Autonomous Scheduler — Idle-aware background task execution.
7
+ *
8
+ * Detects system idle state via platform-specific APIs, then runs prioritized
9
+ * background tasks during idle windows.
10
+ *
11
+ * State machine:
12
+ * IDLE_WAIT → WINDOW_OPEN → RUNNING → PAUSING → IDLE_WAIT
13
+ *
14
+ * @module autonomous/scheduler
15
+ */
16
+
17
+ import { execSync } from 'node:child_process';
18
+ import { randomUUID } from 'node:crypto';
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Task Priority
22
+ // ---------------------------------------------------------------------------
23
+
24
+ /** @type {Readonly<{CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3, BACKGROUND: 4}>} */
25
+ export const TaskPriority = Object.freeze({
26
+ CRITICAL: 0,
27
+ HIGH: 1,
28
+ MEDIUM: 2,
29
+ LOW: 3,
30
+ BACKGROUND: 4,
31
+ });
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Scheduler State
35
+ // ---------------------------------------------------------------------------
36
+
37
+ /** @type {Readonly<{IDLE_WAIT: 'idle_wait', WINDOW_OPEN: 'window_open', RUNNING: 'running', PAUSING: 'pausing'}>} */
38
+ export const SchedulerState = Object.freeze({
39
+ IDLE_WAIT: 'idle_wait',
40
+ WINDOW_OPEN: 'window_open',
41
+ RUNNING: 'running',
42
+ PAUSING: 'pausing',
43
+ });
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // ScheduledTask
47
+ // ---------------------------------------------------------------------------
48
+
49
+ export class ScheduledTask {
50
+ /**
51
+ * @param {object} opts
52
+ * @param {string} opts.name
53
+ * @param {string} opts.taskType
54
+ * @param {number} opts.priority - TaskPriority value
55
+ * @param {Function} opts.callableFn
56
+ * @param {Array} [opts.args]
57
+ * @param {object} [opts.kwargs]
58
+ * @param {string} [opts.taskId]
59
+ * @param {number} [opts.intervalSeconds]
60
+ * @param {number} [opts.lastRun]
61
+ * @param {number} [opts.nextRun]
62
+ * @param {number} [opts.runCount]
63
+ * @param {number} [opts.maxRuns]
64
+ * @param {boolean} [opts.enabled]
65
+ * @param {boolean} [opts.requiresIdle]
66
+ * @param {string} [opts.createdAt]
67
+ */
68
+ constructor({
69
+ name,
70
+ taskType,
71
+ priority,
72
+ callableFn,
73
+ args = [],
74
+ kwargs = {},
75
+ taskId = randomUUID().replace(/-/g, ''),
76
+ intervalSeconds = 0,
77
+ lastRun = 0,
78
+ nextRun = 0,
79
+ runCount = 0,
80
+ maxRuns = 0,
81
+ enabled = true,
82
+ requiresIdle = true,
83
+ createdAt = new Date().toISOString(),
84
+ }) {
85
+ this.name = name;
86
+ this.taskType = taskType;
87
+ this.priority = priority;
88
+ this.callableFn = callableFn;
89
+ this.args = args;
90
+ this.kwargs = kwargs;
91
+ this.taskId = taskId;
92
+ this.intervalSeconds = intervalSeconds;
93
+ this.lastRun = lastRun;
94
+ this.nextRun = nextRun;
95
+ this.runCount = runCount;
96
+ this.maxRuns = maxRuns;
97
+ this.enabled = enabled;
98
+ this.requiresIdle = requiresIdle;
99
+ this.createdAt = createdAt;
100
+ }
101
+
102
+ /**
103
+ * Return true if the task should run at the given epoch time.
104
+ * @param {number} [now]
105
+ * @returns {boolean}
106
+ */
107
+ isDue(now) {
108
+ if (!this.enabled) return false;
109
+ if (this.maxRuns > 0 && this.runCount >= this.maxRuns) return false;
110
+ now = now ?? Date.now() / 1000;
111
+ return now >= this.nextRun;
112
+ }
113
+
114
+ /**
115
+ * Mark the task as having just executed.
116
+ * @param {number} [now]
117
+ */
118
+ recordRun(now) {
119
+ now = now ?? Date.now() / 1000;
120
+ this.lastRun = now;
121
+ this.runCount += 1;
122
+ if (this.intervalSeconds > 0) {
123
+ this.nextRun = now + this.intervalSeconds;
124
+ } else {
125
+ // One-shot — disable after run
126
+ this.enabled = false;
127
+ }
128
+ }
129
+ }
130
+
131
+ // ---------------------------------------------------------------------------
132
+ // TaskResult
133
+ // ---------------------------------------------------------------------------
134
+
135
+ export class TaskResult {
136
+ /**
137
+ * @param {object} opts
138
+ * @param {string} opts.taskId
139
+ * @param {string} opts.taskName
140
+ * @param {number} opts.startedAt
141
+ * @param {number} opts.finishedAt
142
+ * @param {boolean} opts.success
143
+ * @param {string|null} [opts.error]
144
+ * @param {*} [opts.result]
145
+ */
146
+ constructor({ taskId, taskName, startedAt, finishedAt, success, error = null, result = null }) {
147
+ this.taskId = taskId;
148
+ this.taskName = taskName;
149
+ this.startedAt = startedAt;
150
+ this.finishedAt = finishedAt;
151
+ this.success = success;
152
+ this.error = error;
153
+ this.result = result;
154
+ }
155
+
156
+ get durationMs() {
157
+ return (this.finishedAt - this.startedAt) * 1000;
158
+ }
159
+ }
160
+
161
+ // ---------------------------------------------------------------------------
162
+ // LastRequestTracker
163
+ // ---------------------------------------------------------------------------
164
+
165
+ export class LastRequestTracker {
166
+ constructor() {
167
+ this._lastTouch = Date.now() / 1000;
168
+ }
169
+
170
+ /** Record an interaction right now. */
171
+ touch() {
172
+ this._lastTouch = Date.now() / 1000;
173
+ }
174
+
175
+ /** Seconds elapsed since the last recorded interaction. */
176
+ secondsSinceLast() {
177
+ return Date.now() / 1000 - this._lastTouch;
178
+ }
179
+ }
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // IdleDetector
183
+ // ---------------------------------------------------------------------------
184
+
185
+ export class IdleDetector {
186
+ /**
187
+ * @param {LastRequestTracker} [fallbackTracker]
188
+ */
189
+ constructor(fallbackTracker) {
190
+ this._platform = process.platform; // 'darwin', 'linux', 'win32'
191
+ this._tracker = fallbackTracker || new LastRequestTracker();
192
+ this._method = this._detectMethod();
193
+ }
194
+
195
+ /** Return estimated seconds the system has been idle. */
196
+ idleSeconds() {
197
+ if (this._method === 'ioreg') return this._idleMacos();
198
+ if (this._method === 'xprintidle') return this._idleLinux();
199
+ return this._idleFallback();
200
+ }
201
+
202
+ /**
203
+ * Return true if the system has been idle for at least thresholdMinutes.
204
+ * @param {number} [thresholdMinutes=15]
205
+ */
206
+ isIdle(thresholdMinutes = 15) {
207
+ return this.idleSeconds() >= thresholdMinutes * 60;
208
+ }
209
+
210
+ /** Expose the underlying request tracker. */
211
+ get tracker() {
212
+ return this._tracker;
213
+ }
214
+
215
+ /** @returns {string} */
216
+ _detectMethod() {
217
+ if (this._platform === 'darwin') {
218
+ try {
219
+ execSync('ioreg -c IOHIDSystem', { timeout: 2000, stdio: 'pipe' });
220
+ return 'ioreg';
221
+ } catch { /* fall through */ }
222
+ } else if (this._platform === 'linux') {
223
+ try {
224
+ execSync('xprintidle', { timeout: 2000, stdio: 'pipe' });
225
+ return 'xprintidle';
226
+ } catch { /* fall through */ }
227
+ }
228
+ return 'fallback';
229
+ }
230
+
231
+ /** macOS: read HIDIdleTime from IOKit registry (nanoseconds). */
232
+ _idleMacos() {
233
+ try {
234
+ const result = execSync('ioreg -c IOHIDSystem -d 4', {
235
+ timeout: 5000,
236
+ encoding: 'utf-8',
237
+ stdio: ['pipe', 'pipe', 'pipe'],
238
+ });
239
+ for (const line of result.split('\n')) {
240
+ if (line.includes('HIDIdleTime')) {
241
+ const parts = line.split('=');
242
+ if (parts.length === 2) {
243
+ const ns = parseInt(parts[1].trim(), 10);
244
+ if (!isNaN(ns)) return Math.floor(ns / 1_000_000_000);
245
+ }
246
+ }
247
+ }
248
+ } catch { /* fall through */ }
249
+ return this._idleFallback();
250
+ }
251
+
252
+ /** Linux: use xprintidle (milliseconds). */
253
+ _idleLinux() {
254
+ try {
255
+ const result = execSync('xprintidle', {
256
+ timeout: 5000,
257
+ encoding: 'utf-8',
258
+ stdio: ['pipe', 'pipe', 'pipe'],
259
+ });
260
+ const ms = parseInt(result.trim(), 10);
261
+ if (!isNaN(ms)) return Math.floor(ms / 1000);
262
+ } catch { /* fall through */ }
263
+ return this._idleFallback();
264
+ }
265
+
266
+ /** Fallback: use LastRequestTracker as idle proxy. */
267
+ _idleFallback() {
268
+ return Math.floor(this._tracker.secondsSinceLast());
269
+ }
270
+ }
271
+
272
+ // ---------------------------------------------------------------------------
273
+ // CipherScheduler
274
+ // ---------------------------------------------------------------------------
275
+
276
+ export class CipherScheduler {
277
+ static TICK_INTERVAL = 30.0; // seconds
278
+
279
+ /**
280
+ * @param {object} [opts]
281
+ * @param {number} [opts.idleThresholdMinutes=15]
282
+ * @param {string} [opts.sleepStart='23:00']
283
+ * @param {string} [opts.sleepEnd='07:00']
284
+ */
285
+ constructor({
286
+ idleThresholdMinutes = 15,
287
+ sleepStart = '23:00',
288
+ sleepEnd = '07:00',
289
+ } = {}) {
290
+ this._idleThreshold = idleThresholdMinutes;
291
+ this._sleepStart = CipherScheduler._parseTime(sleepStart);
292
+ this._sleepEnd = CipherScheduler._parseTime(sleepEnd);
293
+ this._idleDetector = new IdleDetector();
294
+ this._state = SchedulerState.IDLE_WAIT;
295
+ /** @type {Map<string, ScheduledTask>} */
296
+ this._tasks = new Map();
297
+ /** @type {TaskResult[]} */
298
+ this._history = [];
299
+ this._maxHistory = 200;
300
+ this._running = false;
301
+ this._stopRequested = false;
302
+ this._tickTimer = null;
303
+ }
304
+
305
+ // -- task management ---------------------------------------------------
306
+
307
+ /** @param {ScheduledTask} task */
308
+ addTask(task) {
309
+ this._tasks.set(task.taskId, task);
310
+ }
311
+
312
+ /**
313
+ * Remove a task by ID. Returns true if found and removed.
314
+ * @param {string} taskId
315
+ * @returns {boolean}
316
+ */
317
+ removeTask(taskId) {
318
+ return this._tasks.delete(taskId);
319
+ }
320
+
321
+ /**
322
+ * Retrieve a task by ID.
323
+ * @param {string} taskId
324
+ * @returns {ScheduledTask|undefined}
325
+ */
326
+ getTask(taskId) {
327
+ return this._tasks.get(taskId);
328
+ }
329
+
330
+ // -- idle window detection ---------------------------------------------
331
+
332
+ /**
333
+ * @param {string} t - 'HH:MM'
334
+ * @returns {[number, number]}
335
+ */
336
+ static _parseTime(t) {
337
+ const parts = t.trim().split(':');
338
+ return [parseInt(parts[0], 10), parseInt(parts[1], 10)];
339
+ }
340
+
341
+ /** Return true if current local time is within the sleep window. */
342
+ _inSleepWindow() {
343
+ const now = new Date();
344
+ const currentMinutes = now.getHours() * 60 + now.getMinutes();
345
+ const startMinutes = this._sleepStart[0] * 60 + this._sleepStart[1];
346
+ const endMinutes = this._sleepEnd[0] * 60 + this._sleepEnd[1];
347
+
348
+ if (startMinutes <= endMinutes) {
349
+ return currentMinutes >= startMinutes && currentMinutes < endMinutes;
350
+ }
351
+ // Overnight window
352
+ return currentMinutes >= startMinutes || currentMinutes < endMinutes;
353
+ }
354
+
355
+ /** Return true if conditions are right for background work. */
356
+ _isIdleWindow() {
357
+ if (this._inSleepWindow()) return true;
358
+ if (this._idleDetector.isIdle(this._idleThreshold)) {
359
+ const trackerIdle = this._idleDetector.tracker.secondsSinceLast();
360
+ return trackerIdle >= this._idleThreshold * 60;
361
+ }
362
+ return false;
363
+ }
364
+
365
+ // -- state machine -----------------------------------------------------
366
+
367
+ /** Single iteration of the scheduler state machine. */
368
+ _tick() {
369
+ const idleNow = this._isIdleWindow();
370
+
371
+ if (this._state === SchedulerState.IDLE_WAIT) {
372
+ if (idleNow) {
373
+ this._state = SchedulerState.WINDOW_OPEN;
374
+ }
375
+ } else if (this._state === SchedulerState.WINDOW_OPEN) {
376
+ this._state = SchedulerState.RUNNING;
377
+ this._executeDueTasks();
378
+ if (!idleNow) {
379
+ this._state = SchedulerState.PAUSING;
380
+ } else if (!this._hasDueTasks()) {
381
+ this._state = SchedulerState.IDLE_WAIT;
382
+ }
383
+ } else if (this._state === SchedulerState.RUNNING) {
384
+ if (!idleNow) {
385
+ this._state = SchedulerState.PAUSING;
386
+ } else if (this._hasDueTasks()) {
387
+ this._executeDueTasks();
388
+ } else {
389
+ this._state = SchedulerState.IDLE_WAIT;
390
+ }
391
+ } else if (this._state === SchedulerState.PAUSING) {
392
+ this._state = SchedulerState.IDLE_WAIT;
393
+ }
394
+ }
395
+
396
+ // -- task execution ----------------------------------------------------
397
+
398
+ _hasDueTasks() {
399
+ const now = Date.now() / 1000;
400
+ for (const t of this._tasks.values()) {
401
+ if (t.isDue(now)) return true;
402
+ }
403
+ return false;
404
+ }
405
+
406
+ /** @returns {ScheduledTask[]} */
407
+ _getDueTasksSorted() {
408
+ const now = Date.now() / 1000;
409
+ const due = [];
410
+ for (const t of this._tasks.values()) {
411
+ if (t.isDue(now)) due.push(t);
412
+ }
413
+ due.sort((a, b) => a.priority - b.priority || a.nextRun - b.nextRun);
414
+ return due;
415
+ }
416
+
417
+ _executeDueTasks() {
418
+ const dueTasks = this._getDueTasksSorted();
419
+ for (const task of dueTasks) {
420
+ if (this._stopRequested) break;
421
+ if (task.requiresIdle && !this._isIdleWindow()) break;
422
+ this._runSingleTask(task);
423
+ }
424
+ }
425
+
426
+ /**
427
+ * @param {ScheduledTask} task
428
+ * @returns {TaskResult}
429
+ */
430
+ _runSingleTask(task) {
431
+ const started = Date.now() / 1000;
432
+ let result;
433
+
434
+ try {
435
+ const resultValue = task.callableFn(...task.args);
436
+ const finished = Date.now() / 1000;
437
+ task.recordRun(finished);
438
+ result = new TaskResult({
439
+ taskId: task.taskId,
440
+ taskName: task.name,
441
+ startedAt: started,
442
+ finishedAt: finished,
443
+ success: true,
444
+ result: resultValue,
445
+ });
446
+ } catch (exc) {
447
+ const finished = Date.now() / 1000;
448
+ task.recordRun(finished);
449
+ result = new TaskResult({
450
+ taskId: task.taskId,
451
+ taskName: task.name,
452
+ startedAt: started,
453
+ finishedAt: finished,
454
+ success: false,
455
+ error: `${exc.constructor.name}: ${exc.message}`,
456
+ });
457
+ }
458
+
459
+ this._recordHistory(result);
460
+ return result;
461
+ }
462
+
463
+ /** @param {TaskResult} result */
464
+ _recordHistory(result) {
465
+ this._history.push(result);
466
+ if (this._history.length > this._maxHistory) {
467
+ this._history = this._history.slice(-this._maxHistory);
468
+ }
469
+ }
470
+
471
+ // -- main loop ---------------------------------------------------------
472
+
473
+ /** Start the scheduler tick loop using setInterval. */
474
+ start() {
475
+ if (this._running) return;
476
+ this._running = true;
477
+ this._stopRequested = false;
478
+ this._tickTimer = setInterval(() => this._tick(), CipherScheduler.TICK_INTERVAL * 1000);
479
+ // Unref so it doesn't keep the process alive
480
+ if (this._tickTimer.unref) this._tickTimer.unref();
481
+ }
482
+
483
+ /** Stop the scheduler. */
484
+ stop() {
485
+ this._stopRequested = true;
486
+ if (this._tickTimer) {
487
+ clearInterval(this._tickTimer);
488
+ this._tickTimer = null;
489
+ }
490
+ this._running = false;
491
+ }
492
+
493
+ // -- status & introspection --------------------------------------------
494
+
495
+ getStatus() {
496
+ const now = Date.now() / 1000;
497
+ const taskSummaries = [];
498
+ for (const t of this._tasks.values()) {
499
+ taskSummaries.push({
500
+ taskId: t.taskId,
501
+ name: t.name,
502
+ type: t.taskType,
503
+ priority: t.priority,
504
+ enabled: t.enabled,
505
+ runCount: t.runCount,
506
+ isDue: t.isDue(now),
507
+ nextRunIn: t.nextRun > 0 ? Math.max(0, t.nextRun - now) : 0,
508
+ requiresIdle: t.requiresIdle,
509
+ });
510
+ }
511
+ return {
512
+ state: this._state,
513
+ running: this._running,
514
+ idleThresholdMinutes: this._idleThreshold,
515
+ sleepWindow: `${String(this._sleepStart[0]).padStart(2, '0')}:${String(this._sleepStart[1]).padStart(2, '0')}→${String(this._sleepEnd[0]).padStart(2, '0')}:${String(this._sleepEnd[1]).padStart(2, '0')}`,
516
+ isIdleWindow: this._isIdleWindow(),
517
+ systemIdleSeconds: this._idleDetector.idleSeconds(),
518
+ tasksTotal: taskSummaries.length,
519
+ tasksDue: taskSummaries.filter(t => t.isDue).length,
520
+ tasks: taskSummaries,
521
+ historySize: this._history.length,
522
+ };
523
+ }
524
+
525
+ /**
526
+ * Return recent task execution results.
527
+ * @param {number} [limit=50]
528
+ */
529
+ getTaskHistory(limit = 50) {
530
+ const recent = this._history.slice(-limit);
531
+ return recent.map(r => ({
532
+ taskId: r.taskId,
533
+ taskName: r.taskName,
534
+ startedAt: new Date(r.startedAt * 1000).toISOString(),
535
+ durationMs: Math.round(r.durationMs * 100) / 100,
536
+ success: r.success,
537
+ error: r.error,
538
+ }));
539
+ }
540
+
541
+ get idleDetector() {
542
+ return this._idleDetector;
543
+ }
544
+
545
+ get state() {
546
+ return this._state;
547
+ }
548
+
549
+ // Expose for testing — force state transition
550
+ set state(val) {
551
+ this._state = val;
552
+ }
553
+ }
554
+
555
+ // ---------------------------------------------------------------------------
556
+ // Default Tasks Factory
557
+ // ---------------------------------------------------------------------------
558
+
559
+ function _noopMemoryConsolidation() {
560
+ return 'memory_consolidation: complete';
561
+ }
562
+
563
+ function _noopSkillMetricUpdate() {
564
+ return 'skill_metric_update: complete';
565
+ }
566
+
567
+ function _noopMemoryDecay() {
568
+ return 'memory_decay: complete';
569
+ }
570
+
571
+ function _noopStaleEngagementCleanup() {
572
+ return 'stale_engagement_cleanup: complete';
573
+ }
574
+
575
+ /**
576
+ * Create the standard set of background self-improvement tasks.
577
+ * @returns {ScheduledTask[]}
578
+ */
579
+ export function createDefaultTasks() {
580
+ const now = Date.now() / 1000;
581
+ return [
582
+ new ScheduledTask({
583
+ name: 'memory_consolidation',
584
+ taskType: 'memory_consolidation',
585
+ priority: TaskPriority.MEDIUM,
586
+ callableFn: _noopMemoryConsolidation,
587
+ intervalSeconds: 3600,
588
+ nextRun: now + 3600,
589
+ }),
590
+ new ScheduledTask({
591
+ name: 'skill_metric_update',
592
+ taskType: 'metric_update',
593
+ priority: TaskPriority.LOW,
594
+ callableFn: _noopSkillMetricUpdate,
595
+ intervalSeconds: 1800,
596
+ nextRun: now + 1800,
597
+ }),
598
+ new ScheduledTask({
599
+ name: 'memory_decay',
600
+ taskType: 'memory_consolidation',
601
+ priority: TaskPriority.BACKGROUND,
602
+ callableFn: _noopMemoryDecay,
603
+ intervalSeconds: 21600,
604
+ nextRun: now + 21600,
605
+ }),
606
+ new ScheduledTask({
607
+ name: 'stale_engagement_cleanup',
608
+ taskType: 'memory_consolidation',
609
+ priority: TaskPriority.BACKGROUND,
610
+ callableFn: _noopStaleEngagementCleanup,
611
+ intervalSeconds: 86400,
612
+ nextRun: now + 86400,
613
+ }),
614
+ ];
615
+ }