principles-disciple 1.7.5 → 1.7.8
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/dist/commands/context.js +5 -15
- package/dist/commands/evolution-status.js +29 -48
- package/dist/commands/export.js +61 -8
- package/dist/commands/nocturnal-review.d.ts +24 -0
- package/dist/commands/nocturnal-review.js +265 -0
- package/dist/commands/nocturnal-rollout.d.ts +27 -0
- package/dist/commands/nocturnal-rollout.js +671 -0
- package/dist/commands/nocturnal-train.d.ts +25 -0
- package/dist/commands/nocturnal-train.js +919 -0
- package/dist/commands/pain.js +8 -21
- package/dist/config/defaults/runtime.d.ts +40 -0
- package/dist/config/defaults/runtime.js +44 -0
- package/dist/config/errors.d.ts +84 -0
- package/dist/config/errors.js +94 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.js +7 -0
- package/dist/constants/diagnostician.d.ts +0 -4
- package/dist/constants/diagnostician.js +0 -4
- package/dist/constants/tools.d.ts +2 -2
- package/dist/constants/tools.js +1 -1
- package/dist/core/adaptive-thresholds.d.ts +186 -0
- package/dist/core/adaptive-thresholds.js +300 -0
- package/dist/core/config.d.ts +2 -38
- package/dist/core/config.js +6 -61
- package/dist/core/control-ui-db.d.ts +27 -0
- package/dist/core/control-ui-db.js +18 -0
- package/dist/core/event-log.d.ts +1 -2
- package/dist/core/event-log.js +0 -3
- package/dist/core/evolution-engine.js +1 -21
- package/dist/core/evolution-reducer.d.ts +7 -1
- package/dist/core/evolution-reducer.js +56 -4
- package/dist/core/evolution-types.d.ts +61 -9
- package/dist/core/evolution-types.js +31 -9
- package/dist/core/external-training-contract.d.ts +276 -0
- package/dist/core/external-training-contract.js +269 -0
- package/dist/core/local-worker-routing.d.ts +175 -0
- package/dist/core/local-worker-routing.js +525 -0
- package/dist/core/model-deployment-registry.d.ts +218 -0
- package/dist/core/model-deployment-registry.js +503 -0
- package/dist/core/model-training-registry.d.ts +295 -0
- package/dist/core/model-training-registry.js +475 -0
- package/dist/core/nocturnal-arbiter.d.ts +159 -0
- package/dist/core/nocturnal-arbiter.js +534 -0
- package/dist/core/nocturnal-candidate-scoring.d.ts +137 -0
- package/dist/core/nocturnal-candidate-scoring.js +266 -0
- package/dist/core/nocturnal-compliance.d.ts +175 -0
- package/dist/core/nocturnal-compliance.js +824 -0
- package/dist/core/nocturnal-dataset.d.ts +224 -0
- package/dist/core/nocturnal-dataset.js +443 -0
- package/dist/core/nocturnal-executability.d.ts +85 -0
- package/dist/core/nocturnal-executability.js +331 -0
- package/dist/core/nocturnal-export.d.ts +124 -0
- package/dist/core/nocturnal-export.js +275 -0
- package/dist/core/nocturnal-paths.d.ts +124 -0
- package/dist/core/nocturnal-paths.js +214 -0
- package/dist/core/nocturnal-trajectory-extractor.d.ts +242 -0
- package/dist/core/nocturnal-trajectory-extractor.js +307 -0
- package/dist/core/nocturnal-trinity.d.ts +311 -0
- package/dist/core/nocturnal-trinity.js +880 -0
- package/dist/core/path-resolver.js +2 -1
- package/dist/core/paths.d.ts +6 -0
- package/dist/core/paths.js +6 -0
- package/dist/core/principle-training-state.d.ts +121 -0
- package/dist/core/principle-training-state.js +321 -0
- package/dist/core/promotion-gate.d.ts +238 -0
- package/dist/core/promotion-gate.js +529 -0
- package/dist/core/session-tracker.d.ts +10 -0
- package/dist/core/session-tracker.js +14 -0
- package/dist/core/shadow-observation-registry.d.ts +217 -0
- package/dist/core/shadow-observation-registry.js +308 -0
- package/dist/core/training-program.d.ts +233 -0
- package/dist/core/training-program.js +433 -0
- package/dist/core/trajectory.d.ts +155 -1
- package/dist/core/trajectory.js +292 -8
- package/dist/core/workspace-context.d.ts +0 -6
- package/dist/core/workspace-context.js +0 -12
- package/dist/hooks/bash-risk.d.ts +57 -0
- package/dist/hooks/bash-risk.js +137 -0
- package/dist/hooks/edit-verification.d.ts +62 -0
- package/dist/hooks/edit-verification.js +256 -0
- package/dist/hooks/gate-block-helper.d.ts +44 -0
- package/dist/hooks/gate-block-helper.js +119 -0
- package/dist/hooks/gate.d.ts +18 -0
- package/dist/hooks/gate.js +62 -751
- package/dist/hooks/gfi-gate.d.ts +40 -0
- package/dist/hooks/gfi-gate.js +113 -0
- package/dist/hooks/pain.js +6 -9
- package/dist/hooks/progressive-trust-gate.d.ts +51 -0
- package/dist/hooks/progressive-trust-gate.js +89 -0
- package/dist/hooks/prompt.d.ts +11 -11
- package/dist/hooks/prompt.js +167 -77
- package/dist/hooks/subagent.js +43 -6
- package/dist/hooks/thinking-checkpoint.d.ts +37 -0
- package/dist/hooks/thinking-checkpoint.js +51 -0
- package/dist/http/principles-console-route.js +13 -3
- package/dist/i18n/commands.js +8 -8
- package/dist/index.js +129 -28
- package/dist/service/central-database.js +2 -1
- package/dist/service/control-ui-query-service.d.ts +1 -1
- package/dist/service/control-ui-query-service.js +3 -3
- package/dist/service/evolution-query-service.d.ts +1 -1
- package/dist/service/evolution-query-service.js +5 -5
- package/dist/service/evolution-worker.d.ts +52 -4
- package/dist/service/evolution-worker.js +328 -16
- package/dist/service/nocturnal-runtime.d.ts +183 -0
- package/dist/service/nocturnal-runtime.js +352 -0
- package/dist/service/nocturnal-service.d.ts +163 -0
- package/dist/service/nocturnal-service.js +787 -0
- package/dist/service/nocturnal-target-selector.d.ts +145 -0
- package/dist/service/nocturnal-target-selector.js +315 -0
- package/dist/service/phase3-input-filter.d.ts +48 -12
- package/dist/service/phase3-input-filter.js +84 -18
- package/dist/service/runtime-summary-service.d.ts +34 -10
- package/dist/service/runtime-summary-service.js +87 -48
- package/dist/tools/deep-reflect.js +2 -1
- package/dist/types/event-types.d.ts +4 -10
- package/dist/types/runtime-summary.d.ts +47 -0
- package/dist/types/runtime-summary.js +1 -0
- package/dist/types.d.ts +0 -3
- package/dist/types.js +0 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/templates/langs/en/skills/pd-mentor/SKILL.md +5 -5
- package/templates/langs/zh/skills/pd-mentor/SKILL.md +5 -5
- package/templates/pain_settings.json +0 -6
- package/dist/commands/trust.d.ts +0 -4
- package/dist/commands/trust.js +0 -78
- package/dist/core/trust-engine.d.ts +0 -96
- package/dist/core/trust-engine.js +0 -286
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Thresholds — Bounded Threshold State Management
|
|
3
|
+
* ========================================================
|
|
4
|
+
*
|
|
5
|
+
* PURPOSE: Manage adaptive thresholds for Trinity candidate scoring with
|
|
6
|
+
* bounded, observable, and reproducible threshold changes.
|
|
7
|
+
*
|
|
8
|
+
* DESIGN CONSTRAINTS:
|
|
9
|
+
* - Thresholds only move within bounded ranges (min/max)
|
|
10
|
+
* - Changes depend on explicit observable signals only
|
|
11
|
+
* - No hidden learning loops
|
|
12
|
+
* - Threshold state is persisted and can be rolled back
|
|
13
|
+
* - Corruption or missing state falls back to safe defaults
|
|
14
|
+
*
|
|
15
|
+
* OBSERVABLE SIGNALS:
|
|
16
|
+
* - recent malformed rate (arbiter/executability failures)
|
|
17
|
+
* - recent arbiter reject rate
|
|
18
|
+
* - recent executability reject rate
|
|
19
|
+
* - reviewed subset quality delta
|
|
20
|
+
*
|
|
21
|
+
* PHASE 6 ONLY — No real training, no automatic deployment
|
|
22
|
+
*/
|
|
23
|
+
import * as fs from 'fs';
|
|
24
|
+
import * as path from 'path';
|
|
25
|
+
import { withLock } from '../utils/file-lock.js';
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Constants
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/** File name for threshold state */
|
|
30
|
+
export const THRESHOLD_STATE_FILE = 'nocturnal-threshold-state.json';
|
|
31
|
+
/** Default threshold values */
|
|
32
|
+
export const DEFAULT_THRESHOLDS = {
|
|
33
|
+
/** Minimum score to pass arbiter validation */
|
|
34
|
+
schemaCompletenessMin: 0.6,
|
|
35
|
+
/** Minimum principle alignment score */
|
|
36
|
+
principleAlignmentMin: 0.7,
|
|
37
|
+
/** Minimum executability score */
|
|
38
|
+
executabilityMin: 0.65,
|
|
39
|
+
/** Minimum boundedness score */
|
|
40
|
+
boundednessMin: 0.5,
|
|
41
|
+
/** Minimum confidence/consistency score */
|
|
42
|
+
confidenceMin: 0.6,
|
|
43
|
+
/** Minimum aggregate score to be tournament-eligible */
|
|
44
|
+
aggregateMin: 0.65,
|
|
45
|
+
};
|
|
46
|
+
/** Minimum threshold value (safety bound) */
|
|
47
|
+
export const THRESHOLD_MIN = 0.0;
|
|
48
|
+
/** Maximum threshold value (safety bound) */
|
|
49
|
+
export const THRESHOLD_MAX = 1.0;
|
|
50
|
+
/** Maximum adjustment per update (bounded step size) */
|
|
51
|
+
export const MAX_ADJUSTMENT_PER_STEP = 0.05;
|
|
52
|
+
/** Minimum adjustment to trigger a change */
|
|
53
|
+
export const MIN_ADJUSTMENT_TO_RECORD = 0.01;
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// State Persistence
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Get the threshold state file path.
|
|
59
|
+
*/
|
|
60
|
+
function getStatePath(stateDir) {
|
|
61
|
+
return path.join(stateDir, THRESHOLD_STATE_FILE);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create default threshold persistence state.
|
|
65
|
+
*/
|
|
66
|
+
function createDefaultState() {
|
|
67
|
+
const now = new Date().toISOString();
|
|
68
|
+
const thresholds = {};
|
|
69
|
+
for (const [name, defaultValue] of Object.entries(DEFAULT_THRESHOLDS)) {
|
|
70
|
+
thresholds[name] = {
|
|
71
|
+
currentValue: defaultValue,
|
|
72
|
+
minValue: THRESHOLD_MIN,
|
|
73
|
+
maxValue: THRESHOLD_MAX,
|
|
74
|
+
lastUpdatedAt: now,
|
|
75
|
+
adjustmentCount: 0,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
thresholds,
|
|
80
|
+
lastUpdatedAt: now,
|
|
81
|
+
version: 1,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Read threshold state from disk (with locking).
|
|
86
|
+
*/
|
|
87
|
+
function readState(stateDir) {
|
|
88
|
+
const statePath = getStatePath(stateDir);
|
|
89
|
+
if (!fs.existsSync(statePath)) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const content = fs.readFileSync(statePath, 'utf-8');
|
|
94
|
+
const parsed = JSON.parse(content);
|
|
95
|
+
return parsed;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Corrupted — return null to trigger default fallback
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Write threshold state to disk (with locking).
|
|
104
|
+
*/
|
|
105
|
+
function writeState(stateDir, state) {
|
|
106
|
+
const statePath = getStatePath(stateDir);
|
|
107
|
+
const stateDirPath = path.dirname(statePath);
|
|
108
|
+
if (!fs.existsSync(stateDirPath)) {
|
|
109
|
+
fs.mkdirSync(stateDirPath, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
withLock(statePath, () => {
|
|
112
|
+
const tmpPath = `${statePath}.tmp`;
|
|
113
|
+
fs.writeFileSync(tmpPath, JSON.stringify(state, null, 2), 'utf-8');
|
|
114
|
+
fs.renameSync(tmpPath, statePath);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Core Threshold Operations
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
/**
|
|
121
|
+
* Load threshold values with fallback to defaults on corruption.
|
|
122
|
+
*
|
|
123
|
+
* @param stateDir - State directory
|
|
124
|
+
* @returns LoadThresholdResult with current values and status
|
|
125
|
+
*/
|
|
126
|
+
export function loadThresholdState(stateDir) {
|
|
127
|
+
const rawState = readState(stateDir);
|
|
128
|
+
if (!rawState) {
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
thresholds: { ...DEFAULT_THRESHOLDS },
|
|
132
|
+
usedDefaults: true,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Validate and reconstruct threshold values
|
|
136
|
+
const thresholds = { ...DEFAULT_THRESHOLDS };
|
|
137
|
+
let usedDefaults = false;
|
|
138
|
+
for (const [name, defaultValue] of Object.entries(DEFAULT_THRESHOLDS)) {
|
|
139
|
+
const key = name;
|
|
140
|
+
const state = rawState.thresholds[key];
|
|
141
|
+
if (state && typeof state.currentValue === 'number') {
|
|
142
|
+
// Clamp to bounds (defensive)
|
|
143
|
+
thresholds[key] = Math.max(state.minValue, Math.min(state.maxValue, state.currentValue));
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
thresholds[key] = defaultValue;
|
|
147
|
+
usedDefaults = true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
success: true,
|
|
152
|
+
thresholds: thresholds,
|
|
153
|
+
usedDefaults,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get effective threshold values (alias for loadThresholdState).
|
|
158
|
+
*
|
|
159
|
+
* @param stateDir - State directory
|
|
160
|
+
* @returns Current threshold values
|
|
161
|
+
*/
|
|
162
|
+
export function getEffectiveThresholds(stateDir) {
|
|
163
|
+
const result = loadThresholdState(stateDir);
|
|
164
|
+
return result.thresholds;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Update a single threshold with bounded step size.
|
|
168
|
+
*
|
|
169
|
+
* @param stateDir - State directory
|
|
170
|
+
* @param thresholdName - Name of threshold to update
|
|
171
|
+
* @param newValue - New value (will be clamped to bounds)
|
|
172
|
+
* @param reason - Reason for the adjustment (required for tracking)
|
|
173
|
+
* @returns UpdateThresholdResult
|
|
174
|
+
*/
|
|
175
|
+
export function updateThresholdState(stateDir, thresholdName, newValue, reason) {
|
|
176
|
+
// Read current state
|
|
177
|
+
let rawState = readState(stateDir);
|
|
178
|
+
if (!rawState) {
|
|
179
|
+
rawState = createDefaultState();
|
|
180
|
+
}
|
|
181
|
+
const currentState = rawState.thresholds[thresholdName];
|
|
182
|
+
if (!currentState) {
|
|
183
|
+
return {
|
|
184
|
+
success: false,
|
|
185
|
+
thresholds: { ...DEFAULT_THRESHOLDS },
|
|
186
|
+
changed: false,
|
|
187
|
+
error: `Unknown threshold: ${thresholdName}`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// Calculate bounded new value
|
|
191
|
+
const clampedValue = Math.max(currentState.minValue, Math.min(currentState.maxValue, newValue));
|
|
192
|
+
// Check if change is meaningful
|
|
193
|
+
const delta = Math.abs(clampedValue - currentState.currentValue);
|
|
194
|
+
if (delta < MIN_ADJUSTMENT_TO_RECORD) {
|
|
195
|
+
return {
|
|
196
|
+
success: true,
|
|
197
|
+
thresholds: getEffectiveThresholds(stateDir),
|
|
198
|
+
changed: false,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// Enforce maximum step size for bounded, safe threshold adjustments
|
|
202
|
+
let finalValue = clampedValue;
|
|
203
|
+
if (delta > MAX_ADJUSTMENT_PER_STEP) {
|
|
204
|
+
const direction = clampedValue > currentState.currentValue ? 1 : -1;
|
|
205
|
+
finalValue = currentState.currentValue + direction * MAX_ADJUSTMENT_PER_STEP;
|
|
206
|
+
}
|
|
207
|
+
// Update state
|
|
208
|
+
const now = new Date().toISOString();
|
|
209
|
+
rawState.thresholds[thresholdName] = {
|
|
210
|
+
...currentState,
|
|
211
|
+
currentValue: finalValue,
|
|
212
|
+
lastUpdatedAt: now,
|
|
213
|
+
adjustmentReason: reason,
|
|
214
|
+
adjustmentCount: currentState.adjustmentCount + 1,
|
|
215
|
+
};
|
|
216
|
+
rawState.lastUpdatedAt = now;
|
|
217
|
+
writeState(stateDir, rawState);
|
|
218
|
+
return {
|
|
219
|
+
success: true,
|
|
220
|
+
thresholds: getEffectiveThresholds(stateDir),
|
|
221
|
+
changed: true,
|
|
222
|
+
changedThreshold: thresholdName,
|
|
223
|
+
oldValue: currentState.currentValue,
|
|
224
|
+
newValue: finalValue,
|
|
225
|
+
reason,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Reset all thresholds to defaults.
|
|
230
|
+
*
|
|
231
|
+
* @param stateDir - State directory
|
|
232
|
+
*/
|
|
233
|
+
export function resetThresholdState(stateDir) {
|
|
234
|
+
const defaultState = createDefaultState();
|
|
235
|
+
writeState(stateDir, defaultState);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get detailed threshold state for debugging/inspection.
|
|
239
|
+
*
|
|
240
|
+
* @param stateDir - State directory
|
|
241
|
+
* @returns Detailed threshold state or null if corrupted
|
|
242
|
+
*/
|
|
243
|
+
export function getDetailedThresholdState(stateDir) {
|
|
244
|
+
return readState(stateDir);
|
|
245
|
+
}
|
|
246
|
+
// ---------------------------------------------------------------------------
|
|
247
|
+
// Signal-Based Threshold Adjustment
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
/**
|
|
250
|
+
* Adjust thresholds based on observable signals.
|
|
251
|
+
*
|
|
252
|
+
* This is a simple proportional controller that adjusts thresholds
|
|
253
|
+
* based on observed rejection rates. The adjustment is bounded
|
|
254
|
+
* and requires a minimum signal magnitude to trigger.
|
|
255
|
+
*
|
|
256
|
+
* @param stateDir - State directory
|
|
257
|
+
* @param signals - Observable signals
|
|
258
|
+
* @returns UpdateThresholdResult describing the most significant change
|
|
259
|
+
*/
|
|
260
|
+
export function adjustThresholdsFromSignals(stateDir, signals) {
|
|
261
|
+
const currentThresholds = getEffectiveThresholds(stateDir);
|
|
262
|
+
let bestResult = {
|
|
263
|
+
success: true,
|
|
264
|
+
thresholds: currentThresholds,
|
|
265
|
+
changed: false,
|
|
266
|
+
};
|
|
267
|
+
// High malformed rate → tighten schema completeness threshold
|
|
268
|
+
if (signals.malformedRate > 0.3) {
|
|
269
|
+
const adjustment = signals.malformedRate * 0.1;
|
|
270
|
+
const newValue = currentThresholds.schemaCompletenessMin + adjustment;
|
|
271
|
+
const result = updateThresholdState(stateDir, 'schemaCompletenessMin', newValue, `High malformed rate (${signals.malformedRate.toFixed(2)}) → tightening schema threshold`);
|
|
272
|
+
if (result.changed)
|
|
273
|
+
bestResult = result;
|
|
274
|
+
}
|
|
275
|
+
// High arbiter reject rate → tighten principle alignment threshold
|
|
276
|
+
if (signals.arbiterRejectRate > 0.25) {
|
|
277
|
+
const adjustment = signals.arbiterRejectRate * 0.08;
|
|
278
|
+
const result = updateThresholdState(stateDir, 'principleAlignmentMin', currentThresholds.principleAlignmentMin + adjustment, `High arbiter reject rate (${signals.arbiterRejectRate.toFixed(2)}) → tightening alignment threshold`);
|
|
279
|
+
if (result.changed && (!bestResult.changed || (result.newValue - result.oldValue) > 0)) {
|
|
280
|
+
bestResult = result;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// High executability reject rate → tighten executability threshold
|
|
284
|
+
if (signals.executabilityRejectRate > 0.3) {
|
|
285
|
+
const adjustment = signals.executabilityRejectRate * 0.1;
|
|
286
|
+
const result = updateThresholdState(stateDir, 'executabilityMin', currentThresholds.executabilityMin + adjustment, `High executability reject rate (${signals.executabilityRejectRate.toFixed(2)}) → tightening executability threshold`);
|
|
287
|
+
if (result.changed && (!bestResult.changed || (result.newValue - result.oldValue) > 0)) {
|
|
288
|
+
bestResult = result;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Good quality delta → slightly loosen thresholds (reward good performance)
|
|
292
|
+
if (signals.qualityDelta > 0.1) {
|
|
293
|
+
const reward = Math.min(signals.qualityDelta * 0.05, MAX_ADJUSTMENT_PER_STEP);
|
|
294
|
+
const result = updateThresholdState(stateDir, 'aggregateMin', Math.max(currentThresholds.aggregateMin - reward, THRESHOLD_MIN), `Positive quality delta (${signals.qualityDelta.toFixed(2)}) → rewarding with slightly lower aggregate threshold`);
|
|
295
|
+
if (result.changed && (!bestResult.changed || (result.oldValue - result.newValue) > 0)) {
|
|
296
|
+
bestResult = result;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return bestResult;
|
|
300
|
+
}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -21,51 +21,16 @@ export interface GfiGateSettings {
|
|
|
21
21
|
large_change_block: number;
|
|
22
22
|
};
|
|
23
23
|
large_change_lines: number;
|
|
24
|
-
|
|
24
|
+
ep_tier_multipliers: {
|
|
25
25
|
'1': number;
|
|
26
26
|
'2': number;
|
|
27
27
|
'3': number;
|
|
28
28
|
'4': number;
|
|
29
|
+
'5': number;
|
|
29
30
|
};
|
|
30
31
|
bash_safe_patterns: string[];
|
|
31
32
|
bash_dangerous_patterns: string[];
|
|
32
33
|
}
|
|
33
|
-
export interface TrustSettings {
|
|
34
|
-
stages: {
|
|
35
|
-
stage_1_observer: number;
|
|
36
|
-
stage_2_editor: number;
|
|
37
|
-
stage_3_developer: number;
|
|
38
|
-
};
|
|
39
|
-
cold_start: {
|
|
40
|
-
initial_trust: number;
|
|
41
|
-
grace_failures: number;
|
|
42
|
-
cold_start_period_ms: number;
|
|
43
|
-
};
|
|
44
|
-
penalties: {
|
|
45
|
-
tool_failure_base: number;
|
|
46
|
-
risky_failure_base: number;
|
|
47
|
-
gate_bypass_attempt: number;
|
|
48
|
-
failure_streak_multiplier: number;
|
|
49
|
-
max_penalty: number;
|
|
50
|
-
};
|
|
51
|
-
rewards: {
|
|
52
|
-
success_base: number;
|
|
53
|
-
subagent_success: number;
|
|
54
|
-
tool_success_reward: number;
|
|
55
|
-
streak_bonus_threshold: number;
|
|
56
|
-
streak_bonus: number;
|
|
57
|
-
recovery_boost: number;
|
|
58
|
-
max_reward: number;
|
|
59
|
-
};
|
|
60
|
-
limits: {
|
|
61
|
-
stage_2_max_lines: number;
|
|
62
|
-
stage_3_max_lines: number;
|
|
63
|
-
stage_2_max_percentage: number;
|
|
64
|
-
stage_3_max_percentage: number;
|
|
65
|
-
min_lines_fallback: number;
|
|
66
|
-
};
|
|
67
|
-
history_limit?: number;
|
|
68
|
-
}
|
|
69
34
|
export interface DiagnosticianSettings {
|
|
70
35
|
context: {
|
|
71
36
|
time_window_minutes: number;
|
|
@@ -110,7 +75,6 @@ export interface PainSettings {
|
|
|
110
75
|
initial_delay_ms: number;
|
|
111
76
|
task_timeout_ms: number;
|
|
112
77
|
};
|
|
113
|
-
trust: TrustSettings;
|
|
114
78
|
deep_reflection?: DeepReflectionSettings;
|
|
115
79
|
empathy_engine?: {
|
|
116
80
|
enabled?: boolean;
|
package/dist/core/config.js
CHANGED
|
@@ -46,46 +46,6 @@ export const DEFAULT_SETTINGS = {
|
|
|
46
46
|
initial_delay_ms: 5000,
|
|
47
47
|
task_timeout_ms: 60 * 60 * 1000 // 1 hour, matching evolution-worker.ts default
|
|
48
48
|
},
|
|
49
|
-
trust: {
|
|
50
|
-
stages: {
|
|
51
|
-
stage_1_observer: 30,
|
|
52
|
-
stage_2_editor: 60,
|
|
53
|
-
stage_3_developer: 80,
|
|
54
|
-
},
|
|
55
|
-
cold_start: {
|
|
56
|
-
// 🚀 The most important change: Start at 85 (Developer level)
|
|
57
|
-
// This allows the AI to perform medium-sized edits right out of the box
|
|
58
|
-
// without needing to beg for a PLAN.md on every single change.
|
|
59
|
-
initial_trust: 85,
|
|
60
|
-
grace_failures: 5, // Give the AI 5 free mistakes before deducting any trust points
|
|
61
|
-
cold_start_period_ms: 24 * 60 * 60 * 1000,
|
|
62
|
-
},
|
|
63
|
-
penalties: {
|
|
64
|
-
// 🛡️ Forgiving penalties for exploration
|
|
65
|
-
tool_failure_base: -2, // Was -8. A simple 'ls' typo shouldn't cost 8 points.
|
|
66
|
-
risky_failure_base: -10, // Was -15.
|
|
67
|
-
gate_bypass_attempt: -5,
|
|
68
|
-
failure_streak_multiplier: -2,
|
|
69
|
-
max_penalty: -20,
|
|
70
|
-
},
|
|
71
|
-
rewards: {
|
|
72
|
-
success_base: 2, // Was 1. Faster recovery
|
|
73
|
-
subagent_success: 5, // Was 3.
|
|
74
|
-
tool_success_reward: 0.2, // 👈 Minor reward for tool success, but resets streak!
|
|
75
|
-
streak_bonus_threshold: 3, // Was 5. Easier to get bonuses
|
|
76
|
-
streak_bonus: 5,
|
|
77
|
-
recovery_boost: 5, // Was 3. If trust drops low, it's easier to climb back up
|
|
78
|
-
max_reward: 15,
|
|
79
|
-
},
|
|
80
|
-
limits: {
|
|
81
|
-
stage_2_max_lines: 50, // Was 10. 10 lines is barely enough to fix a function signature.
|
|
82
|
-
stage_3_max_lines: 300, // Was 100. Allow substantial feature implementation.
|
|
83
|
-
stage_2_max_percentage: 10, // Percentage-based threshold for Stage 2
|
|
84
|
-
stage_3_max_percentage: 15, // Percentage-based threshold for Stage 3
|
|
85
|
-
min_lines_fallback: 20, // Minimum threshold even for small files
|
|
86
|
-
},
|
|
87
|
-
history_limit: 50
|
|
88
|
-
},
|
|
89
49
|
deep_reflection: {
|
|
90
50
|
enabled: true,
|
|
91
51
|
mode: 'auto',
|
|
@@ -122,11 +82,12 @@ export const DEFAULT_SETTINGS = {
|
|
|
122
82
|
large_change_block: 50, // 大规模修改警告阈值
|
|
123
83
|
},
|
|
124
84
|
large_change_lines: 50,
|
|
125
|
-
|
|
126
|
-
'1': 0.5, //
|
|
127
|
-
'2': 0.75, //
|
|
128
|
-
'3': 1.0, //
|
|
129
|
-
'4': 1.5, //
|
|
85
|
+
ep_tier_multipliers: {
|
|
86
|
+
'1': 0.5, // Seed: 更严格,阈值减半
|
|
87
|
+
'2': 0.75, // Sprout: 阈值降低 25%
|
|
88
|
+
'3': 1.0, // Sapling: 标准阈值
|
|
89
|
+
'4': 1.5, // Tree: 更宽松
|
|
90
|
+
'5': 2.0, // Forest: 最宽松
|
|
130
91
|
},
|
|
131
92
|
bash_safe_patterns: [
|
|
132
93
|
'^(ls|dir|pwd|which|where|echo|env|cat|type|head|tail|less|more)\\b',
|
|
@@ -216,25 +177,9 @@ export class PainConfig {
|
|
|
216
177
|
* Basic validation for critical settings
|
|
217
178
|
*/
|
|
218
179
|
validate(settings) {
|
|
219
|
-
// Ensure trust scores stay within 0-100 logical range
|
|
220
|
-
const s = settings.trust.stages;
|
|
221
|
-
if (s.stage_1_observer < 0 || s.stage_1_observer > 100)
|
|
222
|
-
s.stage_1_observer = 30;
|
|
223
|
-
if (s.stage_2_editor < 0 || s.stage_2_editor > 100)
|
|
224
|
-
s.stage_2_editor = 60;
|
|
225
|
-
if (s.stage_3_developer < 0 || s.stage_3_developer > 100)
|
|
226
|
-
s.stage_3_developer = 80;
|
|
227
180
|
// Ensure intervals are positive
|
|
228
181
|
if (settings.intervals.worker_poll_ms < 1000)
|
|
229
182
|
settings.intervals.worker_poll_ms = 15 * 60 * 1000;
|
|
230
|
-
// Ensure percentage limits are in valid range [0, 100]
|
|
231
|
-
const l = settings.trust.limits;
|
|
232
|
-
if (l.stage_2_max_percentage < 0 || l.stage_2_max_percentage > 100)
|
|
233
|
-
l.stage_2_max_percentage = 10;
|
|
234
|
-
if (l.stage_3_max_percentage < 0 || l.stage_3_max_percentage > 100)
|
|
235
|
-
l.stage_3_max_percentage = 15;
|
|
236
|
-
if (l.min_lines_fallback < 1)
|
|
237
|
-
l.min_lines_fallback = 20;
|
|
238
183
|
}
|
|
239
184
|
/**
|
|
240
185
|
* Gets a value using dot notation (e.g. 'thresholds.pain_trigger')
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control UI database stores ANALYTICS READ MODELS.
|
|
3
|
+
*
|
|
4
|
+
* PURPOSE: Aggregated data for dashboard visualization and historical insights.
|
|
5
|
+
* USAGE: Control UI queries and dashboard displays.
|
|
6
|
+
* NOT FOR: Control decisions, Phase 3 eligibility, or real-time operations.
|
|
7
|
+
*
|
|
8
|
+
* Runtime truth comes from: queue state, workspace trust scorecard, active sessions
|
|
9
|
+
*/
|
|
1
10
|
export interface ThinkingModelEventInput {
|
|
2
11
|
sessionId: string;
|
|
3
12
|
runId: string;
|
|
@@ -59,8 +68,26 @@ export declare class ControlUiDatabase {
|
|
|
59
68
|
constructor(opts: ControlUiDatabaseOptions);
|
|
60
69
|
dispose(): void;
|
|
61
70
|
recordThinkingModelEvent(input: ThinkingModelEventInput): number;
|
|
71
|
+
/**
|
|
72
|
+
* Get recent thinking context for a session.
|
|
73
|
+
*
|
|
74
|
+
* Returns: Analytics data (read model) aggregated from trajectory database.
|
|
75
|
+
* Not: Runtime truth or real-time queue state.
|
|
76
|
+
*/
|
|
62
77
|
getRecentThinkingContext(sessionId: string, beforeCreatedAt: string, limit?: number): RecentThinkingContext;
|
|
78
|
+
/**
|
|
79
|
+
* Execute SQL query and return all rows.
|
|
80
|
+
*
|
|
81
|
+
* Returns: Analytics data (read model) aggregated from trajectory database.
|
|
82
|
+
* Not: Runtime truth or real-time queue state.
|
|
83
|
+
*/
|
|
63
84
|
all<T>(sql: string, ...params: unknown[]): T[];
|
|
85
|
+
/**
|
|
86
|
+
* Execute SQL query and return first row.
|
|
87
|
+
*
|
|
88
|
+
* Returns: Analytics data (read model) aggregated from trajectory database.
|
|
89
|
+
* Not: Runtime truth or real-time queue state.
|
|
90
|
+
*/
|
|
64
91
|
get<T>(sql: string, ...params: unknown[]): T | undefined;
|
|
65
92
|
restoreRawText(inlineText?: string | null, blobRef?: string | null): string;
|
|
66
93
|
private initSchema;
|
|
@@ -39,6 +39,12 @@ export class ControlUiDatabase {
|
|
|
39
39
|
return Number(result.lastInsertRowid);
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Get recent thinking context for a session.
|
|
44
|
+
*
|
|
45
|
+
* Returns: Analytics data (read model) aggregated from trajectory database.
|
|
46
|
+
* Not: Runtime truth or real-time queue state.
|
|
47
|
+
*/
|
|
42
48
|
getRecentThinkingContext(sessionId, beforeCreatedAt, limit = 5) {
|
|
43
49
|
return {
|
|
44
50
|
toolCalls: this.all(`
|
|
@@ -107,9 +113,21 @@ export class ControlUiDatabase {
|
|
|
107
113
|
})),
|
|
108
114
|
};
|
|
109
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Execute SQL query and return all rows.
|
|
118
|
+
*
|
|
119
|
+
* Returns: Analytics data (read model) aggregated from trajectory database.
|
|
120
|
+
* Not: Runtime truth or real-time queue state.
|
|
121
|
+
*/
|
|
110
122
|
all(sql, ...params) {
|
|
111
123
|
return this.db.prepare(sql).all(...params);
|
|
112
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Execute SQL query and return first row.
|
|
127
|
+
*
|
|
128
|
+
* Returns: Analytics data (read model) aggregated from trajectory database.
|
|
129
|
+
* Not: Runtime truth or real-time queue state.
|
|
130
|
+
*/
|
|
113
131
|
get(sql, ...params) {
|
|
114
132
|
return this.db.prepare(sql).get(...params);
|
|
115
133
|
}
|
package/dist/core/event-log.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EventLogEntry, DailyStats, EmpathyEventStats, ToolCallEventData, PainSignalEventData, RuleMatchEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, DeepReflectionEventData,
|
|
1
|
+
import type { EventLogEntry, DailyStats, EmpathyEventStats, ToolCallEventData, PainSignalEventData, RuleMatchEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, DeepReflectionEventData, EmpathyRollbackEventData } from '../types/event-types.js';
|
|
2
2
|
import type { PluginLogger } from '../openclaw-sdk.js';
|
|
3
3
|
/**
|
|
4
4
|
* EventLog - Structured event logging with daily statistics aggregation.
|
|
@@ -23,7 +23,6 @@ export declare class EventLog {
|
|
|
23
23
|
recordPlanApproval(sessionId: string | undefined, data: PlanApprovalEventData): void;
|
|
24
24
|
recordEvolutionTask(data: EvolutionTaskEventData): void;
|
|
25
25
|
recordDeepReflection(sessionId: string | undefined, data: DeepReflectionEventData): void;
|
|
26
|
-
recordTrustChange(sessionId: string | undefined, data: TrustChangeEventData): void;
|
|
27
26
|
recordEmpathyRollback(sessionId: string | undefined, data: EmpathyRollbackEventData): void;
|
|
28
27
|
recordError(sessionId: string | undefined, message: string, context?: Record<string, unknown>): void;
|
|
29
28
|
recordWarn(sessionId: string | undefined, message: string, context?: Record<string, unknown>): void;
|
package/dist/core/event-log.js
CHANGED
|
@@ -57,9 +57,6 @@ export class EventLog {
|
|
|
57
57
|
const category = data.passed ? 'passed' : data.timeout ? 'failure' : 'completed';
|
|
58
58
|
this.record('deep_reflection', category, sessionId, data);
|
|
59
59
|
}
|
|
60
|
-
recordTrustChange(sessionId, data) {
|
|
61
|
-
this.record('trust_change', 'changed', sessionId, data);
|
|
62
|
-
}
|
|
63
60
|
recordEmpathyRollback(sessionId, data) {
|
|
64
61
|
this.record('empathy_rollback', 'rolled_back', sessionId, data);
|
|
65
62
|
}
|
|
@@ -14,7 +14,7 @@ import * as fs from 'fs';
|
|
|
14
14
|
import * as path from 'path';
|
|
15
15
|
import { resolvePdPath } from './paths.js';
|
|
16
16
|
import { withLock } from '../utils/file-lock.js';
|
|
17
|
-
import { CONSTRUCTIVE_TOOLS,
|
|
17
|
+
import { CONSTRUCTIVE_TOOLS, EXPLORATORY_TOOLS, HIGH_RISK_TOOLS, } from '../constants/tools.js';
|
|
18
18
|
import { EvolutionTier, DEFAULT_EVOLUTION_CONFIG, TIER_DEFINITIONS, TASK_DIFFICULTY_CONFIG, getTierDefinition, getTierByPoints, } from './evolution-types.js';
|
|
19
19
|
// ===== 主引擎 =====
|
|
20
20
|
export class EvolutionEngine {
|
|
@@ -137,26 +137,6 @@ export class EvolutionEngine {
|
|
|
137
137
|
beforeToolCall(context) {
|
|
138
138
|
const tierDef = this.getTierDefinition();
|
|
139
139
|
const perms = tierDef.permissions;
|
|
140
|
-
// 行数检查(仅针对写操作工具)
|
|
141
|
-
if (CONTENT_LIMITED_TOOLS.has(context.toolName)) {
|
|
142
|
-
if (context.content) {
|
|
143
|
-
const lineCount = context.content.split('\n').length;
|
|
144
|
-
if (lineCount > perms.maxLinesPerWrite) {
|
|
145
|
-
return {
|
|
146
|
-
allowed: false,
|
|
147
|
-
reason: `Tier ${this.scorecard.currentTier} (${tierDef.name}) 限制: 最多 ${perms.maxLinesPerWrite} 行,当前 ${lineCount} 行`,
|
|
148
|
-
currentTier: this.scorecard.currentTier,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
if (context.lineCount && context.lineCount > perms.maxLinesPerWrite) {
|
|
153
|
-
return {
|
|
154
|
-
allowed: false,
|
|
155
|
-
reason: `Tier ${this.scorecard.currentTier} (${tierDef.name}) 限制: 最多 ${perms.maxLinesPerWrite} 行`,
|
|
156
|
-
currentTier: this.scorecard.currentTier,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
140
|
// 风险路径检查
|
|
161
141
|
if (context.isRiskPath && !perms.allowRiskPath) {
|
|
162
142
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EvolutionLoopEvent, Principle } from './evolution-types.js';
|
|
1
|
+
import type { EvolutionLoopEvent, Principle, PrincipleDetectorSpec, PrincipleEvaluatorLevel } from './evolution-types.js';
|
|
2
2
|
export interface EvolutionReducer {
|
|
3
3
|
emit(event: EvolutionLoopEvent): void;
|
|
4
4
|
emitSync(event: EvolutionLoopEvent): void;
|
|
@@ -21,6 +21,10 @@ export interface EvolutionReducer {
|
|
|
21
21
|
triggerPattern: string;
|
|
22
22
|
action: string;
|
|
23
23
|
source: string;
|
|
24
|
+
/** Evaluability level — defaults to 'manual_only' if omitted */
|
|
25
|
+
evaluability?: PrincipleEvaluatorLevel;
|
|
26
|
+
/** Detector metadata — absent or malformed = 'manual_only' evaluability */
|
|
27
|
+
detectorMetadata?: PrincipleDetectorSpec;
|
|
24
28
|
}): string | null;
|
|
25
29
|
getStats(): {
|
|
26
30
|
candidateCount: number;
|
|
@@ -65,6 +69,8 @@ export declare class EvolutionReducerImpl implements EvolutionReducer {
|
|
|
65
69
|
triggerPattern: string;
|
|
66
70
|
action: string;
|
|
67
71
|
source: string;
|
|
72
|
+
evaluability?: PrincipleEvaluatorLevel;
|
|
73
|
+
detectorMetadata?: PrincipleDetectorSpec;
|
|
68
74
|
}): string | null;
|
|
69
75
|
getStats(): {
|
|
70
76
|
candidateCount: number;
|