principles-disciple 1.28.1 → 1.28.2

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 (56) hide show
  1. package/openclaw.plugin.json +4 -4
  2. package/package.json +1 -1
  3. package/src/commands/context.ts +1 -0
  4. package/src/commands/disable-impl.ts +2 -0
  5. package/src/commands/evolution-status.ts +2 -0
  6. package/src/commands/focus.ts +2 -0
  7. package/src/commands/pain.ts +1 -0
  8. package/src/commands/principle-rollback.ts +1 -0
  9. package/src/commands/rollback-impl.ts +1 -0
  10. package/src/core/adaptive-thresholds.ts +1 -0
  11. package/src/core/dictionary.ts +1 -0
  12. package/src/core/empathy-keyword-matcher.ts +1 -0
  13. package/src/core/event-log.ts +2 -0
  14. package/src/core/evolution-engine.ts +1 -0
  15. package/src/core/external-training-contract.ts +1 -0
  16. package/src/core/focus-history.ts +3 -0
  17. package/src/core/init.ts +1 -0
  18. package/src/core/nocturnal-arbiter.ts +3 -0
  19. package/src/core/nocturnal-compliance.ts +1 -0
  20. package/src/core/nocturnal-dataset.ts +1 -0
  21. package/src/core/nocturnal-executability.ts +1 -0
  22. package/src/core/nocturnal-reasoning-deriver.ts +1 -0
  23. package/src/core/nocturnal-rule-implementation-validator.ts +1 -0
  24. package/src/core/nocturnal-trinity.ts +3 -0
  25. package/src/core/pain-context-extractor.ts +1 -0
  26. package/src/core/pain.ts +1 -0
  27. package/src/core/pd-task-reconciler.ts +1 -0
  28. package/src/core/pd-task-service.ts +1 -0
  29. package/src/core/principle-internalization/deprecated-readiness.ts +1 -0
  30. package/src/core/principle-internalization/principle-lifecycle-service.ts +1 -0
  31. package/src/core/principle-tree-migration.ts +1 -0
  32. package/src/core/replay-engine.ts +4 -0
  33. package/src/core/risk-calculator.ts +1 -0
  34. package/src/core/rule-host.ts +2 -0
  35. package/src/core/session-tracker.ts +2 -0
  36. package/src/core/thinking-models.ts +1 -0
  37. package/src/core/trajectory.ts +4 -0
  38. package/src/hooks/lifecycle-routing.ts +1 -0
  39. package/src/hooks/pain.ts +1 -0
  40. package/src/hooks/prompt.ts +1 -0
  41. package/src/hooks/trajectory-collector.ts +1 -0
  42. package/src/http/principles-console-route.ts +2 -0
  43. package/src/service/central-database.ts +2 -0
  44. package/src/service/central-sync-service.ts +1 -0
  45. package/src/service/control-ui-query-service.ts +2 -0
  46. package/src/service/event-log-auditor.ts +2 -0
  47. package/src/service/evolution-worker.ts +1 -0
  48. package/src/service/health-query-service.ts +5 -0
  49. package/src/service/nocturnal-runtime.ts +4 -0
  50. package/src/service/runtime-summary-service.ts +5 -0
  51. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +1 -0
  52. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +2 -0
  53. package/src/service/subagent-workflow/subagent-error-utils.ts +1 -0
  54. package/src/service/subagent-workflow/workflow-manager-base.ts +1 -0
  55. package/src/tools/critique-prompt.ts +1 -0
  56. package/src/utils/io.ts +1 -0
@@ -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.28.1",
5
+ "version": "1.28.2",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
@@ -76,8 +76,8 @@
76
76
  }
77
77
  },
78
78
  "buildFingerprint": {
79
- "gitSha": "27d380ef1db5",
80
- "bundleMd5": "e6f2b6946eddc217169568fc45c5569e",
81
- "builtAt": "2026-04-13T08:32:02.125Z"
79
+ "gitSha": "25bfc2bb209f",
80
+ "bundleMd5": "b735aa483374dd2c7071295b11161676",
81
+ "builtAt": "2026-04-13T14:25:24.799Z"
82
82
  }
83
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "1.28.1",
3
+ "version": "1.28.2",
4
4
  "description": "Native OpenClaw plugin for Principles Disciple",
5
5
  "type": "module",
6
6
  "main": "./dist/bundle.js",
