principles-disciple 1.28.1 → 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 (101) hide show
  1. package/openclaw.plugin.json +4 -4
  2. package/package.json +1 -1
  3. package/src/commands/archive-impl.ts +3 -0
  4. package/src/commands/context.ts +4 -0
  5. package/src/commands/disable-impl.ts +2 -0
  6. package/src/commands/evolution-status.ts +2 -0
  7. package/src/commands/focus.ts +4 -0
  8. package/src/commands/nocturnal-train.ts +9 -1
  9. package/src/commands/pain.ts +3 -0
  10. package/src/commands/pd-reflect.ts +2 -0
  11. package/src/commands/principle-rollback.ts +1 -0
  12. package/src/commands/rollback-impl.ts +5 -0
  13. package/src/commands/rollback.ts +2 -1
  14. package/src/commands/samples.ts +1 -0
  15. package/src/commands/workflow-debug.ts +1 -0
  16. package/src/core/adaptive-thresholds.ts +2 -0
  17. package/src/core/code-implementation-storage.ts +2 -0
  18. package/src/core/config.ts +1 -0
  19. package/src/core/diagnostician-task-store.ts +2 -0
  20. package/src/core/dictionary.ts +1 -0
  21. package/src/core/empathy-keyword-matcher.ts +4 -0
  22. package/src/core/event-log.ts +6 -1
  23. package/src/core/evolution-engine.ts +4 -0
  24. package/src/core/evolution-logger.ts +1 -0
  25. package/src/core/external-training-contract.ts +2 -0
  26. package/src/core/focus-history.ts +15 -0
  27. package/src/core/init.ts +3 -0
  28. package/src/core/merge-gate-audit.ts +3 -0
  29. package/src/core/model-deployment-registry.ts +1 -0
  30. package/src/core/model-training-registry.ts +1 -0
  31. package/src/core/nocturnal-arbiter.ts +4 -0
  32. package/src/core/nocturnal-candidate-scoring.ts +5 -0
  33. package/src/core/nocturnal-compliance.ts +22 -0
  34. package/src/core/nocturnal-dataset.ts +3 -0
  35. package/src/core/nocturnal-executability.ts +1 -0
  36. package/src/core/nocturnal-export.ts +5 -0
  37. package/src/core/nocturnal-reasoning-deriver.ts +6 -0
  38. package/src/core/nocturnal-rule-implementation-validator.ts +1 -0
  39. package/src/core/nocturnal-snapshot-contract.ts +1 -0
  40. package/src/core/nocturnal-trinity.ts +24 -0
  41. package/src/core/pain-context-extractor.ts +3 -0
  42. package/src/core/pain.ts +3 -0
  43. package/src/core/pd-task-reconciler.ts +3 -0
  44. package/src/core/pd-task-service.ts +1 -0
  45. package/src/core/pd-task-store.ts +1 -0
  46. package/src/core/principle-internalization/deprecated-readiness.ts +2 -0
  47. package/src/core/principle-internalization/principle-lifecycle-service.ts +1 -0
  48. package/src/core/principle-training-state.ts +2 -0
  49. package/src/core/principle-tree-ledger.ts +4 -0
  50. package/src/core/principle-tree-migration.ts +2 -0
  51. package/src/core/promotion-gate.ts +7 -1
  52. package/src/core/replay-engine.ts +10 -0
  53. package/src/core/risk-calculator.ts +2 -0
  54. package/src/core/rule-host.ts +3 -0
  55. package/src/core/session-tracker.ts +5 -0
  56. package/src/core/shadow-observation-registry.ts +1 -0
  57. package/src/core/thinking-models.ts +1 -0
  58. package/src/core/thinking-os-parser.ts +1 -0
  59. package/src/core/trajectory.ts +9 -1
  60. package/src/hooks/bash-risk.ts +2 -0
  61. package/src/hooks/edit-verification.ts +3 -0
  62. package/src/hooks/gate-block-helper.ts +3 -0
  63. package/src/hooks/gate.ts +8 -0
  64. package/src/hooks/gfi-gate.ts +2 -0
  65. package/src/hooks/lifecycle-routing.ts +1 -0
  66. package/src/hooks/lifecycle.ts +1 -0
  67. package/src/hooks/llm.ts +1 -0
  68. package/src/hooks/pain.ts +3 -0
  69. package/src/hooks/progressive-trust-gate.ts +3 -0
  70. package/src/hooks/prompt.ts +5 -1
  71. package/src/hooks/subagent.ts +1 -0
  72. package/src/hooks/thinking-checkpoint.ts +1 -0
  73. package/src/hooks/trajectory-collector.ts +2 -0
  74. package/src/http/principles-console-route.ts +5 -0
  75. package/src/index.ts +7 -0
  76. package/src/service/central-database.ts +2 -0
  77. package/src/service/central-health-service.ts +1 -0
  78. package/src/service/central-overview-service.ts +2 -0
  79. package/src/service/central-sync-service.ts +1 -0
  80. package/src/service/control-ui-query-service.ts +2 -0
  81. package/src/service/event-log-auditor.ts +2 -0
  82. package/src/service/evolution-query-service.ts +1 -0
  83. package/src/service/evolution-worker.ts +31 -0
  84. package/src/service/health-query-service.ts +6 -1
  85. package/src/service/monitoring-query-service.ts +4 -0
  86. package/src/service/nocturnal-runtime.ts +7 -1
  87. package/src/service/nocturnal-service.ts +21 -0
  88. package/src/service/nocturnal-target-selector.ts +2 -0
  89. package/src/service/runtime-summary-service.ts +6 -0
  90. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +2 -0
  91. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +2 -0
  92. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +3 -0
  93. package/src/service/subagent-workflow/subagent-error-utils.ts +1 -0
  94. package/src/service/subagent-workflow/workflow-manager-base.ts +6 -0
  95. package/src/service/subagent-workflow/workflow-store.ts +2 -0
  96. package/src/tools/critique-prompt.ts +1 -0
  97. package/src/tools/deep-reflect.ts +9 -0
  98. package/src/tools/model-index.ts +1 -0
  99. package/src/tools/write-pain-flag.ts +1 -0
  100. package/src/utils/file-lock.ts +1 -0
  101. package/src/utils/io.ts +2 -0
