principles-disciple 1.143.0 → 1.144.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.
@@ -1,4 +1,4 @@
1
- import type { EventLogEntry, DailyStats, EmpathyEventStats, ToolCallEventData, PainSignalEventData, RuleMatchEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, EmpathyRollbackEventData, DiagnosisTaskEventData, HeartbeatDiagnosisEventData, DiagnosticianReportEventData, PrincipleCandidateEventData, RuleEnforcedEventData, RuleHostEvaluatedEventData, RuleHostBlockedEventData, RuleHostRequireApprovalEventData, RuleHostAutoCorrectProposedEventData, RuleHostAutoCorrectAppliedEventData, RuntimeV2PromptActivationsInjectedEventData, RuleHostUnhealthyEventData } from '../types/event-types.js';
1
+ import type { EventLogEntry, DailyStats, EmpathyEventStats, ToolCallEventData, PainSignalEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, EmpathyRollbackEventData, DiagnosisTaskEventData, HeartbeatDiagnosisEventData, DiagnosticianReportEventData, PrincipleCandidateEventData, RuleEnforcedEventData, RuleHostEvaluatedEventData, RuleHostBlockedEventData, RuleHostRequireApprovalEventData, RuleHostAutoCorrectProposedEventData, RuleHostAutoCorrectAppliedEventData, RuntimeV2PromptActivationsInjectedEventData, RuleHostUnhealthyEventData } from '../types/event-types.js';
2
2
  import type { PluginLogger } from '../openclaw-sdk.js';
