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