create-principles-disciple 1.89.0 → 1.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/console/dist/ui/api.d.ts +2 -1
  2. package/console/dist/ui/api.js +7 -1
  3. package/console/dist/ui/i18n/en.json +18 -1
  4. package/console/dist/ui/i18n/zh-CN.json +18 -1
  5. package/console/dist/ui/pages/focus/FocusPage.js +48 -4
  6. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +70 -2
  7. package/console/dist/web/assets/app.js +1541 -1223
  8. package/console/package.json +1 -1
  9. package/core/dist/prompt-builder/__tests__/routing-guidance.test.d.ts +1 -2
  10. package/core/dist/prompt-builder/__tests__/routing-guidance.test.d.ts.map +1 -1
  11. package/core/dist/prompt-builder/__tests__/routing-guidance.test.js +1 -2
  12. package/core/dist/prompt-builder/__tests__/routing-guidance.test.js.map +1 -1
  13. package/core/dist/prompt-builder/routing-guidance.d.ts +0 -1
  14. package/core/dist/prompt-builder/routing-guidance.d.ts.map +1 -1
  15. package/core/dist/prompt-builder/routing-guidance.js +0 -1
  16. package/core/dist/prompt-builder/routing-guidance.js.map +1 -1
  17. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +5 -43
  18. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  19. package/core/dist/runtime-v2/adapter/__tests__/pi-ai-runtime-adapter.test.js +205 -2
  20. package/core/dist/runtime-v2/adapter/__tests__/pi-ai-runtime-adapter.test.js.map +1 -1
  21. package/core/dist/runtime-v2/adapter/__tests__/schema-prompt-adapter.test.js +17 -1
  22. package/core/dist/runtime-v2/adapter/__tests__/schema-prompt-adapter.test.js.map +1 -1
  23. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts +4 -1
  24. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts.map +1 -1
  25. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +6 -3
  26. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
  27. package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.d.ts +20 -7
  28. package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.d.ts.map +1 -1
  29. package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.js +19 -3
  30. package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.js.map +1 -1
  31. package/core/dist/runtime-v2/feature-flags/__tests__/plugin-surface-registry.test.js +3 -3
  32. package/core/dist/runtime-v2/feature-flags/__tests__/plugin-surface-registry.test.js.map +1 -1
  33. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.d.ts.map +1 -1
  34. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js +0 -18
  35. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js.map +1 -1
  36. package/package.json +1 -1
  37. package/plugin/dist/hooks/prompt.js +4 -5
  38. package/plugin/dist/index.js +0 -83
  39. package/plugin/package.json +1 -1
  40. package/plugin/dist/core/local-worker-routing.d.ts +0 -124
  41. package/plugin/dist/core/local-worker-routing.js +0 -216
  42. package/plugin/dist/core/model-deployment-registry.d.ts +0 -218
  43. package/plugin/dist/core/model-deployment-registry.js +0 -502
  44. package/plugin/dist/core/model-training-registry.d.ts +0 -295
  45. package/plugin/dist/core/model-training-registry.js +0 -474
  46. package/plugin/dist/core/promotion-gate.d.ts +0 -243
  47. package/plugin/dist/core/promotion-gate.js +0 -554
  48. package/plugin/dist/core/shadow-observation-registry.d.ts +0 -217
  49. package/plugin/dist/core/shadow-observation-registry.js +0 -280
  50. package/plugin/dist/utils/shadow-fingerprint.d.ts +0 -16
  51. package/plugin/dist/utils/shadow-fingerprint.js +0 -34
