principles-disciple 1.28.2 → 1.28.3

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 (87) hide show
  1. package/openclaw.plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/src/commands/archive-impl.ts +3 -0
  4. package/src/commands/context.ts +4 -1
  5. package/src/commands/disable-impl.ts +2 -2
  6. package/src/commands/evolution-status.ts +2 -2
  7. package/src/commands/focus.ts +4 -2
  8. package/src/commands/nocturnal-train.ts +9 -1
  9. package/src/commands/pain.ts +3 -1
  10. package/src/commands/pd-reflect.ts +2 -0
  11. package/src/commands/rollback-impl.ts +5 -1
  12. package/src/commands/rollback.ts +2 -1
  13. package/src/commands/samples.ts +1 -0
  14. package/src/commands/workflow-debug.ts +1 -0
  15. package/src/core/adaptive-thresholds.ts +2 -1
  16. package/src/core/code-implementation-storage.ts +2 -0
  17. package/src/core/config.ts +1 -0
  18. package/src/core/diagnostician-task-store.ts +2 -0
  19. package/src/core/empathy-keyword-matcher.ts +4 -1
  20. package/src/core/event-log.ts +6 -3
  21. package/src/core/evolution-engine.ts +4 -1
  22. package/src/core/evolution-logger.ts +1 -0
  23. package/src/core/external-training-contract.ts +2 -1
  24. package/src/core/focus-history.ts +15 -3
  25. package/src/core/init.ts +3 -1
  26. package/src/core/merge-gate-audit.ts +3 -0
  27. package/src/core/model-deployment-registry.ts +1 -0
  28. package/src/core/model-training-registry.ts +1 -0
  29. package/src/core/nocturnal-arbiter.ts +4 -3
  30. package/src/core/nocturnal-candidate-scoring.ts +5 -0
  31. package/src/core/nocturnal-compliance.ts +22 -1
  32. package/src/core/nocturnal-dataset.ts +3 -1
  33. package/src/core/nocturnal-export.ts +5 -0
  34. package/src/core/nocturnal-reasoning-deriver.ts +6 -1
  35. package/src/core/nocturnal-snapshot-contract.ts +1 -0
  36. package/src/core/nocturnal-trinity.ts +24 -3
  37. package/src/core/pain-context-extractor.ts +3 -1
  38. package/src/core/pain.ts +3 -1
  39. package/src/core/pd-task-reconciler.ts +3 -1
  40. package/src/core/pd-task-store.ts +1 -0
  41. package/src/core/principle-internalization/deprecated-readiness.ts +2 -1
  42. package/src/core/principle-training-state.ts +2 -0
  43. package/src/core/principle-tree-ledger.ts +4 -0
  44. package/src/core/principle-tree-migration.ts +2 -1
  45. package/src/core/promotion-gate.ts +7 -1
  46. package/src/core/replay-engine.ts +10 -4
  47. package/src/core/risk-calculator.ts +2 -1
  48. package/src/core/rule-host.ts +3 -2
  49. package/src/core/session-tracker.ts +5 -2
  50. package/src/core/shadow-observation-registry.ts +1 -0
  51. package/src/core/thinking-os-parser.ts +1 -0
  52. package/src/core/trajectory.ts +9 -5
  53. package/src/hooks/bash-risk.ts +2 -0
  54. package/src/hooks/edit-verification.ts +3 -0
  55. package/src/hooks/gate-block-helper.ts +3 -0
  56. package/src/hooks/gate.ts +8 -0
  57. package/src/hooks/gfi-gate.ts +2 -0
  58. package/src/hooks/lifecycle.ts +1 -0
  59. package/src/hooks/llm.ts +1 -0
  60. package/src/hooks/pain.ts +3 -1
  61. package/src/hooks/progressive-trust-gate.ts +3 -0
  62. package/src/hooks/prompt.ts +5 -2
  63. package/src/hooks/subagent.ts +1 -0
  64. package/src/hooks/thinking-checkpoint.ts +1 -0
  65. package/src/hooks/trajectory-collector.ts +2 -1
  66. package/src/http/principles-console-route.ts +5 -2
  67. package/src/index.ts +7 -0
  68. package/src/service/central-health-service.ts +1 -0
  69. package/src/service/central-overview-service.ts +2 -0
  70. package/src/service/evolution-query-service.ts +1 -0
  71. package/src/service/evolution-worker.ts +31 -1
  72. package/src/service/health-query-service.ts +6 -6
  73. package/src/service/monitoring-query-service.ts +4 -0
  74. package/src/service/nocturnal-runtime.ts +7 -5
  75. package/src/service/nocturnal-service.ts +21 -0
  76. package/src/service/nocturnal-target-selector.ts +2 -0
  77. package/src/service/runtime-summary-service.ts +6 -5
  78. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +2 -1
  79. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +2 -0
  80. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +3 -2
  81. package/src/service/subagent-workflow/workflow-manager-base.ts +6 -1
  82. package/src/service/subagent-workflow/workflow-store.ts +2 -0
  83. package/src/tools/deep-reflect.ts +9 -0
  84. package/src/tools/model-index.ts +1 -0
  85. package/src/tools/write-pain-flag.ts +1 -0
  86. package/src/utils/file-lock.ts +1 -0
  87. package/src/utils/io.ts +2 -1
