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.
- package/openclaw.plugin.json +4 -4
- package/package.json +1 -1
- package/src/commands/archive-impl.ts +3 -0
- package/src/commands/context.ts +4 -0
- package/src/commands/disable-impl.ts +2 -0
- package/src/commands/evolution-status.ts +2 -0
- package/src/commands/focus.ts +4 -0
- package/src/commands/nocturnal-train.ts +9 -1
- package/src/commands/pain.ts +3 -0
- package/src/commands/pd-reflect.ts +2 -0
- package/src/commands/principle-rollback.ts +1 -0
- package/src/commands/rollback-impl.ts +5 -0
- package/src/commands/rollback.ts +2 -1
- package/src/commands/samples.ts +1 -0
- package/src/commands/workflow-debug.ts +1 -0
- package/src/core/adaptive-thresholds.ts +2 -0
- package/src/core/code-implementation-storage.ts +2 -0
- package/src/core/config.ts +1 -0
- package/src/core/diagnostician-task-store.ts +2 -0
- package/src/core/dictionary.ts +1 -0
- package/src/core/empathy-keyword-matcher.ts +4 -0
- package/src/core/event-log.ts +6 -1
- package/src/core/evolution-engine.ts +4 -0
- package/src/core/evolution-logger.ts +1 -0
- package/src/core/external-training-contract.ts +2 -0
- package/src/core/focus-history.ts +15 -0
- package/src/core/init.ts +3 -0
- package/src/core/merge-gate-audit.ts +3 -0
- package/src/core/model-deployment-registry.ts +1 -0
- package/src/core/model-training-registry.ts +1 -0
- package/src/core/nocturnal-arbiter.ts +4 -0
- package/src/core/nocturnal-candidate-scoring.ts +5 -0
- package/src/core/nocturnal-compliance.ts +22 -0
- package/src/core/nocturnal-dataset.ts +3 -0
- package/src/core/nocturnal-executability.ts +1 -0
- package/src/core/nocturnal-export.ts +5 -0
- package/src/core/nocturnal-reasoning-deriver.ts +6 -0
- package/src/core/nocturnal-rule-implementation-validator.ts +1 -0
- package/src/core/nocturnal-snapshot-contract.ts +1 -0
- package/src/core/nocturnal-trinity.ts +24 -0
- package/src/core/pain-context-extractor.ts +3 -0
- package/src/core/pain.ts +3 -0
- package/src/core/pd-task-reconciler.ts +3 -0
- package/src/core/pd-task-service.ts +1 -0
- package/src/core/pd-task-store.ts +1 -0
- package/src/core/principle-internalization/deprecated-readiness.ts +2 -0
- package/src/core/principle-internalization/principle-lifecycle-service.ts +1 -0
- package/src/core/principle-training-state.ts +2 -0
- package/src/core/principle-tree-ledger.ts +4 -0
- package/src/core/principle-tree-migration.ts +2 -0
- package/src/core/promotion-gate.ts +7 -1
- package/src/core/replay-engine.ts +10 -0
- package/src/core/risk-calculator.ts +2 -0
- package/src/core/rule-host.ts +3 -0
- package/src/core/session-tracker.ts +5 -0
- package/src/core/shadow-observation-registry.ts +1 -0
- package/src/core/thinking-models.ts +1 -0
- package/src/core/thinking-os-parser.ts +1 -0
- package/src/core/trajectory.ts +9 -1
- package/src/hooks/bash-risk.ts +2 -0
- package/src/hooks/edit-verification.ts +3 -0
- package/src/hooks/gate-block-helper.ts +3 -0
- package/src/hooks/gate.ts +8 -0
- package/src/hooks/gfi-gate.ts +2 -0
- package/src/hooks/lifecycle-routing.ts +1 -0
- package/src/hooks/lifecycle.ts +1 -0
- package/src/hooks/llm.ts +1 -0
- package/src/hooks/pain.ts +3 -0
- package/src/hooks/progressive-trust-gate.ts +3 -0
- package/src/hooks/prompt.ts +5 -1
- package/src/hooks/subagent.ts +1 -0
- package/src/hooks/thinking-checkpoint.ts +1 -0
- package/src/hooks/trajectory-collector.ts +2 -0
- package/src/http/principles-console-route.ts +5 -0
- package/src/index.ts +7 -0
- package/src/service/central-database.ts +2 -0
- package/src/service/central-health-service.ts +1 -0
- package/src/service/central-overview-service.ts +2 -0
- package/src/service/central-sync-service.ts +1 -0
- package/src/service/control-ui-query-service.ts +2 -0
- package/src/service/event-log-auditor.ts +2 -0
- package/src/service/evolution-query-service.ts +1 -0
- package/src/service/evolution-worker.ts +31 -0
- package/src/service/health-query-service.ts +6 -1
- package/src/service/monitoring-query-service.ts +4 -0
- package/src/service/nocturnal-runtime.ts +7 -1
- package/src/service/nocturnal-service.ts +21 -0
- package/src/service/nocturnal-target-selector.ts +2 -0
- package/src/service/runtime-summary-service.ts +6 -0
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +2 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +2 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +3 -0
- package/src/service/subagent-workflow/subagent-error-utils.ts +1 -0
- package/src/service/subagent-workflow/workflow-manager-base.ts +6 -0
- package/src/service/subagent-workflow/workflow-store.ts +2 -0
- package/src/tools/critique-prompt.ts +1 -0
- package/src/tools/deep-reflect.ts +9 -0
- package/src/tools/model-index.ts +1 -0
- package/src/tools/write-pain-flag.ts +1 -0
- package/src/utils/file-lock.ts +1 -0
- 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 [
|
|
@@ -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) {
|
|
@@ -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);
|