principles-disciple 1.7.6 → 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 +2 -9
- 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/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/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/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 +95 -1
- package/dist/core/trajectory.js +220 -6
- package/dist/core/workspace-context.d.ts +0 -6
- package/dist/core/workspace-context.js +0 -12
- package/dist/hooks/bash-risk.d.ts +6 -6
- package/dist/hooks/bash-risk.js +8 -8
- package/dist/hooks/gate-block-helper.js +1 -1
- package/dist/hooks/gate.d.ts +1 -1
- package/dist/hooks/gate.js +2 -2
- package/dist/hooks/gfi-gate.d.ts +3 -3
- package/dist/hooks/gfi-gate.js +15 -14
- package/dist/hooks/pain.js +6 -9
- package/dist/hooks/progressive-trust-gate.d.ts +21 -49
- package/dist/hooks/progressive-trust-gate.js +51 -204
- package/dist/hooks/prompt.d.ts +11 -11
- package/dist/hooks/prompt.js +158 -72
- package/dist/hooks/subagent.js +43 -6
- package/dist/i18n/commands.js +8 -8
- package/dist/index.js +129 -28
- package/dist/service/evolution-worker.d.ts +42 -4
- package/dist/service/evolution-worker.js +321 -13
- 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 +2 -23
- package/dist/service/phase3-input-filter.js +3 -27
- package/dist/service/runtime-summary-service.d.ts +0 -10
- package/dist/service/runtime-summary-service.js +1 -54
- package/dist/tools/deep-reflect.js +2 -1
- package/dist/types/event-types.d.ts +2 -10
- package/dist/types/runtime-summary.d.ts +1 -8
- 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;
|
|
@@ -242,6 +260,24 @@ export declare class TrajectoryDatabase {
|
|
|
242
260
|
completed: number;
|
|
243
261
|
failed: number;
|
|
244
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
|
+
}>;
|
|
245
281
|
/**
|
|
246
282
|
* List assistant turns for a session.
|
|
247
283
|
*
|
|
@@ -249,6 +285,52 @@ export declare class TrajectoryDatabase {
|
|
|
249
285
|
* Not: Runtime truth or real-time queue state.
|
|
250
286
|
*/
|
|
251
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
|
+
}>;
|
|
252
334
|
/**
|
|
253
335
|
* List correction samples with optional review status filter.
|
|
254
336
|
*
|
|
@@ -256,6 +338,18 @@ export declare class TrajectoryDatabase {
|
|
|
256
338
|
* Not: Runtime truth or real-time queue state.
|
|
257
339
|
*/
|
|
258
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
|
+
}>;
|
|
259
353
|
reviewCorrectionSample(sampleId: string, status: Exclude<CorrectionSampleReviewStatus, 'pending'>, note?: string): CorrectionSampleRecord;
|
|
260
354
|
/**
|
|
261
355
|
* Export correction samples to JSONL file.
|
package/dist/core/trajectory.js
CHANGED
|
@@ -115,6 +115,9 @@ export class TrajectoryDatabase {
|
|
|
115
115
|
recordToolCall(input) {
|
|
116
116
|
this.recordSession({ sessionId: input.sessionId, startedAt: input.createdAt });
|
|
117
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;
|
|
118
121
|
const rowId = this.withWrite(() => {
|
|
119
122
|
const result = this.db.prepare(`
|
|
120
123
|
INSERT INTO tool_calls (
|
|
@@ -173,23 +176,34 @@ export class TrajectoryDatabase {
|
|
|
173
176
|
}
|
|
174
177
|
recordEvolutionTask(input) {
|
|
175
178
|
const now = nowIso();
|
|
179
|
+
// Cast to V2 to access new fields
|
|
180
|
+
const v2 = input;
|
|
176
181
|
this.withWrite(() => {
|
|
177
182
|
this.db.prepare(`
|
|
178
183
|
INSERT INTO evolution_tasks (
|
|
179
184
|
task_id, trace_id, source, reason, score, status,
|
|
180
|
-
enqueued_at, started_at, completed_at, resolution, created_at, updated_at
|
|
181
|
-
|
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
182
188
|
ON CONFLICT(task_id) DO UPDATE SET
|
|
183
189
|
status = excluded.status,
|
|
184
190
|
started_at = excluded.started_at,
|
|
185
191
|
completed_at = excluded.completed_at,
|
|
186
192
|
resolution = excluded.resolution,
|
|
187
|
-
updated_at = excluded.updated_at
|
|
188
|
-
|
|
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);
|
|
189
201
|
});
|
|
190
202
|
}
|
|
191
203
|
updateEvolutionTask(taskId, updates) {
|
|
192
204
|
const now = nowIso();
|
|
205
|
+
// Cast to V2 to access new fields
|
|
206
|
+
const v2Updates = updates;
|
|
193
207
|
this.withWrite(() => {
|
|
194
208
|
const setClauses = ['updated_at = ?'];
|
|
195
209
|
const values = [now];
|
|
@@ -213,6 +227,31 @@ export class TrajectoryDatabase {
|
|
|
213
227
|
setClauses.push('score = ?');
|
|
214
228
|
values.push(updates.score);
|
|
215
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
|
+
}
|
|
216
255
|
values.push(taskId);
|
|
217
256
|
this.db.prepare(`
|
|
218
257
|
UPDATE evolution_tasks SET ${setClauses.join(', ')} WHERE task_id = ?
|
|
@@ -253,7 +292,8 @@ export class TrajectoryDatabase {
|
|
|
253
292
|
const offset = filters.offset ?? 0;
|
|
254
293
|
const rows = this.db.prepare(`
|
|
255
294
|
SELECT id, task_id, trace_id, source, reason, score, status,
|
|
256
|
-
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
|
|
257
297
|
FROM evolution_tasks
|
|
258
298
|
${whereClause}
|
|
259
299
|
ORDER BY created_at DESC
|
|
@@ -273,6 +313,12 @@ export class TrajectoryDatabase {
|
|
|
273
313
|
resolution: row.resolution ? String(row.resolution) : null,
|
|
274
314
|
createdAt: String(row.created_at),
|
|
275
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,
|
|
276
322
|
}));
|
|
277
323
|
}
|
|
278
324
|
/**
|
|
@@ -323,7 +369,8 @@ export class TrajectoryDatabase {
|
|
|
323
369
|
getEvolutionTaskByTraceId(traceId) {
|
|
324
370
|
const row = this.db.prepare(`
|
|
325
371
|
SELECT id, task_id, trace_id, source, reason, score, status,
|
|
326
|
-
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
|
|
327
374
|
FROM evolution_tasks
|
|
328
375
|
WHERE trace_id = ?
|
|
329
376
|
LIMIT 1
|
|
@@ -344,6 +391,12 @@ export class TrajectoryDatabase {
|
|
|
344
391
|
resolution: row.resolution ? String(row.resolution) : null,
|
|
345
392
|
createdAt: String(row.created_at),
|
|
346
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,
|
|
347
400
|
};
|
|
348
401
|
}
|
|
349
402
|
/**
|
|
@@ -370,6 +423,41 @@ export class TrajectoryDatabase {
|
|
|
370
423
|
}
|
|
371
424
|
return stats;
|
|
372
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
|
+
}
|
|
373
461
|
/**
|
|
374
462
|
* List assistant turns for a session.
|
|
375
463
|
*
|
|
@@ -395,6 +483,92 @@ export class TrajectoryDatabase {
|
|
|
395
483
|
createdAt: String(row.created_at),
|
|
396
484
|
}));
|
|
397
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
|
+
}
|
|
398
572
|
/**
|
|
399
573
|
* List correction samples with optional review status filter.
|
|
400
574
|
*
|
|
@@ -425,6 +599,26 @@ export class TrajectoryDatabase {
|
|
|
425
599
|
updatedAt: String(row.updated_at),
|
|
426
600
|
}));
|
|
427
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
|
+
}
|
|
428
622
|
reviewCorrectionSample(sampleId, status, note) {
|
|
429
623
|
const updatedAt = nowIso();
|
|
430
624
|
const updated = this.withWrite(() => {
|
|
@@ -722,6 +916,26 @@ export class TrajectoryDatabase {
|
|
|
722
916
|
metadata_json TEXT,
|
|
723
917
|
created_at TEXT NOT NULL
|
|
724
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(`
|
|
725
939
|
CREATE VIEW IF NOT EXISTS v_error_clusters AS
|
|
726
940
|
SELECT tool_name, COALESCE(error_type, 'unknown') AS error_type, COUNT(*) AS occurrences
|
|
727
941
|
FROM tool_calls
|
|
@@ -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
|
*/
|
|
@@ -3,7 +3,6 @@ import { PathResolver } from './path-resolver.js';
|
|
|
3
3
|
import { ConfigService } from './config-service.js';
|
|
4
4
|
import { EventLogService } from './event-log.js';
|
|
5
5
|
import { DictionaryService } from './dictionary-service.js';
|
|
6
|
-
import { TrustEngine } from './trust-engine.js';
|
|
7
6
|
import { HygieneTracker } from './hygiene/tracker.js';
|
|
8
7
|
import { EvolutionReducerImpl } from './evolution-reducer.js';
|
|
9
8
|
import { TrajectoryRegistry } from './trajectory.js';
|
|
@@ -19,7 +18,6 @@ export class WorkspaceContext {
|
|
|
19
18
|
_config;
|
|
20
19
|
_eventLog;
|
|
21
20
|
_dictionary;
|
|
22
|
-
_trust;
|
|
23
21
|
_hygiene;
|
|
24
22
|
_evolutionReducer;
|
|
25
23
|
_trajectory;
|
|
@@ -54,15 +52,6 @@ export class WorkspaceContext {
|
|
|
54
52
|
}
|
|
55
53
|
return this._dictionary;
|
|
56
54
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Trust engine service bound to this workspace.
|
|
59
|
-
*/
|
|
60
|
-
get trust() {
|
|
61
|
-
if (!this._trust) {
|
|
62
|
-
this._trust = new TrustEngine(this.workspaceDir);
|
|
63
|
-
}
|
|
64
|
-
return this._trust;
|
|
65
|
-
}
|
|
66
55
|
/**
|
|
67
56
|
* Hygiene tracking service for this workspace.
|
|
68
57
|
*/
|
|
@@ -148,7 +137,6 @@ export class WorkspaceContext {
|
|
|
148
137
|
this._config = undefined;
|
|
149
138
|
this._eventLog = undefined;
|
|
150
139
|
this._dictionary = undefined;
|
|
151
|
-
this._trust = undefined;
|
|
152
140
|
this._evolutionReducer = undefined;
|
|
153
141
|
this._trajectory = undefined;
|
|
154
142
|
}
|
|
@@ -39,19 +39,19 @@ export declare function analyzeBashCommand(command: string, safePatterns: string
|
|
|
39
39
|
}): BashRiskLevel;
|
|
40
40
|
export interface DynamicThresholdConfig {
|
|
41
41
|
large_change_lines: number;
|
|
42
|
-
|
|
42
|
+
ep_tier_multipliers: Record<string, number>;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
-
* Calculates the dynamic GFI threshold based on
|
|
45
|
+
* Calculates the dynamic GFI threshold based on EP tier and line changes.
|
|
46
46
|
*
|
|
47
47
|
* The threshold is adjusted by:
|
|
48
|
-
* 1.
|
|
48
|
+
* 1. EP tier multiplier (higher tiers get higher thresholds)
|
|
49
49
|
* 2. Large change reduction (big edits lower the threshold to catch more issues)
|
|
50
50
|
*
|
|
51
51
|
* @param baseThreshold - The base GFI threshold (typically 50 for GFI)
|
|
52
|
-
* @param
|
|
52
|
+
* @param epTier - Current EP tier (1-5)
|
|
53
53
|
* @param lineChanges - Number of lines being changed
|
|
54
|
-
* @param config - Configuration with large_change_lines and
|
|
54
|
+
* @param config - Configuration with large_change_lines and ep_tier_multipliers
|
|
55
55
|
* @returns The adjusted threshold (minimum 0)
|
|
56
56
|
*/
|
|
57
|
-
export declare function calculateDynamicThreshold(baseThreshold: number,
|
|
57
|
+
export declare function calculateDynamicThreshold(baseThreshold: number, epTier: number, lineChanges: number, config: DynamicThresholdConfig): number;
|
package/dist/hooks/bash-risk.js
CHANGED
|
@@ -112,22 +112,22 @@ export function analyzeBashCommand(command, safePatterns, dangerousPatterns, log
|
|
|
112
112
|
return 'safe';
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
* Calculates the dynamic GFI threshold based on
|
|
115
|
+
* Calculates the dynamic GFI threshold based on EP tier and line changes.
|
|
116
116
|
*
|
|
117
117
|
* The threshold is adjusted by:
|
|
118
|
-
* 1.
|
|
118
|
+
* 1. EP tier multiplier (higher tiers get higher thresholds)
|
|
119
119
|
* 2. Large change reduction (big edits lower the threshold to catch more issues)
|
|
120
120
|
*
|
|
121
121
|
* @param baseThreshold - The base GFI threshold (typically 50 for GFI)
|
|
122
|
-
* @param
|
|
122
|
+
* @param epTier - Current EP tier (1-5)
|
|
123
123
|
* @param lineChanges - Number of lines being changed
|
|
124
|
-
* @param config - Configuration with large_change_lines and
|
|
124
|
+
* @param config - Configuration with large_change_lines and ep_tier_multipliers
|
|
125
125
|
* @returns The adjusted threshold (minimum 0)
|
|
126
126
|
*/
|
|
127
|
-
export function calculateDynamicThreshold(baseThreshold,
|
|
128
|
-
// 1.
|
|
129
|
-
const
|
|
130
|
-
let threshold = baseThreshold *
|
|
127
|
+
export function calculateDynamicThreshold(baseThreshold, epTier, lineChanges, config) {
|
|
128
|
+
// 1. EP Tier multiplier
|
|
129
|
+
const tierMultiplier = config.ep_tier_multipliers[epTier.toString()] || 1.0;
|
|
130
|
+
let threshold = baseThreshold * tierMultiplier;
|
|
131
131
|
// 2. Large scale modification reduces threshold
|
|
132
132
|
if (lineChanges > config.large_change_lines) {
|
|
133
133
|
const ratio = Math.min(lineChanges / 200, 0.5); // Reduce by up to 50%
|
|
@@ -91,7 +91,7 @@ Reason: ${reason}
|
|
|
91
91
|
4. Retry the operation
|
|
92
92
|
|
|
93
93
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
94
|
-
This is a mandatory security gate. The operation was blocked because the modification exceeds the allowed threshold for your current
|
|
94
|
+
This is a mandatory security gate. The operation was blocked because the modification exceeds the allowed threshold for your current evolution tier.
|
|
95
95
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
96
96
|
};
|
|
97
97
|
}
|
package/dist/hooks/gate.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 2. Thinking OS Checkpoint (P-10): Deep reflection enforcement
|
|
8
8
|
* 3. GFI Gate: Fatigue index-based blocking
|
|
9
9
|
* 4. Bash Mutation Detection: Heuristic for bash file modifications
|
|
10
|
-
* 5. Progressive
|
|
10
|
+
* 5. Progressive Gate: EP tier-based access control
|
|
11
11
|
* 6. Edit Verification (P-03): Exact/fuzzy match for edit operations
|
|
12
12
|
*
|
|
13
13
|
* IMPORTANT: This is the SINGLE AUTHORITATIVE orchestration path.
|
package/dist/hooks/gate.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 2. Thinking OS Checkpoint (P-10): Deep reflection enforcement
|
|
8
8
|
* 3. GFI Gate: Fatigue index-based blocking
|
|
9
9
|
* 4. Bash Mutation Detection: Heuristic for bash file modifications
|
|
10
|
-
* 5. Progressive
|
|
10
|
+
* 5. Progressive Gate: EP tier-based access control
|
|
11
11
|
* 6. Edit Verification (P-03): Exact/fuzzy match for edit operations
|
|
12
12
|
*
|
|
13
13
|
* IMPORTANT: This is the SINGLE AUTHORITATIVE orchestration path.
|
|
@@ -134,7 +134,7 @@ export function handleBeforeToolCall(event, ctx) {
|
|
|
134
134
|
return progressiveGateResult;
|
|
135
135
|
}
|
|
136
136
|
// NOTE: Do NOT return here! Continue to edit verification.
|
|
137
|
-
//
|
|
137
|
+
// All allowed operations (regardless of EP tier) should still run edit verification.
|
|
138
138
|
}
|
|
139
139
|
else {
|
|
140
140
|
// FALLBACK: Legacy Gate Logic (when progressive gate is disabled)
|
package/dist/hooks/gfi-gate.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles Fatigue Index (GFI) based tool blocking with TIER 0-3 classification.
|
|
5
5
|
*
|
|
6
6
|
* **Responsibilities:**
|
|
7
|
-
* - Calculate dynamic GFI thresholds based on
|
|
7
|
+
* - Calculate dynamic GFI thresholds based on EP tier and line changes
|
|
8
8
|
* - Apply tier-based tool blocking:
|
|
9
9
|
* - TIER 0: Read-only tools (never blocked)
|
|
10
10
|
* - TIER 1: Low-risk writes (blocked when GFI >= low_risk_block threshold)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* **Configuration:**
|
|
16
16
|
* - GFI thresholds from config.gfi_gate
|
|
17
|
-
* -
|
|
17
|
+
* - EP tier multipliers for dynamic threshold calculation
|
|
18
18
|
* - Large change adjustments
|
|
19
19
|
*
|
|
20
20
|
* **Block Persistence:**
|
|
@@ -30,7 +30,7 @@ export interface GfiGateConfig {
|
|
|
30
30
|
high_risk_block?: number;
|
|
31
31
|
};
|
|
32
32
|
large_change_lines?: number;
|
|
33
|
-
|
|
33
|
+
ep_tier_multipliers?: Record<string, number>;
|
|
34
34
|
bash_safe_patterns?: string[];
|
|
35
35
|
bash_dangerous_patterns?: string[];
|
|
36
36
|
}
|