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
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 3 Input Filter
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL: evaluatePhase3Inputs() does NOT read or use evolution_directive.json
|
|
5
|
+
* Directive is a compatibility-only display artifact, not a truth source.
|
|
6
|
+
*
|
|
7
|
+
* Phase 3 eligibility depends ONLY on:
|
|
8
|
+
* - Queue truth (valid evolution samples from queue)
|
|
9
|
+
*
|
|
10
|
+
* Any directive file is ignored for eligibility decisions.
|
|
11
|
+
*
|
|
12
|
+
* THREE-LANE CLASSIFICATION:
|
|
13
|
+
* - authoritative: Valid inputs that can be used for Phase 3 eligibility decisions
|
|
14
|
+
* - reference_only: Valid evidence that must NOT be used as positive eligibility input
|
|
15
|
+
* (e.g., timeout-only outcomes - they indicate completion but not success)
|
|
16
|
+
* - rejected: Invalid, corrupt, or policy-prohibited input
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Legacy queue statuses that are rejected for Phase 3
|
|
20
|
+
*/
|
|
21
|
+
const LEGACY_QUEUE_STATUSES = ['resolved', 'blocked', 'failed', 'cancelled', 'paused'];
|
|
1
22
|
function normalizeTaskId(value) {
|
|
2
23
|
if (typeof value !== 'string')
|
|
3
24
|
return null;
|
|
@@ -12,6 +33,13 @@ function normalizeStatus(value) {
|
|
|
12
33
|
return 'pending';
|
|
13
34
|
return null;
|
|
14
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Checks if a status is a legacy value that should be rejected
|
|
38
|
+
*/
|
|
39
|
+
function isLegacyStatus(value) {
|
|
40
|
+
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
41
|
+
return LEGACY_QUEUE_STATUSES.includes(normalized);
|
|
42
|
+
}
|
|
15
43
|
function normalizeTimestamp(value) {
|
|
16
44
|
if (typeof value !== 'string')
|
|
17
45
|
return null;
|
|
@@ -24,8 +52,31 @@ function normalizeTimestamp(value) {
|
|
|
24
52
|
function dedupe(values) {
|
|
25
53
|
return [...new Set(values)];
|
|
26
54
|
}
|
|
27
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Checks if a task has a timeout-only outcome (resolution indicates only timeout)
|
|
57
|
+
*/
|
|
58
|
+
function isTimeoutOnlyOutcome(item) {
|
|
59
|
+
const resolution = typeof item?.resolution === 'string' ? item.resolution.trim().toLowerCase() : '';
|
|
60
|
+
return resolution === 'auto_completed_timeout';
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Evaluates Phase 3 readiness based on queue inputs.
|
|
64
|
+
*
|
|
65
|
+
* IMPORTANT: Does NOT use evolution_directive.json.
|
|
66
|
+
* Directive is compatibility-only display artifact, not a truth source.
|
|
67
|
+
* Queue is the only authoritative execution truth source for Phase 3.
|
|
68
|
+
*
|
|
69
|
+
* THREE-LANE CLASSIFICATION:
|
|
70
|
+
* - authoritative: Valid inputs for Phase 3 eligibility
|
|
71
|
+
* - reference_only: Valid evidence but not for eligibility (e.g., timeout outcomes)
|
|
72
|
+
* - rejected: Invalid, corrupt, or policy-prohibited input
|
|
73
|
+
*
|
|
74
|
+
* @param queue - Evolution queue items to validate
|
|
75
|
+
* @returns Phase 3 eligibility results
|
|
76
|
+
*/
|
|
77
|
+
export function evaluatePhase3Inputs(queue) {
|
|
28
78
|
const eligible = [];
|
|
79
|
+
const referenceOnly = [];
|
|
29
80
|
const rejected = [];
|
|
30
81
|
const taskIdCounts = new Map();
|
|
31
82
|
for (const item of queue) {
|
|
@@ -40,13 +91,22 @@ export function evaluatePhase3Inputs(queue, trust) {
|
|
|
40
91
|
const reasons = [];
|
|
41
92
|
const startedAt = normalizeTimestamp(item?.started_at);
|
|
42
93
|
const completedAt = normalizeTimestamp(item?.completed_at);
|
|
94
|
+
// Check for legacy statuses first (before other status validation)
|
|
95
|
+
if (isLegacyStatus(item?.status)) {
|
|
96
|
+
reasons.push('legacy_queue_status');
|
|
97
|
+
}
|
|
98
|
+
// Check for null status separately
|
|
99
|
+
if (item?.status === null) {
|
|
100
|
+
reasons.push('missing_status');
|
|
101
|
+
}
|
|
43
102
|
if (!taskId) {
|
|
44
103
|
reasons.push('missing_task_id');
|
|
45
104
|
}
|
|
46
105
|
else if ((taskIdCounts.get(taskId) ?? 0) > 1) {
|
|
47
106
|
reasons.push('reused_task_id');
|
|
48
107
|
}
|
|
49
|
-
if
|
|
108
|
+
// Only add invalid_status if it's not a legacy status and not null
|
|
109
|
+
if (!status && !isLegacyStatus(item?.status) && item?.status !== null) {
|
|
50
110
|
reasons.push('invalid_status');
|
|
51
111
|
}
|
|
52
112
|
if (typeof item?.started_at === 'string' && item.started_at.trim() && !startedAt) {
|
|
@@ -61,6 +121,7 @@ export function evaluatePhase3Inputs(queue, trust) {
|
|
|
61
121
|
if (status === 'completed' && !completedAt) {
|
|
62
122
|
reasons.push('missing_completed_at');
|
|
63
123
|
}
|
|
124
|
+
// Handle rejected items first
|
|
64
125
|
if (reasons.length > 0) {
|
|
65
126
|
rejected.push({
|
|
66
127
|
taskId,
|
|
@@ -72,6 +133,18 @@ export function evaluatePhase3Inputs(queue, trust) {
|
|
|
72
133
|
if (!taskId || !status) {
|
|
73
134
|
continue;
|
|
74
135
|
}
|
|
136
|
+
// Check for timeout-only outcomes (REFERENCE_ONLY, not rejected)
|
|
137
|
+
// These are valid completions but shouldn't count as positive evidence
|
|
138
|
+
if (status === 'completed' && isTimeoutOnlyOutcome(item)) {
|
|
139
|
+
referenceOnly.push({
|
|
140
|
+
taskId,
|
|
141
|
+
status: 'completed',
|
|
142
|
+
classification: 'timeout_only',
|
|
143
|
+
reason: 'Task completed via timeout - valid execution but not positive capability evidence',
|
|
144
|
+
});
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// Valid eligible sample
|
|
75
148
|
eligible.push({
|
|
76
149
|
taskId,
|
|
77
150
|
status,
|
|
@@ -79,28 +152,21 @@ export function evaluatePhase3Inputs(queue, trust) {
|
|
|
79
152
|
completedAt,
|
|
80
153
|
});
|
|
81
154
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const trustInputReady = trustRejectedReasons.length === 0;
|
|
91
|
-
const queueTruthReady = queue.length > 0 && rejected.length === 0 && eligible.length > 0;
|
|
92
|
-
const phase3ShadowEligible = queueTruthReady && trustInputReady;
|
|
155
|
+
// Queue is ready when:
|
|
156
|
+
// 1. Queue has items
|
|
157
|
+
// 2. No invalid/corrupt items (rejected is empty)
|
|
158
|
+
// 3. Either eligible OR referenceOnly has items (valid data exists)
|
|
159
|
+
// Note: referenceOnly (timeout outcomes) is valid data, just not positive evidence
|
|
160
|
+
const hasValidData = eligible.length > 0 || referenceOnly.length > 0;
|
|
161
|
+
const queueTruthReady = queue.length > 0 && rejected.length === 0 && hasValidData;
|
|
162
|
+
const phase3ShadowEligible = queueTruthReady && eligible.length > 0;
|
|
93
163
|
return {
|
|
94
164
|
queueTruthReady,
|
|
95
|
-
trustInputReady,
|
|
96
165
|
phase3ShadowEligible,
|
|
97
166
|
evolution: {
|
|
98
167
|
eligible,
|
|
168
|
+
referenceOnly,
|
|
99
169
|
rejected,
|
|
100
170
|
},
|
|
101
|
-
trust: {
|
|
102
|
-
eligible: trustInputReady,
|
|
103
|
-
rejectedReasons: trustRejectedReasons,
|
|
104
|
-
},
|
|
105
171
|
};
|
|
106
172
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RuntimeTruth, AnalyticsTruth } from '../types/runtime-summary.js';
|
|
1
2
|
export type RuntimeDataQuality = 'authoritative' | 'partial';
|
|
2
3
|
export type RuntimeRewardPolicy = 'frozen_all_positive' | 'frozen_atomic_positive_keep_plan_ready';
|
|
3
4
|
interface RuntimeSummarySource {
|
|
@@ -13,19 +14,23 @@ interface RuntimePainSignal {
|
|
|
13
14
|
reason: string | null;
|
|
14
15
|
}
|
|
15
16
|
export interface RuntimeSummary {
|
|
17
|
+
/**
|
|
18
|
+
* Runtime truth represents the current state of the system.
|
|
19
|
+
* Used for control decisions, Phase 3 eligibility, and real-time operations.
|
|
20
|
+
*/
|
|
21
|
+
runtime: RuntimeTruth;
|
|
22
|
+
/**
|
|
23
|
+
* Analytics truth represents historical data and aggregated metrics.
|
|
24
|
+
* Used for insights, trends, and supporting evidence (where explicitly allowed).
|
|
25
|
+
* NOT used for control decisions or Phase 3 eligibility.
|
|
26
|
+
*/
|
|
27
|
+
analytics: AnalyticsTruth;
|
|
16
28
|
gfi: {
|
|
17
29
|
current: number | null;
|
|
18
30
|
peak: number | null;
|
|
19
31
|
sources: RuntimeSummarySource[];
|
|
20
32
|
dataQuality: RuntimeDataQuality;
|
|
21
33
|
};
|
|
22
|
-
legacyTrust: {
|
|
23
|
-
score: number | null;
|
|
24
|
-
stage: 1 | 2 | 3 | 4 | null;
|
|
25
|
-
frozen: true;
|
|
26
|
-
lastUpdated: string | null;
|
|
27
|
-
rewardPolicy: RuntimeRewardPolicy;
|
|
28
|
-
};
|
|
29
34
|
evolution: {
|
|
30
35
|
queue: {
|
|
31
36
|
pending: number;
|
|
@@ -42,12 +47,20 @@ export interface RuntimeSummary {
|
|
|
42
47
|
};
|
|
43
48
|
phase3: {
|
|
44
49
|
queueTruthReady: boolean;
|
|
45
|
-
trustInputReady: boolean;
|
|
46
50
|
phase3ShadowEligible: boolean;
|
|
47
51
|
evolutionEligible: number;
|
|
52
|
+
evolutionReferenceOnly: number;
|
|
53
|
+
evolutionReferenceOnlyReasons: string[];
|
|
48
54
|
evolutionRejected: number;
|
|
49
55
|
evolutionRejectedReasons: string[];
|
|
50
|
-
|
|
56
|
+
legacyDirectiveFilePresent: boolean;
|
|
57
|
+
directiveStatus: 'compatibility-only' | 'missing' | 'present';
|
|
58
|
+
directiveIgnoredReason: string;
|
|
59
|
+
/**
|
|
60
|
+
* Source of Phase 3 eligibility calculation.
|
|
61
|
+
* Should always be 'runtime_truth' - analytics not used for control decisions.
|
|
62
|
+
*/
|
|
63
|
+
eligibilitySource: 'runtime_truth';
|
|
51
64
|
};
|
|
52
65
|
pain: {
|
|
53
66
|
activeFlag: boolean;
|
|
@@ -76,8 +89,12 @@ export declare class RuntimeSummaryService {
|
|
|
76
89
|
private static selectSession;
|
|
77
90
|
private static mergeSessionSnapshots;
|
|
78
91
|
private static buildQueueStats;
|
|
92
|
+
/**
|
|
93
|
+
* Builds directive summary for compatibility display only.
|
|
94
|
+
* NOT a truth source for Phase 3 eligibility or decisions.
|
|
95
|
+
* Queue is the only authoritative execution truth source.
|
|
96
|
+
*/
|
|
79
97
|
private static buildDirectiveSummary;
|
|
80
|
-
private static readLegacyTrust;
|
|
81
98
|
private static readEvents;
|
|
82
99
|
private static buildGfiSources;
|
|
83
100
|
private static findLastPainSignal;
|
|
@@ -94,5 +111,12 @@ export declare class RuntimeSummaryService {
|
|
|
94
111
|
private static warnOnLegacyDirectiveMismatch;
|
|
95
112
|
private static readJsonFile;
|
|
96
113
|
private static asFiniteNumber;
|
|
114
|
+
/**
|
|
115
|
+
* Read trajectory analytics data from trajectory database.
|
|
116
|
+
*
|
|
117
|
+
* Returns: Analytics data (historical metrics) aggregated from trajectory database.
|
|
118
|
+
* Not: Runtime truth or real-time queue state.
|
|
119
|
+
*/
|
|
120
|
+
private static readTrajectoryStats;
|
|
97
121
|
}
|
|
98
122
|
export {};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { readPainFlagData } from '../core/pain.js';
|
|
4
|
-
import { resolvePdPath } from '../core/paths.js';
|
|
5
4
|
import { listSessions } from '../core/session-tracker.js';
|
|
6
5
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
7
6
|
import { evaluatePhase3Inputs } from './phase3-input-filter.js';
|
|
7
|
+
import { TrajectoryRegistry } from '../core/trajectory.js';
|
|
8
8
|
const MAX_SOURCE_EVENTS = 5;
|
|
9
|
-
const LEGACY_TRUST_REWARD_POLICY = 'frozen_all_positive';
|
|
10
9
|
const GFI_PARTIAL_WARNING = 'GFI source attribution remains partial in Phase 2b because only the empathy slice is source-attributed; most non-empathy friction still lacks full per-source attribution.';
|
|
11
10
|
const DAILY_GFI_WARNING = 'daily-stats.gfi is not authoritative in Phase 1 and is used only as a fallback reference.';
|
|
12
11
|
const EVENT_BUFFER_WARNING = 'Live event buffer is unavailable in this context, so status may lag until events.jsonl flushes.';
|
|
@@ -30,8 +29,11 @@ export class RuntimeSummaryService {
|
|
|
30
29
|
: [];
|
|
31
30
|
const events = this.mergeEvents(persistedEvents, bufferedEvents);
|
|
32
31
|
const dailyStats = this.readJsonFile(path.join(wctx.stateDir, 'logs', 'daily-stats.json'), warnings, false);
|
|
32
|
+
// Get most recent date from daily stats, fallback to today
|
|
33
33
|
const today = generatedAt.slice(0, 10);
|
|
34
|
-
const
|
|
34
|
+
const availableDates = Object.keys(dailyStats || {}).sort().reverse();
|
|
35
|
+
const statsDate = availableDates.length > 0 ? availableDates[0] : today;
|
|
36
|
+
const dailyGfiPeak = dailyStats?.[statsDate]?.gfi?.peak;
|
|
35
37
|
const gfiCurrent = selectedSession.session && Number.isFinite(selectedSession.session.currentGfi)
|
|
36
38
|
? Number(selectedSession.session.currentGfi)
|
|
37
39
|
: null;
|
|
@@ -50,24 +52,63 @@ export class RuntimeSummaryService {
|
|
|
50
52
|
pushWarning(warnings, 'No persisted session state was found; current session GFI is unavailable.');
|
|
51
53
|
}
|
|
52
54
|
const queue = this.readJsonFile(wctx.resolve('EVOLUTION_QUEUE'), warnings, false);
|
|
55
|
+
// compatibility-only display artifact - not a truth source for Phase 3 eligibility
|
|
56
|
+
// queue is the only authoritative execution truth source for Phase 3
|
|
53
57
|
const directive = this.readJsonFile(wctx.resolve('EVOLUTION_DIRECTIVE'), warnings, false);
|
|
54
58
|
const queueStats = this.buildQueueStats(queue);
|
|
55
59
|
const directiveSummary = this.buildDirectiveSummary(queue, directive, generatedAt, warnings);
|
|
56
60
|
const painFlag = readPainFlagData(workspaceDir);
|
|
57
61
|
const painCandidates = this.readJsonFile(wctx.resolve('PAIN_CANDIDATES'), warnings, false);
|
|
58
|
-
const
|
|
59
|
-
const phase3Inputs = evaluatePhase3Inputs(queue ?? [], legacyTrust.phase3Input);
|
|
62
|
+
const phase3Inputs = evaluatePhase3Inputs(queue ?? []);
|
|
60
63
|
const lastPainSignal = this.findLastPainSignal(events, selectedSessionId);
|
|
61
64
|
const gfiSources = this.buildGfiSources(events, selectedSessionId);
|
|
62
65
|
const gateStats = this.buildGateStats(events, selectedSessionId, warnings);
|
|
66
|
+
// Read trajectory analytics data (historical data, NOT runtime truth)
|
|
67
|
+
const trajectoryStats = this.readTrajectoryStats(workspaceDir, warnings);
|
|
68
|
+
// Build runtime truth section (current state for control decisions)
|
|
69
|
+
const activeSessionIds = sessions.map(s => s.sessionId);
|
|
70
|
+
const runtimeTruth = {
|
|
71
|
+
queueState: {
|
|
72
|
+
total: queueStats.pending + queueStats.inProgress + queueStats.completed,
|
|
73
|
+
pending: queueStats.pending,
|
|
74
|
+
inProgress: queueStats.inProgress,
|
|
75
|
+
completed: queueStats.completed,
|
|
76
|
+
lastUpdated: generatedAt,
|
|
77
|
+
},
|
|
78
|
+
activeSessions: activeSessionIds,
|
|
79
|
+
};
|
|
80
|
+
// Build analytics truth section (historical data for insights)
|
|
81
|
+
const analyticsTruth = {
|
|
82
|
+
trajectoryData: {
|
|
83
|
+
totalTasks: trajectoryStats.assistantTurns + trajectoryStats.userTurns,
|
|
84
|
+
successRate: trajectoryStats.toolCalls > 0
|
|
85
|
+
? (trajectoryStats.toolCalls - trajectoryStats.failures) / trajectoryStats.toolCalls
|
|
86
|
+
: 0,
|
|
87
|
+
timeoutRate: trajectoryStats.failures > 0
|
|
88
|
+
? trajectoryStats.failures / (trajectoryStats.assistantTurns + trajectoryStats.userTurns || 1)
|
|
89
|
+
: 0,
|
|
90
|
+
lastUpdated: trajectoryStats.lastIngestAt ?? generatedAt,
|
|
91
|
+
},
|
|
92
|
+
dailyStats: {
|
|
93
|
+
toolCalls: dailyStats?.[statsDate]?.toolCalls ?? 0,
|
|
94
|
+
painSignals: dailyStats?.[statsDate]?.painSignals ?? 0,
|
|
95
|
+
evolutionTasks: dailyStats?.[statsDate]?.evolutionTasks ?? 0,
|
|
96
|
+
lastUpdated: statsDate,
|
|
97
|
+
},
|
|
98
|
+
trends: {
|
|
99
|
+
sevenDay: { successRateChange: 0, toolCallVolumeChange: 0, painSignalRateChange: 0 },
|
|
100
|
+
thirtyDay: { successRateChange: 0, toolCallVolumeChange: 0, painSignalRateChange: 0 },
|
|
101
|
+
},
|
|
102
|
+
};
|
|
63
103
|
return {
|
|
104
|
+
runtime: runtimeTruth,
|
|
105
|
+
analytics: analyticsTruth,
|
|
64
106
|
gfi: {
|
|
65
107
|
current: gfiCurrent,
|
|
66
108
|
peak: gfiPeak,
|
|
67
109
|
sources: gfiSources,
|
|
68
110
|
dataQuality: 'partial',
|
|
69
111
|
},
|
|
70
|
-
legacyTrust: legacyTrust.summary,
|
|
71
112
|
evolution: {
|
|
72
113
|
queue: queueStats,
|
|
73
114
|
directive: directiveSummary,
|
|
@@ -75,12 +116,16 @@ export class RuntimeSummaryService {
|
|
|
75
116
|
},
|
|
76
117
|
phase3: {
|
|
77
118
|
queueTruthReady: phase3Inputs.queueTruthReady,
|
|
78
|
-
trustInputReady: phase3Inputs.trustInputReady,
|
|
79
119
|
phase3ShadowEligible: phase3Inputs.phase3ShadowEligible,
|
|
80
120
|
evolutionEligible: phase3Inputs.evolution.eligible.length,
|
|
121
|
+
evolutionReferenceOnly: phase3Inputs.evolution.referenceOnly.length,
|
|
122
|
+
evolutionReferenceOnlyReasons: [...new Set(phase3Inputs.evolution.referenceOnly.map((entry) => entry.classification))],
|
|
81
123
|
evolutionRejected: phase3Inputs.evolution.rejected.length,
|
|
82
124
|
evolutionRejectedReasons: phase3Inputs.evolution.rejected.flatMap((entry) => entry.reasons),
|
|
83
|
-
|
|
125
|
+
legacyDirectiveFilePresent: directive !== null,
|
|
126
|
+
directiveStatus: directive ? 'compatibility-only' : 'missing',
|
|
127
|
+
directiveIgnoredReason: 'queue is only truth source',
|
|
128
|
+
eligibilitySource: 'runtime_truth',
|
|
84
129
|
},
|
|
85
130
|
pain: {
|
|
86
131
|
activeFlag: Object.keys(painFlag).length > 0,
|
|
@@ -168,6 +213,11 @@ export class RuntimeSummaryService {
|
|
|
168
213
|
}
|
|
169
214
|
return stats;
|
|
170
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Builds directive summary for compatibility display only.
|
|
218
|
+
* NOT a truth source for Phase 3 eligibility or decisions.
|
|
219
|
+
* Queue is the only authoritative execution truth source.
|
|
220
|
+
*/
|
|
171
221
|
static buildDirectiveSummary(queue, directive, generatedAt, warnings) {
|
|
172
222
|
const inProgressTask = this.selectInProgressTask(queue);
|
|
173
223
|
if (!inProgressTask) {
|
|
@@ -200,46 +250,6 @@ export class RuntimeSummaryService {
|
|
|
200
250
|
taskPreview: derivedTaskPreview,
|
|
201
251
|
};
|
|
202
252
|
}
|
|
203
|
-
static readLegacyTrust(scorecardPath, wctx, warnings) {
|
|
204
|
-
const scorecard = this.readJsonFile(scorecardPath, warnings, false);
|
|
205
|
-
const score = Number.isFinite(scorecard?.trust_score) ? Number(scorecard?.trust_score) : null;
|
|
206
|
-
const rawFrozen = scorecard?.frozen === true ? true : false;
|
|
207
|
-
const settings = wctx.config.get('trust');
|
|
208
|
-
const stageThresholds = settings?.stages ?? {
|
|
209
|
-
stage_1_observer: 30,
|
|
210
|
-
stage_2_editor: 60,
|
|
211
|
-
stage_3_developer: 80,
|
|
212
|
-
};
|
|
213
|
-
let stage = null;
|
|
214
|
-
if (score !== null) {
|
|
215
|
-
if (score < (stageThresholds.stage_1_observer ?? 30)) {
|
|
216
|
-
stage = 1;
|
|
217
|
-
}
|
|
218
|
-
else if (score < (stageThresholds.stage_2_editor ?? 60)) {
|
|
219
|
-
stage = 2;
|
|
220
|
-
}
|
|
221
|
-
else if (score < (stageThresholds.stage_3_developer ?? 80)) {
|
|
222
|
-
stage = 3;
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
stage = 4;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
summary: {
|
|
230
|
-
score,
|
|
231
|
-
stage,
|
|
232
|
-
frozen: true,
|
|
233
|
-
lastUpdated: scorecard?.last_updated ?? null,
|
|
234
|
-
rewardPolicy: LEGACY_TRUST_REWARD_POLICY,
|
|
235
|
-
},
|
|
236
|
-
phase3Input: {
|
|
237
|
-
score,
|
|
238
|
-
frozen: rawFrozen,
|
|
239
|
-
lastUpdated: scorecard?.last_updated ?? null,
|
|
240
|
-
},
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
253
|
static readEvents(eventsPath, warnings) {
|
|
244
254
|
if (!fs.existsSync(eventsPath)) {
|
|
245
255
|
warnings.push('No events.jsonl file exists yet; recent pain and gate summaries are partial.');
|
|
@@ -443,4 +453,33 @@ export class RuntimeSummaryService {
|
|
|
443
453
|
static asFiniteNumber(value) {
|
|
444
454
|
return Number.isFinite(value) ? Number(value) : undefined;
|
|
445
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* Read trajectory analytics data from trajectory database.
|
|
458
|
+
*
|
|
459
|
+
* Returns: Analytics data (historical metrics) aggregated from trajectory database.
|
|
460
|
+
* Not: Runtime truth or real-time queue state.
|
|
461
|
+
*/
|
|
462
|
+
static readTrajectoryStats(workspaceDir, warnings) {
|
|
463
|
+
try {
|
|
464
|
+
// Use transient database instance to avoid locking issues
|
|
465
|
+
const stats = TrajectoryRegistry.use(workspaceDir, (db) => db.getDataStats());
|
|
466
|
+
return {
|
|
467
|
+
assistantTurns: stats.assistantTurns,
|
|
468
|
+
userTurns: stats.userTurns,
|
|
469
|
+
toolCalls: stats.toolCalls,
|
|
470
|
+
failures: stats.painEvents, // Approximate failures from pain events
|
|
471
|
+
lastIngestAt: stats.lastIngestAt,
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
pushWarning(warnings, `Failed to read trajectory analytics: ${error instanceof Error ? error.message : String(error)}`);
|
|
476
|
+
return {
|
|
477
|
+
assistantTurns: 0,
|
|
478
|
+
userTurns: 0,
|
|
479
|
+
toolCalls: 0,
|
|
480
|
+
failures: 0,
|
|
481
|
+
lastIngestAt: null,
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
}
|
|
446
485
|
}
|
|
@@ -12,8 +12,9 @@ import { reflectionLogRetentionDays } from '../types.js';
|
|
|
12
12
|
*/
|
|
13
13
|
function writeToReflectionLog(workspaceDir, context, insights, modelId, depth) {
|
|
14
14
|
const reflectionLogPath = resolvePdPath(workspaceDir, 'REFLECTION_LOG');
|
|
15
|
+
// Ensure memory directory exists (backward-compatible: create if missing)
|
|
16
|
+
// Note: resolvePdPath returns the full path; ensure parent dir exists
|
|
15
17
|
const memoryDir = path.dirname(reflectionLogPath);
|
|
16
|
-
// Ensure memory directory exists
|
|
17
18
|
if (!fs.existsSync(memoryDir)) {
|
|
18
19
|
fs.mkdirSync(memoryDir, { recursive: true });
|
|
19
20
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Event types for structured logging and daily statistics.
|
|
3
3
|
*/
|
|
4
|
-
export type EventType = 'tool_call' | 'pain_signal' | 'rule_match' | 'rule_promotion' | 'hook_execution' | 'gate_block' | 'gate_bypass' | 'plan_approval' | 'evolution_task' | 'deep_reflection' | '
|
|
4
|
+
export type EventType = 'tool_call' | 'pain_signal' | 'rule_match' | 'rule_promotion' | 'hook_execution' | 'gate_block' | 'gate_bypass' | 'plan_approval' | 'evolution_task' | 'deep_reflection' | 'empathy_rollback' | 'error' | 'warn';
|
|
5
5
|
export type EventCategory = 'success' | 'failure' | 'detected' | 'blocked' | 'bypassed' | 'approved' | 'enqueued' | 'completed' | 'promoted' | 'passed' | 'changed' | 'rolled_back';
|
|
6
6
|
/**
|
|
7
7
|
* Base event structure for JSONL logging.
|
|
@@ -22,12 +22,6 @@ export interface EventLogEntry {
|
|
|
22
22
|
/** Event-specific data */
|
|
23
23
|
data: Record<string, unknown>;
|
|
24
24
|
}
|
|
25
|
-
export interface TrustChangeEventData {
|
|
26
|
-
previousScore: number;
|
|
27
|
-
newScore: number;
|
|
28
|
-
delta: number;
|
|
29
|
-
reason: string;
|
|
30
|
-
}
|
|
31
25
|
export interface ToolCallEventData {
|
|
32
26
|
toolName: string;
|
|
33
27
|
filePath?: string;
|
|
@@ -75,13 +69,13 @@ export interface GateBlockEventData {
|
|
|
75
69
|
filePath: string;
|
|
76
70
|
reason: string;
|
|
77
71
|
planStatus?: string;
|
|
72
|
+
/** Source module that triggered the block (for audit trail) */
|
|
73
|
+
blockSource?: string;
|
|
78
74
|
}
|
|
79
75
|
export interface GateBypassEventData {
|
|
80
76
|
toolName: string;
|
|
81
77
|
filePath: string;
|
|
82
|
-
bypassType: 'stage4_architect' | '
|
|
83
|
-
trustScore: number;
|
|
84
|
-
trustStage: number;
|
|
78
|
+
bypassType: 'stage4_architect' | 'whitelisted';
|
|
85
79
|
}
|
|
86
80
|
export interface PlanApprovalEventData {
|
|
87
81
|
toolName: string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime truth represents the current state of the system.
|
|
3
|
+
* Used for control decisions, Phase 3 eligibility, and real-time operations.
|
|
4
|
+
* Sources: queue state, active session registry
|
|
5
|
+
*/
|
|
6
|
+
export interface RuntimeTruth {
|
|
7
|
+
queueState: {
|
|
8
|
+
total: number;
|
|
9
|
+
pending: number;
|
|
10
|
+
inProgress: number;
|
|
11
|
+
completed: number;
|
|
12
|
+
lastUpdated: string;
|
|
13
|
+
};
|
|
14
|
+
activeSessions: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Analytics truth represents historical data and aggregated metrics.
|
|
18
|
+
* Used for insights, trends, and supporting evidence (where explicitly allowed).
|
|
19
|
+
* NOT used for control decisions or Phase 3 eligibility.
|
|
20
|
+
* Sources: trajectory.db, daily-stats.json, control-ui DB
|
|
21
|
+
*/
|
|
22
|
+
export interface AnalyticsTruth {
|
|
23
|
+
trajectoryData: {
|
|
24
|
+
totalTasks: number;
|
|
25
|
+
successRate: number;
|
|
26
|
+
timeoutRate: number;
|
|
27
|
+
lastUpdated: string;
|
|
28
|
+
};
|
|
29
|
+
dailyStats: {
|
|
30
|
+
toolCalls: number;
|
|
31
|
+
painSignals: number;
|
|
32
|
+
evolutionTasks: number;
|
|
33
|
+
lastUpdated: string;
|
|
34
|
+
};
|
|
35
|
+
trends: {
|
|
36
|
+
sevenDay: TrendMetrics;
|
|
37
|
+
thirtyDay: TrendMetrics;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Trend metrics for analytics aggregation.
|
|
42
|
+
*/
|
|
43
|
+
export interface TrendMetrics {
|
|
44
|
+
successRateChange: number;
|
|
45
|
+
toolCallVolumeChange: number;
|
|
46
|
+
painSignalRateChange: number;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -22,8 +22,6 @@ export interface ContextInjectionConfig {
|
|
|
22
22
|
projectFocus: ProjectFocusMode;
|
|
23
23
|
/** Reflection log - can be toggled */
|
|
24
24
|
reflectionLog: boolean;
|
|
25
|
-
/** Trust score awareness - can be toggled */
|
|
26
|
-
trustScore: boolean;
|
|
27
25
|
/** Evolution task context injection settings */
|
|
28
26
|
evolutionContext: EvolutionContextConfig;
|
|
29
27
|
}
|
|
@@ -34,7 +32,6 @@ export interface ContextInjectionConfig {
|
|
|
34
32
|
* - thinkingOs: true (can be turned off)
|
|
35
33
|
* - projectFocus: 'off' (default closed, user can enable)
|
|
36
34
|
* - reflectionLog: true (default on)
|
|
37
|
-
* - trustScore: true (can be turned off)
|
|
38
35
|
*/
|
|
39
36
|
export declare const defaultContextConfig: ContextInjectionConfig;
|
|
40
37
|
/**
|
package/dist/types.js
CHANGED
|
@@ -5,13 +5,11 @@
|
|
|
5
5
|
* - thinkingOs: true (can be turned off)
|
|
6
6
|
* - projectFocus: 'off' (default closed, user can enable)
|
|
7
7
|
* - reflectionLog: true (default on)
|
|
8
|
-
* - trustScore: true (can be turned off)
|
|
9
8
|
*/
|
|
10
9
|
export const defaultContextConfig = {
|
|
11
10
|
thinkingOs: true,
|
|
12
11
|
projectFocus: 'off',
|
|
13
12
|
reflectionLog: true,
|
|
14
|
-
trustScore: true,
|
|
15
13
|
evolutionContext: {
|
|
16
14
|
enabled: true,
|
|
17
15
|
maxMessages: 4,
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@ I'm your intelligent mentor, helping you understand and use all features of Prin
|
|
|
32
32
|
| `/pd-thinking` | Manage mental models and candidates | Metacognition |
|
|
33
33
|
| `/pd-evolve` | Execute full evolution loop | Bug fix |
|
|
34
34
|
| `/pd-daily` | Configure and send evolution daily report | Daily review |
|
|
35
|
-
| `/pd-
|
|
35
|
+
| `/pd-evolution-status` | View trust score and security stage | Permission check |
|
|
36
36
|
| `/pd-status` | View system status (GFI and Pain Dictionary) | Health check |
|
|
37
37
|
| `/pd-grooming` | Workspace digital cleanup | Entropy reduction |
|
|
38
38
|
| `/pd-help` | Get interactive command guidance | This skill |
|
|
@@ -72,7 +72,7 @@ I'm your intelligent mentor, helping you understand and use all features of Prin
|
|
|
72
72
|
|
|
73
73
|
**Recommended Flow**:
|
|
74
74
|
1. `/pd-daily` - Send today's evolution report
|
|
75
|
-
2. `/pd-
|
|
75
|
+
2. `/pd-evolution-status` - View current trust score
|
|
76
76
|
3. `/pd-okr` - Check OKR alignment
|
|
77
77
|
|
|
78
78
|
**Script**: "Daily report in hand, evolution I command. Let me help you review today's achievements."
|
|
@@ -95,7 +95,7 @@ I'm your intelligent mentor, helping you understand and use all features of Prin
|
|
|
95
95
|
**Trigger**: User says "not enough permissions", "blocked", "security level"
|
|
96
96
|
|
|
97
97
|
**Recommended Flow**:
|
|
98
|
-
1. `/pd-
|
|
98
|
+
1. `/pd-evolution-status` - View trust score and security stage
|
|
99
99
|
2. Explain current stage's capability boundaries
|
|
100
100
|
|
|
101
101
|
**Script**: "Trust is earned, not given. Let me help you understand your current security level."
|
|
@@ -207,8 +207,8 @@ These skills are usually called automatically by the system, but advanced users
|
|
|
207
207
|
**Q: What is GFI (Friction Index)?**
|
|
208
208
|
A: GFI (Global Friction Index) measures the system's "pain level", range 0-100. Higher values indicate more friction, requiring attention.
|
|
209
209
|
|
|
210
|
-
**Q: How is
|
|
211
|
-
A:
|
|
210
|
+
**Q: How is EP (Evolution Points) calculated?**
|
|
211
|
+
A: EP is earned through successful task completion and problem resolution. Failures may deduct EP but have protection mechanisms. Reaching EP thresholds automatically upgrades your tier, unlocking more permissions (larger code modification limits).
|
|
212
212
|
|
|
213
213
|
**Q: What is Pain Signal?**
|
|
214
214
|
A: Pain Signal is a problem signal detected by the system, stored in `.state/.pain_flag`. When triggered, the system starts the evolution loop.
|