principles-disciple 1.183.0 → 1.185.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.
- package/dist/service/evolution-dedup.d.ts +1 -1
- package/dist/service/evolution-worker.d.ts +7 -31
- package/dist/service/evolution-worker.js +17 -36
- package/dist/service/queue-io.js +14 -2
- package/dist/service/queue-migration.d.ts +27 -26
- package/dist/service/queue-migration.js +57 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/service/evolution-queue-migration.d.ts +0 -128
- package/dist/service/evolution-queue-migration.js +0 -53
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Dedup logic for preventing duplicate pain tasks and redundant reflections.
|
|
5
5
|
* Extracted from evolution-worker.ts.
|
|
6
6
|
*/
|
|
7
|
-
import type { EvolutionQueueItem } from '
|
|
7
|
+
import type { EvolutionQueueItem } from '../core/evolution-types.js';
|
|
8
8
|
/**
|
|
9
9
|
* Dedup window for pain queue tasks (30 minutes).
|
|
10
10
|
*/
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { OpenClawPluginServiceContext, OpenClawPluginApi, PluginLogger } from '../openclaw-sdk.js';
|
|
2
2
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
3
|
-
import type { TaskKind, TaskPriority } from '../core/trajectory-types.js';
|
|
4
3
|
export type { TaskKind, TaskPriority } from '../core/trajectory-types.js';
|
|
5
4
|
export { loadEvolutionQueue, saveEvolutionQueue, withQueueLock, acquireQueueLock, requireQueueLock } from './queue-io.js';
|
|
6
5
|
export { EVOLUTION_QUEUE_LOCK_SUFFIX, LOCK_MAX_RETRIES, LOCK_RETRY_DELAY_MS, LOCK_STALE_MS } from './queue-io.js';
|
|
@@ -24,37 +23,14 @@ export type { WatchdogResult };
|
|
|
24
23
|
* Pain diagnosis is Runtime v2 only: after_tool_call / pd pain record ->
|
|
25
24
|
* PainSignalBridge -> SplitDiagnosticianRunner. EvolutionWorker does not read
|
|
26
25
|
* .pain_flag or process pain_diagnosis queue items.
|
|
26
|
+
*
|
|
27
|
+
* Types (QueueStatus / TaskResolution / EvolutionQueueItem) are re-exported
|
|
28
|
+
* from queue-migration.ts, which sources them from evolution-types.ts
|
|
29
|
+
* (canonical single source of truth).
|
|
27
30
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
export
|
|
31
|
-
export interface EvolutionQueueItem {
|
|
32
|
-
id: string;
|
|
33
|
-
taskKind: TaskKind;
|
|
34
|
-
priority: TaskPriority;
|
|
35
|
-
source: string;
|
|
36
|
-
traceId?: string;
|
|
37
|
-
task?: string;
|
|
38
|
-
score: number;
|
|
39
|
-
reason: string;
|
|
40
|
-
timestamp: string;
|
|
41
|
-
enqueued_at?: string;
|
|
42
|
-
started_at?: string;
|
|
43
|
-
completed_at?: string;
|
|
44
|
-
assigned_session_key?: string;
|
|
45
|
-
trigger_text_preview?: string;
|
|
46
|
-
status: QueueStatus;
|
|
47
|
-
resolution?: TaskResolution;
|
|
48
|
-
session_id?: string;
|
|
49
|
-
agent_id?: string;
|
|
50
|
-
retryCount: number;
|
|
51
|
-
maxRetries: number;
|
|
52
|
-
lastError?: string;
|
|
53
|
-
resultRef?: string;
|
|
54
|
-
painEventId?: number;
|
|
55
|
-
}
|
|
56
|
-
import { migrateToV2, isLegacyQueueItem, migrateQueueToV2, LegacyEvolutionQueueItem, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES, type RawQueueItem } from './queue-migration.js';
|
|
57
|
-
export { migrateToV2, isLegacyQueueItem, migrateQueueToV2, LegacyEvolutionQueueItem, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES };
|
|
31
|
+
export type { QueueStatus, TaskResolution, EvolutionQueueItem } from './queue-migration.js';
|
|
32
|
+
import { migrateToV2, isLegacyQueueItem, migrateQueueToV2, LegacyEvolutionQueueItem, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES, validateQueueItem, VALID_TASK_KINDS, isValidQueueItem, type RawQueueItem, type EvolutionQueueItem } from './queue-migration.js';
|
|
33
|
+
export { migrateToV2, isLegacyQueueItem, migrateQueueToV2, LegacyEvolutionQueueItem, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES, validateQueueItem, VALID_TASK_KINDS, isValidQueueItem };
|
|
58
34
|
export type { RawQueueItem };
|
|
59
35
|
export declare function extractEvolutionTaskId(task: string): string | null;
|
|
60
36
|
export declare function purgeStaleFailedTasks(queue: EvolutionQueueItem[], logger: PluginLogger): {
|
|
@@ -11,7 +11,7 @@ import { atomicWriteFileSync } from '../utils/io.js';
|
|
|
11
11
|
// Re-export queue I/O (extracted to queue-io.ts)
|
|
12
12
|
export { loadEvolutionQueue, saveEvolutionQueue, withQueueLock, acquireQueueLock, requireQueueLock } from './queue-io.js';
|
|
13
13
|
export { EVOLUTION_QUEUE_LOCK_SUFFIX, LOCK_MAX_RETRIES, LOCK_RETRY_DELAY_MS, LOCK_STALE_MS } from './queue-io.js';
|
|
14
|
-
import { saveEvolutionQueue, requireQueueLock } from './queue-io.js';
|
|
14
|
+
import { saveEvolutionQueue, requireQueueLock, loadEvolutionQueue } from './queue-io.js';
|
|
15
15
|
import { WorkflowStore } from './subagent-workflow/workflow-store.js';
|
|
16
16
|
import { PrincipleCompiler } from '../core/principle-compiler/index.js';
|
|
17
17
|
import { loadLedger, updatePrinciple } from '../core/principle-tree-ledger.js';
|
|
@@ -58,8 +58,8 @@ import { runWorkflowWatchdog } from './workflow-watchdog.js';
|
|
|
58
58
|
export { runWorkflowWatchdog };
|
|
59
59
|
let timeoutId = null;
|
|
60
60
|
// ── Queue Migration (extracted to queue-migration.ts) ────────────────────────
|
|
61
|
-
import { migrateToV2, isLegacyQueueItem, migrateQueueToV2, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES } from './queue-migration.js';
|
|
62
|
-
export { migrateToV2, isLegacyQueueItem, migrateQueueToV2, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES };
|
|
61
|
+
import { migrateToV2, isLegacyQueueItem, migrateQueueToV2, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES, validateQueueItem, VALID_TASK_KINDS, isValidQueueItem } from './queue-migration.js';
|
|
62
|
+
export { migrateToV2, isLegacyQueueItem, migrateQueueToV2, DEFAULT_TASK_KIND, DEFAULT_PRIORITY, DEFAULT_MAX_RETRIES, validateQueueItem, VALID_TASK_KINDS, isValidQueueItem };
|
|
63
63
|
// Queue lock constants and requireQueueLock are imported from queue-io.ts
|
|
64
64
|
export function extractEvolutionTaskId(task) {
|
|
65
65
|
if (!task)
|
|
@@ -302,30 +302,12 @@ async function processEvolutionQueue(wctx, logger, _eventLog, _api) {
|
|
|
302
302
|
logger?.info?.(`[PD:EvolutionWorker] Dropped ${beforeLegacyPainDrop - queue.length} legacy pain_diagnosis queue item(s); use PainSignalBridge/pd pain record`);
|
|
303
303
|
}
|
|
304
304
|
// Validate queue items — filter out malformed entries before processing.
|
|
305
|
-
//
|
|
305
|
+
// rc-1/rc-4 (ERR-007): consolidated in validateQueueItem (queue-migration.ts)
|
|
306
|
+
// so every load path applies the same filter. Malformed items are logged +
|
|
307
|
+
// skipped; they never crash the evolution cycle.
|
|
306
308
|
const beforeValidation = queue.length;
|
|
307
309
|
queue = queue.filter((item) => {
|
|
308
|
-
const errors =
|
|
309
|
-
if (!item.id || typeof item.id !== 'string')
|
|
310
|
-
errors.push('missing/invalid id');
|
|
311
|
-
if (!item.source || typeof item.source !== 'string')
|
|
312
|
-
errors.push('missing/invalid source');
|
|
313
|
-
if (typeof item.score !== 'number')
|
|
314
|
-
errors.push('missing/invalid score');
|
|
315
|
-
if (!item.status || typeof item.status !== 'string')
|
|
316
|
-
errors.push('missing/invalid status');
|
|
317
|
-
if (!item.taskKind || typeof item.taskKind !== 'string')
|
|
318
|
-
errors.push('missing/invalid taskKind');
|
|
319
|
-
else {
|
|
320
|
-
const validTaskKinds = ['model_eval'];
|
|
321
|
-
if (!validTaskKinds.includes(item.taskKind)) {
|
|
322
|
-
errors.push(`invalid taskKind value '${item.taskKind}' (expected one of: ${validTaskKinds.join(', ')})`);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
if (typeof item.retryCount !== 'number')
|
|
326
|
-
errors.push('missing/invalid retryCount');
|
|
327
|
-
if (typeof item.maxRetries !== 'number')
|
|
328
|
-
errors.push('missing/invalid maxRetries');
|
|
310
|
+
const errors = validateQueueItem(item);
|
|
329
311
|
if (errors.length > 0) {
|
|
330
312
|
logger?.warn?.(`[PD:EvolutionWorker] Skipping malformed queue item: ${errors.join(', ')} | ${JSON.stringify(item).slice(0, 200)}`);
|
|
331
313
|
SystemLogger.log(wctx.workspaceDir, 'QUEUE_ITEM_MALFORMED', `Skipped: ${errors.join(', ')} | id=${item.id || 'N/A'}`);
|
|
@@ -361,16 +343,11 @@ export async function registerEvolutionTaskSession(workspaceResolve, taskId, ses
|
|
|
361
343
|
return false;
|
|
362
344
|
const releaseLock = await requireQueueLock(queuePath, logger, 'registerEvolutionTaskSession');
|
|
363
345
|
try {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
logger?.warn?.(`[PD:EvolutionWorker] Failed to parse EVOLUTION_QUEUE for session registration: ${queuePath} - ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
|
|
370
|
-
return false;
|
|
371
|
-
}
|
|
372
|
-
// V2: Migrate queue to current schema
|
|
373
|
-
const queue = migrateQueueToV2(rawQueue);
|
|
346
|
+
// loadEvolutionQueue handles JSON parse + migrate + validate (rc-1/rc-4).
|
|
347
|
+
// Previously this inlined JSON.parse + migrate cast without validating,
|
|
348
|
+
// so malformed queue items could reach the find() below. Reusing the
|
|
349
|
+
// shared loader keeps a single chokepoint for queue validation.
|
|
350
|
+
const queue = loadEvolutionQueue(queuePath);
|
|
374
351
|
const task = queue.find((item) => item.id === taskId && item.status === 'in_progress');
|
|
375
352
|
if (!task) {
|
|
376
353
|
logger?.warn?.(`[PD:EvolutionWorker] Could not find in-progress evolution task ${taskId} for session assignment`);
|
|
@@ -406,7 +383,11 @@ async function processEvolutionQueueWithResult(wctx, logger, eventLog, api) {
|
|
|
406
383
|
if (!fs.existsSync(queuePath)) {
|
|
407
384
|
return { queue: queueResult, errors };
|
|
408
385
|
}
|
|
409
|
-
|
|
386
|
+
// rc-1/rc-2/rc-4 (ERR-001/ERR-005/ERR-007): use the canonical loader
|
|
387
|
+
// instead of raw JSON.parse + cast. loadEvolutionQueue handles parse,
|
|
388
|
+
// migrate, and element-wise validation; malformed items are dropped
|
|
389
|
+
// with a console.warn (rc-9: no silent fallback).
|
|
390
|
+
const queue = loadEvolutionQueue(queuePath);
|
|
410
391
|
// Purge stale failed tasks before processing (keeps queue lean)
|
|
411
392
|
const purgeResult = purgeStaleFailedTasks(queue, logger);
|
|
412
393
|
if (purgeResult.purged > 0) {
|
package/dist/service/queue-io.js
CHANGED
|
@@ -11,7 +11,7 @@ import { createHash } from 'crypto';
|
|
|
11
11
|
import { acquireLockAsync, releaseLock as releaseImportedLock } from '../utils/file-lock.js';
|
|
12
12
|
import { atomicWriteFileSync } from '../utils/io.js';
|
|
13
13
|
import { LockUnavailableError } from '../config/errors.js';
|
|
14
|
-
import { migrateQueueToV2 } from './queue-migration.js';
|
|
14
|
+
import { migrateQueueToV2, validateQueueItem } from './queue-migration.js';
|
|
15
15
|
export const EVOLUTION_QUEUE_LOCK_SUFFIX = '.lock';
|
|
16
16
|
export const LOCK_MAX_RETRIES = 50;
|
|
17
17
|
export const LOCK_RETRY_DELAY_MS = 50;
|
|
@@ -72,7 +72,19 @@ export function loadEvolutionQueue(queuePath) {
|
|
|
72
72
|
rawQueue = [];
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
// rc-1/rc-4 (ERR-007): every element of the parsed array is untrusted disk
|
|
76
|
+
// JSON — validate before returning. Malformed items are filtered out and
|
|
77
|
+
// reported via console.warn (rc-9: no silent drop). This is the single
|
|
78
|
+
// chokepoint that loadEvolutionQueue callers inherit.
|
|
79
|
+
const migrated = migrateQueueToV2(rawQueue);
|
|
80
|
+
return migrated.filter((item) => {
|
|
81
|
+
const errors = validateQueueItem(item);
|
|
82
|
+
if (errors.length > 0) {
|
|
83
|
+
console.warn(`[queue-io] Dropping malformed queue item: ${errors.join(', ')} | id=${item?.id ?? 'N/A'}`);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
});
|
|
76
88
|
}
|
|
77
89
|
export function saveEvolutionQueue(queuePath, queue) {
|
|
78
90
|
atomicWriteFileSync(queuePath, JSON.stringify(queue, null, 2));
|
|
@@ -5,32 +5,8 @@
|
|
|
5
5
|
* to the V2 schema. Zero I/O, zero imports from evolution-worker.ts.
|
|
6
6
|
*/
|
|
7
7
|
import type { TaskKind, TaskPriority } from '../core/trajectory-types.js';
|
|
8
|
-
|
|
9
|
-
export type
|
|
10
|
-
export interface EvolutionQueueItem {
|
|
11
|
-
id: string;
|
|
12
|
-
taskKind: TaskKind;
|
|
13
|
-
priority: TaskPriority;
|
|
14
|
-
source: string;
|
|
15
|
-
traceId?: string;
|
|
16
|
-
task?: string;
|
|
17
|
-
score: number;
|
|
18
|
-
reason: string;
|
|
19
|
-
timestamp: string;
|
|
20
|
-
enqueued_at?: string;
|
|
21
|
-
started_at?: string;
|
|
22
|
-
completed_at?: string;
|
|
23
|
-
assigned_session_key?: string;
|
|
24
|
-
trigger_text_preview?: string;
|
|
25
|
-
status: QueueStatus;
|
|
26
|
-
resolution?: TaskResolution;
|
|
27
|
-
session_id?: string;
|
|
28
|
-
agent_id?: string;
|
|
29
|
-
retryCount: number;
|
|
30
|
-
maxRetries: number;
|
|
31
|
-
lastError?: string;
|
|
32
|
-
resultRef?: string;
|
|
33
|
-
}
|
|
8
|
+
import type { EvolutionQueueItem } from '../core/evolution-types.js';
|
|
9
|
+
export type { QueueStatus, TaskResolution, EvolutionQueueItem } from '../core/evolution-types.js';
|
|
34
10
|
/**
|
|
35
11
|
* Legacy queue item shape (pre-V2) for migration compatibility.
|
|
36
12
|
* These items lack taskKind, priority, retryCount, maxRetries, lastError fields.
|
|
@@ -81,3 +57,28 @@ export declare function isLegacyQueueItem(item: RawQueueItem): boolean;
|
|
|
81
57
|
* Returns a new array with all items migrated to V2 format.
|
|
82
58
|
*/
|
|
83
59
|
export declare function migrateQueueToV2(queue: RawQueueItem[]): EvolutionQueueItem[];
|
|
60
|
+
/**
|
|
61
|
+
* Canonical set of valid taskKind values. Single source of truth — mirrors
|
|
62
|
+
* TaskKind in trajectory-types.ts. Previously the inline validator in
|
|
63
|
+
* evolution-worker.ts hard-coded `['model_eval']`, which silently rejected
|
|
64
|
+
* three legitimate taskKind values (pain_diagnosis / sleep_reflection /
|
|
65
|
+
* keyword_optimization). Keep this in sync with TaskKind.
|
|
66
|
+
*/
|
|
67
|
+
export declare const VALID_TASK_KINDS: readonly TaskKind[];
|
|
68
|
+
/**
|
|
69
|
+
* Validate a single queue item loaded from untrusted disk JSON.
|
|
70
|
+
*
|
|
71
|
+
* Returns an array of human-readable error reasons; an empty array means the
|
|
72
|
+
* item is valid. Use {@link isValidQueueItem} for a type-guard form.
|
|
73
|
+
*
|
|
74
|
+
* This consolidates the inline validation that lived in processEvolutionQueue
|
|
75
|
+
* (evolution-worker.ts) so every queue load path (loadEvolutionQueue,
|
|
76
|
+
* registerEvolutionTaskSession) applies the same filter. rc-4 (ERR-007):
|
|
77
|
+
* array elements from parsed JSON must be element-wise validated.
|
|
78
|
+
*/
|
|
79
|
+
export declare function validateQueueItem(item: unknown): string[];
|
|
80
|
+
/**
|
|
81
|
+
* Type-guard convenience over {@link validateQueueItem}.
|
|
82
|
+
* Drops the reason strings (callers that need them should call validateQueueItem).
|
|
83
|
+
*/
|
|
84
|
+
export declare function isValidQueueItem(item: unknown): item is EvolutionQueueItem;
|
|
@@ -54,3 +54,60 @@ export function isLegacyQueueItem(item) {
|
|
|
54
54
|
export function migrateQueueToV2(queue) {
|
|
55
55
|
return queue.map(item => isLegacyQueueItem(item) ? migrateToV2(item) : item);
|
|
56
56
|
}
|
|
57
|
+
// ── Validation (rc-1/rc-2, rc-4: validate array elements from untrusted JSON) ─
|
|
58
|
+
/**
|
|
59
|
+
* Canonical set of valid taskKind values. Single source of truth — mirrors
|
|
60
|
+
* TaskKind in trajectory-types.ts. Previously the inline validator in
|
|
61
|
+
* evolution-worker.ts hard-coded `['model_eval']`, which silently rejected
|
|
62
|
+
* three legitimate taskKind values (pain_diagnosis / sleep_reflection /
|
|
63
|
+
* keyword_optimization). Keep this in sync with TaskKind.
|
|
64
|
+
*/
|
|
65
|
+
export const VALID_TASK_KINDS = [
|
|
66
|
+
'pain_diagnosis',
|
|
67
|
+
'sleep_reflection',
|
|
68
|
+
'model_eval',
|
|
69
|
+
'keyword_optimization',
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Validate a single queue item loaded from untrusted disk JSON.
|
|
73
|
+
*
|
|
74
|
+
* Returns an array of human-readable error reasons; an empty array means the
|
|
75
|
+
* item is valid. Use {@link isValidQueueItem} for a type-guard form.
|
|
76
|
+
*
|
|
77
|
+
* This consolidates the inline validation that lived in processEvolutionQueue
|
|
78
|
+
* (evolution-worker.ts) so every queue load path (loadEvolutionQueue,
|
|
79
|
+
* registerEvolutionTaskSession) applies the same filter. rc-4 (ERR-007):
|
|
80
|
+
* array elements from parsed JSON must be element-wise validated.
|
|
81
|
+
*/
|
|
82
|
+
export function validateQueueItem(item) {
|
|
83
|
+
const errors = [];
|
|
84
|
+
if (item === null || typeof item !== 'object' || Array.isArray(item)) {
|
|
85
|
+
return ['item is not an object'];
|
|
86
|
+
}
|
|
87
|
+
const it = item;
|
|
88
|
+
if (!it.id || typeof it.id !== 'string')
|
|
89
|
+
errors.push('missing/invalid id');
|
|
90
|
+
if (!it.source || typeof it.source !== 'string')
|
|
91
|
+
errors.push('missing/invalid source');
|
|
92
|
+
if (typeof it.score !== 'number')
|
|
93
|
+
errors.push('missing/invalid score');
|
|
94
|
+
if (!it.status || typeof it.status !== 'string')
|
|
95
|
+
errors.push('missing/invalid status');
|
|
96
|
+
if (!it.taskKind || typeof it.taskKind !== 'string')
|
|
97
|
+
errors.push('missing/invalid taskKind');
|
|
98
|
+
else if (!VALID_TASK_KINDS.includes(it.taskKind)) {
|
|
99
|
+
errors.push(`invalid taskKind value '${it.taskKind}' (expected one of: ${VALID_TASK_KINDS.join(', ')})`);
|
|
100
|
+
}
|
|
101
|
+
if (typeof it.retryCount !== 'number')
|
|
102
|
+
errors.push('missing/invalid retryCount');
|
|
103
|
+
if (typeof it.maxRetries !== 'number')
|
|
104
|
+
errors.push('missing/invalid maxRetries');
|
|
105
|
+
return errors;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Type-guard convenience over {@link validateQueueItem}.
|
|
109
|
+
* Drops the reason strings (callers that need them should call validateQueueItem).
|
|
110
|
+
*/
|
|
111
|
+
export function isValidQueueItem(item) {
|
|
112
|
+
return validateQueueItem(item).length === 0;
|
|
113
|
+
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "principles-disciple",
|
|
3
3
|
"name": "Principles Disciple",
|
|
4
4
|
"description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.185.0",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onCapabilities": [
|
|
8
8
|
"hook"
|
package/package.json
CHANGED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Evolution Queue Migration — V1 to V2 Schema
|
|
3
|
-
*
|
|
4
|
-
* Pure transformation functions and shared queue types.
|
|
5
|
-
*/
|
|
6
|
-
import type { TaskKind, TaskPriority } from '../core/trajectory-types.js';
|
|
7
|
-
export type { TaskKind, TaskPriority } from '../core/trajectory-types.js';
|
|
8
|
-
/**
|
|
9
|
-
* Queue item status values.
|
|
10
|
-
*/
|
|
11
|
-
export type QueueStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'canceled';
|
|
12
|
-
/**
|
|
13
|
-
* Task resolution strings.
|
|
14
|
-
*/
|
|
15
|
-
export type TaskResolution = 'marker_detected' | 'auto_completed_timeout' | 'failed_max_retries' | 'runtime_unavailable' | 'canceled' | 'late_marker_principle_created' | 'late_marker_no_principle' | 'stub_fallback' | 'skipped_thin_violation' | 'noise_classified' | 'retired';
|
|
16
|
-
/**
|
|
17
|
-
* Recent pain context for sleep_reflection tasks.
|
|
18
|
-
* Attached to queue items to provide pain signal context.
|
|
19
|
-
*/
|
|
20
|
-
export interface RecentPainContext {
|
|
21
|
-
mostRecent: {
|
|
22
|
-
score: number;
|
|
23
|
-
source: string;
|
|
24
|
-
reason: string;
|
|
25
|
-
timestamp: string;
|
|
26
|
-
sessionId: string;
|
|
27
|
-
} | null;
|
|
28
|
-
recentPainCount: number;
|
|
29
|
-
recentMaxPainScore: number;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Default values for new V2 fields when migrating legacy items.
|
|
33
|
-
*/
|
|
34
|
-
export declare const DEFAULT_TASK_KIND: TaskKind;
|
|
35
|
-
export declare const DEFAULT_PRIORITY: TaskPriority;
|
|
36
|
-
export declare const DEFAULT_MAX_RETRIES = 3;
|
|
37
|
-
/**
|
|
38
|
-
* Legacy (pre-V2) queue item schema.
|
|
39
|
-
*/
|
|
40
|
-
export interface LegacyEvolutionQueueItem {
|
|
41
|
-
id: string;
|
|
42
|
-
source: string;
|
|
43
|
-
traceId?: string;
|
|
44
|
-
task?: string;
|
|
45
|
-
score: number;
|
|
46
|
-
reason: string;
|
|
47
|
-
timestamp: string;
|
|
48
|
-
enqueued_at?: string;
|
|
49
|
-
started_at?: string;
|
|
50
|
-
completed_at?: string;
|
|
51
|
-
assigned_session_key?: string;
|
|
52
|
-
trigger_text_preview?: string;
|
|
53
|
-
status?: string;
|
|
54
|
-
resolution?: string;
|
|
55
|
-
session_id?: string;
|
|
56
|
-
agent_id?: string;
|
|
57
|
-
taskKind?: string;
|
|
58
|
-
priority?: string;
|
|
59
|
-
retryCount?: number;
|
|
60
|
-
maxRetries?: number;
|
|
61
|
-
lastError?: string;
|
|
62
|
-
resultRef?: string;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* V2 queue item schema.
|
|
66
|
-
*/
|
|
67
|
-
export interface EvolutionQueueItem {
|
|
68
|
-
id: string;
|
|
69
|
-
taskKind: TaskKind;
|
|
70
|
-
priority: TaskPriority;
|
|
71
|
-
source: string;
|
|
72
|
-
traceId?: string;
|
|
73
|
-
task?: string;
|
|
74
|
-
score: number;
|
|
75
|
-
reason: string;
|
|
76
|
-
timestamp: string;
|
|
77
|
-
enqueued_at?: string;
|
|
78
|
-
started_at?: string;
|
|
79
|
-
completed_at?: string;
|
|
80
|
-
assigned_session_key?: string;
|
|
81
|
-
trigger_text_preview?: string;
|
|
82
|
-
status: QueueStatus;
|
|
83
|
-
resolution?: TaskResolution;
|
|
84
|
-
session_id?: string;
|
|
85
|
-
agent_id?: string;
|
|
86
|
-
retryCount: number;
|
|
87
|
-
maxRetries: number;
|
|
88
|
-
lastError?: string;
|
|
89
|
-
resultRef?: string;
|
|
90
|
-
recentPainContext?: RecentPainContext;
|
|
91
|
-
}
|
|
92
|
-
export type RawQueueItem = Record<string, unknown>;
|
|
93
|
-
/**
|
|
94
|
-
* Migrate a legacy queue item to V2 schema.
|
|
95
|
-
* Old items without taskKind are assumed to be pain_diagnosis for backward compatibility.
|
|
96
|
-
*/
|
|
97
|
-
export declare function migrateToV2(item: LegacyEvolutionQueueItem): {
|
|
98
|
-
id: string;
|
|
99
|
-
taskKind: TaskKind;
|
|
100
|
-
priority: TaskPriority;
|
|
101
|
-
source: string;
|
|
102
|
-
traceId?: string;
|
|
103
|
-
task?: string;
|
|
104
|
-
score: number;
|
|
105
|
-
reason: string;
|
|
106
|
-
timestamp: string;
|
|
107
|
-
enqueued_at?: string;
|
|
108
|
-
started_at?: string;
|
|
109
|
-
completed_at?: string;
|
|
110
|
-
assigned_session_key?: string;
|
|
111
|
-
trigger_text_preview?: string;
|
|
112
|
-
status: QueueStatus;
|
|
113
|
-
resolution?: TaskResolution;
|
|
114
|
-
session_id?: string;
|
|
115
|
-
agent_id?: string;
|
|
116
|
-
retryCount: number;
|
|
117
|
-
maxRetries: number;
|
|
118
|
-
lastError?: string;
|
|
119
|
-
resultRef?: string;
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* Check if an item is a legacy (pre-V2) queue item.
|
|
123
|
-
*/
|
|
124
|
-
export declare function isLegacyQueueItem(item: RawQueueItem): boolean;
|
|
125
|
-
/**
|
|
126
|
-
* Migrate entire queue to V2 schema if needed.
|
|
127
|
-
*/
|
|
128
|
-
export declare function migrateQueueToV2(queue: RawQueueItem[]): ReturnType<typeof migrateToV2>[];
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Evolution Queue Migration — V1 to V2 Schema
|
|
3
|
-
*
|
|
4
|
-
* Pure transformation functions and shared queue types.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Default values for new V2 fields when migrating legacy items.
|
|
8
|
-
*/
|
|
9
|
-
export const DEFAULT_TASK_KIND = 'pain_diagnosis';
|
|
10
|
-
export const DEFAULT_PRIORITY = 'medium';
|
|
11
|
-
export const DEFAULT_MAX_RETRIES = 3;
|
|
12
|
-
/**
|
|
13
|
-
* Migrate a legacy queue item to V2 schema.
|
|
14
|
-
* Old items without taskKind are assumed to be pain_diagnosis for backward compatibility.
|
|
15
|
-
*/
|
|
16
|
-
export function migrateToV2(item) {
|
|
17
|
-
return {
|
|
18
|
-
id: item.id,
|
|
19
|
-
taskKind: item.taskKind || DEFAULT_TASK_KIND,
|
|
20
|
-
priority: item.priority || DEFAULT_PRIORITY,
|
|
21
|
-
source: item.source,
|
|
22
|
-
traceId: item.traceId,
|
|
23
|
-
task: item.task,
|
|
24
|
-
score: item.score,
|
|
25
|
-
reason: item.reason,
|
|
26
|
-
timestamp: item.timestamp,
|
|
27
|
-
enqueued_at: item.enqueued_at,
|
|
28
|
-
started_at: item.started_at,
|
|
29
|
-
completed_at: item.completed_at,
|
|
30
|
-
assigned_session_key: item.assigned_session_key,
|
|
31
|
-
trigger_text_preview: item.trigger_text_preview,
|
|
32
|
-
status: item.status || 'pending',
|
|
33
|
-
resolution: item.resolution,
|
|
34
|
-
session_id: item.session_id,
|
|
35
|
-
agent_id: item.agent_id,
|
|
36
|
-
retryCount: item.retryCount || 0,
|
|
37
|
-
maxRetries: item.maxRetries || DEFAULT_MAX_RETRIES,
|
|
38
|
-
lastError: item.lastError,
|
|
39
|
-
resultRef: item.resultRef,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Check if an item is a legacy (pre-V2) queue item.
|
|
44
|
-
*/
|
|
45
|
-
export function isLegacyQueueItem(item) {
|
|
46
|
-
return item && typeof item === 'object' && !('taskKind' in item);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Migrate entire queue to V2 schema if needed.
|
|
50
|
-
*/
|
|
51
|
-
export function migrateQueueToV2(queue) {
|
|
52
|
-
return queue.map(item => isLegacyQueueItem(item) ? migrateToV2(item) : item);
|
|
53
|
-
}
|