@@ -342,6 +342,7 @@ function hasValidEvidenceSummary(parsed: unknown): boolean {
342
342
  * Validate a single replay report file and return its category.
343
343
  */
344
344
  function validateSingleReplayReport(reportPath: string): ReplayValidationCategory {
345
+ // eslint-disable-next-line @typescript-eslint/init-declarations
345
346
  let rawContent: string;
346
347
  try {
347
348
  rawContent = fs.readFileSync(reportPath, 'utf-8');
@@ -349,6 +350,7 @@ function validateSingleReplayReport(reportPath: string): ReplayValidationCategor
349
350
  return 'io_error';
350
351
  }
351
352
 
353
+ // eslint-disable-next-line @typescript-eslint/init-declarations
352
354
  let parsed: unknown;
353
355
  try {
354
356
  parsed = JSON.parse(rawContent);
@@ -364,6 +366,7 @@ function validateSingleReplayReport(reportPath: string): ReplayValidationCategor
364
366
  return 'missing_evidence_summary';
365
367
  }
366
368
 
369
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
367
370
  const evidenceSummary = parsed.evidenceSummary;
368
371
  if (parsed.overallDecision === 'pass' && evidenceSummary.totalSamples === 0) {
369
372
  return 'unsupported_pass';
@@ -350,6 +350,7 @@ export function assertPromotionGatePassed(stateDir: string, checkpointId: string
350
350
  * @throws Error if checkpoint's targetModelFamily violates profile constraints
351
351
  */
352
352
 
353
+ // eslint-disable-next-line @typescript-eslint/max-params
353
354
  export function bindCheckpointToWorkerProfile(
354
355
  stateDir: string,
355
356
  workerProfile: WorkerProfile,
@@ -322,6 +322,7 @@ export function registerTrainingRun(
322
322
  * @throws Error if run not found or transition is invalid
323
323
  */
324
324
 
325
+ // eslint-disable-next-line @typescript-eslint/max-params
325
326
  export function updateTrainingRunStatus(
326
327
  stateDir: string,
327
328
  trainRunId: string,
@@ -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
+
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
+
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
+
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`);
@@ -691,6 +694,7 @@ export function parseAndValidateArtifact(
691
694
  ): ArbiterResult {
692
695
  // Step 1: Parse JSON
693
696
 
697
+ // eslint-disable-next-line @typescript-eslint/init-declarations
694
698
  let parsed: unknown;
695
699
  try {
696
700
  parsed = JSON.parse(jsonString);
@@ -293,6 +293,7 @@ export function validateCandidateDiversity(
293
293
 
294
294
  for (let i = 0; i < candidates.length; i++) {
295
295
  for (let j = i + 1; j < candidates.length; j++) {
296
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
296
297
  const overlap = computeKeywordOverlap(
297
298
  candidates[i].betterDecision ?? '',
298
299
  candidates[j].betterDecision ?? '',
@@ -334,7 +335,9 @@ export function validateCandidateDiversity(
334
335
  * Returns value between 0 and 1.
335
336
  */
336
337
  function computeKeywordOverlap(textA: string, textB: string): number {
338
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
337
339
  const wordsA = extractKeywords(textA);
340
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
338
341
  const wordsB = extractKeywords(textB);
339
342
 
340
343
  if (wordsA.length === 0 && wordsB.length === 0) return 0;
@@ -373,6 +376,7 @@ function extractKeywords(text: string): string[] {
373
376
  * @returns All scored and ranked candidates
374
377
  */
375
378
 
379
+ // eslint-disable-next-line @typescript-eslint/max-params
376
380
  export function rankCandidates(
377
381
  candidates: DreamerCandidate[],
378
382
  judgments: PhilosopherJudgment[],
@@ -460,6 +464,7 @@ export function rankCandidates(
460
464
  * @returns Tournament result with winner
461
465
  */
462
466
 
467
+ // eslint-disable-next-line @typescript-eslint/max-params
463
468
  export function runTournament(
464
469
  candidates: DreamerCandidate[],
465
470
  judgments: PhilosopherJudgment[],
@@ -242,22 +242,31 @@ export function detectOpportunity(principleId: string, session: SessionEvents):
242
242
 
243
243
  switch (principleId) {
244
244
  case 'T-01':
245
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
245
246
  return detectT01Opportunity(session);
246
247
  case 'T-02':
248
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
247
249
  return detectT02Opportunity(session);
248
250
  case 'T-03':
251
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
249
252
  return detectT03Opportunity(session);
250
253
  case 'T-04':
254
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
251
255
  return detectT04Opportunity(session);
252
256
  case 'T-05':
257
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
253
258
  return detectT05Opportunity(session);
254
259
  case 'T-06':
260
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
255
261
  return detectT06Opportunity(session);
256
262
  case 'T-07':
263
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
257
264
  return detectT07Opportunity(session);
258
265
  case 'T-08':
266
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
259
267
  return detectT08Opportunity(session);
260
268
  case 'T-09':
269
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
261
270
  return detectT09Opportunity(session);
262
271
  default:
263
272
  return { applicable: false, reason: `Unknown principle: ${principleId}` };
@@ -513,6 +522,7 @@ function detectT09Opportunity(session: SessionEvents): OpportunityMatch {
513
522
  * trigger pattern. Since P_* principles don't have T-xx specific detectors,
514
523
  * we use the presence of negative signals as violation evidence.
515
524
  */
525
+
516
526
  export function detectViolation(principleId: string, session: SessionEvents): ViolationMatch {
517
527
  // #216: P_* principles (pain-derived) — generic violation detection
518
528
  if (principleId.startsWith('P_')) {
@@ -540,22 +550,31 @@ export function detectViolation(principleId: string, session: SessionEvents): Vi
540
550
 
541
551
  switch (principleId) {
542
552
  case 'T-01':
553
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
543
554
  return detectT01Violation(session);
544
555
  case 'T-02':
556
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
545
557
  return detectT02Violation(session);
546
558
  case 'T-03':
559
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
547
560
  return detectT03Violation(session);
548
561
  case 'T-04':
562
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
549
563
  return detectT04Violation(session);
550
564
  case 'T-05':
565
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
551
566
  return detectT05Violation(session);
552
567
  case 'T-06':
568
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
553
569
  return detectT06Violation(session);
554
570
  case 'T-07':
571
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
555
572
  return detectT07Violation(session);
556
573
  case 'T-08':
574
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
557
575
  return detectT08Violation(session);
558
576
  case 'T-09':
577
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
559
578
  return detectT09Violation(session);
560
579
  default:
561
580
  console.warn(`[PD:Compliance] Unknown principle ID: ${principleId} — treating as no violation. Check for typos (P-001 vs P_001).`);
@@ -914,9 +933,11 @@ export function computeCompliance(
914
933
  : 0;
915
934
 
916
935
  // Compute violationTrend using windows
936
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
917
937
  const violationTrend = computeViolationTrend(applicableSessions, windowSize);
918
938
 
919
939
  // Build explanation
940
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
920
941
  const explanation = buildExplanation(
921
942
  principleId,
922
943
  applicableOpportunityCount,
@@ -988,6 +1009,7 @@ function computeViolationTrend(
988
1009
  * Builds a human-readable explanation for the compliance result.
989
1010
  */
990
1011
 
1012
+ // eslint-disable-next-line @typescript-eslint/max-params
991
1013
  function buildExplanation(
992
1014
  principleId: string,
993
1015
  applicableOpportunityCount: number,
@@ -284,6 +284,7 @@ function withRegistryLock<T>(workspaceDir: string, fn: (_records: NocturnalDatas
284
284
  * @returns RegisterSampleResult
285
285
  */
286
286
 
287
+ // eslint-disable-next-line @typescript-eslint/max-params
287
288
  export function registerSample(
288
289
  workspaceDir: string,
289
290
  artifact: NocturnalArtifact,
@@ -426,6 +427,7 @@ const VALID_TRANSITIONS: Record<NocturnalReviewStatus, NocturnalReviewStatus[]>
426
427
  * @throws Error if transition is invalid
427
428
  */
428
429
 
430
+ // eslint-disable-next-line @typescript-eslint/max-params
429
431
  export function updateReviewStatus(
430
432
  workspaceDir: string,
431
433
  sampleFingerprint: string,
@@ -645,6 +647,7 @@ export function getDatasetStats(
645
647
  * @param targetModelFamily - Default target family for migrated samples
646
648
  * @returns Number of newly registered samples
647
649
  */
650
+
648
651
  export function migrateSampleArtifacts(
649
652
  workspaceDir: string,
650
653
  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;
@@ -158,6 +158,7 @@ function computeDatasetFingerprint(sampleFingerprints: string[]): string {
158
158
  * Caller guarantees record.targetModelFamily is non-null.
159
159
  */
160
160
 
161
+ // eslint-disable-next-line @typescript-eslint/max-params
161
162
  function serializeORPOSample(
162
163
  record: NocturnalDatasetRecord,
163
164
  artifact: ReturnType<typeof readDatasetArtifact>,
@@ -166,6 +167,7 @@ function serializeORPOSample(
166
167
  datasetFingerprint: string
167
168
  ): ORPOSample {
168
169
  const now = new Date().toISOString();
170
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
169
171
  const rejected = buildEvidenceBoundedRejected(artifact, evidenceSummary);
170
172
 
171
173
  return {
@@ -178,6 +180,7 @@ function serializeORPOSample(
178
180
  prompt: rejected,
179
181
  chosen: artifact.betterDecision,
180
182
  rejected,
183
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
181
184
  rationale: buildEvidenceBoundedRationale(evidenceSummary),
182
185
  datasetMetadata: {
183
186
  sampleFingerprint: record.sampleFingerprint,
@@ -292,6 +295,7 @@ export function exportORPOSamples(
292
295
  });
293
296
 
294
297
 
298
+ // eslint-disable-next-line @typescript-eslint/init-declarations
295
299
  let eligibleRecords: typeof allApprovedRecords;
296
300
 
297
301
  if (targetModelFamily !== undefined && targetModelFamily !== null) {
@@ -341,6 +345,7 @@ export function exportORPOSamples(
341
345
 
342
346
  // Read artifact (throws on error — distinguishes read failure from missing artifact)
343
347
 
348
+ // eslint-disable-next-line @typescript-eslint/init-declarations
344
349
  let artifact;
345
350
  try {
346
351
  artifact = readDatasetArtifact(workspaceDir, record.sampleFingerprint);
@@ -11,6 +11,7 @@
11
11
  * - deriveContextualFactors: Compute contextual factors from snapshot (Plan 02)
12
12
  */
13
13
 
14
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
14
15
  import type { NocturnalAssistantTurn, NocturnalToolCall, NocturnalUserTurn, NocturnalSessionSnapshot } from './nocturnal-trajectory-extractor.js';
15
16
  import { detectThinkingModelMatches, listThinkingModels } from './thinking-models.js';
16
17
 
@@ -143,6 +144,7 @@ export function deriveReasoningChain(assistantTurns: NocturnalAssistantTurn[]):
143
144
  // Without thinking tags we cannot extract a genuine reasoning trace, so
144
145
  // we fall back to 'low' rather than misleading the downstream pipeline
145
146
  // with activation derived from non-thinking patterns in the response text.
147
+ // eslint-disable-next-line @typescript-eslint/init-declarations
146
148
  let confidenceSignal: "high" | "medium" | "low";
147
149
  if (thinkingContent.length === 0) {
148
150
  confidenceSignal = 'low';
@@ -211,6 +213,7 @@ export function deriveDecisionPoints(
211
213
 
212
214
  // Binary search: find rightmost assistant turn with createdAt < tcTime
213
215
  const findBeforeTurn = (tcTime: number): NocturnalAssistantTurn | undefined => {
216
+ // eslint-disable-next-line @typescript-eslint/init-declarations
214
217
  let lo = 0, hi = sortedTurns.length - 1, result: NocturnalAssistantTurn | undefined;
215
218
  while (lo <= hi) {
216
219
  const mid = (lo + hi) >>> 1;
@@ -233,7 +236,9 @@ export function deriveDecisionPoints(
233
236
  : '';
234
237
 
235
238
  // On failure, find next assistant turn after tool call
239
+ // eslint-disable-next-line @typescript-eslint/init-declarations
236
240
  let afterReflection: string | undefined;
241
+ // eslint-disable-next-line @typescript-eslint/init-declarations
237
242
  let confidenceDelta: number | undefined;
238
243
 
239
244
  if (tc.outcome === 'failure') {
@@ -280,6 +285,7 @@ export function deriveDecisionPoints(
280
285
  *
281
286
  * Empty/missing data returns all-false defaults. Never throws.
282
287
  */
288
+
283
289
  export function deriveContextualFactors(
284
290
  snapshot: NocturnalSessionSnapshot,
285
291
  ): 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 [
@@ -53,6 +53,7 @@ export function validateNocturnalSnapshotIngress(
53
53
  }
54
54
  }
55
55
 
56
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
56
57
  const stats = value.stats;
57
58
  if (!isObjectRecord(stats)) {
58
59
  reasons.push('snapshot.stats must be an object');
@@ -584,6 +584,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
584
584
  this.cleanupStaleTempDirs();
585
585
  }
586
586
 
587
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
587
588
  isRuntimeAvailable(): boolean {
588
589
  return true;
589
590
  }
@@ -642,6 +643,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
642
643
  * runEmbeddedPiAgent does NOT read config.agents.defaults.model —
643
644
  * it requires explicit params.provider and params.model.
644
645
  */
646
+
645
647
  private resolveModel(): { provider: string; model: string } {
646
648
  const config = this.loadFullConfig();
647
649
  const agents = config?.agents as Record<string, unknown> | undefined;
@@ -680,6 +682,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
680
682
  /**
681
683
  * Extract text from runEmbeddedPiAgent result.
682
684
  */
685
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
683
686
  private extractPayloadText(result: { payloads?: { isError?: boolean; text?: string }[] }): string {
684
687
  return (result.payloads ?? [])
685
688
  .filter(p => !p.isError)
@@ -689,11 +692,13 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
689
692
  }
690
693
 
691
694
  /** Clamp a value to [0, 1] range — used for LLM-produced scores that may be out of range */
695
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
692
696
  private clamp01(val: unknown, fallback = 0): number {
693
697
  if (typeof val !== 'number' || !Number.isFinite(val)) return fallback;
694
698
  return Math.min(1, Math.max(0, val));
695
699
  }
696
700
 
701
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
697
702
  private classifyRuntimeError(error: unknown): TrinityRuntimeFailureCode {
698
703
  const detail = error instanceof Error ? error.message : String(error);
699
704
  return /timeout/i.test(detail) ? 'runtime_timeout' : 'runtime_run_failed';
@@ -741,6 +746,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
741
746
  } catch (err) {
742
747
  return this.buildRuntimeFailureDreamerOutput(this.classifyRuntimeError(err), err);
743
748
  } finally {
749
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
744
750
  try { fs.unlinkSync(sessionFile); } catch (err) { this.api.logger?.warn?.(`[Trinity] Failed to delete session file: ${sessionFile}`); }
745
751
  }
746
752
  }
@@ -785,11 +791,13 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
785
791
  } catch (err) {
786
792
  return this.buildRuntimeFailurePhilosopherOutput(this.classifyRuntimeError(err), err);
787
793
  } finally {
794
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
788
795
  try { fs.unlinkSync(sessionFile); } catch (err) { this.api.logger?.warn?.(`[Trinity] Failed to delete session file: ${sessionFile}`); }
789
796
  }
790
797
  }
791
798
 
792
799
 
800
+ // eslint-disable-next-line @typescript-eslint/max-params
793
801
  async invokeScribe(
794
802
  dreamerOutput: DreamerOutput,
795
803
  philosopherOutput: PhilosopherOutput,
@@ -833,6 +841,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
833
841
  this.recordFailure(this.classifyRuntimeError(err), err);
834
842
  return null;
835
843
  } finally {
844
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
836
845
  try { fs.unlinkSync(sessionFile); } catch (err) { this.api.logger?.warn?.(`[Trinity] Failed to delete session file: ${sessionFile}`); }
837
846
  }
838
847
  }
@@ -856,6 +865,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
856
865
  // ---------------------------------------------------------------------------
857
866
 
858
867
 
868
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
859
869
  private buildDreamerPrompt(
860
870
  snapshot: NocturnalSessionSnapshot,
861
871
  principleId: string,
@@ -952,6 +962,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
952
962
  }
953
963
 
954
964
 
965
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
955
966
  private buildPhilosopherPrompt(
956
967
  dreamerOutput: DreamerOutput,
957
968
  principleId: string,
@@ -1034,8 +1045,10 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
1034
1045
 
1035
1046
  return sections.join('\n');
1036
1047
  }
1048
+
1037
1049
 
1038
1050
 
1051
+ // eslint-disable-next-line @typescript-eslint/max-params, @typescript-eslint/class-methods-use-this
1039
1052
  private buildScribePrompt(
1040
1053
  dreamerOutput: DreamerOutput,
1041
1054
  philosopherOutput: PhilosopherOutput,
@@ -1244,10 +1257,12 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
1244
1257
  falsePositiveEstimate?: number;
1245
1258
  implementationComplexity: string;
1246
1259
  breakingChangeRisk: boolean;
1260
+
1247
1261
  } = {
1248
1262
  implementationComplexity: (risks.implementationComplexity as string) ?? 'medium',
1249
1263
  breakingChangeRisk: Boolean(risks.breakingChangeRisk),
1250
1264
  };
1265
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
1251
1266
  if (hasFp) risksObj.falsePositiveEstimate = this.clamp01(fp as number);
1252
1267
  return { risks: risksObj };
1253
1268
  })() : {}),
@@ -1291,6 +1306,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
1291
1306
  }
1292
1307
 
1293
1308
 
1309
+ // eslint-disable-next-line @typescript-eslint/max-params
1294
1310
  private parseScribeOutput(
1295
1311
  text: string,
1296
1312
  snapshot: NocturnalSessionSnapshot,
@@ -1359,6 +1375,7 @@ export class OpenClawTrinityRuntimeAdapter implements TrinityRuntimeAdapter {
1359
1375
  * Extract JSON object from text that may contain markdown code blocks.
1360
1376
  */
1361
1377
 
1378
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
1362
1379
  private extractJson(text: string): string | null {
1363
1380
  // Try direct parse first
1364
1381
  try {
@@ -1698,6 +1715,7 @@ export interface TrinityResult {
1698
1715
  * In production, this would call the actual Dreamer subagent.
1699
1716
  * The stub generates plausible candidates based on snapshot signals.
1700
1717
  */
1718
+
1701
1719
  export function invokeStubDreamer(
1702
1720
  snapshot: NocturnalSessionSnapshot,
1703
1721
  principleId: string,
@@ -1894,7 +1912,9 @@ export function invokeStubPhilosopher(
1894
1912
 
1895
1913
  // Deterministic 6D scores based on strategic perspective (Phase 35 D-07 mapping)
1896
1914
  const perspective = candidate.strategicPerspective;
1915
+ // eslint-disable-next-line @typescript-eslint/init-declarations
1897
1916
  let sixDScores: Philosopher6DScores;
1917
+ // eslint-disable-next-line @typescript-eslint/init-declarations
1898
1918
  let riskAssessment: PhilosopherRiskAssessment;
1899
1919
 
1900
1920
  if (perspective === 'conservative_fix') {
@@ -1994,6 +2014,7 @@ export function invokeStubPhilosopher(
1994
2014
  * The stub uses tournament selection (scoring + thresholds) to pick the winner.
1995
2015
  */
1996
2016
 
2017
+ // eslint-disable-next-line @typescript-eslint/max-params
1997
2018
  export function invokeStubScribe(
1998
2019
  dreamerOutput: DreamerOutput,
1999
2020
  philosopherOutput: PhilosopherOutput,
@@ -2072,6 +2093,7 @@ export function runTrinity(options: RunTrinityOptions): TrinityResult {
2072
2093
  // Stub path: use synchronous stub implementations
2073
2094
  if (config.useStubs) {
2074
2095
 
2096
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
2075
2097
  return runTrinityWithStubs(snapshot, principleId, config);
2076
2098
  }
2077
2099
 
@@ -2111,6 +2133,7 @@ export async function runTrinityAsync(options: RunTrinityOptions): Promise<Trini
2111
2133
  if (config.useStubs) {
2112
2134
  // Stub path: use synchronous stubs
2113
2135
 
2136
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
2114
2137
  return runTrinityWithStubs(snapshot, principleId, config);
2115
2138
  }
2116
2139
 
@@ -2248,6 +2271,7 @@ export async function runTrinityAsync(options: RunTrinityOptions): Promise<Trini
2248
2271
 
2249
2272
  /**
2250
2273
  * Internal: Run Trinity chain with stub implementations (synchronous).
2274
+ // eslint-disable-next-line complexity, @typescript-eslint/class-methods-use-this -- complexity 14, refactor candidate
2251
2275
  */
2252
2276
  function runTrinityWithStubs(
2253
2277
  snapshot: NocturnalSessionSnapshot,
@@ -54,6 +54,7 @@ async function safeTail(filePath: string): Promise<string[]> {
54
54
  try {
55
55
  // Check existence and stats asynchronously
56
56
 
57
+ // eslint-disable-next-line @typescript-eslint/init-declarations
57
58
  let stat: fs.Stats;
58
59
  try {
59
60
  stat = await fsPromises.stat(filePath);
@@ -203,6 +204,7 @@ function extractTurn(msg: ParsedMessage): string | null {
203
204
  * SAFETY: Tail-only read, skip oversized lines, cap output.
204
205
  * Returns empty string on any failure — caller should use pain reason as fallback.
205
206
  */
207
+
206
208
  export async function extractRecentConversation(
207
209
  sessionId: string,
208
210
  agentId = 'main',
@@ -235,6 +237,7 @@ export async function extractRecentConversation(
235
237
  /**
236
238
  * Extracts failed tool call context with argument correlation.
237
239
  */
240
+ // eslint-disable-next-line @typescript-eslint/max-params
238
241
  export async function extractFailedToolContext(
239
242
  sessionId: string,
240
243
  agentId: string,
package/src/core/pain.ts CHANGED
@@ -98,6 +98,7 @@ export function validatePainFlag(data: Record<string, string>): string[] {
98
98
  return missing;
99
99
  }
100
100
 
101
+ // eslint-disable-next-line @typescript-eslint/max-params
101
102
  export function computePainScore(rc: number, isSpiral: boolean, missingTestCommand: boolean, softScore: number, projectDir?: string): number {
102
103
  let score = Math.max(0, softScore || 0);
103
104
 
@@ -211,6 +212,7 @@ export function readPainFlagData(projectDir: string): Record<string, string> {
211
212
 
212
213
  // Detect JSON format (wrong — should be KV)
213
214
  if (content.startsWith('{')) {
215
+ // eslint-disable-next-line @typescript-eslint/init-declarations
214
216
  let json: Record<string, unknown>;
215
217
  try {
216
218
  json = JSON.parse(content);
@@ -279,6 +281,7 @@ export function readPainFlagContract(projectDir: string): PainFlagContractResult
279
281
  * Errors are silently ignored to avoid disrupting the pain pipeline.
280
282
  */
281
283
 
284
+ // eslint-disable-next-line @typescript-eslint/max-params -- complexity 12, refactor candidate
282
285
  export function trackPrincipleValue(
283
286
  workspaceDir: string,
284
287
  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
+
106
107
  function diff(declared: PDTaskSpec[], actual: CronJob[]): DiffAction[] {
107
108
  const actions: DiffAction[] = [];
108
109
  const actualByName = new Map<string, CronJob>();
@@ -159,6 +160,7 @@ function buildCronJob(
159
160
  payload: {
160
161
  kind: 'agentTurn',
161
162
 
163
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
162
164
  message: buildTaskPrompt(task, logger),
163
165
  lightContext: task.execution.lightContext ?? true,
164
166
  timeoutSeconds: task.execution.timeoutSeconds ?? 120,
@@ -293,6 +295,7 @@ export async function reconcilePDTasks(
293
295
 
294
296
  const cronStore = await readCronStore(logger);
295
297
 
298
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
296
299
  const healthUpdated = healthCheck(declared, cronStore, logger);
297
300
  const actions = diff(healthUpdated, cronStore.jobs);
298
301
 
@@ -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) {
@@ -56,6 +56,7 @@ export function initTaskMeta(task: PDTaskSpec): PDTaskSpec {
56
56
  }
57
57
 
58
58
 
59
+ // eslint-disable-next-line @typescript-eslint/max-params
59
60
  export function updateSyncMeta(
60
61
  task: PDTaskSpec,
61
62
  status: 'ok' | 'error',
@@ -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
+
30
31
  export function assessDeprecatedReadiness(
31
32
  principle: PrincipleLifecycleEvidence,
32
33
  precomputedRuleMetrics?: Record<string, RuleMetricResult>,
@@ -64,6 +65,7 @@ export function assessDeprecatedReadiness(
64
65
  );
65
66
 
66
67
 
68
+ // eslint-disable-next-line @typescript-eslint/init-declarations
67
69
  let status: DeprecatedReadinessStatus;
68
70
  if (blockingReasons.length === 0 && stableCoverageRatio === 1) {
69
71
  status = 'ready';
@@ -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,
@@ -63,6 +63,7 @@ export function createDefaultPrincipleState(principleId: string): PrincipleTrain
63
63
 
64
64
  export function loadStore(stateDir: string): PrincipleTrainingStore {
65
65
 
66
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
66
67
  return ledgerTrainingStore(stateDir);
67
68
  }
68
69
 
@@ -76,6 +77,7 @@ export function saveStore(stateDir: string, store: PrincipleTrainingStore): void
76
77
 
77
78
  export async function loadStoreAsync(stateDir: string): Promise<PrincipleTrainingStore> {
78
79
 
80
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
79
81
  return ledgerTrainingStore(stateDir);
80
82
  }
81
83
 
@@ -78,6 +78,7 @@ function isRecord(value: unknown): value is Record<string, unknown> {
78
78
  }
79
79
 
80
80
 
81
+ // eslint-disable-next-line @typescript-eslint/max-params
81
82
  function clampFloat(value: unknown, min: number, max: number, fallback: number): number {
82
83
  if (typeof value !== 'number' || !Number.isFinite(value)) {
83
84
  return fallback;
@@ -86,6 +87,7 @@ function clampFloat(value: unknown, min: number, max: number, fallback: number):
86
87
  }
87
88
 
88
89
 
90
+ // eslint-disable-next-line @typescript-eslint/max-params
89
91
  function clampInt(value: unknown, min: number, max: number, fallback: number): number {
90
92
  if (typeof value !== 'number' || !Number.isFinite(value)) {
91
93
  return fallback;
@@ -318,6 +320,7 @@ function writeLedgerUnlocked(filePath: string, store: HybridLedgerStore): void {
318
320
 
319
321
  function mutateLedger<T>(stateDir: string, mutate: (store: HybridLedgerStore) => T): T {
320
322
 
323
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
321
324
  const filePath = getLedgerFilePath(stateDir);
322
325
  return withLock(filePath, () => {
323
326
  const store = readLedgerFromFile(filePath);
@@ -330,6 +333,7 @@ function mutateLedger<T>(stateDir: string, mutate: (store: HybridLedgerStore) =>
330
333
 
331
334
  async function mutateLedgerAsync<T>(stateDir: string, mutate: (store: HybridLedgerStore) => Promise<T>): Promise<T> {
332
335
 
336
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
333
337
  const filePath = getLedgerFilePath(stateDir);
334
338
  return withLockAsync(filePath, async () => {
335
339
  const store = readLedgerFromFile(filePath);