@@ -305,6 +305,7 @@ function showHelp(isZh: boolean): string {
305
305
  /**
306
306
  * Main command handler
307
307
  */
308
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
308
309
  export function handleContextCommand(ctx: PluginCommandContext): PluginCommandResult {
309
310
  const workspaceDir = getWorkspaceDir(ctx);
310
311
  const args = (ctx.args || '').trim().split(/\s+/);
@@ -70,6 +70,7 @@ function _handleListActive(
70
70
  }
71
71
 
72
72
 
73
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
73
74
  function _handleDisableImpl(
74
75
  workspaceDir: string,
75
76
  stateDir: string,
@@ -130,6 +131,7 @@ function _handleDisableImpl(
130
131
  * /pd-disable-impl <implId> - Disable an implementation
131
132
  * /pd-disable-impl <implId> --reason "<reason>" - Disable with reason
132
133
  */
134
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
133
135
  export function handleDisableImplCommand(ctx: PluginCommandContext): PluginCommandResult {
134
136
  const workspaceDir = (ctx.config?.workspaceDir as string) || process.cwd();
135
137
  const {stateDir} = WorkspaceContext.fromHookContext({ ...ctx, workspaceDir });
@@ -46,6 +46,7 @@ function formatRouteRecommendations(
46
46
  }
47
47
 
48
48
 
49
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
49
50
  function buildEnglishOutput(
50
51
  workspaceDir: string,
51
52
  sessionId: string | null,
@@ -98,6 +99,7 @@ function buildEnglishOutput(
98
99
  }
99
100
 
100
101
 
102
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
101
103
  function buildChineseOutput(
102
104
  workspaceDir: string,
103
105
  sessionId: string | null,
@@ -47,6 +47,7 @@ function getWorkspaceDir(ctx: PluginCommandContext): string {
47
47
  * - 清理:Working Memory 超过 10 条记录时保留最近 10 条
48
48
  * - 验证:文件引用指向不存在的文件时移除
49
49
  */
50
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
50
51
  function compressFocusContent(content: string, workspaceDir?: string): string {
51
52
  // 首先使用 cleanupStaleInfo 进行基础清理
52
53
  let result = cleanupStaleInfo(content, workspaceDir);
@@ -346,6 +347,7 @@ ${milestoneNote ? `${milestoneNote}\n` : ''}
346
347
  /**
347
348
  * 回滚到历史版本
348
349
  */
350
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
349
351
  function rollbackFocus(workspaceDir: string, index: number, isZh: boolean): string {
350
352
  const wctx = WorkspaceContext.fromHookContext({ workspaceDir });
351
353
  const focusPath = wctx.resolve('CURRENT_FOCUS');
@@ -216,6 +216,7 @@ export function handlePainCommand(ctx: PluginCommandContext): PluginCommandResul
216
216
  * Handle /pd-status empathy subcommand
217
217
  */
218
218
 
219
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
219
220
  function handleEmpathySubcommand(
220
221
  wctx: WorkspaceContext,
221
222
  args: string,
@@ -1,6 +1,7 @@
1
1
  import { WorkspaceContext } from '../core/workspace-context.js';
2
2
  import type { PluginCommandContext } from '../openclaw-sdk.js';
3
3
 
4
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
4
5
  export function handlePrincipleRollbackCommand(ctx: PluginCommandContext): { text: string } {
5
6
  const workspaceDir = (ctx.config?.workspaceDir as string) || process.cwd();
6
7
  const argText = (ctx.args || '').trim();
@@ -41,6 +41,7 @@ function getAllImplementations(stateDir: string): Implementation[] {
41
41
  * /pd-rollback-impl <implId> - Rollback current active
42
42
  * /pd-rollback-impl <implId> --reason "<reason>" - Rollback with reason
43
43
  */
44
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
44
45
  export function handleRollbackImplCommand(ctx: PluginCommandContext): PluginCommandResult {
45
46
  const workspaceDir = (ctx.config?.workspaceDir as string) || process.cwd();
46
47
  const {stateDir} = WorkspaceContext.fromHookContext({ ...ctx, workspaceDir });
@@ -407,6 +407,7 @@ export function getDetailedThresholdState(
407
407
  * @param signals - Observable signals
408
408
  * @returns UpdateThresholdResult describing the most significant change
409
409
  */
410
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
410
411
  export function adjustThresholdsFromSignals(
411
412
  stateDir: string,
412
413
  signals: ThresholdSignals
@@ -116,6 +116,7 @@ export class PainDictionary {
116
116
  }
117
117
  }
118
118
 
119
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
119
120
  match(text: string): { ruleId: string; severity: number } | undefined {
120
121
  if (shouldIgnorePainProtocolText(text)) return undefined;
121
122
 
@@ -207,6 +207,7 @@ export function matchEmpathyKeywords(
207
207
  * This is called when the empathy optimizer subagent completes its analysis
208
208
  * and returns suggested updates to the keyword store.
209
209
  */
210
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
210
211
  export function applyKeywordUpdates(
211
212
  store: EmpathyKeywordStore,
212
213
  updates: Record<string, {
@@ -244,6 +244,7 @@ export class EventLog {
244
244
  }
245
245
 
246
246
 
247
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
247
248
  private getEventDedupKey(entry: EventLogEntry): string {
248
249
  const eventId = typeof (entry.data as { eventId?: unknown } | undefined)?.eventId === 'string'
249
250
  ? String((entry.data as { eventId?: string }).eventId)
@@ -340,6 +341,7 @@ export class EventLog {
340
341
  * @param range 'today' | 'week' | 'session'
341
342
  * @param sessionId Optional session ID for session-scoped stats
342
343
  */
344
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
343
345
  getEmpathyStats(range: 'today' | 'week' | 'session', sessionId?: string): EmpathyEventStats {
344
346
  const now = new Date();
345
347
  const today = this.formatDate(now);
@@ -165,6 +165,7 @@ export class EvolutionEngine {
165
165
 
166
166
  // ===== 记录失败 =====
167
167
 
168
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
168
169
  public recordFailure(
169
170
  toolName: string,
170
171
  options?: {
@@ -285,6 +285,7 @@ export interface ValidationResult {
285
285
  * @param result - The trainer result to validate
286
286
  * @returns ValidationResult indicating pass/fail and any errors
287
287
  */
288
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
288
289
  export function validateTrainerResult(
289
290
  spec: TrainingExperimentSpec,
290
291
  result: TrainingExperimentResult
@@ -265,6 +265,7 @@ export function compressFocus(focusPath: string, newContent: string): {
265
265
  * @param content CURRENT_FOCUS.md 内容
266
266
  * @param maxLines 最大行数
267
267
  */
268
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
268
269
  export function extractSummary(content: string, maxLines = 30): string {
269
270
  const lines = content.split('\n');
270
271
  const sections: { [key: string]: string[] } = {
@@ -805,6 +806,7 @@ function generateWorkingMemorySection(snapshot: WorkingMemorySnapshot): string {
805
806
  /**
806
807
  * 生成工作记忆注入字符串(用于 prompt 注入)
807
808
  */
809
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
808
810
  export function workingMemoryToInjection(snapshot: WorkingMemorySnapshot | null): string {
809
811
  if (!snapshot) return '';
810
812
 
@@ -884,6 +886,7 @@ interface CompressionConfig {
884
886
  * @param stateDir state 目录路径
885
887
  * @returns 压缩配置
886
888
  */
889
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
887
890
  function loadCompressionConfig(stateDir?: string): CompressionConfig {
888
891
  if (!stateDir) {
889
892
  return DEFAULT_COMPRESSION_CONFIG;
package/src/core/init.ts CHANGED
@@ -34,6 +34,7 @@ function hasOutdatedCoreGuidance(file: string, content: string): boolean {
34
34
  * Ensures that the workspace has the necessary template files for Principles Disciple.
35
35
  * This function flattens 'core' templates to the root so OpenClaw can find them.
36
36
  */
37
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
37
38
  export function ensureWorkspaceTemplates(api: OpenClawPluginApi, workspaceDir: string, language = 'en') {
38
39
  try {
39
40
  const __filename = fileURLToPath(import.meta.url);
@@ -159,6 +159,7 @@ export interface TrinityStageValidationResult {
159
159
  * Validate a Dreamer output contract.
160
160
  * Ensures the output is well-formed before passing to Philosopher.
161
161
  */
162
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
162
163
  export function validateDreamerOutput(output: unknown): TrinityStageValidationResult {
163
164
  const failures: string[] = [];
164
165
 
@@ -237,6 +238,7 @@ export function validateDreamerOutput(output: unknown): TrinityStageValidationRe
237
238
  * Validate a Philosopher output contract.
238
239
  * Ensures the output is well-formed before passing to Scribe.
239
240
  */
241
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
240
242
  export function validatePhilosopherOutput(output: unknown): TrinityStageValidationResult {
241
243
  const failures: string[] = [];
242
244
 
@@ -260,6 +262,7 @@ export function validatePhilosopherOutput(output: unknown): TrinityStageValidati
260
262
  failures.push('Philosopher output must have a judgments array');
261
263
  } else {
262
264
  // Validate each judgment
265
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
263
266
  obj.judgments.forEach((judgment: unknown, idx: number) => {
264
267
  if (judgment === null || judgment === undefined || typeof judgment !== 'object') {
265
268
  failures.push(`Philosopher judgment at index ${idx} is not an object`);
@@ -513,6 +513,7 @@ function detectT09Opportunity(session: SessionEvents): OpportunityMatch {
513
513
  * trigger pattern. Since P_* principles don't have T-xx specific detectors,
514
514
  * we use the presence of negative signals as violation evidence.
515
515
  */
516
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
516
517
  export function detectViolation(principleId: string, session: SessionEvents): ViolationMatch {
517
518
  // #216: P_* principles (pain-derived) — generic violation detection
518
519
  if (principleId.startsWith('P_')) {
@@ -645,6 +645,7 @@ export function getDatasetStats(
645
645
  * @param targetModelFamily - Default target family for migrated samples
646
646
  * @returns Number of newly registered samples
647
647
  */
648
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
648
649
  export function migrateSampleArtifacts(
649
650
  workspaceDir: string,
650
651
  targetModelFamily: string | null = null
@@ -278,6 +278,7 @@ function isTooGeneric(text: string): boolean {
278
278
  * @param artifact - The validated artifact from arbiter (passed = true)
279
279
  * @returns ExecutabilityResult
280
280
  */
281
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
281
282
  export function validateExecutability(artifact: {
282
283
  badDecision: string;
283
284
  betterDecision: string;
@@ -280,6 +280,7 @@ export function deriveDecisionPoints(
280
280
  *
281
281
  * Empty/missing data returns all-false defaults. Never throws.
282
282
  */
283
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
283
284
  export function deriveContextualFactors(
284
285
  snapshot: NocturnalSessionSnapshot,
285
286
  ): DerivedContextualFactors {
@@ -85,6 +85,7 @@ function extractHelperUsage(sourceCode: string): string[] {
85
85
  );
86
86
  }
87
87
 
88
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
88
89
  function validateMeta(meta: unknown): RuleImplementationValidationFailure[] {
89
90
  if (!meta || typeof meta !== 'object') {
90
91
  return [
@@ -642,6 +642,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
642
642
  * runEmbeddedPiAgent does NOT read config.agents.defaults.model —
643
643
  * it requires explicit params.provider and params.model.
644
644
  */
645
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
645
646
  private resolveModel(): { provider: string; model: string } {
646
647
  const config = this.loadFullConfig();
647
648
  const agents = config?.agents as Record<string, unknown> | undefined;
@@ -1698,6 +1699,7 @@ export interface TrinityResult {
1698
1699
  * In production, this would call the actual Dreamer subagent.
1699
1700
  * The stub generates plausible candidates based on snapshot signals.
1700
1701
  */
1702
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
1701
1703
  export function invokeStubDreamer(
1702
1704
  snapshot: NocturnalSessionSnapshot,
1703
1705
  principleId: string,
@@ -2248,6 +2250,7 @@ export async function runTrinityAsync(options: RunTrinityOptions): Promise<Trini
2248
2250
 
2249
2251
  /**
2250
2252
  * Internal: Run Trinity chain with stub implementations (synchronous).
2253
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
2251
2254
  */
2252
2255
  function runTrinityWithStubs(
2253
2256
  snapshot: NocturnalSessionSnapshot,
@@ -203,6 +203,7 @@ function extractTurn(msg: ParsedMessage): string | null {
203
203
  * SAFETY: Tail-only read, skip oversized lines, cap output.
204
204
  * Returns empty string on any failure — caller should use pain reason as fallback.
205
205
  */
206
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
206
207
  export async function extractRecentConversation(
207
208
  sessionId: string,
208
209
  agentId = 'main',
package/src/core/pain.ts CHANGED
@@ -279,6 +279,7 @@ export function readPainFlagContract(projectDir: string): PainFlagContractResult
279
279
  * Errors are silently ignored to avoid disrupting the pain pipeline.
280
280
  */
281
281
 
282
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
282
283
  export function trackPrincipleValue(
283
284
  workspaceDir: string,
284
285
  painData: { reason?: string; source?: string; score?: string },
@@ -103,6 +103,7 @@ async function writeCronStore(store: CronStoreFile): Promise<void> {
103
103
  });
104
104
  }
105
105
 
106
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
106
107
  function diff(declared: PDTaskSpec[], actual: CronJob[]): DiffAction[] {
107
108
  const actions: DiffAction[] = [];
108
109
  const actualByName = new Map<string, CronJob>();
@@ -4,6 +4,7 @@ import { reconcilePDTasks } from './pd-task-reconciler.js';
4
4
  export const PDTaskService: OpenClawPluginService = {
5
5
  id: 'principles-disciple-task-manager',
6
6
 
7
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
7
8
  async start(ctx: OpenClawPluginServiceContext): Promise<void> {
8
9
  const {workspaceDir} = ctx;
9
10
  if (!workspaceDir) {
@@ -27,6 +27,7 @@ function clampScore(value: number): number {
27
27
  return Math.max(0, Math.min(100, Number(value.toFixed(2))));
28
28
  }
29
29
 
30
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
30
31
  export function assessDeprecatedReadiness(
31
32
  principle: PrincipleLifecycleEvidence,
32
33
  precomputedRuleMetrics?: Record<string, RuleMetricResult>,
@@ -38,6 +38,7 @@ export interface PrincipleLifecycleAssessment {
38
38
  routeRecommendation: InternalizationRouteRecommendation;
39
39
  }
40
40
 
41
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
41
42
  function createValueMetrics(
42
43
  principle: PrincipleLifecycleEvidence,
43
44
  adherence: PrincipleAdherenceResult,
@@ -92,6 +92,7 @@ function mapInternalizationStatusToPrincipleStatus(
92
92
  * This function is idempotent: it only migrates principles that don't exist
93
93
  * in tree.principles yet.
94
94
  */
95
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
95
96
  export function migratePrincipleTree(
96
97
  stateDir: string,
97
98
  workspaceDir?: string
@@ -236,6 +236,7 @@ export class ReplayEngine {
236
236
  };
237
237
  }
238
238
 
239
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
239
240
  private _buildRuleHostInput(sample: ReplaySample): RuleHostInput | null {
240
241
  const snapshot = getNocturnalSessionSnapshot(
241
242
  TrajectoryRegistry.get(this.workspaceDir),
@@ -294,6 +295,7 @@ export class ReplayEngine {
294
295
  }
295
296
 
296
297
 
298
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
297
299
  private _selectToolCall(
298
300
  snapshot: NocturnalSessionSnapshot,
299
301
  classification: SampleClassification,
@@ -380,7 +382,9 @@ export class ReplayEngine {
380
382
  return toolCall.outcome === 'success' ? 'safe' : 'normal';
381
383
  }
382
384
 
385
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
383
386
 
387
+ // eslint-disable-next-line complexity -- complexity 11
384
388
  private _scoreEvaluation(
385
389
  sample: ReplaySample,
386
390
  result: RuleHostResult,
@@ -9,6 +9,7 @@ export interface FileModification {
9
9
  params: Record<string, unknown>;
10
10
  }
11
11
 
12
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
12
13
  export function estimateLineChanges(modification: FileModification): number {
13
14
  const { toolName, params } = modification;
14
15
 
@@ -59,6 +59,7 @@ export class RuleHost {
59
59
  * - { decision: 'block', ... } when any implementation returns block (short-circuits)
60
60
  * - { decision: 'requireApproval', ... } when any implementation returns requireApproval
61
61
  */
62
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
62
63
  evaluate(input: RuleHostInput): RuleHostResult | undefined {
63
64
  try {
64
65
  // Load active code implementations from the ledger
@@ -181,6 +182,7 @@ export class RuleHost {
181
182
  * Uses the shared isolated runtime loader so candidate code does not execute
182
183
  * in the host global realm.
183
184
  */
185
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
184
186
  private _loadSingleImplementation(
185
187
  impl: Implementation
186
188
  ): LoadedImplementation | null {
@@ -243,6 +243,7 @@ export function trackToolRead(sessionId: string, filePath: string, workspaceDir?
243
243
  }
244
244
 
245
245
 
246
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
246
247
  export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined, config?: PainConfig, workspaceDir?: string, sessionKey?: string, trigger?: string): SessionState {
247
248
  const state = getOrCreateSession(sessionId, workspaceDir, sessionKey, trigger);
248
249
  state.llmTurns += 1;
@@ -282,6 +283,7 @@ export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined,
282
283
  * Tracks physical friction based on tool execution failures.
283
284
  */
284
285
 
286
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
285
287
  export function trackFriction(
286
288
  sessionId: string,
287
289
  deltaF: number,
@@ -202,6 +202,7 @@ let _cachedWorkspace: string | null = null;
202
202
  *
203
203
  * @param workspaceDir Optional. If provided, loads from that workspace's THINKING_OS.md.
204
204
  */
205
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
205
206
  export function listThinkingModels(workspaceDir?: string): ThinkingModelDefinition[] {
206
207
  const cacheKey = workspaceDir ?? '__global__';
207
208
  if (_cachedDefinitions && _cachedWorkspace === cacheKey) {
@@ -442,6 +442,7 @@ export class TrajectoryDatabase {
442
442
  const now = nowIso();
443
443
  // Cast to V2 to access new fields
444
444
  const v2Updates = updates;
445
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
445
446
  this.withWrite(() => {
446
447
  const setClauses: string[] = ['updated_at = ?'];
447
448
  const values: unknown[] = [now];
@@ -554,6 +555,7 @@ export class TrajectoryDatabase {
554
555
  LIMIT ? OFFSET ?
555
556
  `).all(...values, limit, offset) as Record<string, unknown>[];
556
557
 
558
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
557
559
  return rows.map((row) => ({
558
560
  id: Number(row.id),
559
561
  taskId: String(row.task_id),
@@ -625,6 +627,7 @@ export class TrajectoryDatabase {
625
627
  * Returns: Analytics data aggregated from trajectory database.
626
628
  * Not: Runtime truth or real-time queue state.
627
629
  */
630
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
628
631
  getEvolutionTaskByTraceId(traceId: string): EvolutionTaskRecord | null {
629
632
  const row = this.db.prepare(`
630
633
  SELECT id, task_id, trace_id, source, reason, score, status,
@@ -775,6 +778,7 @@ export class TrajectoryDatabase {
775
778
  WHERE session_id = ?
776
779
  ORDER BY id ASC
777
780
  `).all(sessionId) as Record<string, unknown>[];
781
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
778
782
 
779
783
  return rows.map((row) => {
780
784
  // Extract filePath from params_json if present
@@ -66,6 +66,7 @@ export type LifecycleIntent = 'promote' | 'disable' | 'rollback' | null;
66
66
  * Detect implementation lifecycle intent from user message.
67
67
  * Returns the detected intent type or null.
68
68
  */
69
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
69
70
  export function detectLifecycleIntent(message: string): LifecycleIntent {
70
71
  // Check promote patterns
71
72
  for (const p of PROMOTE_PATTERNS_EN) {
package/src/hooks/pain.ts CHANGED
@@ -391,6 +391,7 @@ export function handleAfterToolCall(
391
391
  });
392
392
  }
393
393
 
394
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
394
395
  function extractErrorType(error: unknown): string {
395
396
  if (!error) return 'Unknown';
396
397
  const msg = String(error);
@@ -202,6 +202,7 @@ export function loadContextInjectionConfig(workspaceDir: string): ContextInjecti
202
202
  * Falls back to main model if no diagnostician model is configured
203
203
  * @internal Helper for model configuration resolution
204
204
  */
205
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
205
206
  export function getDiagnosticianModel(api: PromptHookApi | null, logger?: PluginLogger): string {
206
207
  // Determines logger: prefer api.logger, fallback to provided logger
207
208
  // 1. getDiagnosticianModel(api) - uses api.logger
@@ -212,6 +212,7 @@ export function handleLlmOutput(
212
212
  * 消息写入前的处理
213
213
  * 记录:用户/助手消息内容
214
214
  */
215
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
215
216
  export function handleBeforeMessageWrite(
216
217
  event: PluginHookBeforeMessageWriteEvent,
217
218
  ctx: PluginHookAgentContext & { workspaceDir?: string }
@@ -578,6 +578,7 @@ export function createPrinciplesConsoleRoutes(api: OpenClawPluginApi): OpenClawP
578
578
  path: ROUTE_PREFIX,
579
579
  auth: 'plugin',
580
580
  match: 'prefix',
581
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
581
582
  async handler(req, res) {
582
583
  if (!api.rootDir) { text(res, 500, 'Plugin rootDir not available'); return true; }
583
584
  const url = new URL(req.url || ROUTE_PREFIX, 'http://127.0.0.1');
@@ -640,6 +641,7 @@ export function createPrinciplesConsoleRoute(api: OpenClawPluginApi): OpenClawPl
640
641
  path: ROUTE_PREFIX,
641
642
  auth: 'plugin',
642
643
  match: 'prefix',
644
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
643
645
  async handler(req, res) {
644
646
  if (!api.rootDir) { text(res, 500, 'Plugin rootDir not available'); return true; }
645
647
  const url = new URL(req.url || ROUTE_PREFIX, 'http://127.0.0.1');
@@ -200,6 +200,7 @@ export class CentralDatabase {
200
200
  /**
201
201
  * Sync data from a single workspace into the central database
202
202
  */
203
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
203
204
  syncWorkspace(workspaceName: string): number {
204
205
  const workspace = this.workspaces.find(w => w.name === workspaceName);
205
206
  if (!workspace) {
@@ -713,6 +714,7 @@ export class CentralDatabase {
713
714
  syncEnabled: c.sync_enabled === 1,
714
715
  }));
715
716
  }
717
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
716
718
 
717
719
  updateWorkspaceConfig(
718
720
  workspaceName: string,
@@ -18,6 +18,7 @@ let centralDb: CentralDatabase | null = null;
18
18
  */
19
19
  const DEFAULT_SYNC_INTERVAL_MS = 5 * 60 * 1000;
20
20
 
21
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
21
22
  async function runSyncCycle(): Promise<void> {
22
23
  if (!centralDb) {
23
24
  logger?.warn?.('[PD:CentralSync] CentralDatabase not initialized, skipping sync');
@@ -255,6 +255,7 @@ export class ControlUiQueryService {
255
255
  this.uiDb.dispose();
256
256
  }
257
257
 
258
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
258
259
  getOverview(days = 30): OverviewResponse {
259
260
  const stats = this.trajectory.getDataStats();
260
261
  const regressionRows = this.uiDb.all<{
@@ -399,6 +400,7 @@ export class ControlUiQueryService {
399
400
  };
400
401
  }
401
402
 
403
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
402
404
  listSamples(filters: SampleListFilters = {}): SamplesResponse {
403
405
  const page = Math.max(1, Number(filters.page ?? 1));
404
406
  const pageSize = clampPageSize(filters.pageSize);
@@ -137,6 +137,7 @@ function countAllHooks(filePath: string): Record<string, number> {
137
137
  * @param openclawDir - Base OpenClaw directory (e.g., ~/.openclaw)
138
138
  * @param expectedToolHooks - Hook names that should appear in the primary workspace
139
139
  */
140
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
140
141
  export async function auditEventLogs(
141
142
  openclawDir: string,
142
143
  expectedToolHooks: string[] = ['before_tool_call', 'after_tool_call'],
@@ -209,6 +210,7 @@ export async function auditEventLogs(
209
210
  /**
210
211
  * Format audit report for display.
211
212
  */
213
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
212
214
  export function formatAuditReport(report: AuditReport): string {
213
215
  const lines: string[] = [];
214
216
 
@@ -1873,6 +1873,7 @@ async function processEvolutionQueue(wctx: WorkspaceContext, logger: PluginLogge
1873
1873
  }
1874
1874
  }
1875
1875
 
1876
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
1876
1877
  async function processDetectionQueue(wctx: WorkspaceContext, api: OpenClawPluginApi, eventLog: EventLog) {
1877
1878
  const {logger} = api;
1878
1879
  try {
@@ -337,6 +337,7 @@ export class HealthQueryService {
337
337
  }));
338
338
  }
339
339
 
340
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
340
341
  getGateStats(): {
341
342
  today: {
342
343
  gfiBlocks: number;
@@ -658,6 +659,7 @@ export class HealthQueryService {
658
659
  return null;
659
660
  }
660
661
 
662
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
661
663
  private readNocturnalTraining(): {
662
664
  queue: { pending: number; inProgress: number; completed: number };
663
665
  trinityRecords: { artifactId: string; status: string; createdAt: string }[];
@@ -786,6 +788,7 @@ export class HealthQueryService {
786
788
 
787
789
 
788
790
  // eslint-disable-next-line @typescript-eslint/class-methods-use-this
791
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
789
792
  private getEventDedupKey(entry: EventLogEntry): string {
790
793
  const eventId = typeof entry.data?.eventId === 'string' ? entry.data.eventId : null;
791
794
  if (eventId) {
@@ -856,6 +859,7 @@ export class HealthQueryService {
856
859
  }
857
860
 
858
861
 
862
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
859
863
  // eslint-disable-next-line @typescript-eslint/class-methods-use-this
860
864
  private resolveGateType(row: GateBlockRow): string {
861
865
  if (typeof row.gate_type === 'string' && row.gate_type.trim().length > 0) {
@@ -990,6 +994,7 @@ export class HealthQueryService {
990
994
  * Read the most recent session JSON file from disk.
991
995
  * Used to sync GFI from session-tracker's persistence into SQLite.
992
996
  */
997
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
993
998
  private readLatestSessionFromFile(): SessionState | null {
994
999
  const sessionsDir = path.join(this.stateDir, 'sessions');
995
1000
  if (!fs.existsSync(sessionsDir)) {
@@ -40,6 +40,7 @@ import { withLockAsync } from '../utils/file-lock.js';
40
40
  * Excluded (NOT system sessions):
41
41
  * - User sessions like agent:main:feishu:user:xxx — third component is channel type
42
42
  */
43
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
43
44
  function isSystemSession(state: SessionState): boolean {
44
45
  const { sessionId, sessionKey, trigger } = state;
45
46
 
@@ -269,6 +270,7 @@ async function writeState(stateDir: string, state: NocturnalRuntimeState): Promi
269
270
  * @param trajectoryLastActivityAt - Optional trajectory timestamp as secondary guardrail
270
271
  * @returns IdleCheckResult with full diagnostic information
271
272
  */
273
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
272
274
  export function checkWorkspaceIdle(
273
275
  workspaceDir: string,
274
276
  options: {
@@ -355,6 +357,7 @@ export function checkWorkspaceIdle(
355
357
  * @param options - Cooldown configuration options
356
358
  * @returns CooldownCheckResult
357
359
  */
360
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
358
361
  export function checkCooldown(
359
362
  stateDir: string,
360
363
  principleId?: string,
@@ -555,6 +558,7 @@ export interface PreflightCheckResult {
555
558
  * @param idleCheckOverride - Optional override for idle check result (for testing)
556
559
  */
557
560
 
561
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
558
562
  export function checkPreflight(
559
563
  workspaceDir: string,
560
564
  stateDir: string,
@@ -362,6 +362,7 @@ export class RuntimeSummaryService {
362
362
  return { session: sessions[0], reason: 'latest_active' };
363
363
  }
364
364
 
365
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
365
366
  private static mergeSessionSnapshots(
366
367
  persistedSessions: PersistedSessionState[],
367
368
  workspaceDir: string
@@ -510,7 +511,9 @@ export class RuntimeSummaryService {
510
511
  })
511
512
  .slice(-MAX_SOURCE_EVENTS)
512
513
  .reverse();
514
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
513
515
 
516
+ // eslint-disable-next-line complexity -- complexity 11
514
517
  return filtered.map((entry) => {
515
518
  if (entry.type === 'pain_signal') {
516
519
  return {
@@ -581,6 +584,7 @@ export class RuntimeSummaryService {
581
584
  return [...merged.values()].sort((a, b) => (a.ts || '').localeCompare(b.ts || ''));
582
585
  }
583
586
 
587
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
584
588
  private static getEventDedupKey(entry: EventLogEntry): string {
585
589
  const eventId = typeof entry.data?.eventId === 'string' ? entry.data.eventId : null;
586
590
  if (eventId) {
@@ -637,6 +641,7 @@ export class RuntimeSummaryService {
637
641
  return candidate ? new Date(candidate).getTime() : NaN;
638
642
  }
639
643
 
644
+ // eslint-disable-next-line complexity -- complexity 14, refactor candidate
640
645
  private static buildDirectiveTaskPreview(item: QueueItem): string {
641
646
  const task = typeof item.task === 'string' ? item.task.trim() : '';
642
647
  if (task && task.toLowerCase() !== 'undefined') {
@@ -150,6 +150,7 @@ export const deepReflectWorkflowSpec: SubagentWorkflowSpec<DeepReflectResult> =
150
150
  };
151
151
  },
152
152
 
153
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
153
154
  async persistResult(ctx: WorkflowPersistContext<DeepReflectResult>): Promise<void> {
154
155
  const { result, metadata, workspaceDir } = ctx;
155
156
 
@@ -243,6 +243,7 @@ export class NocturnalWorkflowManager implements WorkflowManager {
243
243
  // #213: Wrap fire-and-forget Promise with .catch() to prevent
244
244
  // unhandled promise rejections if anything throws outside the try-catch
245
245
  // (e.g., during parameter construction or environment errors).
246
+ // eslint-disable-next-line complexity -- complexity 15, refactor candidate
246
247
  Promise.resolve().then(async () => {
247
248
  try {
248
249
  const result = await executeNocturnalReflectionAsync(
@@ -651,6 +652,7 @@ export class NocturnalWorkflowManager implements WorkflowManager {
651
652
  * Derives stage events from TrinityResult.telemetry and TrinityResult.failures.
652
653
  * Always records _start event for each stage that ran, plus _complete or _failed based on outcome.
653
654
  */
655
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
654
656
  private recordStageEvents(workflowId: string, result: TrinityResult): void {
655
657
  const { telemetry, failures } = result;
656
658
 
@@ -5,6 +5,7 @@
5
5
  *
6
6
  * Callers should suppress warnings for these errors — they are not real failures.
7
7
  */
8
+ // eslint-disable-next-line complexity -- complexity 13, refactor candidate
8
9
  export function isExpectedSubagentError(err: unknown): boolean {
9
10
  const msg = String(err);
10
11
  return (
@@ -449,6 +449,7 @@ export abstract class WorkflowManagerBase implements WorkflowManager {
449
449
  }
450
450
  }
451
451
 
452
+ // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
452
453
  async sweepExpiredWorkflows(maxAgeMs?: number): Promise<number> {
453
454
  const ttl = maxAgeMs ?? this.defaultTtlMs;
454
455
  const expired = this.store.getExpiredWorkflows(ttl);
@@ -17,6 +17,7 @@ const DEPTH_INSTRUCTIONS = {
17
17
  * 严格按照测试用例的调用习惯和断言要求进行重写。
18
18
  * 增加 OpenClaw 兼容性路径解析。
19
19
  */
20
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
20
21
  export function buildCritiquePromptV2(
21
22
  params: {
22
23
  context: string;
package/src/utils/io.ts CHANGED
@@ -2,6 +2,7 @@ import * as path from 'path';
2
2
  import * as fs from 'fs';
3
3
  import { resolvePdPath } from '../core/paths.js';
4
4
 
5
+ // eslint-disable-next-line complexity -- complexity 12, refactor candidate
5
6
  export function normalizePath(filePath: string, projectDir: string): string {
6
7
  if (!filePath) return '';
7
8