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.
Files changed (129) hide show
  1. package/dist/commands/context.js +5 -15
  2. package/dist/commands/evolution-status.js +29 -48
  3. package/dist/commands/export.js +61 -8
  4. package/dist/commands/nocturnal-review.d.ts +24 -0
  5. package/dist/commands/nocturnal-review.js +265 -0
  6. package/dist/commands/nocturnal-rollout.d.ts +27 -0
  7. package/dist/commands/nocturnal-rollout.js +671 -0
  8. package/dist/commands/nocturnal-train.d.ts +25 -0
  9. package/dist/commands/nocturnal-train.js +919 -0
  10. package/dist/commands/pain.js +8 -21
  11. package/dist/config/defaults/runtime.d.ts +40 -0
  12. package/dist/config/defaults/runtime.js +44 -0
  13. package/dist/config/errors.d.ts +84 -0
  14. package/dist/config/errors.js +94 -0
  15. package/dist/config/index.d.ts +7 -0
  16. package/dist/config/index.js +7 -0
  17. package/dist/constants/diagnostician.d.ts +0 -4
  18. package/dist/constants/diagnostician.js +0 -4
  19. package/dist/constants/tools.d.ts +2 -2
  20. package/dist/constants/tools.js +1 -1
  21. package/dist/core/adaptive-thresholds.d.ts +186 -0
  22. package/dist/core/adaptive-thresholds.js +300 -0
  23. package/dist/core/config.d.ts +2 -38
  24. package/dist/core/config.js +6 -61
  25. package/dist/core/control-ui-db.d.ts +27 -0
  26. package/dist/core/control-ui-db.js +18 -0
  27. package/dist/core/event-log.d.ts +1 -2
  28. package/dist/core/event-log.js +0 -3
  29. package/dist/core/evolution-engine.js +1 -21
  30. package/dist/core/evolution-reducer.d.ts +7 -1
  31. package/dist/core/evolution-reducer.js +56 -4
  32. package/dist/core/evolution-types.d.ts +61 -9
  33. package/dist/core/evolution-types.js +31 -9
  34. package/dist/core/external-training-contract.d.ts +276 -0
  35. package/dist/core/external-training-contract.js +269 -0
  36. package/dist/core/local-worker-routing.d.ts +175 -0
  37. package/dist/core/local-worker-routing.js +525 -0
  38. package/dist/core/model-deployment-registry.d.ts +218 -0
  39. package/dist/core/model-deployment-registry.js +503 -0
  40. package/dist/core/model-training-registry.d.ts +295 -0
  41. package/dist/core/model-training-registry.js +475 -0
  42. package/dist/core/nocturnal-arbiter.d.ts +159 -0
  43. package/dist/core/nocturnal-arbiter.js +534 -0
  44. package/dist/core/nocturnal-candidate-scoring.d.ts +137 -0
  45. package/dist/core/nocturnal-candidate-scoring.js +266 -0
  46. package/dist/core/nocturnal-compliance.d.ts +175 -0
  47. package/dist/core/nocturnal-compliance.js +824 -0
  48. package/dist/core/nocturnal-dataset.d.ts +224 -0
  49. package/dist/core/nocturnal-dataset.js +443 -0
  50. package/dist/core/nocturnal-executability.d.ts +85 -0
  51. package/dist/core/nocturnal-executability.js +331 -0
  52. package/dist/core/nocturnal-export.d.ts +124 -0
  53. package/dist/core/nocturnal-export.js +275 -0
  54. package/dist/core/nocturnal-paths.d.ts +124 -0
  55. package/dist/core/nocturnal-paths.js +214 -0
  56. package/dist/core/nocturnal-trajectory-extractor.d.ts +242 -0
  57. package/dist/core/nocturnal-trajectory-extractor.js +307 -0
  58. package/dist/core/nocturnal-trinity.d.ts +311 -0
  59. package/dist/core/nocturnal-trinity.js +880 -0
  60. package/dist/core/path-resolver.js +2 -1
  61. package/dist/core/paths.d.ts +6 -0
  62. package/dist/core/paths.js +6 -0
  63. package/dist/core/principle-training-state.d.ts +121 -0
  64. package/dist/core/principle-training-state.js +321 -0
  65. package/dist/core/promotion-gate.d.ts +238 -0
  66. package/dist/core/promotion-gate.js +529 -0
  67. package/dist/core/session-tracker.d.ts +10 -0
  68. package/dist/core/session-tracker.js +14 -0
  69. package/dist/core/shadow-observation-registry.d.ts +217 -0
  70. package/dist/core/shadow-observation-registry.js +308 -0
  71. package/dist/core/training-program.d.ts +233 -0
  72. package/dist/core/training-program.js +433 -0
  73. package/dist/core/trajectory.d.ts +155 -1
  74. package/dist/core/trajectory.js +292 -8
  75. package/dist/core/workspace-context.d.ts +0 -6
  76. package/dist/core/workspace-context.js +0 -12
  77. package/dist/hooks/bash-risk.d.ts +57 -0
  78. package/dist/hooks/bash-risk.js +137 -0
  79. package/dist/hooks/edit-verification.d.ts +62 -0
  80. package/dist/hooks/edit-verification.js +256 -0
  81. package/dist/hooks/gate-block-helper.d.ts +44 -0
  82. package/dist/hooks/gate-block-helper.js +119 -0
  83. package/dist/hooks/gate.d.ts +18 -0
  84. package/dist/hooks/gate.js +62 -751
  85. package/dist/hooks/gfi-gate.d.ts +40 -0
  86. package/dist/hooks/gfi-gate.js +113 -0
  87. package/dist/hooks/pain.js +6 -9
  88. package/dist/hooks/progressive-trust-gate.d.ts +51 -0
  89. package/dist/hooks/progressive-trust-gate.js +89 -0
  90. package/dist/hooks/prompt.d.ts +11 -11
  91. package/dist/hooks/prompt.js +167 -77
  92. package/dist/hooks/subagent.js +43 -6
  93. package/dist/hooks/thinking-checkpoint.d.ts +37 -0
  94. package/dist/hooks/thinking-checkpoint.js +51 -0
  95. package/dist/http/principles-console-route.js +13 -3
  96. package/dist/i18n/commands.js +8 -8
  97. package/dist/index.js +129 -28
  98. package/dist/service/central-database.js +2 -1
  99. package/dist/service/control-ui-query-service.d.ts +1 -1
  100. package/dist/service/control-ui-query-service.js +3 -3
  101. package/dist/service/evolution-query-service.d.ts +1 -1
  102. package/dist/service/evolution-query-service.js +5 -5
  103. package/dist/service/evolution-worker.d.ts +52 -4
  104. package/dist/service/evolution-worker.js +328 -16
  105. package/dist/service/nocturnal-runtime.d.ts +183 -0
  106. package/dist/service/nocturnal-runtime.js +352 -0
  107. package/dist/service/nocturnal-service.d.ts +163 -0
  108. package/dist/service/nocturnal-service.js +787 -0
  109. package/dist/service/nocturnal-target-selector.d.ts +145 -0
  110. package/dist/service/nocturnal-target-selector.js +315 -0
  111. package/dist/service/phase3-input-filter.d.ts +48 -12
  112. package/dist/service/phase3-input-filter.js +84 -18
  113. package/dist/service/runtime-summary-service.d.ts +34 -10
  114. package/dist/service/runtime-summary-service.js +87 -48
  115. package/dist/tools/deep-reflect.js +2 -1
  116. package/dist/types/event-types.d.ts +4 -10
  117. package/dist/types/runtime-summary.d.ts +47 -0
  118. package/dist/types/runtime-summary.js +1 -0
  119. package/dist/types.d.ts +0 -3
  120. package/dist/types.js +0 -2
  121. package/openclaw.plugin.json +1 -1
  122. package/package.json +1 -1
  123. package/templates/langs/en/skills/pd-mentor/SKILL.md +5 -5
  124. package/templates/langs/zh/skills/pd-mentor/SKILL.md +5 -5
  125. package/templates/pain_settings.json +0 -6
  126. package/dist/commands/trust.d.ts +0 -4
  127. package/dist/commands/trust.js +0 -78
  128. package/dist/core/trust-engine.d.ts +0 -96
  129. 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
