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.
Files changed (129) hide show
  1. package/dist/commands/context.js +5 -15
  2. package/dist/commands/evolution-status.js +29 -48
  3. package/dist/commands/export.js +61 -8
  4. package/dist/commands/nocturnal-review.d.ts +24 -0
  5. package/dist/commands/nocturnal-review.js +265 -0
  6. package/dist/commands/nocturnal-rollout.d.ts +27 -0
  7. package/dist/commands/nocturnal-rollout.js +671 -0
  8. package/dist/commands/nocturnal-train.d.ts +25 -0
  9. package/dist/commands/nocturnal-train.js +919 -0
  10. package/dist/commands/pain.js +8 -21
  11. package/dist/config/defaults/runtime.d.ts +40 -0
  12. package/dist/config/defaults/runtime.js +44 -0
  13. package/dist/config/errors.d.ts +84 -0
  14. package/dist/config/errors.js +94 -0
  15. package/dist/config/index.d.ts +7 -0
  16. package/dist/config/index.js +7 -0
  17. package/dist/constants/diagnostician.d.ts +0 -4
  18. package/dist/constants/diagnostician.js +0 -4
  19. package/dist/constants/tools.d.ts +2 -2
  20. package/dist/constants/tools.js +1 -1
  21. package/dist/core/adaptive-thresholds.d.ts +186 -0
  22. package/dist/core/adaptive-thresholds.js +300 -0
  23. package/dist/core/config.d.ts +2 -38
  24. package/dist/core/config.js +6 -61
  25. package/dist/core/control-ui-db.d.ts +27 -0
  26. package/dist/core/control-ui-db.js +18 -0
  27. package/dist/core/event-log.d.ts +1 -2
  28. package/dist/core/event-log.js +0 -3
  29. package/dist/core/evolution-engine.js +1 -21
  30. package/dist/core/evolution-reducer.d.ts +7 -1
  31. package/dist/core/evolution-reducer.js +56 -4
  32. package/dist/core/evolution-types.d.ts +61 -9
  33. package/dist/core/evolution-types.js +31 -9
  34. package/dist/core/external-training-contract.d.ts +276 -0
  35. package/dist/core/external-training-contract.js +269 -0
  36. package/dist/core/local-worker-routing.d.ts +175 -0
  37. package/dist/core/local-worker-routing.js +525 -0
  38. package/dist/core/model-deployment-registry.d.ts +218 -0
  39. package/dist/core/model-deployment-registry.js +503 -0
  40. package/dist/core/model-training-registry.d.ts +295 -0
  41. package/dist/core/model-training-registry.js +475 -0
  42. package/dist/core/nocturnal-arbiter.d.ts +159 -0
  43. package/dist/core/nocturnal-arbiter.js +534 -0
  44. package/dist/core/nocturnal-candidate-scoring.d.ts +137 -0
  45. package/dist/core/nocturnal-candidate-scoring.js +266 -0
  46. package/dist/core/nocturnal-compliance.d.ts +175 -0
  47. package/dist/core/nocturnal-compliance.js +824 -0
  48. package/dist/core/nocturnal-dataset.d.ts +224 -0
  49. package/dist/core/nocturnal-dataset.js +443 -0
  50. package/dist/core/nocturnal-executability.d.ts +85 -0
  51. package/dist/core/nocturnal-executability.js +331 -0
  52. package/dist/core/nocturnal-export.d.ts +124 -0
  53. package/dist/core/nocturnal-export.js +275 -0
  54. package/dist/core/nocturnal-paths.d.ts +124 -0
  55. package/dist/core/nocturnal-paths.js +214 -0
  56. package/dist/core/nocturnal-trajectory-extractor.d.ts +242 -0
  57. package/dist/core/nocturnal-trajectory-extractor.js +307 -0
  58. package/dist/core/nocturnal-trinity.d.ts +311 -0
  59. package/dist/core/nocturnal-trinity.js +880 -0
  60. package/dist/core/path-resolver.js +2 -1
  61. package/dist/core/paths.d.ts +6 -0
  62. package/dist/core/paths.js +6 -0
  63. package/dist/core/principle-training-state.d.ts +121 -0
  64. package/dist/core/principle-training-state.js +321 -0
  65. package/dist/core/promotion-gate.d.ts +238 -0
  66. package/dist/core/promotion-gate.js +529 -0
  67. package/dist/core/session-tracker.d.ts +10 -0
  68. package/dist/core/session-tracker.js +14 -0
  69. package/dist/core/shadow-observation-registry.d.ts +217 -0
  70. package/dist/core/shadow-observation-registry.js +308 -0
  71. package/dist/core/training-program.d.ts +233 -0
  72. package/dist/core/training-program.js +433 -0
  73. package/dist/core/trajectory.d.ts +155 -1
  74. package/dist/core/trajectory.js +292 -8
  75. package/dist/core/workspace-context.d.ts +0 -6
  76. package/dist/core/workspace-context.js +0 -12
  77. package/dist/hooks/bash-risk.d.ts +57 -0
  78. package/dist/hooks/bash-risk.js +137 -0
  79. package/dist/hooks/edit-verification.d.ts +62 -0
  80. package/dist/hooks/edit-verification.js +256 -0
  81. package/dist/hooks/gate-block-helper.d.ts +44 -0
  82. package/dist/hooks/gate-block-helper.js +119 -0
  83. package/dist/hooks/gate.d.ts +18 -0
  84. package/dist/hooks/gate.js +62 -751
  85. package/dist/hooks/gfi-gate.d.ts +40 -0
  86. package/dist/hooks/gfi-gate.js +113 -0
  87. package/dist/hooks/pain.js +6 -9
  88. package/dist/hooks/progressive-trust-gate.d.ts +51 -0
  89. package/dist/hooks/progressive-trust-gate.js +89 -0
  90. package/dist/hooks/prompt.d.ts +11 -11
  91. package/dist/hooks/prompt.js +167 -77
  92. package/dist/hooks/subagent.js +43 -6
  93. package/dist/hooks/thinking-checkpoint.d.ts +37 -0
  94. package/dist/hooks/thinking-checkpoint.js +51 -0
  95. package/dist/http/principles-console-route.js +13 -3
  96. package/dist/i18n/commands.js +8 -8
  97. package/dist/index.js +129 -28
  98. package/dist/service/central-database.js +2 -1
  99. package/dist/service/control-ui-query-service.d.ts +1 -1
  100. package/dist/service/control-ui-query-service.js +3 -3
  101. package/dist/service/evolution-query-service.d.ts +1 -1
  102. package/dist/service/evolution-query-service.js +5 -5
  103. package/dist/service/evolution-worker.d.ts +52 -4
  104. package/dist/service/evolution-worker.js +328 -16
  105. package/dist/service/nocturnal-runtime.d.ts +183 -0
  106. package/dist/service/nocturnal-runtime.js +352 -0
  107. package/dist/service/nocturnal-service.d.ts +163 -0
  108. package/dist/service/nocturnal-service.js +787 -0
  109. package/dist/service/nocturnal-target-selector.d.ts +145 -0
  110. package/dist/service/nocturnal-target-selector.js +315 -0
  111. package/dist/service/phase3-input-filter.d.ts +48 -12
  112. package/dist/service/phase3-input-filter.js +84 -18
  113. package/dist/service/runtime-summary-service.d.ts +34 -10
  114. package/dist/service/runtime-summary-service.js +87 -48
  115. package/dist/tools/deep-reflect.js +2 -1
  116. package/dist/types/event-types.d.ts +4 -10
  117. package/dist/types/runtime-summary.d.ts +47 -0
  118. package/dist/types/runtime-summary.js +1 -0
  119. package/dist/types.d.ts +0 -3
  120. package/dist/types.js +0 -2
  121. package/openclaw.plugin.json +1 -1
  122. package/package.json +1 -1
  123. package/templates/langs/en/skills/pd-mentor/SKILL.md +5 -5
  124. package/templates/langs/zh/skills/pd-mentor/SKILL.md +5 -5
  125. package/templates/pain_settings.json +0 -6
  126. package/dist/commands/trust.d.ts +0 -4
  127. package/dist/commands/trust.js +0 -78
  128. package/dist/core/trust-engine.d.ts +0 -96
  129. package/dist/core/trust-engine.js +0 -286