@@ -1,217 +0,0 @@
1
- /**
2
- * Shadow Observation Registry — Runtime Shadow Evidence for Promotion Gate
3
- * =======================================================================
4
- *
5
- * PURPOSE: Track real-world runtime evidence from shadow deployments to inform
6
- * promotion gate decisions. Real evidence replaces eval verdict proxies.
7
- *
8
- * ARCHITECTURE:
9
- * - Shadow observations are recorded by the routing system when a checkpoint
10
- * is routed in shadow mode
11
- * - Each observation captures whether the routing decision was accepted,
12
- * rejected, or escalated by the runtime
13
- * - The promotion gate queries this registry to get real arbiter/executability
14
- * reject rates instead of using eval verdict as a proxy
15
- *
16
- * SHADOW OBSERVATION LIFECYCLE:
17
- * 1. Routing system routes task to shadow checkpoint (shadow_ready state)
18
- * 2. Observation recorded: { checkpointId, taskFingerprint, routedAt }
19
- * 3. Task completes or times out
20
- * 4. Observation updated: { completedAt, accepted/rejected/escalated, failureSignals }
21
- * 5. After sufficient observations, promotion gate can query real reject rates
22
- *
23
- * DATA RETENTION:
24
- * - Observations are kept for 7 days by default
25
- * - Can be queried by checkpointId, time window, or outcome
26
- *
27
- * DESIGN CONSTRAINTS:
28
- * - Fail-closed: if no shadow evidence exists, fall back to eval proxies
29
- * - Shadow evidence must be statistically significant (min sample size)
30
- * - Observations are retained until cleanup removes expired entries
31
- */
32
- /**
33
- * Default observation retention period in milliseconds.
34
- * 7 days
35
- */
36
- export declare const DEFAULT_RETENTION_MS: number;
37
- /**
38
- * Minimum number of shadow observations required before trusting the evidence.
39
- * Below this, we fall back to eval proxies.
40
- */
41
- export declare const MIN_OBSERVATIONS_FOR_TRUST = 5;
42
- /**
43
- * Time window for computing recent reject rates.
44
- * Only observations within this window are considered.
45
- * 24 hours
46
- */
47
- export declare const RECENT_WINDOW_MS: number;
48
- /**
49
- * Outcome of a shadow routing observation.
50
- */
51
- export type ShadowOutcome = 'accepted' | 'rejected' | 'escalated';
52
- /**
53
- * Runtime failure signals captured during shadow routing.
54
- */
55
- export interface RuntimeFailureSignals {
56
- /** Whether the task timed out */
57
- timedOut: boolean;
58
- /** Whether an exception was thrown */
59
- threwException: boolean;
60
- /** Whether the output was empty or invalid */
61
- invalidOutput: boolean;
62
- /** Whether the worker profile rejected the routing */
63
- profileRejected: boolean;
64
- /** Additional failure signals (free-form for extensibility) */
65
- extra: Record<string, boolean>;
66
- }
67
- /**
68
- * A shadow observation — records a single shadow routing event.
69
- */
70
- export interface ShadowObservation {
71
- /** Unique identifier for this observation */
72
- observationId: string;
73
- /** Checkpoint being routed to in shadow mode */
74
- checkpointId: string;
75
- /** Worker profile this observation is for */
76
- workerProfile: string;
77
- /** Task fingerprint (hash of task input for deduplication) */
78
- taskFingerprint: string;
79
- /** ISO-8601 timestamp when routing decision was made */
80
- routedAt: string;
81
- /** ISO-8601 timestamp when task completed (null if still pending) */
82
- completedAt?: string;
83
- /** Outcome of the shadow routing */
84
- outcome?: ShadowOutcome;
85
- /** Runtime failure signals (null if still pending) */
86
- failureSignals?: RuntimeFailureSignals;
87
- /** Whether this observation was used in a promotion gate evaluation */
88
- usedInGate?: boolean;
89
- }
90
- /**
91
- * Computed statistics from shadow observations.
92
- */
93
- export interface ShadowStats {
94
- /** Checkpoint ID these stats are for */
95
- checkpointId: string;
96
- /** Total observations in the time window */
97
- totalCount: number;
98
- /** Count by outcome */
99
- acceptedCount: number;
100
- rejectedCount: number;
101
- escalatedCount: number;
102
- /** Computed rates */
103
- rejectRate: number;
104
- escalationRate: number;
105
- acceptanceRate: number;
106
- /** Failure signal frequencies */
107
- timedOutRate: number;
108
- threwExceptionRate: number;
109
- invalidOutputRate: number;
110
- profileRejectedRate: number;
111
- /** Whether this has enough data to trust */
112
- isStatisticallySignificant: boolean;
113
- /** Time window used for computation */
114
- windowStart: string;
115
- windowEnd: string;
116
- }
117
- /**
118
- * The complete shadow registry.
119
- */
120
- export interface ShadowRegistry {
121
- observations: ShadowObservation[];
122
- /** Schema version for migration support */
123
- version: number;
124
- }
125
- /**
126
- * Parameters for recording a shadow routing observation.
127
- */
128
- export interface RecordObservationParams {
129
- /** Checkpoint being routed to in shadow mode */
130
- checkpointId: string;
131
- /** Worker profile */
132
- workerProfile: string;
133
- /** Task fingerprint for deduplication */
134
- taskFingerprint: string;
135
- /** ISO-8601 timestamp when routing decision was made */
136
- routedAt?: string;
137
- }
138
- /**
139
- * Record a new shadow observation (when task is routed to shadow checkpoint).
140
- *
141
- * @param stateDir - Workspace state directory
142
- * @param params - Observation parameters
143
- * @returns The created ShadowObservation
144
- */
145
- export declare function recordShadowRouting(stateDir: string, params: RecordObservationParams): ShadowObservation;
146
- /**
147
- * Parameters for completing a shadow observation.
148
- */
149
- export interface CompleteObservationParams {
150
- /** Observation ID to complete */
151
- observationId: string;
152
- /** Outcome of the shadow routing */
153
- outcome: ShadowOutcome;
154
- /** Runtime failure signals */
155
- failureSignals?: RuntimeFailureSignals;
156
- }
157
- /**
158
- * Complete a pending shadow observation (when task finishes).
159
- *
160
- * @param stateDir - Workspace state directory
161
- * @param params - Completion parameters
162
- * @returns The updated ShadowObservation, or null if not found
163
- */
164
- export declare function completeShadowObservation(stateDir: string, params: CompleteObservationParams): ShadowObservation | null;
165
- /**
166
- * Complete a shadow observation by task fingerprint (alternative lookup).
167
- *
168
- * @param stateDir - Workspace state directory
169
- * @param taskFingerprint - Task fingerprint to look up
170
- * @param outcome - Outcome of the shadow routing
171
- * @param failureSignals - Runtime failure signals
172
- * @returns The updated ShadowObservation, or null if not found
173
- */
174
- export declare function completeShadowObservationByTask(stateDir: string, taskFingerprint: string, outcome: ShadowOutcome, failureSignals?: RuntimeFailureSignals): ShadowObservation | null;
175
- /**
176
- * Parameters for computing shadow statistics.
177
- */
178
- export interface ComputeShadowStatsParams {
179
- /** Checkpoint ID to compute stats for */
180
- checkpointId: string;
181
- /** Time window in milliseconds (default: RECENT_WINDOW_MS) */
182
- windowMs?: number;
183
- /** Retention period in milliseconds (default: DEFAULT_RETENTION_MS) */
184
- retentionMs?: number;
185
- }
186
- /**
187
- * Compute shadow routing statistics for a checkpoint.
188
- *
189
- * @param stateDir - Workspace state directory
190
- * @param params - Computation parameters
191
- * @returns ShadowStats with computed rates, or null if not enough data
192
- */
193
- export declare function computeShadowStats(stateDir: string, params: ComputeShadowStatsParams): ShadowStats | null;
194
- /**
195
- * Query shadow observations for a checkpoint.
196
- *
197
- * @param stateDir - Workspace state directory
198
- * @param checkpointId - Checkpoint ID to query
199
- * @param limit - Maximum observations to return (default: 100)
200
- * @returns Array of shadow observations
201
- */
202
- export declare function queryShadowObservations(stateDir: string, checkpointId: string, limit?: number): ShadowObservation[];
203
- /**
204
- * Mark observations as used in a promotion gate evaluation.
205
- *
206
- * @param stateDir - Workspace state directory
207
- * @param observationIds - IDs of observations to mark
208
- */
209
- export declare function markObservationsUsedInGate(stateDir: string, observationIds: string[]): void;
210
- /**
211
- * Clean up expired observations (older than retention period).
212
- *
213
- * @param stateDir - Workspace state directory
214
- * @param retentionMs - Retention period in milliseconds (default: DEFAULT_RETENTION_MS)
215
- * @returns Number of observations removed
216
- */
217
- export declare function cleanupExpiredObservations(stateDir: string, retentionMs?: number): number;
@@ -1,280 +0,0 @@
1
- /**
2
- * Shadow Observation Registry — Runtime Shadow Evidence for Promotion Gate
3
- * =======================================================================
4
- *
5
- * PURPOSE: Track real-world runtime evidence from shadow deployments to inform
6
- * promotion gate decisions. Real evidence replaces eval verdict proxies.
7
- *
8
- * ARCHITECTURE:
9
- * - Shadow observations are recorded by the routing system when a checkpoint
10
- * is routed in shadow mode
11
- * - Each observation captures whether the routing decision was accepted,
12
- * rejected, or escalated by the runtime
13
- * - The promotion gate queries this registry to get real arbiter/executability
14
- * reject rates instead of using eval verdict as a proxy
15
- *
16
- * SHADOW OBSERVATION LIFECYCLE:
17
- * 1. Routing system routes task to shadow checkpoint (shadow_ready state)
18
- * 2. Observation recorded: { checkpointId, taskFingerprint, routedAt }
19
- * 3. Task completes or times out
20
- * 4. Observation updated: { completedAt, accepted/rejected/escalated, failureSignals }
21
- * 5. After sufficient observations, promotion gate can query real reject rates
22
- *
23
- * DATA RETENTION:
24
- * - Observations are kept for 7 days by default
25
- * - Can be queried by checkpointId, time window, or outcome
26
- *
27
- * DESIGN CONSTRAINTS:
28
- * - Fail-closed: if no shadow evidence exists, fall back to eval proxies
29
- * - Shadow evidence must be statistically significant (min sample size)
30
- * - Observations are retained until cleanup removes expired entries
31
- */
32
- import * as path from 'path';
33
- import * as crypto from 'crypto';
34
- import { withLock } from '../utils/file-lock.js';
35
- import { JsonFileStore } from './file-store.js';
36
- // ---------------------------------------------------------------------------
37
- // Constants
38
- // ---------------------------------------------------------------------------
39
- /**
40
- * Registry file for shadow observations.
41
- */
42
- const SHADOW_REGISTRY_FILE = 'shadow-registry.json';
43
- /**
44
- * Default observation retention period in milliseconds.
45
- * 7 days
46
- */
47
- export const DEFAULT_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
48
- /**
49
- * Minimum number of shadow observations required before trusting the evidence.
50
- * Below this, we fall back to eval proxies.
51
- */
52
- export const MIN_OBSERVATIONS_FOR_TRUST = 5;
53
- /**
54
- * Time window for computing recent reject rates.
55
- * Only observations within this window are considered.
56
- * 24 hours
57
- */
58
- export const RECENT_WINDOW_MS = 24 * 60 * 60 * 1000;
59
- // ---------------------------------------------------------------------------
60
- // Registry Path & Store
61
- // ---------------------------------------------------------------------------
62
- let _store = new Map();
63
- function getRegistryPath(stateDir) {
64
- return path.join(stateDir, SHADOW_REGISTRY_FILE);
65
- }
66
- function getStore(stateDir) {
67
- let store = _store.get(stateDir);
68
- if (!store) {
69
- const filePath = path.join(stateDir, SHADOW_REGISTRY_FILE);
70
- store = new JsonFileStore(filePath, () => ({ observations: [], version: 1 }));
71
- _store.set(stateDir, store);
72
- }
73
- return store;
74
- }
75
- // ---------------------------------------------------------------------------
76
- // File Operations
77
- // ---------------------------------------------------------------------------
78
- /**
79
- * Execute a read-modify-write under an exclusive file lock.
80
- */
81
- function withShadowRegistryLock(stateDir, fn) {
82
- const store = getStore(stateDir);
83
- const filePath = getRegistryPath(stateDir);
84
- // Re-create lock behavior using the store's mutate under a simple fs-based lock
85
- return withLock(filePath, () => {
86
- const registry = store.load();
87
- const result = fn(registry);
88
- store.save(registry);
89
- return result;
90
- });
91
- }
92
- /**
93
- * Record a new shadow observation (when task is routed to shadow checkpoint).
94
- *
95
- * @param stateDir - Workspace state directory
96
- * @param params - Observation parameters
97
- * @returns The created ShadowObservation
98
- */
99
- export function recordShadowRouting(stateDir, params) {
100
- const observation = {
101
- observationId: crypto.randomUUID(),
102
- checkpointId: params.checkpointId,
103
- workerProfile: params.workerProfile,
104
- taskFingerprint: params.taskFingerprint,
105
- routedAt: params.routedAt ?? new Date().toISOString(),
106
- };
107
- return withShadowRegistryLock(stateDir, (registry) => {
108
- registry.observations.push(observation);
109
- return observation;
110
- });
111
- }
112
- /**
113
- * Complete a pending shadow observation (when task finishes).
114
- *
115
- * @param stateDir - Workspace state directory
116
- * @param params - Completion parameters
117
- * @returns The updated ShadowObservation, or null if not found
118
- */
119
- export function completeShadowObservation(stateDir, params) {
120
- return withShadowRegistryLock(stateDir, (registry) => {
121
- const idx = registry.observations.findIndex((o) => o.observationId === params.observationId);
122
- if (idx === -1) {
123
- return null;
124
- }
125
- const observation = registry.observations[idx];
126
- observation.completedAt = new Date().toISOString();
127
- observation.outcome = params.outcome;
128
- observation.failureSignals = params.failureSignals ?? {
129
- timedOut: false,
130
- threwException: false,
131
- invalidOutput: false,
132
- profileRejected: false,
133
- extra: {},
134
- };
135
- return observation;
136
- });
137
- }
138
- /**
139
- * Complete a shadow observation by task fingerprint (alternative lookup).
140
- *
141
- * @param stateDir - Workspace state directory
142
- * @param taskFingerprint - Task fingerprint to look up
143
- * @param outcome - Outcome of the shadow routing
144
- * @param failureSignals - Runtime failure signals
145
- * @returns The updated ShadowObservation, or null if not found
146
- */
147
- export function completeShadowObservationByTask(stateDir, taskFingerprint, outcome, failureSignals) {
148
- return withShadowRegistryLock(stateDir, (registry) => {
149
- // Find the oldest pending observation for this task
150
- const pendingObs = registry.observations
151
- .filter((o) => o.taskFingerprint === taskFingerprint && !o.completedAt)
152
- .sort((a, b) => a.routedAt.localeCompare(b.routedAt));
153
- if (pendingObs.length === 0) {
154
- return null;
155
- }
156
- const [observation] = pendingObs;
157
- observation.completedAt = new Date().toISOString();
158
- observation.outcome = outcome;
159
- observation.failureSignals = failureSignals ?? {
160
- timedOut: false,
161
- threwException: false,
162
- invalidOutput: false,
163
- profileRejected: false,
164
- extra: {},
165
- };
166
- return observation;
167
- });
168
- }
169
- /**
170
- * Compute shadow routing statistics for a checkpoint.
171
- *
172
- * @param stateDir - Workspace state directory
173
- * @param params - Computation parameters
174
- * @returns ShadowStats with computed rates, or null if not enough data
175
- */
176
- export function computeShadowStats(stateDir, params) {
177
- const { checkpointId, windowMs = RECENT_WINDOW_MS, retentionMs = DEFAULT_RETENTION_MS, } = params;
178
- const now = Date.now();
179
- const windowStart = new Date(now - windowMs).toISOString();
180
- const windowEnd = new Date(now).toISOString();
181
- return withShadowRegistryLock(stateDir, (registry) => {
182
- // Filter observations:
183
- // 1. For this checkpoint
184
- // 2. Within the time window
185
- // 3. Not expired (within retention period)
186
- const cutoff = new Date(now - retentionMs).toISOString();
187
- const relevantObs = registry.observations.filter((o) => {
188
- if (o.checkpointId !== checkpointId)
189
- return false;
190
- if (o.routedAt < cutoff)
191
- return false; // expired
192
- if (o.routedAt < windowStart)
193
- return false; // outside window
194
- if (!o.completedAt)
195
- return false; // still pending
196
- return true;
197
- });
198
- const totalCount = relevantObs.length;
199
- // Not enough data - fail closed (return null to use eval proxies)
200
- if (totalCount < MIN_OBSERVATIONS_FOR_TRUST) {
201
- return null;
202
- }
203
- const acceptedCount = relevantObs.filter((o) => o.outcome === 'accepted').length;
204
- const rejectedCount = relevantObs.filter((o) => o.outcome === 'rejected').length;
205
- const escalatedCount = relevantObs.filter((o) => o.outcome === 'escalated').length;
206
- // Failure signal counts
207
- const withTimedOut = relevantObs.filter((o) => o.failureSignals?.timedOut).length;
208
- const withThrewException = relevantObs.filter((o) => o.failureSignals?.threwException).length;
209
- const withInvalidOutput = relevantObs.filter((o) => o.failureSignals?.invalidOutput).length;
210
- const withProfileRejected = relevantObs.filter((o) => o.failureSignals?.profileRejected).length;
211
- const rejectRate = totalCount > 0 ? rejectedCount / totalCount : 0;
212
- const escalationRate = totalCount > 0 ? escalatedCount / totalCount : 0;
213
- const acceptanceRate = totalCount > 0 ? acceptedCount / totalCount : 0;
214
- return {
215
- checkpointId,
216
- totalCount,
217
- acceptedCount,
218
- rejectedCount,
219
- escalatedCount,
220
- rejectRate: Math.round(rejectRate * 1000) / 1000,
221
- escalationRate: Math.round(escalationRate * 1000) / 1000,
222
- acceptanceRate: Math.round(acceptanceRate * 1000) / 1000,
223
- timedOutRate: Math.round((withTimedOut / totalCount) * 1000) / 1000,
224
- threwExceptionRate: Math.round((withThrewException / totalCount) * 1000) / 1000,
225
- invalidOutputRate: Math.round((withInvalidOutput / totalCount) * 1000) / 1000,
226
- profileRejectedRate: Math.round((withProfileRejected / totalCount) * 1000) / 1000,
227
- isStatisticallySignificant: totalCount >= MIN_OBSERVATIONS_FOR_TRUST,
228
- windowStart,
229
- windowEnd,
230
- };
231
- });
232
- }
233
- /**
234
- * Query shadow observations for a checkpoint.
235
- *
236
- * @param stateDir - Workspace state directory
237
- * @param checkpointId - Checkpoint ID to query
238
- * @param limit - Maximum observations to return (default: 100)
239
- * @returns Array of shadow observations
240
- */
241
- export function queryShadowObservations(stateDir, checkpointId, limit = 100) {
242
- return withShadowRegistryLock(stateDir, (registry) => {
243
- return registry.observations
244
- .filter((o) => o.checkpointId === checkpointId)
245
- .sort((a, b) => b.routedAt.localeCompare(a.routedAt)) // newest first
246
- .slice(0, limit);
247
- });
248
- }
249
- /**
250
- * Mark observations as used in a promotion gate evaluation.
251
- *
252
- * @param stateDir - Workspace state directory
253
- * @param observationIds - IDs of observations to mark
254
- */
255
- export function markObservationsUsedInGate(stateDir, observationIds) {
256
- withShadowRegistryLock(stateDir, (registry) => {
257
- for (const obs of registry.observations) {
258
- if (observationIds.includes(obs.observationId)) {
259
- obs.usedInGate = true;
260
- }
261
- }
262
- });
263
- }
264
- /**
265
- * Clean up expired observations (older than retention period).
266
- *
267
- * @param stateDir - Workspace state directory
268
- * @param retentionMs - Retention period in milliseconds (default: DEFAULT_RETENTION_MS)
269
- * @returns Number of observations removed
270
- */
271
- export function cleanupExpiredObservations(stateDir, retentionMs = DEFAULT_RETENTION_MS) {
272
- const cutoff = new Date(Date.now() - retentionMs).toISOString();
273
- let removed = 0;
274
- withShadowRegistryLock(stateDir, (registry) => {
275
- const before = registry.observations.length;
276
- registry.observations = registry.observations.filter((o) => o.routedAt >= cutoff);
277
- removed = before - registry.observations.length;
278
- });
279
- return removed;
280
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Shadow Observation Fingerprint Utilities
3
- *
4
- * Computes fingerprints for shadow task routing and tracking.
5
- */
6
- import type { PluginHookSubagentSpawningEvent } from '../openclaw-sdk.js';
7
- export declare const PD_LOCAL_PROFILES: ReadonlySet<string>;
8
- /**
9
- * Check if a profile is a local PD profile.
10
- */
11
- export declare function isLocalProfile(profile: string): boolean;
12
- /**
13
- * Compute a fingerprint for runtime shadow task tracking.
14
- * Used to correlate shadow routing decisions with subagent lifecycle events.
15
- */
16
- export declare function computeRuntimeShadowTaskFingerprint(event: PluginHookSubagentSpawningEvent): string;
@@ -1,34 +0,0 @@
1
- /**
2
- * Shadow Observation Fingerprint Utilities
3
- *
4
- * Computes fingerprints for shadow task routing and tracking.
5
- */
6
- import * as crypto from 'crypto';
7
- /**
8
- * PD local worker profiles that are managed by the shadow routing policy.
9
- */
10
- const _pdLocalProfiles = new Set(['local-reader', 'local-editor']);
11
- export const PD_LOCAL_PROFILES = _pdLocalProfiles;
12
- /**
13
- * Check if a profile is a local PD profile.
14
- */
15
- export function isLocalProfile(profile) {
16
- return _pdLocalProfiles.has(profile);
17
- }
18
- const RUNTIME_SHADOW_FINGERPRINT_HEX_LENGTH = 16;
19
- /**
20
- * Compute a fingerprint for runtime shadow task tracking.
21
- * Used to correlate shadow routing decisions with subagent lifecycle events.
22
- */
23
- export function computeRuntimeShadowTaskFingerprint(event) {
24
- const payload = {
25
- childSessionKey: event.childSessionKey,
26
- agentId: event.agentId,
27
- label: event.label ?? '',
28
- mode: event.mode,
29
- threadRequested: event.threadRequested,
30
- requesterChannel: event.requester?.channel ?? '',
31
- requesterThreadId: event.requester?.threadId ?? '',
32
- };
33
- return crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex').slice(0, RUNTIME_SHADOW_FINGERPRINT_HEX_LENGTH);
34
- }