- export function evaluatePhase3Inputs(queue, trust) {
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 (!status) {
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
- const trustRejectedReasons = [];
83
- const score = typeof trust.score === 'number' && Number.isFinite(trust.score) ? trust.score : null;
84
- if (trust.frozen !== true) {
85
- trustRejectedReasons.push('legacy_or_unfrozen_trust_schema');
86
- }
87
- if (score === null) {
88
- trustRejectedReasons.push('missing_trust_score');
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
- trustRejectedReasons: string[];
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 dailyGfiPeak = dailyStats?.[today]?.gfi?.peak;
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 legacyTrust = this.readLegacyTrust(resolvePdPath(workspaceDir, 'AGENT_SCORECARD'), wctx, warnings);
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
- trustRejectedReasons: phase3Inputs.trust.rejectedReasons,
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' | 'trust_change' | 'empathy_rollback' | 'error' | 'warn';
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' | 'plan_approved' | 'whitelisted';
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,
@@ -2,7 +2,7 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
5
- "version": "1.7.4",
5
+ "version": "1.7.8",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "1.7.5",
3
+ "version": "1.7.8",
4
4
  "description": "Native OpenClaw plugin for Principles Disciple",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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-trust` | View trust score and security stage | Permission check |
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-trust` - View current trust score
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-trust` - View trust score and security stage
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 trust score calculated?**
211
- A: Based on successful operations accumulating points, failed operations deducting points. Reaching thresholds automatically upgrades security stage, unlocking more permissions.
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.