principles-disciple 1.30.0 → 1.31.0
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/service/evolution-worker.ts +3 -2
- package/src/service/nocturnal-runtime.ts +5 -3
- package/src/service/nocturnal-service.ts +15 -4
- package/src/service/nocturnal-target-selector.ts +2 -1
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +26 -3
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "principles-disciple",
|
|
3
3
|
"name": "Principles Disciple",
|
|
4
4
|
"description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.31.0",
|
|
6
6
|
"skills": [
|
|
7
7
|
"./skills"
|
|
8
8
|
],
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
78
|
"buildFingerprint": {
|
|
79
|
-
"gitSha": "
|
|
80
|
-
"bundleMd5": "
|
|
81
|
-
"builtAt": "2026-04-
|
|
79
|
+
"gitSha": "15c19a4dc3f2",
|
|
80
|
+
"bundleMd5": "684e47fd5c521d722150a93813fddd02",
|
|
81
|
+
"builtAt": "2026-04-14T03:01:11.396Z"
|
|
82
82
|
}
|
|
83
83
|
}
|
package/package.json
CHANGED
|
@@ -2166,8 +2166,8 @@ export const EvolutionWorkerService: ExtendedEvolutionWorkerService = {
|
|
|
2166
2166
|
shouldTrySleepReflection = true;
|
|
2167
2167
|
}
|
|
2168
2168
|
|
|
2169
|
-
// Path 2: Periodic trigger (
|
|
2170
|
-
if (
|
|
2169
|
+
// Path 2: Periodic trigger (fires regardless of idle state)
|
|
2170
|
+
if (sleepConfig.trigger_mode === 'periodic') {
|
|
2171
2171
|
if (heartbeatCounter >= sleepConfig.period_heartbeats) {
|
|
2172
2172
|
logger?.info?.(`[PD:EvolutionWorker] Periodic trigger: heartbeatCounter=${heartbeatCounter} >= period_heartbeats=${sleepConfig.period_heartbeats}`);
|
|
2173
2173
|
shouldTrySleepReflection = true;
|
|
@@ -2179,6 +2179,7 @@ export const EvolutionWorkerService: ExtendedEvolutionWorkerService = {
|
|
|
2179
2179
|
|
|
2180
2180
|
if (shouldTrySleepReflection) {
|
|
2181
2181
|
const cooldown = checkCooldown(wctx.stateDir, undefined, {
|
|
2182
|
+
globalCooldownMs: sleepConfig.cooldown_ms,
|
|
2182
2183
|
maxRunsPerWindow: sleepConfig.max_runs_per_day,
|
|
2183
2184
|
quotaWindowMs: 24 * 60 * 60 * 1000,
|
|
2184
2185
|
});
|
|
@@ -436,10 +436,12 @@ export function checkCooldown(
|
|
|
436
436
|
*
|
|
437
437
|
* @param stateDir - State directory
|
|
438
438
|
* @param principleId - Target principle ID for this run
|
|
439
|
+
* @param cooldownMs - Global cooldown duration in ms (default: 1 hour)
|
|
439
440
|
*/
|
|
440
441
|
export async function recordRunStart(
|
|
441
442
|
stateDir: string,
|
|
442
|
-
principleId: string
|
|
443
|
+
principleId: string,
|
|
444
|
+
cooldownMs: number = DEFAULT_GLOBAL_COOLDOWN_MS
|
|
443
445
|
): Promise<void> {
|
|
444
446
|
const state = await readState(stateDir);
|
|
445
447
|
const now = new Date().toISOString();
|
|
@@ -450,8 +452,8 @@ export async function recordRunStart(
|
|
|
450
452
|
status: 'skipped', // Will be updated on completion
|
|
451
453
|
};
|
|
452
454
|
|
|
453
|
-
// Set global cooldown
|
|
454
|
-
const cooldownUntil = new Date(Date.now() +
|
|
455
|
+
// Set global cooldown (use configured value, not hardcoded default)
|
|
456
|
+
const cooldownUntil = new Date(Date.now() + cooldownMs).toISOString();
|
|
455
457
|
state.globalCooldownUntil = cooldownUntil;
|
|
456
458
|
|
|
457
459
|
// Add to recent runs for quota tracking
|
|
@@ -96,6 +96,7 @@ import {
|
|
|
96
96
|
type IdleCheckResult,
|
|
97
97
|
type PreflightCheckResult,
|
|
98
98
|
} from './nocturnal-runtime.js';
|
|
99
|
+
import { loadNocturnalConfig } from './nocturnal-config.js';
|
|
99
100
|
import { NocturnalPathResolver } from '../core/nocturnal-paths.js';
|
|
100
101
|
import { registerSample } from '../core/nocturnal-dataset.js';
|
|
101
102
|
import { getPrincipleState, setPrincipleState } from '../core/principle-training-state.js';
|
|
@@ -721,7 +722,8 @@ export function executeNocturnalReflection(
|
|
|
721
722
|
if (!preflight.canRun) {
|
|
722
723
|
return {
|
|
723
724
|
success: false,
|
|
724
|
-
noTargetSelected:
|
|
725
|
+
noTargetSelected: true,
|
|
726
|
+
skipReason: 'preflight_blocked',
|
|
725
727
|
validationFailed: false,
|
|
726
728
|
validationFailures: [],
|
|
727
729
|
diagnostics,
|
|
@@ -784,7 +786,8 @@ export function executeNocturnalReflection(
|
|
|
784
786
|
// -------------------------------------------------------------------------
|
|
785
787
|
// Note: We use a sync approximation here since this is called from sync context
|
|
786
788
|
// The async version would be used in real worker integration
|
|
787
|
-
|
|
789
|
+
const config = loadNocturnalConfig(stateDir);
|
|
790
|
+
void recordRunStart(stateDir, selectedPrincipleId, config.cooldown_ms).catch((err) => {
|
|
788
791
|
console.warn(`[nocturnal-service] Failed to record run start: ${String(err)}`);
|
|
789
792
|
});
|
|
790
793
|
|
|
@@ -1195,7 +1198,14 @@ async function executeNocturnalReflectionWithAdapter(
|
|
|
1195
1198
|
diagnostics.preflight = preflight;
|
|
1196
1199
|
|
|
1197
1200
|
if (!preflight.canRun) {
|
|
1198
|
-
return {
|
|
1201
|
+
return {
|
|
1202
|
+
success: false,
|
|
1203
|
+
noTargetSelected: true,
|
|
1204
|
+
skipReason: 'preflight_blocked',
|
|
1205
|
+
validationFailed: false,
|
|
1206
|
+
validationFailures: [],
|
|
1207
|
+
diagnostics
|
|
1208
|
+
};
|
|
1199
1209
|
}
|
|
1200
1210
|
|
|
1201
1211
|
// Step 2: Target selection (or use override to skip)
|
|
@@ -1317,7 +1327,8 @@ async function executeNocturnalReflectionWithAdapter(
|
|
|
1317
1327
|
}
|
|
1318
1328
|
|
|
1319
1329
|
// Step 3: Record run start
|
|
1320
|
-
|
|
1330
|
+
const config = loadNocturnalConfig(stateDir);
|
|
1331
|
+
void recordRunStart(stateDir, selectedPrincipleId, config.cooldown_ms).catch((err) => {
|
|
1321
1332
|
console.warn(`[nocturnal-service] Failed to record run start: ${String(err)}`);
|
|
1322
1333
|
});
|
|
1323
1334
|
|
|
@@ -63,7 +63,8 @@ export type SkipReason =
|
|
|
63
63
|
| 'workspace_not_idle' // Workspace is active, nocturnal not allowed
|
|
64
64
|
| 'quota_exhausted' // Max runs per quota window reached
|
|
65
65
|
| 'insufficient_snapshot_data' // Sessions exist but lack tool calls / events
|
|
66
|
-
| 'global_cooldown_active'
|
|
66
|
+
| 'global_cooldown_active' // Global cooldown is in effect
|
|
67
|
+
| 'preflight_blocked'; // Preflight check blocked (idle/cooldown/quota)
|
|
67
68
|
|
|
68
69
|
export interface SelectionDiagnostics {
|
|
69
70
|
/** Total evaluable principles found */
|
|
@@ -262,8 +262,10 @@ export class NocturnalWorkflowManager implements WorkflowManager {
|
|
|
262
262
|
painContext,
|
|
263
263
|
// #244: Only skip preflight idle gate for manual/test triggers.
|
|
264
264
|
// Automatic triggers must go through normal idle check.
|
|
265
|
+
// #292: Periodic triggers (source='nocturnal') also bypass idle check for debugging
|
|
265
266
|
...(((options.metadata)?.triggerSource === 'manual' ||
|
|
266
|
-
(options.metadata)?.triggerSource === 'test'
|
|
267
|
+
(options.metadata)?.triggerSource === 'test' ||
|
|
268
|
+
(options.metadata)?.triggerSource === 'nocturnal')
|
|
267
269
|
? {
|
|
268
270
|
idleCheckOverride: {
|
|
269
271
|
isIdle: true,
|
|
@@ -272,7 +274,7 @@ export class NocturnalWorkflowManager implements WorkflowManager {
|
|
|
272
274
|
userActiveSessions: 0,
|
|
273
275
|
abandonedSessionIds: [],
|
|
274
276
|
trajectoryGuardrailConfirmsIdle: true,
|
|
275
|
-
reason: 'manual
|
|
277
|
+
reason: `${(options.metadata)?.triggerSource ?? 'manual'}.test override`,
|
|
276
278
|
},
|
|
277
279
|
}
|
|
278
280
|
: {}),
|
|
@@ -293,7 +295,28 @@ export class NocturnalWorkflowManager implements WorkflowManager {
|
|
|
293
295
|
this.completedWorkflows.set(workflowId, Date.now());
|
|
294
296
|
} else {
|
|
295
297
|
const reason = result.noTargetSelected ? 'no_target_selected' : 'validation_failed';
|
|
296
|
-
|
|
298
|
+
const failuresSummary = result.validationFailures?.length > 0
|
|
299
|
+
? result.validationFailures.join('; ')
|
|
300
|
+
: (result.skipReason ?? 'none');
|
|
301
|
+
this.logger.warn(`[PD:NocturnalWorkflow] [${workflowId}] Pipeline failed: reason=${reason}, noTargetSelected=${result.noTargetSelected}, skipReason=${result.skipReason ?? 'none'}, validationFailures=${result.validationFailures?.length ?? 0}, details=${failuresSummary}`);
|
|
302
|
+
|
|
303
|
+
// Log full result structure for debugging
|
|
304
|
+
this.logger.warn(`[PD:NocturnalWorkflow] [${workflowId}] Full result: success=${result.success}, validationFailed=${result.validationFailed}, noTargetSelected=${result.noTargetSelected}`);
|
|
305
|
+
|
|
306
|
+
// Log diagnostics for debugging
|
|
307
|
+
if (result.diagnostics?.trinityResult) {
|
|
308
|
+
this.logger.warn(`[PD:NocturnalWorkflow] [${workflowId}] Trinity result: success=${result.diagnostics.trinityResult.success}, chainMode=${result.diagnostics.chainModeUsed ?? 'unknown'}`);
|
|
309
|
+
if (!result.diagnostics.trinityResult.success) {
|
|
310
|
+
this.logger.warn(`[PD:NocturnalWorkflow] [${workflowId}] Trinity failures: ${result.diagnostics.trinityResult.failures.map(f => `${f.stage}: ${f.reason}`).join('; ')}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (result.diagnostics?.arbiterResult) {
|
|
314
|
+
this.logger.warn(`[PD:NocturnalWorkflow] [${workflowId}] Arbiter result: passed=${result.diagnostics.arbiterResult.passed}, failures=${result.diagnostics.arbiterResult.failures.map(f => f.reason).join('; ')}`);
|
|
315
|
+
}
|
|
316
|
+
if (result.diagnostics?.selection) {
|
|
317
|
+
this.logger.warn(`[PD:NocturnalWorkflow] [${workflowId}] Selection: decision=${result.diagnostics.selection.decision}, principleId=${result.diagnostics.selection.selectedPrincipleId ?? 'none'}, sessionId=${result.diagnostics.selection.selectedSessionId ?? 'none'}`);
|
|
318
|
+
}
|
|
319
|
+
|
|
297
320
|
this.store.updateWorkflowState(workflowId, 'terminal_error');
|
|
298
321
|
this.store.recordEvent(workflowId, 'nocturnal_failed', null, 'terminal_error', reason, {
|
|
299
322
|
failures: result.validationFailures,
|