principles-disciple 1.7.5 → 1.7.8
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/commands/context.js +5 -15
- package/dist/commands/evolution-status.js +29 -48
- package/dist/commands/export.js +61 -8
- package/dist/commands/nocturnal-review.d.ts +24 -0
- package/dist/commands/nocturnal-review.js +265 -0
- package/dist/commands/nocturnal-rollout.d.ts +27 -0
- package/dist/commands/nocturnal-rollout.js +671 -0
- package/dist/commands/nocturnal-train.d.ts +25 -0
- package/dist/commands/nocturnal-train.js +919 -0
- package/dist/commands/pain.js +8 -21
- package/dist/config/defaults/runtime.d.ts +40 -0
- package/dist/config/defaults/runtime.js +44 -0
- package/dist/config/errors.d.ts +84 -0
- package/dist/config/errors.js +94 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.js +7 -0
- package/dist/constants/diagnostician.d.ts +0 -4
- package/dist/constants/diagnostician.js +0 -4
- package/dist/constants/tools.d.ts +2 -2
- package/dist/constants/tools.js +1 -1
- package/dist/core/adaptive-thresholds.d.ts +186 -0
- package/dist/core/adaptive-thresholds.js +300 -0
- package/dist/core/config.d.ts +2 -38
- package/dist/core/config.js +6 -61
- package/dist/core/control-ui-db.d.ts +27 -0
- package/dist/core/control-ui-db.js +18 -0
- package/dist/core/event-log.d.ts +1 -2
- package/dist/core/event-log.js +0 -3
- package/dist/core/evolution-engine.js +1 -21
- package/dist/core/evolution-reducer.d.ts +7 -1
- package/dist/core/evolution-reducer.js +56 -4
- package/dist/core/evolution-types.d.ts +61 -9
- package/dist/core/evolution-types.js +31 -9
- package/dist/core/external-training-contract.d.ts +276 -0
- package/dist/core/external-training-contract.js +269 -0
- package/dist/core/local-worker-routing.d.ts +175 -0
- package/dist/core/local-worker-routing.js +525 -0
- package/dist/core/model-deployment-registry.d.ts +218 -0
- package/dist/core/model-deployment-registry.js +503 -0
- package/dist/core/model-training-registry.d.ts +295 -0
- package/dist/core/model-training-registry.js +475 -0
- package/dist/core/nocturnal-arbiter.d.ts +159 -0
- package/dist/core/nocturnal-arbiter.js +534 -0
- package/dist/core/nocturnal-candidate-scoring.d.ts +137 -0
- package/dist/core/nocturnal-candidate-scoring.js +266 -0
- package/dist/core/nocturnal-compliance.d.ts +175 -0
- package/dist/core/nocturnal-compliance.js +824 -0
- package/dist/core/nocturnal-dataset.d.ts +224 -0
- package/dist/core/nocturnal-dataset.js +443 -0
- package/dist/core/nocturnal-executability.d.ts +85 -0
- package/dist/core/nocturnal-executability.js +331 -0
- package/dist/core/nocturnal-export.d.ts +124 -0
- package/dist/core/nocturnal-export.js +275 -0
- package/dist/core/nocturnal-paths.d.ts +124 -0
- package/dist/core/nocturnal-paths.js +214 -0
- package/dist/core/nocturnal-trajectory-extractor.d.ts +242 -0
- package/dist/core/nocturnal-trajectory-extractor.js +307 -0
- package/dist/core/nocturnal-trinity.d.ts +311 -0
- package/dist/core/nocturnal-trinity.js +880 -0
- package/dist/core/path-resolver.js +2 -1
- package/dist/core/paths.d.ts +6 -0
- package/dist/core/paths.js +6 -0
- package/dist/core/principle-training-state.d.ts +121 -0
- package/dist/core/principle-training-state.js +321 -0
- package/dist/core/promotion-gate.d.ts +238 -0
- package/dist/core/promotion-gate.js +529 -0
- package/dist/core/session-tracker.d.ts +10 -0
- package/dist/core/session-tracker.js +14 -0
- package/dist/core/shadow-observation-registry.d.ts +217 -0
- package/dist/core/shadow-observation-registry.js +308 -0
- package/dist/core/training-program.d.ts +233 -0
- package/dist/core/training-program.js +433 -0
- package/dist/core/trajectory.d.ts +155 -1
- package/dist/core/trajectory.js +292 -8
- package/dist/core/workspace-context.d.ts +0 -6
- package/dist/core/workspace-context.js +0 -12
- package/dist/hooks/bash-risk.d.ts +57 -0
- package/dist/hooks/bash-risk.js +137 -0
- package/dist/hooks/edit-verification.d.ts +62 -0
- package/dist/hooks/edit-verification.js +256 -0
- package/dist/hooks/gate-block-helper.d.ts +44 -0
- package/dist/hooks/gate-block-helper.js +119 -0
- package/dist/hooks/gate.d.ts +18 -0
- package/dist/hooks/gate.js +62 -751
- package/dist/hooks/gfi-gate.d.ts +40 -0
- package/dist/hooks/gfi-gate.js +113 -0
- package/dist/hooks/pain.js +6 -9
- package/dist/hooks/progressive-trust-gate.d.ts +51 -0
- package/dist/hooks/progressive-trust-gate.js +89 -0
- package/dist/hooks/prompt.d.ts +11 -11
- package/dist/hooks/prompt.js +167 -77
- package/dist/hooks/subagent.js +43 -6
- package/dist/hooks/thinking-checkpoint.d.ts +37 -0
- package/dist/hooks/thinking-checkpoint.js +51 -0
- package/dist/http/principles-console-route.js +13 -3
- package/dist/i18n/commands.js +8 -8
- package/dist/index.js +129 -28
- package/dist/service/central-database.js +2 -1
- package/dist/service/control-ui-query-service.d.ts +1 -1
- package/dist/service/control-ui-query-service.js +3 -3
- package/dist/service/evolution-query-service.d.ts +1 -1
- package/dist/service/evolution-query-service.js +5 -5
- package/dist/service/evolution-worker.d.ts +52 -4
- package/dist/service/evolution-worker.js +328 -16
- package/dist/service/nocturnal-runtime.d.ts +183 -0
- package/dist/service/nocturnal-runtime.js +352 -0
- package/dist/service/nocturnal-service.d.ts +163 -0
- package/dist/service/nocturnal-service.js +787 -0
- package/dist/service/nocturnal-target-selector.d.ts +145 -0
- package/dist/service/nocturnal-target-selector.js +315 -0
- package/dist/service/phase3-input-filter.d.ts +48 -12
- package/dist/service/phase3-input-filter.js +84 -18
- package/dist/service/runtime-summary-service.d.ts +34 -10
- package/dist/service/runtime-summary-service.js +87 -48
- package/dist/tools/deep-reflect.js +2 -1
- package/dist/types/event-types.d.ts +4 -10
- package/dist/types/runtime-summary.d.ts +47 -0
- package/dist/types/runtime-summary.js +1 -0
- package/dist/types.d.ts +0 -3
- package/dist/types.js +0 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/templates/langs/en/skills/pd-mentor/SKILL.md +5 -5
- package/templates/langs/zh/skills/pd-mentor/SKILL.md +5 -5
- package/templates/pain_settings.json +0 -6
- package/dist/commands/trust.d.ts +0 -4
- package/dist/commands/trust.js +0 -78
- package/dist/core/trust-engine.d.ts +0 -96
- package/dist/core/trust-engine.js +0 -286
|
@@ -89,7 +89,9 @@ export interface TrajectorySessionInput {
|
|
|
89
89
|
sessionId: string;
|
|
90
90
|
startedAt?: string;
|
|
91
91
|
}
|
|
92
|
-
export
|
|
92
|
+
export type TaskKind = 'pain_diagnosis' | 'sleep_reflection' | 'model_eval';
|
|
93
|
+
export type TaskPriority = 'high' | 'medium' | 'low';
|
|
94
|
+
interface EvolutionTaskInputBase {
|
|
93
95
|
taskId: string;
|
|
94
96
|
traceId: string;
|
|
95
97
|
source: string;
|
|
@@ -103,6 +105,16 @@ export interface EvolutionTaskInput {
|
|
|
103
105
|
createdAt?: string;
|
|
104
106
|
updatedAt?: string;
|
|
105
107
|
}
|
|
108
|
+
interface EvolutionTaskInputV2 extends EvolutionTaskInputBase {
|
|
109
|
+
taskKind?: TaskKind;
|
|
110
|
+
priority?: TaskPriority;
|
|
111
|
+
retryCount?: number;
|
|
112
|
+
maxRetries?: number;
|
|
113
|
+
lastError?: string | null;
|
|
114
|
+
resultRef?: string | null;
|
|
115
|
+
}
|
|
116
|
+
export type EvolutionTaskInput = EvolutionTaskInputV2;
|
|
117
|
+
export { EvolutionTaskInputV2 };
|
|
106
118
|
export interface EvolutionEventInput {
|
|
107
119
|
traceId: string;
|
|
108
120
|
taskId?: string | null;
|
|
@@ -127,6 +139,12 @@ export interface EvolutionTaskRecord {
|
|
|
127
139
|
resolution: string | null;
|
|
128
140
|
createdAt: string;
|
|
129
141
|
updatedAt: string;
|
|
142
|
+
taskKind: TaskKind | null;
|
|
143
|
+
priority: TaskPriority | null;
|
|
144
|
+
retryCount: number | null;
|
|
145
|
+
maxRetries: number | null;
|
|
146
|
+
lastError: string | null;
|
|
147
|
+
resultRef: string | null;
|
|
130
148
|
}
|
|
131
149
|
export interface EvolutionEventRecord {
|
|
132
150
|
id: number;
|
|
@@ -205,12 +223,36 @@ export declare class TrajectoryDatabase {
|
|
|
205
223
|
recordEvolutionTask(input: EvolutionTaskInput): void;
|
|
206
224
|
updateEvolutionTask(taskId: string, updates: Partial<Omit<EvolutionTaskInput, 'taskId' | 'traceId' | 'source'>>): void;
|
|
207
225
|
recordEvolutionEvent(input: EvolutionEventInput): void;
|
|
226
|
+
/**
|
|
227
|
+
* List evolution tasks with optional filtering.
|
|
228
|
+
*
|
|
229
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
230
|
+
* Not: Runtime truth or real-time queue state.
|
|
231
|
+
*/
|
|
208
232
|
listEvolutionTasks(filters?: EvolutionTaskFilters): EvolutionTaskRecord[];
|
|
233
|
+
/**
|
|
234
|
+
* List evolution events for a trace or globally.
|
|
235
|
+
*
|
|
236
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
237
|
+
* Not: Runtime truth or real-time queue state.
|
|
238
|
+
*/
|
|
209
239
|
listEvolutionEvents(traceId?: string, filters?: {
|
|
210
240
|
limit?: number;
|
|
211
241
|
offset?: number;
|
|
212
242
|
}): EvolutionEventRecord[];
|
|
243
|
+
/**
|
|
244
|
+
* Get evolution task by trace ID.
|
|
245
|
+
*
|
|
246
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
247
|
+
* Not: Runtime truth or real-time queue state.
|
|
248
|
+
*/
|
|
213
249
|
getEvolutionTaskByTraceId(traceId: string): EvolutionTaskRecord | null;
|
|
250
|
+
/**
|
|
251
|
+
* Get evolution task statistics.
|
|
252
|
+
*
|
|
253
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
254
|
+
* Not: Runtime truth or real-time queue state.
|
|
255
|
+
*/
|
|
214
256
|
getEvolutionStats(): {
|
|
215
257
|
total: number;
|
|
216
258
|
pending: number;
|
|
@@ -218,14 +260,120 @@ export declare class TrajectoryDatabase {
|
|
|
218
260
|
completed: number;
|
|
219
261
|
failed: number;
|
|
220
262
|
};
|
|
263
|
+
/**
|
|
264
|
+
* List recent sessions from the trajectory database.
|
|
265
|
+
*
|
|
266
|
+
* Returns: Recent session records ordered by most recently updated.
|
|
267
|
+
*
|
|
268
|
+
* @param options.limit - Maximum number of sessions to return (default: 20)
|
|
269
|
+
* @param options.dateFrom - Only return sessions updated after this date
|
|
270
|
+
* @param options.dateTo - Only return sessions updated before this date
|
|
271
|
+
*/
|
|
272
|
+
listRecentSessions(options?: {
|
|
273
|
+
limit?: number;
|
|
274
|
+
dateFrom?: string;
|
|
275
|
+
dateTo?: string;
|
|
276
|
+
}): Array<{
|
|
277
|
+
sessionId: string;
|
|
278
|
+
startedAt: string;
|
|
279
|
+
updatedAt: string;
|
|
280
|
+
}>;
|
|
281
|
+
/**
|
|
282
|
+
* List assistant turns for a session.
|
|
283
|
+
*
|
|
284
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
285
|
+
* Not: Runtime truth or real-time queue state.
|
|
286
|
+
*/
|
|
221
287
|
listAssistantTurns(sessionId: string): AssistantTurnRecord[];
|
|
288
|
+
/**
|
|
289
|
+
* List tool calls for a session.
|
|
290
|
+
*
|
|
291
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
292
|
+
* Not: Runtime truth or real-time queue state.
|
|
293
|
+
*/
|
|
294
|
+
listToolCallsForSession(sessionId: string): Array<{
|
|
295
|
+
id: number;
|
|
296
|
+
toolName: string;
|
|
297
|
+
outcome: string;
|
|
298
|
+
filePath: string | null;
|
|
299
|
+
durationMs: number | null;
|
|
300
|
+
exitCode: number | null;
|
|
301
|
+
errorType: string | null;
|
|
302
|
+
errorMessage: string | null;
|
|
303
|
+
gfiBefore: number | null;
|
|
304
|
+
gfiAfter: number | null;
|
|
305
|
+
createdAt: string;
|
|
306
|
+
}>;
|
|
307
|
+
/**
|
|
308
|
+
* List pain events for a session.
|
|
309
|
+
*
|
|
310
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
311
|
+
* Not: Runtime truth or real-time queue state.
|
|
312
|
+
*/
|
|
313
|
+
listPainEventsForSession(sessionId: string): Array<{
|
|
314
|
+
id: number;
|
|
315
|
+
source: string;
|
|
316
|
+
score: number;
|
|
317
|
+
reason: string | null;
|
|
318
|
+
severity: string | null;
|
|
319
|
+
origin: string | null;
|
|
320
|
+
confidence: number | null;
|
|
321
|
+
createdAt: string;
|
|
322
|
+
}>;
|
|
323
|
+
/**
|
|
324
|
+
* List user turns for a session.
|
|
325
|
+
* Returns sanitized/reduced fields for nocturnal use — NO raw text.
|
|
326
|
+
*/
|
|
327
|
+
listUserTurnsForSession(sessionId: string): Array<{
|
|
328
|
+
id: number;
|
|
329
|
+
turnIndex: number;
|
|
330
|
+
correctionDetected: boolean;
|
|
331
|
+
correctionCue: string | null;
|
|
332
|
+
createdAt: string;
|
|
333
|
+
}>;
|
|
334
|
+
/**
|
|
335
|
+
* List correction samples with optional review status filter.
|
|
336
|
+
*
|
|
337
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
338
|
+
* Not: Runtime truth or real-time queue state.
|
|
339
|
+
*/
|
|
222
340
|
listCorrectionSamples(status?: CorrectionSampleReviewStatus): CorrectionSampleRecord[];
|
|
341
|
+
/**
|
|
342
|
+
* List gate blocks for a session.
|
|
343
|
+
* Returns minimal fields for nocturnal use — no raw text.
|
|
344
|
+
*/
|
|
345
|
+
listGateBlocksForSession(sessionId: string): Array<{
|
|
346
|
+
id: number;
|
|
347
|
+
toolName: string;
|
|
348
|
+
filePath: string | null;
|
|
349
|
+
reason: string;
|
|
350
|
+
planStatus: string | null;
|
|
351
|
+
createdAt: string;
|
|
352
|
+
}>;
|
|
223
353
|
reviewCorrectionSample(sampleId: string, status: Exclude<CorrectionSampleReviewStatus, 'pending'>, note?: string): CorrectionSampleRecord;
|
|
354
|
+
/**
|
|
355
|
+
* Export correction samples to JSONL file.
|
|
356
|
+
*
|
|
357
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
358
|
+
* Not: Runtime truth or real-time queue state.
|
|
359
|
+
*/
|
|
224
360
|
exportCorrections(opts: {
|
|
225
361
|
mode: CorrectionExportMode;
|
|
226
362
|
approvedOnly: boolean;
|
|
227
363
|
}): TrajectoryExportResult;
|
|
364
|
+
/**
|
|
365
|
+
* Export analytics data to JSON file.
|
|
366
|
+
*
|
|
367
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
368
|
+
* Not: Runtime truth or real-time queue state.
|
|
369
|
+
*/
|
|
228
370
|
exportAnalytics(): TrajectoryExportResult;
|
|
371
|
+
/**
|
|
372
|
+
* Get trajectory database statistics.
|
|
373
|
+
*
|
|
374
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
375
|
+
* Not: Runtime truth or real-time queue state.
|
|
376
|
+
*/
|
|
229
377
|
getDataStats(): TrajectoryDataStats;
|
|
230
378
|
cleanupBlobStorage(): {
|
|
231
379
|
removedFiles: number;
|
|
@@ -234,6 +382,12 @@ export declare class TrajectoryDatabase {
|
|
|
234
382
|
private initSchema;
|
|
235
383
|
private importLegacyArtifacts;
|
|
236
384
|
private migrateSchema;
|
|
385
|
+
/**
|
|
386
|
+
* Get daily metrics for analytics.
|
|
387
|
+
*
|
|
388
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
389
|
+
* Not: Runtime truth or real-time queue state.
|
|
390
|
+
*/
|
|
237
391
|
private dailyMetrics;
|
|
238
392
|
private importLegacySessions;
|
|
239
393
|
private importLegacyEvents;
|
package/dist/core/trajectory.js
CHANGED
|
@@ -4,6 +4,16 @@ import path from 'path';
|
|
|
4
4
|
import crypto from 'crypto';
|
|
5
5
|
import { withLock } from '../utils/file-lock.js';
|
|
6
6
|
import { resolvePdPath } from './paths.js';
|
|
7
|
+
import { SampleNotFoundError } from '../config/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Trajectory database stores HISTORICAL and ANALYTICS data.
|
|
10
|
+
*
|
|
11
|
+
* PURPOSE: Track task outcomes, trust changes, and evolution progress over time.
|
|
12
|
+
* USAGE: Insights, trends, and Phase 3 supporting evidence (where explicitly allowed).
|
|
13
|
+
* NOT FOR: Control decisions, Phase 3 eligibility, or real-time operations.
|
|
14
|
+
*
|
|
15
|
+
* Runtime truth comes from: queue state, workspace trust scorecard, active sessions
|
|
16
|
+
*/
|
|
7
17
|
const DEFAULT_INLINE_THRESHOLD = 16 * 1024;
|
|
8
18
|
const DEFAULT_BUSY_TIMEOUT_MS = 5000;
|
|
9
19
|
const DEFAULT_ORPHAN_BLOB_GRACE_DAYS = 7;
|
|
@@ -105,6 +115,9 @@ export class TrajectoryDatabase {
|
|
|
105
115
|
recordToolCall(input) {
|
|
106
116
|
this.recordSession({ sessionId: input.sessionId, startedAt: input.createdAt });
|
|
107
117
|
const createdAt = input.createdAt ?? nowIso();
|
|
118
|
+
// Extract filePath from paramsJson if provided and is an object with filePath
|
|
119
|
+
const paramsObj = input.paramsJson;
|
|
120
|
+
const filePath = paramsObj && typeof paramsObj.filePath === 'string' ? paramsObj.filePath : null;
|
|
108
121
|
const rowId = this.withWrite(() => {
|
|
109
122
|
const result = this.db.prepare(`
|
|
110
123
|
INSERT INTO tool_calls (
|
|
@@ -163,23 +176,34 @@ export class TrajectoryDatabase {
|
|
|
163
176
|
}
|
|
164
177
|
recordEvolutionTask(input) {
|
|
165
178
|
const now = nowIso();
|
|
179
|
+
// Cast to V2 to access new fields
|
|
180
|
+
const v2 = input;
|
|
166
181
|
this.withWrite(() => {
|
|
167
182
|
this.db.prepare(`
|
|
168
183
|
INSERT INTO evolution_tasks (
|
|
169
184
|
task_id, trace_id, source, reason, score, status,
|
|
170
|
-
enqueued_at, started_at, completed_at, resolution, created_at, updated_at
|
|
171
|
-
|
|
185
|
+
enqueued_at, started_at, completed_at, resolution, created_at, updated_at,
|
|
186
|
+
task_kind, priority, retry_count, max_retries, last_error, result_ref
|
|
187
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
172
188
|
ON CONFLICT(task_id) DO UPDATE SET
|
|
173
189
|
status = excluded.status,
|
|
174
190
|
started_at = excluded.started_at,
|
|
175
191
|
completed_at = excluded.completed_at,
|
|
176
192
|
resolution = excluded.resolution,
|
|
177
|
-
updated_at = excluded.updated_at
|
|
178
|
-
|
|
193
|
+
updated_at = excluded.updated_at,
|
|
194
|
+
task_kind = excluded.task_kind,
|
|
195
|
+
priority = excluded.priority,
|
|
196
|
+
retry_count = excluded.retry_count,
|
|
197
|
+
max_retries = excluded.max_retries,
|
|
198
|
+
last_error = excluded.last_error,
|
|
199
|
+
result_ref = excluded.result_ref
|
|
200
|
+
`).run(input.taskId, input.traceId, input.source, input.reason ?? null, input.score ?? 0, input.status ?? 'pending', input.enqueuedAt ?? null, input.startedAt ?? null, input.completedAt ?? null, input.resolution ?? null, input.createdAt ?? now, input.updatedAt ?? now, v2.taskKind ?? null, v2.priority ?? null, v2.retryCount ?? null, v2.maxRetries ?? null, v2.lastError ?? null, v2.resultRef ?? null);
|
|
179
201
|
});
|
|
180
202
|
}
|
|
181
203
|
updateEvolutionTask(taskId, updates) {
|
|
182
204
|
const now = nowIso();
|
|
205
|
+
// Cast to V2 to access new fields
|
|
206
|
+
const v2Updates = updates;
|
|
183
207
|
this.withWrite(() => {
|
|
184
208
|
const setClauses = ['updated_at = ?'];
|
|
185
209
|
const values = [now];
|
|
@@ -203,6 +227,31 @@ export class TrajectoryDatabase {
|
|
|
203
227
|
setClauses.push('score = ?');
|
|
204
228
|
values.push(updates.score);
|
|
205
229
|
}
|
|
230
|
+
// V2 fields
|
|
231
|
+
if (v2Updates.taskKind !== undefined) {
|
|
232
|
+
setClauses.push('task_kind = ?');
|
|
233
|
+
values.push(v2Updates.taskKind);
|
|
234
|
+
}
|
|
235
|
+
if (v2Updates.priority !== undefined) {
|
|
236
|
+
setClauses.push('priority = ?');
|
|
237
|
+
values.push(v2Updates.priority);
|
|
238
|
+
}
|
|
239
|
+
if (v2Updates.retryCount !== undefined) {
|
|
240
|
+
setClauses.push('retry_count = ?');
|
|
241
|
+
values.push(v2Updates.retryCount);
|
|
242
|
+
}
|
|
243
|
+
if (v2Updates.maxRetries !== undefined) {
|
|
244
|
+
setClauses.push('max_retries = ?');
|
|
245
|
+
values.push(v2Updates.maxRetries);
|
|
246
|
+
}
|
|
247
|
+
if (v2Updates.lastError !== undefined) {
|
|
248
|
+
setClauses.push('last_error = ?');
|
|
249
|
+
values.push(v2Updates.lastError);
|
|
250
|
+
}
|
|
251
|
+
if (v2Updates.resultRef !== undefined) {
|
|
252
|
+
setClauses.push('result_ref = ?');
|
|
253
|
+
values.push(v2Updates.resultRef);
|
|
254
|
+
}
|
|
206
255
|
values.push(taskId);
|
|
207
256
|
this.db.prepare(`
|
|
208
257
|
UPDATE evolution_tasks SET ${setClauses.join(', ')} WHERE task_id = ?
|
|
@@ -217,6 +266,12 @@ export class TrajectoryDatabase {
|
|
|
217
266
|
`).run(input.traceId, input.taskId ?? null, input.stage, input.level ?? 'info', input.message, input.summary ?? null, safeJson(input.metadata), input.createdAt ?? nowIso());
|
|
218
267
|
});
|
|
219
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* List evolution tasks with optional filtering.
|
|
271
|
+
*
|
|
272
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
273
|
+
* Not: Runtime truth or real-time queue state.
|
|
274
|
+
*/
|
|
220
275
|
listEvolutionTasks(filters = {}) {
|
|
221
276
|
const conditions = [];
|
|
222
277
|
const values = [];
|
|
@@ -237,7 +292,8 @@ export class TrajectoryDatabase {
|
|
|
237
292
|
const offset = filters.offset ?? 0;
|
|
238
293
|
const rows = this.db.prepare(`
|
|
239
294
|
SELECT id, task_id, trace_id, source, reason, score, status,
|
|
240
|
-
enqueued_at, started_at, completed_at, resolution, created_at, updated_at
|
|
295
|
+
enqueued_at, started_at, completed_at, resolution, created_at, updated_at,
|
|
296
|
+
task_kind, priority, retry_count, max_retries, last_error, result_ref
|
|
241
297
|
FROM evolution_tasks
|
|
242
298
|
${whereClause}
|
|
243
299
|
ORDER BY created_at DESC
|
|
@@ -257,8 +313,20 @@ export class TrajectoryDatabase {
|
|
|
257
313
|
resolution: row.resolution ? String(row.resolution) : null,
|
|
258
314
|
createdAt: String(row.created_at),
|
|
259
315
|
updatedAt: String(row.updated_at),
|
|
316
|
+
taskKind: row.task_kind ? row.task_kind : null,
|
|
317
|
+
priority: row.priority ? row.priority : null,
|
|
318
|
+
retryCount: row.retry_count != null ? Number(row.retry_count) : null,
|
|
319
|
+
maxRetries: row.max_retries != null ? Number(row.max_retries) : null,
|
|
320
|
+
lastError: row.last_error ? String(row.last_error) : null,
|
|
321
|
+
resultRef: row.result_ref ? String(row.result_ref) : null,
|
|
260
322
|
}));
|
|
261
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* List evolution events for a trace or globally.
|
|
326
|
+
*
|
|
327
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
328
|
+
* Not: Runtime truth or real-time queue state.
|
|
329
|
+
*/
|
|
262
330
|
listEvolutionEvents(traceId, filters = {}) {
|
|
263
331
|
const limit = filters.limit ?? 100;
|
|
264
332
|
const offset = filters.offset ?? 0;
|
|
@@ -292,10 +360,17 @@ export class TrajectoryDatabase {
|
|
|
292
360
|
createdAt: String(row.created_at),
|
|
293
361
|
}));
|
|
294
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Get evolution task by trace ID.
|
|
365
|
+
*
|
|
366
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
367
|
+
* Not: Runtime truth or real-time queue state.
|
|
368
|
+
*/
|
|
295
369
|
getEvolutionTaskByTraceId(traceId) {
|
|
296
370
|
const row = this.db.prepare(`
|
|
297
371
|
SELECT id, task_id, trace_id, source, reason, score, status,
|
|
298
|
-
enqueued_at, started_at, completed_at, resolution, created_at, updated_at
|
|
372
|
+
enqueued_at, started_at, completed_at, resolution, created_at, updated_at,
|
|
373
|
+
task_kind, priority, retry_count, max_retries, last_error, result_ref
|
|
299
374
|
FROM evolution_tasks
|
|
300
375
|
WHERE trace_id = ?
|
|
301
376
|
LIMIT 1
|
|
@@ -316,8 +391,20 @@ export class TrajectoryDatabase {
|
|
|
316
391
|
resolution: row.resolution ? String(row.resolution) : null,
|
|
317
392
|
createdAt: String(row.created_at),
|
|
318
393
|
updatedAt: String(row.updated_at),
|
|
394
|
+
taskKind: row.task_kind ? row.task_kind : null,
|
|
395
|
+
priority: row.priority ? row.priority : null,
|
|
396
|
+
retryCount: row.retry_count != null ? Number(row.retry_count) : null,
|
|
397
|
+
maxRetries: row.max_retries != null ? Number(row.max_retries) : null,
|
|
398
|
+
lastError: row.last_error ? String(row.last_error) : null,
|
|
399
|
+
resultRef: row.result_ref ? String(row.result_ref) : null,
|
|
319
400
|
};
|
|
320
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Get evolution task statistics.
|
|
404
|
+
*
|
|
405
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
406
|
+
* Not: Runtime truth or real-time queue state.
|
|
407
|
+
*/
|
|
321
408
|
getEvolutionStats() {
|
|
322
409
|
const rows = this.db.prepare(`
|
|
323
410
|
SELECT status, COUNT(*) as count FROM evolution_tasks GROUP BY status
|
|
@@ -336,6 +423,47 @@ export class TrajectoryDatabase {
|
|
|
336
423
|
}
|
|
337
424
|
return stats;
|
|
338
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* List recent sessions from the trajectory database.
|
|
428
|
+
*
|
|
429
|
+
* Returns: Recent session records ordered by most recently updated.
|
|
430
|
+
*
|
|
431
|
+
* @param options.limit - Maximum number of sessions to return (default: 20)
|
|
432
|
+
* @param options.dateFrom - Only return sessions updated after this date
|
|
433
|
+
* @param options.dateTo - Only return sessions updated before this date
|
|
434
|
+
*/
|
|
435
|
+
listRecentSessions(options = {}) {
|
|
436
|
+
const conditions = [];
|
|
437
|
+
const values = [];
|
|
438
|
+
if (options.dateFrom) {
|
|
439
|
+
conditions.push('updated_at >= ?');
|
|
440
|
+
values.push(options.dateFrom);
|
|
441
|
+
}
|
|
442
|
+
if (options.dateTo) {
|
|
443
|
+
conditions.push('updated_at <= ?');
|
|
444
|
+
values.push(options.dateTo);
|
|
445
|
+
}
|
|
446
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
447
|
+
const limit = options.limit ?? 20;
|
|
448
|
+
const rows = this.db.prepare(`
|
|
449
|
+
SELECT session_id, started_at, updated_at
|
|
450
|
+
FROM sessions
|
|
451
|
+
${whereClause}
|
|
452
|
+
ORDER BY updated_at DESC
|
|
453
|
+
LIMIT ?
|
|
454
|
+
`).all(...values, limit);
|
|
455
|
+
return rows.map((row) => ({
|
|
456
|
+
sessionId: String(row.session_id),
|
|
457
|
+
startedAt: String(row.started_at),
|
|
458
|
+
updatedAt: String(row.updated_at),
|
|
459
|
+
}));
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* List assistant turns for a session.
|
|
463
|
+
*
|
|
464
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
465
|
+
* Not: Runtime truth or real-time queue state.
|
|
466
|
+
*/
|
|
339
467
|
listAssistantTurns(sessionId) {
|
|
340
468
|
const rows = this.db.prepare(`
|
|
341
469
|
SELECT id, session_id, run_id, provider, model, raw_text, sanitized_text, blob_ref, created_at
|
|
@@ -355,6 +483,98 @@ export class TrajectoryDatabase {
|
|
|
355
483
|
createdAt: String(row.created_at),
|
|
356
484
|
}));
|
|
357
485
|
}
|
|
486
|
+
/**
|
|
487
|
+
* List tool calls for a session.
|
|
488
|
+
*
|
|
489
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
490
|
+
* Not: Runtime truth or real-time queue state.
|
|
491
|
+
*/
|
|
492
|
+
listToolCallsForSession(sessionId) {
|
|
493
|
+
const rows = this.db.prepare(`
|
|
494
|
+
SELECT id, tool_name, outcome, params_json, duration_ms, exit_code, error_type, error_message,
|
|
495
|
+
gfi_before, gfi_after, created_at
|
|
496
|
+
FROM tool_calls
|
|
497
|
+
WHERE session_id = ?
|
|
498
|
+
ORDER BY id ASC
|
|
499
|
+
`).all(sessionId);
|
|
500
|
+
return rows.map((row) => {
|
|
501
|
+
// Extract filePath from params_json if present
|
|
502
|
+
let filePath = null;
|
|
503
|
+
if (row.params_json && typeof row.params_json === 'string') {
|
|
504
|
+
try {
|
|
505
|
+
const params = JSON.parse(row.params_json);
|
|
506
|
+
if (params && typeof params.filePath === 'string') {
|
|
507
|
+
filePath = params.filePath;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
catch {
|
|
511
|
+
// Ignore malformed JSON
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
id: Number(row.id),
|
|
516
|
+
toolName: String(row.tool_name),
|
|
517
|
+
outcome: String(row.outcome),
|
|
518
|
+
filePath,
|
|
519
|
+
durationMs: row.duration_ms != null ? Number(row.duration_ms) : null,
|
|
520
|
+
exitCode: row.exit_code != null ? Number(row.exit_code) : null,
|
|
521
|
+
errorType: row.error_type ? String(row.error_type) : null,
|
|
522
|
+
errorMessage: row.error_message ? String(row.error_message) : null,
|
|
523
|
+
gfiBefore: row.gfi_before != null ? Number(row.gfi_before) : null,
|
|
524
|
+
gfiAfter: row.gfi_after != null ? Number(row.gfi_after) : null,
|
|
525
|
+
createdAt: String(row.created_at),
|
|
526
|
+
};
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* List pain events for a session.
|
|
531
|
+
*
|
|
532
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
533
|
+
* Not: Runtime truth or real-time queue state.
|
|
534
|
+
*/
|
|
535
|
+
listPainEventsForSession(sessionId) {
|
|
536
|
+
const rows = this.db.prepare(`
|
|
537
|
+
SELECT id, source, score, reason, severity, origin, confidence, created_at
|
|
538
|
+
FROM pain_events
|
|
539
|
+
WHERE session_id = ?
|
|
540
|
+
ORDER BY created_at ASC
|
|
541
|
+
`).all(sessionId);
|
|
542
|
+
return rows.map((row) => ({
|
|
543
|
+
id: Number(row.id),
|
|
544
|
+
source: String(row.source),
|
|
545
|
+
score: Number(row.score),
|
|
546
|
+
reason: row.reason ? String(row.reason) : null,
|
|
547
|
+
severity: row.severity ? String(row.severity) : null,
|
|
548
|
+
origin: row.origin ? String(row.origin) : null,
|
|
549
|
+
confidence: row.confidence != null ? Number(row.confidence) : null,
|
|
550
|
+
createdAt: String(row.created_at),
|
|
551
|
+
}));
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* List user turns for a session.
|
|
555
|
+
* Returns sanitized/reduced fields for nocturnal use — NO raw text.
|
|
556
|
+
*/
|
|
557
|
+
listUserTurnsForSession(sessionId) {
|
|
558
|
+
const rows = this.db.prepare(`
|
|
559
|
+
SELECT id, turn_index, correction_detected, correction_cue, created_at
|
|
560
|
+
FROM user_turns
|
|
561
|
+
WHERE session_id = ?
|
|
562
|
+
ORDER BY turn_index ASC
|
|
563
|
+
`).all(sessionId);
|
|
564
|
+
return rows.map((row) => ({
|
|
565
|
+
id: Number(row.id),
|
|
566
|
+
turnIndex: Number(row.turn_index),
|
|
567
|
+
correctionDetected: Boolean(row.correction_detected),
|
|
568
|
+
correctionCue: row.correction_cue ? String(row.correction_cue) : null,
|
|
569
|
+
createdAt: String(row.created_at),
|
|
570
|
+
}));
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* List correction samples with optional review status filter.
|
|
574
|
+
*
|
|
575
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
576
|
+
* Not: Runtime truth or real-time queue state.
|
|
577
|
+
*/
|
|
358
578
|
listCorrectionSamples(status = 'pending') {
|
|
359
579
|
const rows = this.db.prepare(`
|
|
360
580
|
SELECT sample_id, session_id, bad_assistant_turn_id, user_correction_turn_id,
|
|
@@ -379,6 +599,26 @@ export class TrajectoryDatabase {
|
|
|
379
599
|
updatedAt: String(row.updated_at),
|
|
380
600
|
}));
|
|
381
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* List gate blocks for a session.
|
|
604
|
+
* Returns minimal fields for nocturnal use — no raw text.
|
|
605
|
+
*/
|
|
606
|
+
listGateBlocksForSession(sessionId) {
|
|
607
|
+
const rows = this.db.prepare(`
|
|
608
|
+
SELECT id, tool_name, file_path, reason, plan_status, created_at
|
|
609
|
+
FROM gate_blocks
|
|
610
|
+
WHERE session_id = ?
|
|
611
|
+
ORDER BY id ASC
|
|
612
|
+
`).all(sessionId);
|
|
613
|
+
return rows.map((row) => ({
|
|
614
|
+
id: Number(row.id),
|
|
615
|
+
toolName: String(row.tool_name),
|
|
616
|
+
filePath: row.file_path ? String(row.file_path) : null,
|
|
617
|
+
reason: String(row.reason),
|
|
618
|
+
planStatus: row.plan_status ? String(row.plan_status) : null,
|
|
619
|
+
createdAt: String(row.created_at),
|
|
620
|
+
}));
|
|
621
|
+
}
|
|
382
622
|
reviewCorrectionSample(sampleId, status, note) {
|
|
383
623
|
const updatedAt = nowIso();
|
|
384
624
|
const updated = this.withWrite(() => {
|
|
@@ -397,7 +637,7 @@ export class TrajectoryDatabase {
|
|
|
397
637
|
return true;
|
|
398
638
|
});
|
|
399
639
|
if (!updated) {
|
|
400
|
-
throw new
|
|
640
|
+
throw new SampleNotFoundError(sampleId);
|
|
401
641
|
}
|
|
402
642
|
const record = this.db.prepare(`
|
|
403
643
|
SELECT sample_id, session_id, bad_assistant_turn_id, user_correction_turn_id,
|
|
@@ -407,7 +647,7 @@ export class TrajectoryDatabase {
|
|
|
407
647
|
WHERE sample_id = ?
|
|
408
648
|
`).get(sampleId);
|
|
409
649
|
if (!record) {
|
|
410
|
-
throw new
|
|
650
|
+
throw new SampleNotFoundError(`${sampleId} (after update)`);
|
|
411
651
|
}
|
|
412
652
|
return {
|
|
413
653
|
sampleId: String(record.sample_id),
|
|
@@ -424,6 +664,12 @@ export class TrajectoryDatabase {
|
|
|
424
664
|
updatedAt: String(record.updated_at),
|
|
425
665
|
};
|
|
426
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
* Export correction samples to JSONL file.
|
|
669
|
+
*
|
|
670
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
671
|
+
* Not: Runtime truth or real-time queue state.
|
|
672
|
+
*/
|
|
427
673
|
exportCorrections(opts) {
|
|
428
674
|
const rows = this.db.prepare(`
|
|
429
675
|
SELECT cs.sample_id, cs.session_id, cs.recovery_tool_span_json, cs.diff_excerpt, cs.quality_score,
|
|
@@ -462,6 +708,12 @@ export class TrajectoryDatabase {
|
|
|
462
708
|
this.recordExportAudit('corrections', opts.mode, opts.approvedOnly, exportPath, rows.length);
|
|
463
709
|
return { filePath: exportPath, count: rows.length, mode: opts.mode };
|
|
464
710
|
}
|
|
711
|
+
/**
|
|
712
|
+
* Export analytics data to JSON file.
|
|
713
|
+
*
|
|
714
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
715
|
+
* Not: Runtime truth or real-time queue state.
|
|
716
|
+
*/
|
|
465
717
|
exportAnalytics() {
|
|
466
718
|
const payload = {
|
|
467
719
|
generatedAt: nowIso(),
|
|
@@ -476,6 +728,12 @@ export class TrajectoryDatabase {
|
|
|
476
728
|
this.recordExportAudit('analytics', 'raw', true, exportPath, Array.isArray(payload.dailyMetrics) ? payload.dailyMetrics.length : 0);
|
|
477
729
|
return { filePath: exportPath, count: Array.isArray(payload.dailyMetrics) ? payload.dailyMetrics.length : 0 };
|
|
478
730
|
}
|
|
731
|
+
/**
|
|
732
|
+
* Get trajectory database statistics.
|
|
733
|
+
*
|
|
734
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
735
|
+
* Not: Runtime truth or real-time queue state.
|
|
736
|
+
*/
|
|
479
737
|
getDataStats() {
|
|
480
738
|
const getCount = (table, where) => {
|
|
481
739
|
const sql = where ? `SELECT COUNT(*) as count FROM ${table} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${table}`;
|
|
@@ -658,6 +916,26 @@ export class TrajectoryDatabase {
|
|
|
658
916
|
metadata_json TEXT,
|
|
659
917
|
created_at TEXT NOT NULL
|
|
660
918
|
);
|
|
919
|
+
`);
|
|
920
|
+
// V2 migration: Add V2 columns to evolution_tasks if they don't exist
|
|
921
|
+
// SQLite does not support IF NOT EXISTS for ADD COLUMN, so we must check manually
|
|
922
|
+
// before each ALTER to avoid "duplicate column name" errors on existing DBs
|
|
923
|
+
const v2Columns = [
|
|
924
|
+
{ name: 'task_kind', type: 'TEXT' },
|
|
925
|
+
{ name: 'priority', type: 'TEXT' },
|
|
926
|
+
{ name: 'retry_count', type: 'INTEGER' },
|
|
927
|
+
{ name: 'max_retries', type: 'INTEGER' },
|
|
928
|
+
{ name: 'last_error', type: 'TEXT' },
|
|
929
|
+
{ name: 'result_ref', type: 'TEXT' },
|
|
930
|
+
];
|
|
931
|
+
for (const col of v2Columns) {
|
|
932
|
+
const exists = this.db.prepare(`PRAGMA table_info(evolution_tasks)`).all()
|
|
933
|
+
.some((row) => row.name === col.name);
|
|
934
|
+
if (!exists) {
|
|
935
|
+
this.db.exec(`ALTER TABLE evolution_tasks ADD COLUMN ${col.name} ${col.type}`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
this.db.exec(`
|
|
661
939
|
CREATE VIEW IF NOT EXISTS v_error_clusters AS
|
|
662
940
|
SELECT tool_name, COALESCE(error_type, 'unknown') AS error_type, COUNT(*) AS occurrences
|
|
663
941
|
FROM tool_calls
|
|
@@ -729,6 +1007,12 @@ export class TrajectoryDatabase {
|
|
|
729
1007
|
LEFT JOIN correction_daily ON correction_daily.day = tool_daily.day;
|
|
730
1008
|
`);
|
|
731
1009
|
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Get daily metrics for analytics.
|
|
1012
|
+
*
|
|
1013
|
+
* Returns: Analytics data aggregated from trajectory database.
|
|
1014
|
+
* Not: Runtime truth or real-time queue state.
|
|
1015
|
+
*/
|
|
732
1016
|
dailyMetrics() {
|
|
733
1017
|
return this.db.prepare('SELECT * FROM v_daily_metrics ORDER BY day ASC').all();
|
|
734
1018
|
}
|
|
@@ -2,7 +2,6 @@ import { PD_FILES } from './paths.js';
|
|
|
2
2
|
import { PainConfig } from './config.js';
|
|
3
3
|
import { EventLog } from './event-log.js';
|
|
4
4
|
import { PainDictionary } from './dictionary.js';
|
|
5
|
-
import { TrustEngine } from './trust-engine.js';
|
|
6
5
|
import { HygieneTracker } from './hygiene/tracker.js';
|
|
7
6
|
import { EvolutionReducerImpl } from './evolution-reducer.js';
|
|
8
7
|
import { TrajectoryDatabase } from './trajectory.js';
|
|
@@ -18,7 +17,6 @@ export declare class WorkspaceContext {
|
|
|
18
17
|
private _config?;
|
|
19
18
|
private _eventLog?;
|
|
20
19
|
private _dictionary?;
|
|
21
|
-
private _trust?;
|
|
22
20
|
private _hygiene?;
|
|
23
21
|
private _evolutionReducer?;
|
|
24
22
|
private _trajectory?;
|
|
@@ -35,10 +33,6 @@ export declare class WorkspaceContext {
|
|
|
35
33
|
* Pain dictionary service for this workspace.
|
|
36
34
|
*/
|
|
37
35
|
get dictionary(): PainDictionary;
|
|
38
|
-
/**
|
|
39
|
-
* Trust engine service bound to this workspace.
|
|
40
|
-
*/
|
|
41
|
-
get trust(): TrustEngine;
|
|
42
36
|
/**
|
|
43
37
|
* Hygiene tracking service for this workspace.
|
|
44
38
|
*/
|