@@ -106,14 +106,23 @@ function handleApiRoute(api, pathname, req, res) {
106
106
  service.dispose();
107
107
  }
108
108
  };
109
+ // Helper to parse and clamp days parameter
110
+ const parseDays = (param) => {
111
+ const value = param ? Number(param) : 30;
112
+ if (!Number.isFinite(value) || value < 1)
113
+ return 30;
114
+ return Math.min(365, Math.max(1, Math.floor(value)));
115
+ };
109
116
  if (pathname === `${API_PREFIX}/overview` && method === 'GET') {
110
- return done(() => service.getOverview());
117
+ const days = parseDays(url.searchParams.get('days'));
118
+ return done(() => service.getOverview(days));
111
119
  }
112
120
  if (pathname === `${API_PREFIX}/central/overview` && method === 'GET') {
121
+ const days = parseDays(url.searchParams.get('days'));
113
122
  return done(() => {
114
123
  const centralDb = getCentralDatabase();
115
124
  const stats = centralDb.getOverviewStats();
116
- const trend = centralDb.getDailyTrend(14);
125
+ const trend = centralDb.getDailyTrend(days);
117
126
  const regressions = centralDb.getTopRegressions(5);
118
127
  const thinkingStats = centralDb.getThinkingModelStats();
119
128
  const workspaces = centralDb.getWorkspaces();
@@ -370,9 +379,10 @@ function handleApiRoute(api, pathname, req, res) {
370
379
  });
371
380
  }
372
381
  if (pathname === `${API_PREFIX}/evolution/stats` && method === 'GET') {
382
+ const days = parseDays(url.searchParams.get('days'));
373
383
  return done(() => {
374
384
  const evoService = evolutionService();
375
- return evoService.getStats();
385
+ return evoService.getStats(days);
376
386
  });
377
387
  }
378
388
  const evolutionTraceMatch = pathname.match(/^\/plugins\/principles\/api\/evolution\/trace\/([^/]+)$/);
@@ -46,10 +46,6 @@ export const commandDescriptions = {
46
46
  zh: '工作区清理与大扫除',
47
47
  en: 'Workspace cleanup and grooming'
48
48
  },
49
- 'pd-trust': {
50
- zh: '查看信任分数和权限等级 (1-4)',
51
- en: 'View trust score and permission stage (1-4)'
52
- },
53
49
  'pd-help': {
54
50
  zh: '显示所有命令和使用指南',
55
51
  en: 'Show all commands and usage guide'
@@ -59,8 +55,8 @@ export const commandDescriptions = {
59
55
  en: 'View system status (GFI, Pain dictionary)'
60
56
  },
61
57
  'pd-context': {
62
- zh: '控制上下文注入 [status|thinking|trust|reflection|focus|preset] - 输入 /pd-context help 查看详情',
63
- en: 'Control context injection [status|thinking|trust|reflection|focus|preset] - Type /pd-context help for details'
58
+ zh: '控制上下文注入 [status|thinking|reflection|focus|preset] - 输入 /pd-context help 查看详情',
59
+ en: 'Control context injection [status|thinking|reflection|focus|preset] - Type /pd-context help for details'
64
60
  },
65
61
  'pd-focus': {
66
62
  zh: '管理 CURRENT_FOCUS.md [status|history|compress|rollback] - 查看/压缩/回滚焦点文件',
@@ -79,12 +75,16 @@ export const commandDescriptions = {
79
75
  en: 'Rollback empathy event penalty <event-id>|last'
80
76
  },
81
77
  'pd-export': {
82
- zh: '导出 analytics 或纠错样本 [analytics|corrections --redacted]',
83
- en: 'Export analytics or correction samples [analytics|corrections --redacted]'
78
+ zh: '导出数据 [analytics|corrections --redacted|orpo --family=<model>|orpo-list]',
79
+ en: 'Export data [analytics|corrections --redacted|orpo --family=<model>|orpo-list]'
84
80
  },
85
81
  'pd-samples': {
86
82
  zh: '查看或审核纠错样本 [review approve|reject <sample-id> [note]]',
87
83
  en: 'List or review correction samples [review approve|reject <sample-id> [note]]'
84
+ },
85
+ 'pd-nocturnal-review': {
86
+ zh: '审核 nocturnal 数据集样本 [list|show|approve|reject|set-family|stats]',
87
+ en: 'Review nocturnal dataset samples [list|show|approve|reject|set-family|stats]'
88
88
  }
89
89
  };
90
90
  /**
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import * as crypto from 'crypto';
2
+ import { classifyTask } from './core/local-worker-routing.js';
3
+ import { completeShadowObservation, recordShadowRouting } from './core/shadow-observation-registry.js';
1
4
  import { getCommandDescription } from './i18n/commands.js';
2
5
  import { handleBeforePromptBuild } from './hooks/prompt.js';
3
6
  import { handleBeforeToolCall } from './hooks/gate.js';
@@ -11,7 +14,6 @@ import { handleInitStrategy, handleManageOkr } from './commands/strategy.js';
11
14
  import { handleBootstrapTools, handleResearchTools } from './commands/capabilities.js';
12
15
  import { handleThinkingOs } from './commands/thinking-os.js';
13
16
  import { handleEvolveTask } from './commands/evolver.js';
14
- import { handleTrustCommand } from './commands/trust.js';
15
17
  import { handlePainCommand } from './commands/pain.js';
16
18
  import { handleContextCommand } from './commands/context.js';
17
19
  import { handleFocusCommand } from './commands/focus.js';
@@ -20,6 +22,9 @@ import { handleEvolutionStatusCommand } from './commands/evolution-status.js';
20
22
  import { handlePrincipleRollbackCommand } from './commands/principle-rollback.js';
21
23
  import { handleExportCommand } from './commands/export.js';
22
24
  import { handleSamplesCommand } from './commands/samples.js';
25
+ import { handleNocturnalReviewCommand } from './commands/nocturnal-review.js';
26
+ import { handleNocturnalTrainCommand } from './commands/nocturnal-train.js';
27
+ import { handleNocturnalRolloutCommand } from './commands/nocturnal-rollout.js';
23
28
  import { EvolutionWorkerService } from './service/evolution-worker.js';
24
29
  import { TrajectoryService } from './service/trajectory-service.js';
25
30
  import { ensureWorkspaceTemplates } from './core/init.js';
@@ -30,6 +35,23 @@ import { PathResolver } from './core/path-resolver.js';
30
35
  import { createPrinciplesConsoleRoute } from './http/principles-console-route.js';
31
36
  // Track initialization to avoid repeated calls
32
37
  let workspaceInitialized = false;
38
+ // Map from childSessionKey → shadowObservationId
39
+ // Used to complete shadow observations when subagent ends
40
+ const pendingShadowObservations = new Map();
41
+ // PD local worker profiles that are managed by the shadow routing policy
42
+ const PD_LOCAL_PROFILES = new Set(['local-reader', 'local-editor']);
43
+ function computeRuntimeShadowTaskFingerprint(event) {
44
+ const payload = {
45
+ childSessionKey: event.childSessionKey,
46
+ agentId: event.agentId,
47
+ label: event.label ?? '',
48
+ mode: event.mode,
49
+ threadRequested: event.threadRequested,
50
+ requesterChannel: event.requester?.channel ?? '',
51
+ requesterThreadId: event.requester?.threadId ?? '',
52
+ };
53
+ return crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex').slice(0, 16);
54
+ }
33
55
  const plugin = {
34
56
  name: "Principles Disciple",
35
57
  description: "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
@@ -119,13 +141,61 @@ const plugin = {
119
141
  }
120
142
  });
121
143
  // ── Hook: Subagent Loop Closure ──
122
- api.on('subagent_spawning', (_event, _ctx) => {
123
- // No-op for now, just to satisfy the interface expected by tests.
124
- return { status: 'ok' };
144
+ api.on('subagent_spawning', (event, ctx) => {
145
+ try {
146
+ const workspaceDir = ctx.workspaceDir || api.resolvePath('.');
147
+ const { agentId, childSessionKey } = event;
148
+ // Only handle PD local worker profiles
149
+ if (!PD_LOCAL_PROFILES.has(agentId)) {
150
+ return { status: 'ok' };
151
+ }
152
+ // Use the real runtime hook to record shadow evidence. We still consult the
153
+ // routing/deployment state here, but the observation itself must originate
154
+ // from actual subagent execution rather than an operator command path.
155
+ const routingInput = { targetProfile: agentId };
156
+ const decision = classifyTask(routingInput, workspaceDir);
157
+ const shouldRecordShadow = decision.activeCheckpointState === 'shadow_ready' &&
158
+ !!decision.activeCheckpointId &&
159
+ decision.deploymentCheck.routingEnabled &&
160
+ decision.deploymentCheck.checkpointDeployable;
161
+ if (shouldRecordShadow) {
162
+ const observation = recordShadowRouting(workspaceDir, {
163
+ checkpointId: decision.activeCheckpointId,
164
+ workerProfile: agentId,
165
+ taskFingerprint: computeRuntimeShadowTaskFingerprint(event),
166
+ });
167
+ pendingShadowObservations.set(childSessionKey, observation.observationId);
168
+ }
169
+ return { status: 'ok' };
170
+ }
171
+ catch (err) {
172
+ api.logger.error(`[PD] Error in subagent_spawning shadow routing: ${String(err)}`);
173
+ return { status: 'ok' }; // Don't block spawn on shadow observation errors
174
+ }
125
175
  });
126
176
  api.on('subagent_ended', (event, ctx) => {
127
177
  try {
128
178
  const workspaceDir = api.resolvePath('.');
179
+ // Complete any pending shadow observation for this subagent session
180
+ const shadowObsId = pendingShadowObservations.get(event.targetSessionKey);
181
+ if (shadowObsId && workspaceDir) {
182
+ try {
183
+ const outcome = event.outcome === 'ok'
184
+ ? 'accepted'
185
+ : event.outcome === 'error'
186
+ ? 'rejected'
187
+ : 'escalated';
188
+ completeShadowObservation(workspaceDir, {
189
+ observationId: shadowObsId,
190
+ outcome,
191
+ failureSignals: event.outcome === 'error' ? { threwException: true, timedOut: false, invalidOutput: false, profileRejected: false, extra: {} } : undefined,
192
+ });
193
+ pendingShadowObservations.delete(event.targetSessionKey);
194
+ }
195
+ catch (err) {
196
+ api.logger.error(`[PD] Failed to complete shadow observation: ${String(err)}`);
197
+ }
198
+ }
129
199
  handleSubagentEnded(event, { ...ctx, workspaceDir, api });
130
200
  }
131
201
  catch (err) {
@@ -223,10 +293,10 @@ const plugin = {
223
293
  | 命令 | 用途 | 使用时机 |
224
294
  |------|------|----------|
225
295
  | \`/pd-status\` | 查看进化状态 | 想了解当前 GFI 和 Pain 情况 |
226
- | \`/pd-trust\` | 查看信任分数 | 想知道自己的权限等级 |
227
296
  | \`/pd-focus\` | 焦点文件管理 | 查看/压缩/回滚历史版本 |
228
- | \`/pd-export\` | 导出分析/样本 | 导出 analytics 或纠错样本 |
297
+ | \`/pd-export\` | 导出数据 | 导出 analytics/corrections/orpo |
229
298
  | \`/pd-samples\` | 审核纠错样本 | 查看待审核样本并批准/拒绝 |
299
+ | \`/pd-nocturnal-review\` | 审核 nocturnal 样本 | 审核 nocturnal 训练样本并导出 ORPO |
230
300
 
231
301
  ## ⚙️ 配置管理
232
302
  | 命令 | 用途 | 使用时机 |
@@ -259,12 +329,6 @@ const plugin = {
259
329
  /pd-context status
260
330
  \`\`\`
261
331
 
262
- **查看信任分数:**
263
- \`\`\`
264
- /pd-trust
265
- \`\`\`
266
-
267
- ---
268
332
  🔍 输入任意命令后加 \`help\` 可查看详细帮助,如 \`/pd-context help\`
269
333
  `.trim() };
270
334
  }
@@ -282,10 +346,10 @@ const plugin = {
282
346
  | Command | Purpose | When to Use |
283
347
  |---------|---------|-------------|
284
348
  | \`/pd-status\` | View evolution status | Check GFI and Pain status |
285
- | \`/pd-trust\` | View trust score | Check your permission level |
286
349
  | \`/pd-focus\` | Focus file management | View/compress/rollback history |
287
- | \`/pd-export\` | Export analytics/samples | Export analytics or correction samples |
350
+ | \`/pd-export\` | Export data | Export analytics/corrections/orpo |
288
351
  | \`/pd-samples\` | Review correction samples | Review pending correction samples |
352
+ | \`/pd-nocturnal-review\` | Review nocturnal samples | Review nocturnal training samples and export ORPO |
289
353
 
290
354
  ## ⚙️ Configuration
291
355
  | Command | Purpose | When to Use |
@@ -318,25 +382,11 @@ const plugin = {
318
382
  /pd-context status
319
383
  \`\`\`
320
384
 
321
- **Check trust score:**
322
- \`\`\`
323
- /pd-trust
324
- \`\`\`
325
-
326
- ---
327
385
  🔍 Add \`help\` after any command for details, e.g., \`/pd-context help\`
328
386
  `.trim() };
329
387
  }
330
388
  }
331
389
  });
332
- api.registerCommand({
333
- name: "pd-trust",
334
- description: getCommandDescription('pd-trust', language),
335
- handler: (ctx) => {
336
- const workspaceDir = api.resolvePath('.');
337
- return { text: handleTrustCommand({ ...ctx, workspaceDir }) };
338
- }
339
- });
340
390
  api.registerCommand({
341
391
  name: "pd-status",
342
392
  description: getCommandDescription('pd-status', language),
@@ -474,6 +524,57 @@ const plugin = {
474
524
  }
475
525
  }
476
526
  });
527
+ api.registerCommand({
528
+ name: "pd-nocturnal-review",
529
+ description: 'Review nocturnal dataset samples [list|show|approve|reject|set-family|stats]',
530
+ acceptsArgs: true,
531
+ handler: (ctx) => {
532
+ try {
533
+ const workspaceDir = api.resolvePath('.');
534
+ if (ctx.config)
535
+ ctx.config.workspaceDir = workspaceDir;
536
+ return handleNocturnalReviewCommand(ctx);
537
+ }
538
+ catch (err) {
539
+ api.logger.error(`[PD] Command /pd-nocturnal-review failed: ${String(err)}`);
540
+ return { text: language === 'zh' ? "Nocturnal review 命令执行失败,请检查日志。" : "Nocturnal review command failed. Check logs." };
541
+ }
542
+ }
543
+ });
544
+ api.registerCommand({
545
+ name: "nocturnal-train",
546
+ description: 'Nocturnal training operations [create-experiment|show-experiment|import-result|attach-eval|show-lineage|list-experiments|list-checkpoints|stats]',
547
+ acceptsArgs: true,
548
+ handler: (ctx) => {
549
+ try {
550
+ const workspaceDir = api.resolvePath('.');
551
+ if (ctx.config)
552
+ ctx.config.workspaceDir = workspaceDir;
553
+ return handleNocturnalTrainCommand(ctx);
554
+ }
555
+ catch (err) {
556
+ api.logger.error(`[PD] Command /nocturnal-train failed: ${String(err)}`);
557
+ return { text: language === 'zh' ? "Nocturnal train 命令执行失败,请检查日志。" : "Nocturnal train command failed. Check logs." };
558
+ }
559
+ }
560
+ });
561
+ api.registerCommand({
562
+ name: "nocturnal-rollout",
563
+ description: 'Nocturnal rollout and promotion [evaluate-promotion|advance-promotion|bind|enable-routing|disable-routing|rollback|status|show-promotion]',
564
+ acceptsArgs: true,
565
+ handler: (ctx) => {
566
+ try {
567
+ const workspaceDir = api.resolvePath('.');
568
+ if (ctx.config)
569
+ ctx.config.workspaceDir = workspaceDir;
570
+ return handleNocturnalRolloutCommand(ctx);
571
+ }
572
+ catch (err) {
573
+ api.logger.error(`[PD] Command /nocturnal-rollout failed: ${String(err)}`);
574
+ return { text: language === 'zh' ? "Nocturnal rollout 命令执行失败,请检查日志。" : "Nocturnal rollout command failed. Check logs." };
575
+ }
576
+ }
577
+ });
477
578
  api.registerTool(createDeepReflectTool(api));
478
579
  }
479
580
  };
@@ -2,6 +2,7 @@ import Database from 'better-sqlite3';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
+ import { WorkspaceNotFoundError } from '../config/index.js';
5
6
  const CENTRAL_DB_DIR = '.central';
6
7
  const CENTRAL_DB_NAME = 'aggregated.db';
7
8
  /**
@@ -176,7 +177,7 @@ export class CentralDatabase {
176
177
  syncWorkspace(workspaceName) {
177
178
  const workspace = this.workspaces.find(w => w.name === workspaceName);
178
179
  if (!workspace) {
179
- throw new Error(`Workspace not found: ${workspaceName}`);
180
+ throw new WorkspaceNotFoundError(workspaceName);
180
181
  }
181
182
  const trajectoryDbPath = path.join(workspace.path, '.state', 'trajectory.db');
182
183
  if (!fs.existsSync(trajectoryDbPath)) {
@@ -210,7 +210,7 @@ export declare class ControlUiQueryService {
210
210
  private readonly uiDb;
211
211
  constructor(workspaceDir: string);
212
212
  dispose(): void;
213
- getOverview(): OverviewResponse;
213
+ getOverview(days?: number): OverviewResponse;
214
214
  listSamples(filters?: SampleListFilters): SamplesResponse;
215
215
  getSampleDetail(sampleId: string): SampleDetailResponse | null;
216
216
  reviewSample(sampleId: string, decision: 'approved' | 'rejected', note?: string): import("../core/trajectory.js").CorrectionSampleRecord;
@@ -43,7 +43,7 @@ export class ControlUiQueryService {
43
43
  dispose() {
44
44
  this.uiDb.dispose();
45
45
  }
46
- getOverview() {
46
+ getOverview(days = 30) {
47
47
  const stats = this.trajectory.getDataStats();
48
48
  const regressionRows = this.uiDb.all('SELECT tool_name, error_type, occurrences FROM v_error_clusters ORDER BY occurrences DESC LIMIT 5');
49
49
  const failureStats = this.uiDb.get(`
@@ -92,8 +92,8 @@ export class ControlUiQueryService {
92
92
  FROM v_daily_metrics dm
93
93
  LEFT JOIN thinking_daily td ON td.day = dm.day
94
94
  ORDER BY dm.day DESC
95
- LIMIT 14
96
- `).reverse();
95
+ LIMIT ?
96
+ `, days).reverse();
97
97
  const counters = Object.fromEntries(sampleCounters.map((row) => [row.review_status, Number(row.total)]));
98
98
  const activeModels = this.uiDb.get('SELECT COUNT(DISTINCT model_id) AS count FROM thinking_model_events')?.count ?? 0;
99
99
  return {
@@ -147,7 +147,7 @@ export declare class EvolutionQueryService {
147
147
  /**
148
148
  * 获取统计数据
149
149
  */
150
- getStats(): EvolutionStatsResponse;
150
+ getStats(days?: number): EvolutionStatsResponse;
151
151
  }
152
152
  /**
153
153
  * 获取 EvolutionQueryService 实例(单例)
@@ -186,19 +186,19 @@ export class EvolutionQueryService {
186
186
  /**
187
187
  * 获取统计数据
188
188
  */
189
- getStats() {
189
+ getStats(days = 30) {
190
190
  // 获取基础统计
191
191
  const stats = this.trajectory.getEvolutionStats();
192
- // 获取近期活动(最近 7 天)
192
+ // 获取近期活动
193
193
  const now = new Date();
194
- const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
194
+ const daysAgo = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
195
195
  const recentTasks = this.trajectory.listEvolutionTasks({
196
- dateFrom: sevenDaysAgo.toISOString(),
196
+ dateFrom: daysAgo.toISOString(),
197
197
  limit: 10000,
198
198
  });
199
199
  // 按天分组
200
200
  const activityByDay = new Map();
201
- for (let i = 0; i < 7; i++) {
201
+ for (let i = 0; i < days; i++) {
202
202
  const day = new Date(now.getTime() - i * 24 * 60 * 60 * 1000);
203
203
  const dayStr = day.toISOString().split('T')[0];
204
204
  activityByDay.set(dayStr, { created: 0, completed: 0 });
@@ -1,10 +1,44 @@
1
1
  import type { OpenClawPluginServiceContext, OpenClawPluginApi } from '../openclaw-sdk.js';
2
2
  import { WorkspaceContext } from '../core/workspace-context.js';
3
+ /**
4
+ * Queue V2 Schema - Supports multiple task kinds while preserving pain_diagnosis semantics.
5
+ *
6
+ * taskKind semantics:
7
+ * - pain_diagnosis: User-adjacent, triggers HEARTBEAT, injects into user prompts
8
+ * - sleep_reflection: Background-only, never injects into user prompts, no HEARTBEAT
9
+ *
10
+ * Old queue items (without taskKind) are migrated to pain_diagnosis for compatibility.
11
+ */
12
+ export type TaskKind = 'pain_diagnosis' | 'sleep_reflection' | 'model_eval';
13
+ export type TaskPriority = 'high' | 'medium' | 'low';
14
+ export type QueueStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'canceled';
15
+ export type TaskResolution = 'marker_detected' | 'auto_completed_timeout' | 'failed_max_retries' | 'canceled';
16
+ /**
17
+ * Recent pain context attached to sleep_reflection tasks.
18
+ * Carries explicit recent pain signal metadata without being a separate task kind.
19
+ * Used by NocturnalTargetSelector for ranking bias and context enrichment.
20
+ */
21
+ export interface RecentPainContext {
22
+ /** Most recent unresolved pain event */
23
+ mostRecent: {
24
+ score: number;
25
+ source: string;
26
+ reason: string;
27
+ timestamp: string;
28
+ } | null;
29
+ /** Count of pain events in the recent window (for signal strength) */
30
+ recentPainCount: number;
31
+ /** Highest pain score in the recent window */
32
+ recentMaxPainScore: number;
33
+ }
3
34
  export interface EvolutionQueueItem {
4
35
  id: string;
36
+ taskKind: TaskKind;
37
+ priority: TaskPriority;
38
+ source: string;
39
+ traceId?: string;
5
40
  task?: string;
6
41
  score: number;
7
- source: string;
8
42
  reason: string;
9
43
  timestamp: string;
10
44
  enqueued_at?: string;
@@ -12,11 +46,15 @@ export interface EvolutionQueueItem {
12
46
  completed_at?: string;
13
47
  assigned_session_key?: string;
14
48
  trigger_text_preview?: string;
15
- status: 'pending' | 'in_progress' | 'completed';
16
- resolution?: 'marker_detected' | 'auto_completed_timeout';
49
+ status: QueueStatus;
50
+ resolution?: TaskResolution;
17
51
  session_id?: string;
18
52
  agent_id?: string;
19
- traceId?: string;
53
+ retryCount: number;
54
+ maxRetries: number;
55
+ lastError?: string;
56
+ resultRef?: string;
57
+ recentPainContext?: RecentPainContext;
20
58
  }
21
59
  export declare const EVOLUTION_QUEUE_LOCK_SUFFIX = ".lock";
22
60
  export declare const PAIN_CANDIDATES_LOCK_SUFFIX = ".candidates.lock";
@@ -44,6 +82,16 @@ export declare function registerEvolutionTaskSession(workspaceResolve: (key: str
44
82
  warn?: (message: string) => void;
45
83
  info?: (message: string) => void;
46
84
  }): Promise<boolean>;
85
+ /**
86
+ * Evolution Worker - Background service for pain processing and evolution task management.
87
+ *
88
+ * IMPORTANT: evolution_directive.json is a COMPATIBILITY-ONLY DISPLAY ARTIFACT.
89
+ * This service does NOT read or use directive for Phase 3 eligibility or any decisions.
90
+ * Queue (EVOLUTION_QUEUE) is the only authoritative execution truth source.
91
+ *
92
+ * Directive exists solely for UI/backwards compatibility display purposes.
93
+ * Production evidence shows directive stopped updating on 2026-03-22 and is stale.
94
+ */
47
95
  export interface ExtendedEvolutionWorkerService {
48
96
  id: string;
49
97
  api: OpenClawPluginApi | null;