3
3
  export declare class EventLog {
4
4
  private readonly logsDir;
@@ -11,7 +11,6 @@ export declare class EventLog {
11
11
  private flushTimer?;
12
12
  private currentEventsFile;
13
13
  private currentDate;
14
- private readonly painScoreSums;
15
14
  constructor(stateDir: string, logger?: PluginLogger);
16
15
  private getEventsFile;
17
16
  private getTodayStr;
@@ -19,7 +18,6 @@ export declare class EventLog {
19
18
  private cleanupOldEventFiles;
20
19
  recordToolCall(sessionId: string | undefined, data: ToolCallEventData): void;
21
20
  recordPainSignal(sessionId: string | undefined, data: PainSignalEventData): void;
22
- recordRuleMatch(sessionId: string | undefined, data: RuleMatchEventData): void;
23
21
  recordRulePromotion(data: RulePromotionEventData): void;
24
22
  recordHookExecution(data: HookExecutionEventData, opts?: {
25
23
  flushImmediately?: boolean;
@@ -15,7 +15,8 @@ export class EventLog {
15
15
  flushTimer;
16
16
  currentEventsFile;
17
17
  currentDate;
18
- painScoreSums = new Map();
18
+ // painScoreSums map removed (PRI-451 Wave 1.5): it only fed the dead
19
+ // stats.pain.avgScore counter, which is also removed.
19
20
  constructor(stateDir, logger) {
20
21
  this.logsDir = path.join(stateDir, 'logs');
21
22
  if (!fs.existsSync(this.logsDir)) {
@@ -68,9 +69,8 @@ export class EventLog {
68
69
  recordPainSignal(sessionId, data) {
69
70
  this.record('pain_signal', 'detected', sessionId, data);
70
71
  }
71
- recordRuleMatch(sessionId, data) {
72
- this.record('rule_match', 'detected', sessionId, data);
73
- }
72
+ // recordRuleMatch removed (PRI-451 Wave 1): dead code. Its only effect was
73
+ // incrementing stats.pain.rulesMatched (also dead, removed in Wave 1.5).
74
74
  recordRulePromotion(data) {
75
75
  this.record('rule_promotion', 'promoted', undefined, data);
76
76
  }
@@ -293,16 +293,8 @@ export class EventLog {
293
293
  }
294
294
  else if (entry.type === 'pain_signal') {
295
295
  const data = entry.data;
296
- stats.pain.signalsDetected++;
297
- stats.pain.maxScore = Math.max(stats.pain.maxScore, data.score);
298
- if (data.source) {
299
- stats.pain.signalsBySource[data.source] = (stats.pain.signalsBySource[data.source] || 0) + 1;
300
- }
301
- const currentSum = this.painScoreSums.get(entry.date) ?? 0;
302
- this.painScoreSums.set(entry.date, currentSum + (data.score || 0));
303
- stats.pain.avgScore = stats.pain.signalsDetected > 0
304
- ? Math.round((currentSum + (data.score || 0)) / stats.pain.signalsDetected)
305
- : 0;
296
+ // stats.pain.* counters removed (PRI-451 Wave 1.5): no live reader.
297
+ // The user_empathy aggregation below (stats.empathy.*) is LIVE and stays.
306
298
  if (data.source === 'user_empathy') {
307
299
  if (data.deduped) {
308
300
  stats.empathy.dedupedCount++;
@@ -358,14 +350,11 @@ export class EventLog {
358
350
  stats.empathy.rollbackCount++;
359
351
  stats.empathy.rolledBackScore += data.originalScore || 0;
360
352
  }
361
- else if (entry.type === 'rule_match') {
362
- const data = entry.data;
363
- if (data.ruleId) {
364
- stats.pain.rulesMatched[data.ruleId] = (stats.pain.rulesMatched[data.ruleId] || 0) + 1;
365
- }
366
- }
353
+ // rule_match handler removed (PRI-451 Wave 1.5): recordRuleMatch is gone
354
+ // (Wave 1.1), so no rule_match events are emitted; stats.pain.rulesMatched
355
+ // was its only consumer and is also removed.
367
356
  else if (entry.type === 'rule_promotion') {
368
- stats.pain.candidatesPromoted++;
357
+ // stats.pain.candidatesPromoted removed (PRI-451 Wave 1.5): dead counter.
369
358
  stats.evolution.rulesPromoted++;
370
359
  }
371
360
  else if (entry.type === 'evolution_task') {
@@ -52,20 +52,12 @@ export declare class EvolutionReducerImpl implements EvolutionReducer {
52
52
  private readonly failureStreak;
53
53
  private lastPromotedAt;
54
54
  private isReplaying;
55
- /** Registered pain_detected callbacks (e.g., PainSignalBridge). */
56
- private readonly _painCallbacks;
57
55
  constructor(opts: {
58
56
  workspaceDir: string;
59
57
  stateDir?: string;
60
58
  });
61
59
  emit(event: EvolutionLoopEvent): void;
62
60
  emitSync(event: EvolutionLoopEvent): void;
63
- /**
64
- * Register a callback for 'pain_detected' events.
65
- * The callback is invoked synchronously within emitSync() after applyEvent completes.
66
- * HG-4: Callbacks are fire-and-forget from the emitSync perspective.
67
- */
68
- on(callback: (event: EvolutionLoopEvent) => void): void;
69
61
  getEventLog(): EvolutionLoopEvent[];
70
62
  getCandidatePrinciples(): Principle[];
71
63
  getProbationPrinciples(): Principle[];
@@ -38,8 +38,9 @@ export class EvolutionReducerImpl {
38
38
  failureStreak = new Map();
39
39
  lastPromotedAt = null;
40
40
  isReplaying = false;
41
- /** Registered pain_detected callbacks (e.g., PainSignalBridge). */
42
- _painCallbacks = [];
41
+ // _painCallbacks pub/sub removed (PRI-451 Wave 1): no code ever registered a
42
+ // callback via .on(). The pain_detected → PainSignalBridge bridge happens via
43
+ // emitPainDetectedEvent (hooks/pain.ts), not this pub/sub layer.
43
44
  constructor(opts) {
44
45
  this.workspaceDir = opts.workspaceDir;
45
46
  this.stateDir = opts.stateDir;
@@ -77,14 +78,9 @@ export class EvolutionReducerImpl {
77
78
  }
78
79
  // Performance: sweepExpiredProbation() moved to getProbationPrinciples() for lazy cleanup
79
80
  }
80
- /**
81
- * Register a callback for 'pain_detected' events.
82
- * The callback is invoked synchronously within emitSync() after applyEvent completes.
83
- * HG-4: Callbacks are fire-and-forget from the emitSync perspective.
84
- */
85
- on(callback) {
86
- this._painCallbacks.push(callback);
87
- }
81
+ // on(callback) pub/sub registration removed (PRI-451 Wave 1): dead code —
82
+ // no caller ever registered a callback. pain_detected events still flow via
83
+ // emitPainDetectedEvent PainSignalBridge, unaffected.
88
84
  getEventLog() {
89
85
  return [...this.memoryEvents];
90
86
  }
@@ -522,15 +518,9 @@ export class EvolutionReducerImpl {
522
518
  if (!this.isReplaying) {
523
519
  this.onPainDetected(event.data, event.ts);
524
520
  }
525
- // PainSignalBridge subscriptions: invoke registered callbacks (fire-and-forget)
526
- for (const cb of this._painCallbacks) {
527
- try {
528
- cb(event);
529
- }
530
- catch {
531
- // Keep the evolution loop resilient — callback errors must not propagate
532
- }
533
- }
521
+ // _painCallbacks dispatch removed (PRI-451 Wave 1): no callback was ever
522
+ // registered via .on() (also removed). The pain_detected → PainSignalBridge
523
+ // bridge flows through emitPainDetectedEvent (hooks/pain.ts), not here.
534
524
  return;
535
525
  case 'candidate_created':
536
526
  this.onCandidateCreated(event.data, event.ts);
@@ -50,7 +50,6 @@ export declare const PD_FILES: {
50
50
  CURRENT_FOCUS: string;
51
51
  WEEK_STATE: string;
52
52
  THINKING_OS_CANDIDATES: string;
53
- SEMANTIC_PAIN: string;
54
53
  EVOLUTION_STREAM: string;
55
54
  EVOLUTION_LOCK: string;
56
55
  };
@@ -64,7 +64,8 @@ export const PD_FILES = {
64
64
  CURRENT_FOCUS: posixJoin(PD_DIRS.OKR, 'CURRENT_FOCUS.md'),
65
65
  WEEK_STATE: posixJoin(PD_DIRS.OKR, 'WEEK_STATE.json'),
66
66
  THINKING_OS_CANDIDATES: posixJoin(PD_DIRS.MEMORY, 'THINKING_OS_CANDIDATES.md'),
67
- SEMANTIC_PAIN: posixJoin(PD_DIRS.PAIN_SAMPLES, 'confusion_samples.md'),
67
+ // SEMANTIC_PAIN (confusion_samples.md) removed (PRI-451 Wave 1): the file
68
+ // had zero readers. The lifecycle write that populated it was also removed.
68
69
  EVOLUTION_STREAM: posixJoin(PD_DIRS.MEMORY, 'evolution.jsonl'),
69
70
  EVOLUTION_LOCK: posixJoin(PD_DIRS.LOCKS, 'evolution'),
70
71
  };
@@ -72,12 +72,9 @@ export const migration = {
72
72
  )`);
73
73
  db.exec(`CREATE INDEX IF NOT EXISTS idx_pain_events_session_id ON pain_events(session_id)`);
74
74
  db.exec(`CREATE INDEX IF NOT EXISTS idx_pain_events_created_at ON pain_events(created_at)`);
75
- // FTS5
76
- db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS pain_events_fts USING fts5(
77
- text,
78
- pain_event_id UNINDEXED,
79
- tokenize='porter unicode61'
80
- )`);
75
+ // pain_events_fts FTS5 virtual table removed (PRI-451 Wave 1): the only
76
+ // reader (searchPainEvents) was dead code. Existing DBs keep the orphan
77
+ // table harmlessly (CREATE was IF NOT EXISTS); new DBs simply don't create it.
81
78
  db.exec(`CREATE TABLE IF NOT EXISTS gate_blocks (
82
79
  id INTEGER PRIMARY KEY AUTOINCREMENT,
83
80
  session_id TEXT,
@@ -370,15 +370,10 @@ export const SCHEMAS = {
370
370
  FROM thinking_model_events GROUP BY date(created_at), model_id ORDER BY day ASC`,
371
371
  },
372
372
  },
373
- fts: {
374
- 'trajectory.pain_events_fts': {
375
- ddl: `CREATE VIRTUAL TABLE IF NOT EXISTS pain_events_fts USING fts5(
376
- text,
377
- pain_event_id UNINDEXED,
378
- tokenize='porter unicode61'
379
- )`,
380
- },
381
- },
373
+ // pain_events_fts FTS5 catalog entry removed (PRI-451 Wave 1): the only
374
+ // reader (searchPainEvents) was dead code. fts is now empty, matching the
375
+ // other DbType catalogs. Existing DBs keep the orphan table harmlessly.
376
+ fts: {},
382
377
  },
383
378
  // ========================================================================
384
379
  // central.db — Aggregated multi-workspace data
@@ -16,22 +16,6 @@ export declare class TrajectoryDatabase {
16
16
  recordUserTurn(input: TrajectoryUserTurnInput): number;
17
17
  recordToolCall(input: TrajectoryToolCallInput): number;
18
18
  recordPainEvent(input: TrajectoryPainEventInput): number;
19
- /**
20
- * Search pain_events using FTS5 full-text search (MEM-04).
21
- * Returns pain events matching the query, ordered by relevance.
22
- */
23
- searchPainEvents(query: string, limit?: number): {
24
- id: number;
25
- sessionId: string;
26
- source: string;
27
- score: number;
28
- reason: string | null;
29
- severity: string | null;
30
- origin: string | null;
31
- confidence: number | null;
32
- text: string | null;
33
- createdAt: string;
34
- }[];
35
19
  recordGateBlock(input: TrajectoryGateBlockInput): void;
36
20
  recordTrustChange(input: TrajectoryTrustChangeInput): void;
37
21
  recordPrincipleEvent(input: TrajectoryPrincipleEventInput): void;
@@ -170,60 +170,14 @@ export class TrajectoryDatabase {
170
170
  }
171
171
  }
172
172
  });
173
- // FTS indexing is best-effort run outside the transaction so it cannot
174
- // roll back the committed pain event row (MEM-03, MEM-04).
175
- if (input.text && insertedId > 0) {
176
- try {
177
- this.db.prepare(`
178
- INSERT INTO pain_events_fts (text, pain_event_id) VALUES (?, ?)
179
- `).run(input.text, insertedId);
180
- }
181
- catch (err) {
182
- // Non-fatal: FTS index is for search convenience, not correctness.
183
- // Log but do not re-throw — the pain event itself is already committed.
184
- console.warn(`[trajectory] FTS index insert failed for pain_event ${insertedId}: ${String(err)}`);
185
- }
186
- }
173
+ // FTS5 index write removed (PRI-451 Wave 1): the only reader (searchPainEvents)
174
+ // was dead code removed in Wave 1.1. The pain event row itself is committed
175
+ // above; nothing reads the FTS index anymore.
187
176
  return insertedId;
188
177
  }
189
- /**
190
- * Search pain_events using FTS5 full-text search (MEM-04).
191
- * Returns pain events matching the query, ordered by relevance.
192
- */
193
- searchPainEvents(query, limit = 10) {
194
- if (!query || query.trim().length === 0) {
195
- return [];
196
- }
197
- // Escape FTS5 special characters and format query for porter tokenizer
198
- const ftsQuery = query.trim().split(/\s+/).map(term => `"${term.replace(/"/g, '""')}"`).join(' ');
199
- try {
200
- const results = this.db.prepare(`
201
- SELECT pe.*
202
- FROM pain_events_fts pf
203
- JOIN pain_events pe ON pe.id = pf.pain_event_id
204
- WHERE pain_events_fts MATCH ?
205
- ORDER BY bm25(pain_events_fts) DESC
206
- LIMIT ?
207
- `).all(ftsQuery, limit);
208
- return results.map(row => ({
209
- id: row.id,
210
- sessionId: row.session_id,
211
- source: row.source,
212
- score: row.score,
213
- reason: row.reason,
214
- severity: row.severity,
215
- origin: row.origin,
216
- confidence: row.confidence,
217
- text: row.text,
218
- createdAt: row.created_at,
219
- }));
220
- }
221
- catch (err) {
222
- // If FTS5 query fails (e.g., syntax error), return empty results
223
- console.warn(`[PD:TrajectoryDatabase] FTS5 search failed: ${String(err)}`);
224
- return [];
225
- }
226
- }
178
+ // searchPainEvents removed (PRI-451 Wave 1): dead code. Its only caller was
179
+ // processDetectionQueue (also removed). The FTS5 index write it read is
180
+ // removed in Wave 1.2.
227
181
  recordGateBlock(input) {
228
182
  this.withWrite(() => {
229
183
  this.db.prepare(`
@@ -1112,14 +1066,9 @@ export class TrajectoryDatabase {
1112
1066
  ON pain_events(canonical_pain_id)
1113
1067
  WHERE canonical_pain_id IS NOT NULL
1114
1068
  `);
1115
- // Create FTS5 virtual table for pain_events text search (MEM-04)
1116
- this.db.exec(`
1117
- CREATE VIRTUAL TABLE IF NOT EXISTS pain_events_fts USING fts5(
1118
- text,
1119
- pain_event_id UNINDEXED,
1120
- tokenize='porter unicode61'
1121
- )
1122
- `);
1069
+ // pain_events_fts FTS5 virtual table creation removed (PRI-451 Wave 1):
1070
+ // the only reader (searchPainEvents) was dead code. Existing DBs keep the
1071
+ // orphan table harmlessly (CREATE was IF NOT EXISTS); new DBs skip it.
1123
1072
  // V2 migration: Add V2 columns to evolution_tasks if they don't exist
1124
1073
  // SQLite does not support IF NOT EXISTS for ADD COLUMN, so we must check manually
1125
1074
  // before each ALTER to avoid "duplicate column name" errors on existing DBs
@@ -120,12 +120,9 @@ export async function extractPainFromSessionFile(sessionFile, ctx) {
120
120
  if (!fs.existsSync(dir))
121
121
  fs.mkdirSync(dir, { recursive: true });
122
122
  fs.appendFileSync(dailyLogPath, entry, 'utf8');
123
- const semanticPath = wctx.resolve('SEMANTIC_PAIN');
124
- const semanticDir = path.dirname(semanticPath);
125
- if (!fs.existsSync(semanticDir))
126
- fs.mkdirSync(semanticDir, { recursive: true });
127
- let semanticEntry = `\n### Sample ${timestamp}\n- Source: compaction\n\n\`\`\`\n${painPoints.join('\n---\n')}\n\`\`\`\n`;
128
- fs.appendFileSync(semanticPath, semanticEntry, 'utf8');
123
+ // SEMANTIC_PAIN (confusion_samples.md) write removed (PRI-451 Wave 1):
124
+ // the file had zero readers. The MEMORY.md write above and the fatal-intercept
125
+ // emitPainDetectedEvent below are both LIVE and remain.
129
126
  const hasFatal = painPoints.some(p => p.includes('[FATAL INTERCEPT]'));
130
127
  if (hasFatal) {
131
128
  // Emit via the Runtime v2 pain chain — no .pain_flag file written
package/dist/hooks/llm.js CHANGED
@@ -194,14 +194,8 @@ export function handleLlmOutput(event, ctx) {
194
194
  const detectionText = isEmpathyAuditPayload(text) ? '' : text;
195
195
  const detectionService = DetectionService.get(wctx.stateDir);
196
196
  const detection = detectionService.detect(detectionText);
197
- if (detection.detected) {
198
- eventLog.recordRuleMatch(ctx.sessionId, {
199
- ruleId: detection.ruleId || detection.source,
200
- layer: detection.source === 'l1_exact' ? 'L1' : (detection.source === 'l2_cache' ? 'L2' : 'L3'),
201
- severity: detection.severity || 0,
202
- textPreview: detectionText.substring(0, 100)
203
- });
204
- }
197
+ // recordRuleMatch call removed (PRI-451 Wave 1): dead code — its only
198
+ // consumer was stats.pain.rulesMatched (dead counter, removed in Wave 1.5).
205
199
  let painScore = detection.detected ? (detection.severity || 0) : 0;
206
200
  let source = detection.detected
207
201
  ? (detection.ruleId ? `llm_${detection.ruleId.toLowerCase()}` : `llm_${detection.source}`)
@@ -1,8 +1,8 @@
1
1
  /* global NodeJS */
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
- import { DictionaryService } from '../core/dictionary-service.js';
5
- import { DetectionService } from '../core/detection-service.js';
4
+ // DetectionService + DictionaryService imports removed — their only consumer
5
+ // (processDetectionQueue) was dead code retired in PRI-451 Wave 1.
6
6
  import { ensureStateTemplates, ensureCorePrinciples } from '../core/init.js';
7
7
  import { SystemLogger } from '../core/system-logger.js';
8
8
  import { WorkspaceContext } from '../core/workspace-context.js';
@@ -351,62 +351,8 @@ async function processEvolutionQueue(wctx, logger, _eventLog, _api) {
351
351
  }
352
352
  }
353
353
  }
354
- async function processDetectionQueue(wctx, api, eventLog) {
355
- const { logger } = api;
356
- try {
357
- const funnel = DetectionService.get(wctx.stateDir);
358
- const queue = funnel.flushQueue();
359
- if (queue.length === 0)
360
- return;
361
- if (logger)
362
- logger.info(`[PD:EvolutionWorker] Processing ${queue.length} items from detection funnel.`);
363
- const dictionary = DictionaryService.get(wctx.stateDir);
364
- for (const text of queue) {
365
- const match = dictionary.match(text);
366
- if (match) {
367
- if (eventLog) {
368
- eventLog.recordRuleMatch(undefined, {
369
- ruleId: match.ruleId,
370
- layer: 'L2',
371
- severity: match.severity,
372
- textPreview: text.substring(0, 100)
373
- });
374
- }
375
- }
376
- else {
377
- // L3 semantic search via trajectory database FTS5 (MEM-04)
378
- if (wctx.trajectory) {
379
- const searchResults = wctx.trajectory.searchPainEvents(text, 5);
380
- if (searchResults.length > 0) {
381
- const topResult = searchResults[0];
382
- if (!topResult)
383
- continue;
384
- // Found similar pain events - record as L3 semantic hit
385
- if (eventLog) {
386
- eventLog.recordRuleMatch(undefined, {
387
- ruleId: 'l3_semantic',
388
- layer: 'L3',
389
- severity: topResult.score,
390
- textPreview: text.substring(0, 100)
391
- });
392
- }
393
- // Update detection funnel cache with L3 hit result
394
- funnel.updateCache(text, { detected: true, severity: topResult.score });
395
- // Don't track as candidate - this is a confirmed L3 hit
396
- if (logger)
397
- logger.info(`[PD:EvolutionWorker] L3 semantic hit: found ${searchResults.length} similar pain events for "${text.substring(0, 50)}..."`);
398
- continue;
399
- }
400
- }
401
- // No L3 hit — pain candidate tracking removed (D-05)
402
- }
403
- }
404
- }
405
- catch (err) {
406
- if (logger)
407
- logger.warn(`[PD:EvolutionWorker] Detection queue failed: ${String(err)}`);
408
- }
409
- }
354
+ // processDetectionQueue removed (PRI-451 Wave 1): dead code. Its only effects
355
+ // were recordRuleMatch (dead) and searchPainEvents (dead) — see PRI-451.
410
356
  // PAIN_CANDIDATES system removed (D-05, D-06): trackPainCandidate and processPromotion deleted
411
357
  // Evolution queue is now the single active pain→principle path
412
358
  export async function registerEvolutionTaskSession(workspaceResolve, taskId, sessionKey, logger) {
@@ -544,9 +490,7 @@ export const EvolutionWorkerService = {
544
490
  cycleResult.queue = queueResult.queue;
545
491
  if (queueResult.errors)
546
492
  cycleResult.errors.push(...queueResult.errors);
547
- if (api) {
548
- await processDetectionQueue(wctx, api, eventLog);
549
- }
493
+ // processDetectionQueue removed (PRI-451 Wave 1) — was dead code.
550
494
  // processPromotion removed (D-06) — promotion via PAIN_CANDIDATES no longer needed
551
495
  // Correction Observer extracted to independent service (PRI-293) — no longer runs on EvolutionWorker heartbeat
552
496
  try {
@@ -630,9 +574,7 @@ export const EvolutionWorkerService = {
630
574
  if (queueResult.errors.length > 0) {
631
575
  queueResult.errors.forEach((e) => logger?.error?.(`[PD:EvolutionWorker] Startup cycle error: ${e}`));
632
576
  }
633
- if (api) {
634
- await processDetectionQueue(wctx, api, eventLog);
635
- }
577
+ // processDetectionQueue removed (PRI-451 Wave 1) — was dead code.
636
578
  // processPromotion removed (D-06)
637
579
  timeoutId = setTimeout(runCycle, interval);
638
580
  timeoutId.unref();
@@ -1,2 +1,2 @@
1
- export type { EventType, EventCategory, EventLogEntry, ToolCallEventData, PainSignalEventData, RuleMatchEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, EmpathyRollbackEventData, HeartbeatDiagnosisEventData, DiagnosisTaskEventData, DiagnosticianReportEventData, PrincipleCandidateEventData, RuleEnforcedEventData, RuleHostEvaluatedEventData, RuleHostBlockedEventData, RuleHostRequireApprovalEventData, RuleHostAutoCorrectProposedEventData, RuleHostAutoCorrectAppliedEventData, RuntimeV2PromptActivationsInjectedEventData, RuleHostUnhealthyEventData, ToolCallStats, ErrorStats, PainStats, EmpathyEventStats, GfiStats, EvolutionStats as EventEvolutionStats, HookStats, DailyStats, } from '@principles/core/runtime-v2';
1
+ export type { EventType, EventCategory, EventLogEntry, ToolCallEventData, PainSignalEventData, RuleMatchEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, EmpathyRollbackEventData, HeartbeatDiagnosisEventData, DiagnosisTaskEventData, DiagnosticianReportEventData, PrincipleCandidateEventData, RuleEnforcedEventData, RuleHostEvaluatedEventData, RuleHostBlockedEventData, RuleHostRequireApprovalEventData, RuleHostAutoCorrectProposedEventData, RuleHostAutoCorrectAppliedEventData, RuntimeV2PromptActivationsInjectedEventData, RuleHostUnhealthyEventData, ToolCallStats, ErrorStats, EmpathyEventStats, GfiStats, EvolutionStats as EventEvolutionStats, HookStats, DailyStats, } from '@principles/core/runtime-v2';
2
2
  export { createEmptyDailyStats, } from '@principles/core/runtime-v2';
@@ -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.143.0",
5
+ "version": "1.144.0",
6
6
  "activation": {
7
7
  "onCapabilities": [
8
8
  "hook"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "1.143.0",
3
+ "version": "1.144.0",
4
4
  "description": "Native OpenClaw plugin for Principles Disciple",
5
5
  "type": "module",
6
6
  "main": "./dist/bundle.js",