@@ -324,7 +324,7 @@ export function evaluatePromotionGate(
324
324
  ): PromotionGateResult {
325
325
  const {
326
326
  checkpointId,
327
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Reason: reserved for Phase 7 profile-based targeting
327
+
328
328
  targetProfile: _targetProfile,
329
329
  baselineMetrics,
330
330
  minDelta = DEFAULT_MIN_DELTA,
@@ -410,8 +410,10 @@ export function evaluatePromotionGate(
410
410
  // Shadow evidence comes from actual runtime routing decisions
411
411
  const shadowStats = computeShadowStats(stateDir, { checkpointId });
412
412
 
413
+ // eslint-disable-next-line @typescript-eslint/init-declarations
413
414
  let arbiterRejectRate: number;
414
415
 
416
+ // eslint-disable-next-line @typescript-eslint/init-declarations
415
417
  let arbiterRejectSource: 'shadow' | 'eval-proxy';
416
418
 
417
419
  if (shadowStats && shadowStats.isStatisticallySignificant) {
@@ -446,8 +448,10 @@ export function evaluatePromotionGate(
446
448
  // --- Check 6: Executability reject rate constraint ---
447
449
  // PREFER real shadow evidence: escalation rate + profile rejection rate
448
450
 
451
+ // eslint-disable-next-line @typescript-eslint/init-declarations
449
452
  let executabilityRejectRate: number;
450
453
 
454
+ // eslint-disable-next-line @typescript-eslint/init-declarations
451
455
  let executabilityRejectSource: 'shadow' | 'eval-proxy';
452
456
 
453
457
  if (shadowStats && shadowStats.isStatisticallySignificant) {
@@ -506,6 +510,7 @@ export function evaluatePromotionGate(
506
510
 
507
511
  // --- Suggest state based on checks ---
508
512
 
513
+ // eslint-disable-next-line @typescript-eslint/init-declarations
509
514
  let suggestedState: PromotionState | undefined;
510
515
  if (allPassed) {
511
516
  suggestedState = 'candidate_only';
@@ -619,6 +624,7 @@ export function advancePromotion(
619
624
  // (new eval data may reverse a previous rejection)
620
625
  //
621
626
 
627
+ // eslint-disable-next-line @typescript-eslint/init-declarations
622
628
  let targetState: PromotionState;
623
629
  if (!gateResult.passes) {
624
630
  targetState = 'rejected';
@@ -122,6 +122,7 @@ export class ReplayEngine {
122
122
  }
123
123
 
124
124
 
125
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
125
126
  runSingleSample(sample: ReplaySample, evaluator: CandidateEvaluator): ReplayResult {
126
127
  const evaluation = evaluator.evaluate(sample);
127
128
  return {
@@ -236,7 +237,7 @@ export class ReplayEngine {
236
237
  };
237
238
  }
238
239
 
239
- // eslint-disable-next-line complexity -- complexity 13, refactor candidate
240
+
240
241
  private _buildRuleHostInput(sample: ReplaySample): RuleHostInput | null {
241
242
  const snapshot = getNocturnalSessionSnapshot(
242
243
  TrajectoryRegistry.get(this.workspaceDir),
@@ -295,7 +296,7 @@ export class ReplayEngine {
295
296
  }
296
297
 
297
298
 
298
- // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
299
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this -- complexity 11, slightly over threshold
299
300
  private _selectToolCall(
300
301
  snapshot: NocturnalSessionSnapshot,
301
302
  classification: SampleClassification,
@@ -326,6 +327,7 @@ export class ReplayEngine {
326
327
  }
327
328
 
328
329
 
330
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
329
331
  private _matchGateBlock(
330
332
  gateBlocks: NocturnalGateBlock[],
331
333
  toolCall: NocturnalToolCall,
@@ -363,6 +365,7 @@ export class ReplayEngine {
363
365
  }
364
366
 
365
367
 
368
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
366
369
  private _estimateLineChanges(toolCall: NocturnalToolCall): number {
367
370
  if (toolCall.toolName === 'edit' || toolCall.toolName === 'write') {
368
371
  return 20;
@@ -371,6 +374,7 @@ export class ReplayEngine {
371
374
  }
372
375
 
373
376
 
377
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
374
378
  private _inferBashRisk(toolCall: NocturnalToolCall): 'safe' | 'normal' | 'dangerous' | 'unknown' {
375
379
  if (toolCall.toolName !== 'bash' && toolCall.toolName !== 'run_shell_command') {
376
380
  return 'unknown';
@@ -382,9 +386,9 @@ export class ReplayEngine {
382
386
  return toolCall.outcome === 'success' ? 'safe' : 'normal';
383
387
  }
384
388
 
385
- // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
389
+
386
390
 
387
- // eslint-disable-next-line complexity -- complexity 11
391
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this -- complexity 11
388
392
  private _scoreEvaluation(
389
393
  sample: ReplaySample,
390
394
  result: RuleHostResult,
@@ -493,6 +497,7 @@ export class ReplayEngine {
493
497
  }
494
498
 
495
499
 
500
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
496
501
  private _determineDecision(
497
502
  pain: ClassificationSummary,
498
503
  success: ClassificationSummary,
@@ -524,6 +529,7 @@ export class ReplayEngine {
524
529
  }
525
530
 
526
531
 
532
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
527
533
  private _deriveExpectedOutcome(
528
534
  record: NocturnalDatasetRecord,
529
535
  ): ReplaySample['expectedOutcome'] {
@@ -9,7 +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
13
  export function estimateLineChanges(modification: FileModification): number {
14
14
  const { toolName, params } = modification;
15
15
 
@@ -95,6 +95,7 @@ export function getTargetFileLineCount(absoluteFilePath: string): number | null
95
95
  * @returns Maximum allowed lines (at least minLines, at most maxLines if provided)
96
96
  */
97
97
 
98
+ // eslint-disable-next-line @typescript-eslint/max-params
98
99
  export function calculatePercentageThreshold(
99
100
  targetLineCount: number,
100
101
  percentage: number,
@@ -59,7 +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
63
  evaluate(input: RuleHostInput): RuleHostResult | undefined {
64
64
  try {
65
65
  // Load active code implementations from the ledger
@@ -71,6 +71,7 @@ export class RuleHost {
71
71
 
72
72
  // Merge decisions from all active implementations
73
73
 
74
+ // eslint-disable-next-line @typescript-eslint/init-declarations
74
75
  let blocked: RuleHostResult | undefined;
75
76
  const approvals: RuleHostResult[] = [];
76
77
 
@@ -182,7 +183,7 @@ export class RuleHost {
182
183
  * Uses the shared isolated runtime loader so candidate code does not execute
183
184
  * in the host global realm.
184
185
  */
185
- // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
186
+
186
187
  private _loadSingleImplementation(
187
188
  impl: Implementation
188
189
  ): LoadedImplementation | null {
@@ -84,6 +84,7 @@ export function initPersistence(stateDir: string): void {
84
84
 
85
85
  // Load all existing sessions
86
86
 
87
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
87
88
  loadAllSessions();
88
89
  }
89
90
 
@@ -181,6 +182,7 @@ export function flushAllSessions(): void {
181
182
  }
182
183
 
183
184
 
185
+ // eslint-disable-next-line @typescript-eslint/max-params
184
186
  function getOrCreateSession(sessionId: string, workspaceDir?: string, sessionKey?: string, trigger?: string): SessionState {
185
187
  let state = sessions.get(sessionId);
186
188
  if (!state) {
@@ -243,7 +245,7 @@ export function trackToolRead(sessionId: string, filePath: string, workspaceDir?
243
245
  }
244
246
 
245
247
 
246
- // eslint-disable-next-line complexity -- complexity 12, refactor candidate
248
+ // eslint-disable-next-line @typescript-eslint/max-params -- complexity 12, refactor candidate
247
249
  export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined, config?: PainConfig, workspaceDir?: string, sessionKey?: string, trigger?: string): SessionState {
248
250
  const state = getOrCreateSession(sessionId, workspaceDir, sessionKey, trigger);
249
251
  state.llmTurns += 1;
@@ -283,7 +285,7 @@ export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined,
283
285
  * Tracks physical friction based on tool execution failures.
284
286
  */
285
287
 
286
- // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
288
+ // eslint-disable-next-line @typescript-eslint/max-params -- complexity 11, slightly over threshold
287
289
  export function trackFriction(
288
290
  sessionId: string,
289
291
  deltaF: number,
@@ -550,6 +552,7 @@ export function decayGfi(sessionId: string, elapsedMinutes: number): SessionStat
550
552
  if (!state || state.currentGfi <= 0 || elapsedMinutes <= 0) return undefined;
551
553
 
552
554
  // Determine decay rate based on current GFI level (segmented)
555
+ // eslint-disable-next-line @typescript-eslint/init-declarations
553
556
  let decayRate: number;
554
557
  if (state.currentGfi >= 70) {
555
558
  decayRate = 0.03; // 3%/min for severe friction
@@ -342,6 +342,7 @@ export function completeShadowObservation(
342
342
  * @returns The updated ShadowObservation, or null if not found
343
343
  */
344
344
 
345
+ // eslint-disable-next-line @typescript-eslint/max-params
345
346
  export function completeShadowObservationByTask(
346
347
  stateDir: string,
347
348
  taskFingerprint: string,
@@ -45,6 +45,7 @@ export function parseThinkingOsMd(content: string): ThinkingOsDirective[] {
45
45
  // Match all <directive ...> ... </directive> blocks
46
46
  const directiveRegex = /<directive\s+([^>]*)>([\s\S]*?)<\/directive>/gi;
47
47
 
48
+ // eslint-disable-next-line no-useless-assignment
48
49
  let _match: RegExpExecArray | null = null;
49
50
 
50
51
  while ((_match = directiveRegex.exec(content)) !== null) {
@@ -208,7 +208,7 @@ export class TrajectoryDatabase {
208
208
  const createdAt = input.createdAt ?? nowIso();
209
209
  // Extract filePath from paramsJson if provided and is an object with filePath
210
210
  const paramsObj = input.paramsJson as Record<string, unknown> | undefined;
211
- /* eslint-disable @typescript-eslint/no-unused-vars -- Reason: _filePath extracted for potential future use but currently unused */
211
+
212
212
  const _filePath = paramsObj && typeof paramsObj.filePath === 'string' ? paramsObj.filePath : null;
213
213
  const rowId = this.withWrite(() => {
214
214
  const result = this.db.prepare(`
@@ -442,7 +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
446
  this.withWrite(() => {
447
447
  const setClauses: string[] = ['updated_at = ?'];
448
448
  const values: unknown[] = [now];
@@ -555,7 +555,7 @@ export class TrajectoryDatabase {
555
555
  LIMIT ? OFFSET ?
556
556
  `).all(...values, limit, offset) as Record<string, unknown>[];
557
557
 
558
- // eslint-disable-next-line complexity -- complexity 13, refactor candidate
558
+
559
559
  return rows.map((row) => ({
560
560
  id: Number(row.id),
561
561
  taskId: String(row.task_id),
@@ -590,6 +590,7 @@ export class TrajectoryDatabase {
590
590
  const offset = filters.offset ?? 0;
591
591
 
592
592
 
593
+ // eslint-disable-next-line @typescript-eslint/init-declarations
593
594
  let rows: Record<string, unknown>[];
594
595
  if (traceId) {
595
596
  rows = this.db.prepare(`
@@ -627,7 +628,7 @@ export class TrajectoryDatabase {
627
628
  * Returns: Analytics data aggregated from trajectory database.
628
629
  * Not: Runtime truth or real-time queue state.
629
630
  */
630
- // eslint-disable-next-line complexity -- complexity 14, refactor candidate
631
+
631
632
  getEvolutionTaskByTraceId(traceId: string): EvolutionTaskRecord | null {
632
633
  const row = this.db.prepare(`
633
634
  SELECT id, task_id, trace_id, source, reason, score, status,
@@ -778,7 +779,7 @@ export class TrajectoryDatabase {
778
779
  WHERE session_id = ?
779
780
  ORDER BY id ASC
780
781
  `).all(sessionId) as Record<string, unknown>[];
781
- // eslint-disable-next-line complexity -- complexity 12, refactor candidate
782
+
782
783
 
783
784
  return rows.map((row) => {
784
785
  // Extract filePath from params_json if present
@@ -788,6 +789,7 @@ export class TrajectoryDatabase {
788
789
  const params = JSON.parse(row.params_json);
789
790
  if (params && typeof params.filePath === 'string') {
790
791
 
792
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
791
793
  filePath = params.filePath;
792
794
  }
793
795
  } catch {
@@ -1614,6 +1616,7 @@ export class TrajectoryDatabase {
1614
1616
  }
1615
1617
 
1616
1618
 
1619
+ // eslint-disable-next-line @typescript-eslint/max-params
1617
1620
  private recordExportAudit(
1618
1621
  exportKind: string,
1619
1622
  mode: CorrectionExportMode,
@@ -1679,6 +1682,7 @@ export class TrajectoryDatabase {
1679
1682
  if (referenced.has(entry)) continue;
1680
1683
  const fullPath = path.join(this.blobDir, entry);
1681
1684
 
1685
+ // eslint-disable-next-line @typescript-eslint/init-declarations
1682
1686
  let stat: fs.Stats;
1683
1687
  try {
1684
1688
  stat = fs.statSync(fullPath);
@@ -39,6 +39,7 @@ export type BashRiskLevel = 'safe' | 'dangerous' | 'normal';
39
39
  * @returns The risk level: 'safe', 'dangerous', or 'normal'
40
40
  */
41
41
 
42
+ // eslint-disable-next-line @typescript-eslint/max-params
42
43
  export function analyzeBashCommand(
43
44
  command: string,
44
45
  safePatterns: string[],
@@ -153,6 +154,7 @@ export interface DynamicThresholdConfig {
153
154
  * @param config - Configuration with large_change_lines and ep_tier_multipliers
154
155
  * @returns The adjusted threshold (minimum 0)
155
156
  */
157
+ // eslint-disable-next-line @typescript-eslint/max-params
156
158
  export function calculateDynamicThreshold(
157
159
  baseThreshold: number,
158
160
  epTier: number,
@@ -127,6 +127,7 @@ This is enforced by P-03 (精确匹配前验证原则).`;
127
127
  * This enforces P-03 at the tool layer
128
128
  */
129
129
 
130
+ // eslint-disable-next-line @typescript-eslint/max-params
130
131
  export function handleEditVerification(
131
132
  event: PluginHookBeforeToolCallEvent,
132
133
  wctx: WorkspaceContext,
@@ -156,6 +157,7 @@ export function handleEditVerification(
156
157
 
157
158
  // 2. Resolve and read file
158
159
 
160
+ // eslint-disable-next-line @typescript-eslint/init-declarations
159
161
  let absolutePath: string;
160
162
  try {
161
163
  absolutePath = wctx.resolve(filePath);
@@ -223,6 +225,7 @@ export function handleEditVerification(
223
225
 
224
226
  // 3. Read current file content with improved error handling
225
227
 
228
+ // eslint-disable-next-line @typescript-eslint/init-declarations
226
229
  let currentContent: string;
227
230
  try {
228
231
  currentContent = fs.readFileSync(absolutePath, 'utf-8');
@@ -95,6 +95,7 @@ export function recordGateBlockAndReturn(
95
95
  } catch (error: unknown) {
96
96
  logWarn(`[PD_GATE] Failed to record trajectory gate block: ${String(error)}`);
97
97
 
98
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
98
99
  scheduleTrajectoryGateBlockRetry(wctx, trajectoryPayload, 1, logWarn, logError);
99
100
  }
100
101
 
@@ -122,6 +123,7 @@ export function recordGateBlockAndReturn(
122
123
 
123
124
  // Write to pain flag file (merge with existing if present)
124
125
  try {
126
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
125
127
  const workspaceDir = wctx.workspaceDir;
126
128
  const currentFlag = wctx.eventLog.findLatestPainSignal(sessionId);
127
129
  const currentScore = currentFlag?.score ?? 0;
@@ -181,6 +183,7 @@ This is a mandatory security gate. The operation was blocked because the modific
181
183
  * Failures are logged but do not affect the runtime block decision.
182
184
  */
183
185
 
186
+ // eslint-disable-next-line @typescript-eslint/max-params
184
187
  function scheduleTrajectoryGateBlockRetry(
185
188
  wctx: WorkspaceContext,
186
189
  payload: {
package/src/hooks/gate.ts CHANGED
@@ -135,6 +135,7 @@ export function handleBeforeToolCall(
135
135
 
136
136
  if (mutationMatch) {
137
137
 
138
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
138
139
  filePath = mutationMatch[1];
139
140
  } else {
140
141
  const hasRiskPath = profile.risk_paths.some(rp => command.includes(rp));
@@ -168,29 +169,36 @@ export function handleBeforeToolCall(
168
169
  toolName: event.toolName,
169
170
  normalizedPath: relPath,
170
171
 
172
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
171
173
  paramsSummary: _extractParamsSummary(event.params),
172
174
  },
173
175
  workspace: {
174
176
  isRiskPath: risky,
175
177
 
178
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
176
179
  planStatus: _getPlanStatus(ctx.workspaceDir),
177
180
 
181
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
178
182
  hasPlanFile: _hasPlanFile(ctx.workspaceDir),
179
183
  },
180
184
  session: {
181
185
  sessionId: ctx.sessionId,
182
186
 
187
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
183
188
  currentGfi: _getCurrentGfi(ctx.sessionId),
184
189
 
190
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
185
191
  recentThinking: _hasRecentThinking(ctx.sessionId),
186
192
  },
187
193
  evolution: {
188
194
 
195
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
189
196
  epTier: _getEpTier(wctx.workspaceDir),
190
197
  },
191
198
  derived: {
192
199
  estimatedLineChanges: estimateLineChanges({ toolName: event.toolName, params: event.params }),
193
200
 
201
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
194
202
  bashRisk: _getBashRisk(event, profile),
195
203
  },
196
204
  };
@@ -48,6 +48,7 @@ export interface GfiGateConfig {
48
48
  * Internal helper to call the shared block helper with gfi-gate source tag.
49
49
  */
50
50
 
51
+ // eslint-disable-next-line @typescript-eslint/max-params
51
52
  function block(
52
53
  wctx: WorkspaceContext,
53
54
  filePath: string,
@@ -69,6 +70,7 @@ function block(
69
70
  }
70
71
 
71
72
 
73
+ // eslint-disable-next-line @typescript-eslint/max-params
72
74
  export function checkGfiGate(
73
75
  event: PluginHookBeforeToolCallEvent,
74
76
  wctx: WorkspaceContext,
@@ -197,6 +197,7 @@ export async function handleBeforeCompaction(
197
197
 
198
198
  // 新增:提取并保存工作记忆
199
199
 
200
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
200
201
  await extractAndSaveWorkingMemory(event.sessionFile, ctx, wctx);
201
202
  }
202
203
  }
package/src/hooks/llm.ts CHANGED
@@ -256,6 +256,7 @@ export function handleLlmOutput(
256
256
 
257
257
  // ═══ Thinking OS: Mental Model Usage Tracking ═══
258
258
 
259
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
259
260
  trackThinkingModelUsage({
260
261
  text,
261
262
  wctx,
package/src/hooks/pain.ts CHANGED
@@ -131,6 +131,7 @@ export function handleAfterToolCall(
131
131
 
132
132
  // ── Trust Engine: Record failure ──
133
133
 
134
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
134
135
  const errorType = extractErrorType(event.error || errorText);
135
136
  const filePath = params.file_path || params.path || params.file;
136
137
  const relPath = typeof filePath === 'string' ? normalizePath(filePath, effectiveWorkspaceDir) : 'unknown';
@@ -193,6 +194,7 @@ export function handleAfterToolCall(
193
194
  const session = getSession(sessionId);
194
195
  const toolFailureGfi = session?.gfiBySource?.tool_failure || 0;
195
196
 
197
+ // eslint-disable-next-line @typescript-eslint/init-declarations
196
198
  let resetState: SessionState;
197
199
  if (toolFailureGfi > 0) {
198
200
  // Reduce tool_failure source by 50% (relief from successful tool execution)
@@ -391,7 +393,7 @@ export function handleAfterToolCall(
391
393
  });
392
394
  }
393
395
 
394
- // eslint-disable-next-line complexity -- complexity 15, refactor candidate
396
+
395
397
  function extractErrorType(error: unknown): string {
396
398
  if (!error) return 'Unknown';
397
399
  const msg = String(error);
@@ -87,6 +87,7 @@ export function buildEvolutionGateReason(
87
87
  * Internal helper to call the shared block helper with progressive-trust-gate source tag.
88
88
  */
89
89
 
90
+ // eslint-disable-next-line @typescript-eslint/max-params
90
91
  function block(
91
92
  filePath: string,
92
93
  reason: string,
@@ -120,6 +121,7 @@ function block(
120
121
  * @returns PluginHookBeforeToolCallResult to block, or undefined to allow
121
122
  */
122
123
 
124
+ // eslint-disable-next-line @typescript-eslint/max-params
123
125
  export function checkProgressiveTrustGate(
124
126
  event: PluginHookBeforeToolCallEvent,
125
127
  wctx: WorkspaceContext,
@@ -152,6 +154,7 @@ export function checkProgressiveTrustGate(
152
154
 
153
155
  const currentTier = epDecision.currentTier ?? 1;
154
156
 
157
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
155
158
  const tierName = getTierName(currentTier);
156
159
 
157
160
  logger.info?.(`[PD_GATE] EP Gate: Tier ${currentTier} (${tierName}), Tool: ${event.toolName}, Risk: ${risky}, Allowed: ${epDecision.allowed}`);
@@ -202,7 +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
206
  export function getDiagnosticianModel(api: PromptHookApi | null, logger?: PluginLogger): string {
207
207
  // Determines logger: prefer api.logger, fallback to provided logger
208
208
  // 1. getDiagnosticianModel(api) - uses api.logger
@@ -368,6 +368,7 @@ export async function handleBeforePromptBuild(
368
368
  // prependContext: Only short dynamic directives: evolutionDirective + heartbeat
369
369
 
370
370
 
371
+ // eslint-disable-next-line @typescript-eslint/init-declarations
371
372
  let prependSystemContext: string;
372
373
  let prependContext = '';
373
374
  let appendSystemContext = '';
@@ -683,6 +684,7 @@ ${taskBlocks}${processingNote}
683
684
 
684
685
  // ──── 6. Dynamic Attitude Matrix (based on GFI) ────
685
686
 
687
+ // eslint-disable-next-line @typescript-eslint/init-declarations
686
688
  let attitudeDirective: string;
687
689
  const currentGfi = session?.currentGfi || 0;
688
690
 
@@ -908,9 +910,10 @@ ${taskBlocks}${processingNote}
908
910
  const toolMatches = toolPatterns.flatMap(({ pattern, tool }) => {
909
911
  const matches: string[] = [];
910
912
 
913
+ // eslint-disable-next-line @typescript-eslint/init-declarations
911
914
  let _m;
912
915
  const r = new RegExp(pattern.source, pattern.flags);
913
- /* eslint-disable @typescript-eslint/no-unused-vars -- Reason: regex exec side effect used, match variable intentionally unused */
916
+
914
917
  while ((_m = r.exec(latestUserText)) !== null) matches.push(tool);
915
918
  return matches;
916
919
  });
@@ -14,6 +14,7 @@ import type { WorkflowManager } from '../service/subagent-workflow/types.js';
14
14
  * Used by the subagent_ended hook to dispatch lifecycle recovery to the right manager.
15
15
  */
16
16
 
17
+ // eslint-disable-next-line @typescript-eslint/max-params
17
18
  function createWorkflowManagerForType(
18
19
  workflowType: string,
19
20
  workspaceDir: string,
@@ -41,6 +41,7 @@ export interface ThinkingCheckpointConfig {
41
41
  * @returns Block result if thinking required, undefined otherwise
42
42
  */
43
43
 
44
+ // eslint-disable-next-line @typescript-eslint/max-params
44
45
  export function checkThinkingCheckpoint(
45
46
  event: PluginHookBeforeToolCallEvent,
46
47
  config: ThinkingCheckpointConfig,
@@ -212,7 +212,7 @@ export function handleLlmOutput(
212
212
  * 消息写入前的处理
213
213
  * 记录:用户/助手消息内容
214
214
  */
215
- // eslint-disable-next-line complexity -- complexity 11, slightly over threshold
215
+
216
216
  export function handleBeforeMessageWrite(
217
217
  event: PluginHookBeforeMessageWriteEvent,
218
218
  ctx: PluginHookAgentContext & { workspaceDir?: string }
@@ -231,6 +231,7 @@ export function handleBeforeMessageWrite(
231
231
  if (typeof msg.content === 'string') {
232
232
 
233
233
  // Reason: msg.content is string | ContentPart[]; destructuring would require renaming in the else branch
234
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
234
235
  content = msg.content;
235
236
  } else if (Array.isArray(msg.content)) {
236
237
  content = msg.content
@@ -96,6 +96,7 @@ function createService(api: OpenClawPluginApi): ControlUiQueryService {
96
96
  }
97
97
 
98
98
 
99
+ // eslint-disable-next-line @typescript-eslint/max-params
99
100
  function handleApiRoute(
100
101
  api: OpenClawPluginApi,
101
102
  pathname: string,
@@ -104,11 +105,13 @@ function handleApiRoute(
104
105
  ): Promise<boolean> | boolean {
105
106
  // Check authentication for API routes
106
107
 
108
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
107
109
  if (!validateGatewayAuth(req)) {
108
110
  json(res, 401, { error: 'unauthorized', message: 'Valid Gateway token required.' });
109
111
  return true;
110
112
  }
111
113
 
114
+ // eslint-disable-next-line @typescript-eslint/init-declarations
112
115
  let service: ControlUiQueryService;
113
116
  try {
114
117
  service = createService(api);
@@ -578,7 +581,7 @@ export function createPrinciplesConsoleRoutes(api: OpenClawPluginApi): OpenClawP
578
581
  path: ROUTE_PREFIX,
579
582
  auth: 'plugin',
580
583
  match: 'prefix',
581
- // eslint-disable-next-line complexity -- complexity 13, refactor candidate
584
+
582
585
  async handler(req, res) {
583
586
  if (!api.rootDir) { text(res, 500, 'Plugin rootDir not available'); return true; }
584
587
  const url = new URL(req.url || ROUTE_PREFIX, 'http://127.0.0.1');
@@ -641,7 +644,7 @@ export function createPrinciplesConsoleRoute(api: OpenClawPluginApi): OpenClawPl
641
644
  path: ROUTE_PREFIX,
642
645
  auth: 'plugin',
643
646
  match: 'prefix',
644
- // eslint-disable-next-line complexity -- complexity 15, refactor candidate
647
+
645
648
  async handler(req, res) {
646
649
  if (!api.rootDir) { text(res, 500, 'Plugin rootDir not available'); return true; }
647
650
  const url = new URL(req.url || ROUTE_PREFIX, 'http://127.0.0.1');
package/src/index.ts CHANGED
@@ -401,6 +401,7 @@ const plugin = {
401
401
 
402
402
  // ── Slash Commands ──
403
403
  // Register command with optional short alias
404
+ // eslint-disable-next-line @typescript-eslint/max-params, @typescript-eslint/no-explicit-any
404
405
  const registerCommandWithAlias = (name: string, alias: string | null, desc: string, handler: any, opts?: { acceptsArgs?: boolean }) => {
405
406
  const base = {
406
407
  name,
@@ -418,11 +419,17 @@ const plugin = {
418
419
  }
419
420
  };
420
421
 
422
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
421
423
  registerCommandWithAlias('pd-init', 'pdi', getCommandDescription('pd-init', language), (ctx: any) => handleInitStrategy(ctx));
424
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
422
425
  registerCommandWithAlias('pd-okr', 'pdk', getCommandDescription('pd-okr', language), (ctx: any) => handleManageOkr(ctx));
426
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
423
427
  registerCommandWithAlias('pd-bootstrap', 'pdb', getCommandDescription('pd-bootstrap', language), (ctx: any) => handleBootstrapTools(ctx));
428
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
424
429
  registerCommandWithAlias('pd-research', 'pdr', getCommandDescription('pd-research', language), (ctx: any) => handleResearchTools(ctx));
430
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
425
431
  registerCommandWithAlias('pd-thinking', 'pdt', getCommandDescription('pd-thinking', language), (ctx: any) => handleThinkingOs(ctx), { acceptsArgs: true });
432
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
426
433
  registerCommandWithAlias('pd-reflect', 'pdrl', getCommandDescription('pd-reflect', language), (ctx: any) => {
427
434
  try {
428
435
  // Resolve agentId from sessionKey (if available), fallback to 'main'
@@ -18,6 +18,7 @@ export interface CentralHealthResponse {
18
18
  */
19
19
  export class CentralHealthService {
20
20
 
21
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
21
22
  getAllWorkspaceHealth(): CentralHealthResponse {
22
23
  const centralDb = getCentralDatabase();
23
24
  const workspaces: WorkspaceHealthEntry[] = [];
@@ -24,6 +24,7 @@ export class CentralOverviewService {
24
24
  }
25
25
 
26
26
 
27
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
27
28
  dispose(): void {
28
29
  // Do NOT dispose centralDb — it's a singleton shared across all requests.
29
30
  // Individual services that open per-request connections (e.g. HealthQueryService)
@@ -61,6 +62,7 @@ export class CentralOverviewService {
61
62
 
62
63
  // D-06: sampleQueue.counters from aggregated_correction_samples GROUP BY review_status
63
64
 
65
+ // eslint-disable-next-line no-useless-assignment
64
66
  let sampleCounters: Record<string, number> = {};
65
67
  try {
66
68
  sampleCounters = this.centralDb.getSampleCountersByStatus();