@openclawbrain/cli 0.4.25 → 0.4.27
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/src/cli.js +199 -14
- package/dist/src/daemon.d.ts +2 -0
- package/dist/src/daemon.js +19 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +9 -3
- package/dist/src/learning-spine.d.ts +2 -1
- package/dist/src/local-learner.d.ts +17 -1
- package/dist/src/local-learner.js +109 -13
- package/dist/src/openclaw-hook-truth.d.ts +22 -0
- package/dist/src/openclaw-hook-truth.js +117 -0
- package/dist/src/proof-command.js +43 -4
- package/dist/src/status-learning-path.js +130 -0
- package/dist/src/teacher-labeler.d.ts +1 -1
- package/dist/src/teacher-labeler.js +4 -1
- package/dist/src/traced-learning-bridge.js +165 -2
- package/package.json +1 -1
|
@@ -7,10 +7,123 @@ function isSeedAwaitingFirstPromotion(status) {
|
|
|
7
7
|
function normalizeOptionalString(value) {
|
|
8
8
|
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
9
9
|
}
|
|
10
|
+
function normalizeCount(value) {
|
|
11
|
+
return Number.isFinite(value) && value >= 0 ? Math.trunc(value) : 0;
|
|
12
|
+
}
|
|
10
13
|
function formatOptionalFeedbackLatest(tracedLearning) {
|
|
11
14
|
const latestLabel = normalizeOptionalString(tracedLearning?.feedbackSummary?.latestLabel);
|
|
12
15
|
return latestLabel === null ? "" : ` latest=${latestLabel}`;
|
|
13
16
|
}
|
|
17
|
+
function isLearningSurfaceVisible(tracedLearning) {
|
|
18
|
+
return tracedLearning?.present !== false;
|
|
19
|
+
}
|
|
20
|
+
function hasKnownAttributionCoverage(coverage) {
|
|
21
|
+
return coverage !== null &&
|
|
22
|
+
typeof coverage === "object" &&
|
|
23
|
+
!Array.isArray(coverage) &&
|
|
24
|
+
(coverage.visible === true ||
|
|
25
|
+
coverage.gatingVisible === true ||
|
|
26
|
+
Number.isFinite(coverage.completedWithoutEvaluationCount) ||
|
|
27
|
+
Number.isFinite(coverage.readyCount) ||
|
|
28
|
+
Number.isFinite(coverage.delayedCount) ||
|
|
29
|
+
Number.isFinite(coverage.budgetDeferredCount));
|
|
30
|
+
}
|
|
31
|
+
function readSupervisedTraceCount(tracedLearning) {
|
|
32
|
+
return normalizeCount(tracedLearning?.feedbackSummary?.supervisedTraceCount ?? tracedLearning?.supervisionCount);
|
|
33
|
+
}
|
|
34
|
+
function hasLoadedLearningSignal(tracedLearning) {
|
|
35
|
+
return normalizeOptionalString(tracedLearning?.materializedPackId) !== null ||
|
|
36
|
+
normalizeCount(tracedLearning?.routeTraceCount) > 0 ||
|
|
37
|
+
readSupervisedTraceCount(tracedLearning) > 0 ||
|
|
38
|
+
normalizeCount(tracedLearning?.routerUpdateCount) > 0;
|
|
39
|
+
}
|
|
40
|
+
function summarizeOperatorLearningFlow(tracedLearning) {
|
|
41
|
+
const surfaceVisible = isLearningSurfaceVisible(tracedLearning);
|
|
42
|
+
return {
|
|
43
|
+
harvested: surfaceVisible ? normalizeCount(tracedLearning?.teacherArtifactCount) : null,
|
|
44
|
+
eligible: hasKnownAttributionCoverage(tracedLearning?.attributionCoverage)
|
|
45
|
+
? normalizeCount(tracedLearning?.attributionCoverage?.readyCount)
|
|
46
|
+
: null,
|
|
47
|
+
loaded: surfaceVisible ? hasLoadedLearningSignal(tracedLearning) : null,
|
|
48
|
+
pack: surfaceVisible ? normalizeOptionalString(tracedLearning?.materializedPackId) ?? "none" : null,
|
|
49
|
+
matched: surfaceVisible ? normalizeCount(tracedLearning?.routeTraceCount) : null,
|
|
50
|
+
supervised: surfaceVisible ? readSupervisedTraceCount(tracedLearning) : null,
|
|
51
|
+
updated: surfaceVisible ? normalizeCount(tracedLearning?.routerUpdateCount) : null
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function formatKnownOperatorValue(value) {
|
|
55
|
+
return value === null ? "unknown" : String(value);
|
|
56
|
+
}
|
|
57
|
+
function summarizeOperatorLearningState(flow) {
|
|
58
|
+
if (flow.harvested === null &&
|
|
59
|
+
flow.eligible === null &&
|
|
60
|
+
flow.loaded === null &&
|
|
61
|
+
flow.matched === null &&
|
|
62
|
+
flow.supervised === null &&
|
|
63
|
+
flow.updated === null) {
|
|
64
|
+
return {
|
|
65
|
+
state: "learning-unknown",
|
|
66
|
+
detail: "learning stage truth is not visible in the current status surface"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (flow.harvested > 0 &&
|
|
70
|
+
flow.eligible !== null &&
|
|
71
|
+
flow.eligible > 0 &&
|
|
72
|
+
flow.matched === 0 &&
|
|
73
|
+
flow.supervised === 0 &&
|
|
74
|
+
flow.updated === 0) {
|
|
75
|
+
return {
|
|
76
|
+
state: "stalled-learning",
|
|
77
|
+
detail: "harvested artifacts and eligible feedback are visible, but no matched routes, supervision, or router updates are visible"
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if ((flow.matched ?? 0) > 0 || (flow.supervised ?? 0) > 0 || (flow.updated ?? 0) > 0) {
|
|
81
|
+
return {
|
|
82
|
+
state: "progress-visible",
|
|
83
|
+
detail: `matched=${flow.matched ?? 0} supervised=${flow.supervised ?? 0} updated=${flow.updated ?? 0}`
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (flow.harvested > 0 && flow.eligible === 0) {
|
|
87
|
+
return {
|
|
88
|
+
state: "harvested-not-yet-eligible",
|
|
89
|
+
detail: "teacher artifacts are visible, but no eligible feedback is queued yet"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (flow.harvested > 0 && flow.eligible === null) {
|
|
93
|
+
return {
|
|
94
|
+
state: "harvested-eligibility-unknown",
|
|
95
|
+
detail: "teacher artifacts are visible, but eligible feedback truth is not surfaced yet"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (flow.harvested === 0 && flow.eligible !== null && flow.eligible > 0) {
|
|
99
|
+
return {
|
|
100
|
+
state: "eligible-without-harvest",
|
|
101
|
+
detail: "eligible feedback is visible without harvested teacher artifacts"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (flow.harvested === 0 && flow.eligible === 0) {
|
|
105
|
+
return {
|
|
106
|
+
state: "idle-no-eligible-feedback",
|
|
107
|
+
detail: "no harvested teacher artifacts or eligible feedback are visible"
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
state: "learning-unknown",
|
|
112
|
+
detail: "learning stage truth is incomplete"
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function summarizeOperatorDaemonState(teacher) {
|
|
116
|
+
if (teacher?.enabled !== true) {
|
|
117
|
+
return "daemon-disabled";
|
|
118
|
+
}
|
|
119
|
+
if (teacher?.healthy === true) {
|
|
120
|
+
return "healthy-daemon";
|
|
121
|
+
}
|
|
122
|
+
if (teacher?.healthy === false) {
|
|
123
|
+
return "degraded-daemon";
|
|
124
|
+
}
|
|
125
|
+
return "daemon-unknown";
|
|
126
|
+
}
|
|
14
127
|
function formatOperatorFeedbackSummary({ tracedLearning }) {
|
|
15
128
|
const routeTraceCount = tracedLearning?.feedbackSummary?.routeTraceCount ?? tracedLearning?.routeTraceCount ?? 0;
|
|
16
129
|
const supervisedTraceCount = tracedLearning?.feedbackSummary?.supervisedTraceCount ?? tracedLearning?.supervisionCount ?? 0;
|
|
@@ -78,4 +191,21 @@ export function formatOperatorLearningPathSummary({ status, learningPath, traced
|
|
|
78
191
|
...detailParts
|
|
79
192
|
].join(" ");
|
|
80
193
|
}
|
|
194
|
+
export function formatOperatorLearningFlowSummary({ tracedLearning }) {
|
|
195
|
+
const flow = summarizeOperatorLearningFlow(tracedLearning);
|
|
196
|
+
return [
|
|
197
|
+
`harvested=${formatKnownOperatorValue(flow.harvested)}`,
|
|
198
|
+
`eligible=${formatKnownOperatorValue(flow.eligible)}`,
|
|
199
|
+
`loaded=${flow.loaded === null ? "unknown" : flow.loaded ? "yes" : "no"}`,
|
|
200
|
+
`pack=${flow.pack ?? "unknown"}`,
|
|
201
|
+
`matched=${formatKnownOperatorValue(flow.matched)}`,
|
|
202
|
+
`supervised=${formatKnownOperatorValue(flow.supervised)}`,
|
|
203
|
+
`updated=${formatKnownOperatorValue(flow.updated)}`
|
|
204
|
+
].join(" ");
|
|
205
|
+
}
|
|
206
|
+
export function formatOperatorLearningHealthSummary({ tracedLearning, teacher }) {
|
|
207
|
+
const flow = summarizeOperatorLearningFlow(tracedLearning);
|
|
208
|
+
const learning = summarizeOperatorLearningState(flow);
|
|
209
|
+
return `daemon=${summarizeOperatorDaemonState(teacher)} learning=${learning.state} detail=${learning.detail}`;
|
|
210
|
+
}
|
|
81
211
|
export { formatOperatorAttributionCoverageSummary, formatOperatorFeedbackSummary, formatOperatorLearningAttributionSummary };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type NormalizedEventExportV1, type TeacherSupervisionArtifactV1 } from "@openclawbrain/contracts";
|
|
2
|
-
import type { LearningSpineServeRouteDecisionLogEntryV1 } from "
|
|
2
|
+
import type { LearningSpineServeRouteDecisionLogEntryV1 } from "./local-learner.js";
|
|
3
3
|
export interface TeacherLabelerRunInputV1 {
|
|
4
4
|
normalizedEventExport: NormalizedEventExportV1;
|
|
5
5
|
observedAt: string;
|
|
@@ -141,11 +141,14 @@ function buildPrompt(candidates, config) {
|
|
|
141
141
|
payload
|
|
142
142
|
].join("\n");
|
|
143
143
|
}
|
|
144
|
+
function isTeacherLabelerCandidateInteraction(interaction) {
|
|
145
|
+
return interaction.kind === "memory_compiled" || interaction.kind === "message_delivered";
|
|
146
|
+
}
|
|
144
147
|
function collectCandidates(input, config) {
|
|
145
148
|
const decisions = [...(input.serveTimeDecisions ?? [])].sort((left, right) => Date.parse(right.recordedAt) - Date.parse(left.recordedAt));
|
|
146
149
|
const matchServeTimeDecision = createServeTimeDecisionMatcher(decisions);
|
|
147
150
|
return input.normalizedEventExport.interactionEvents
|
|
148
|
-
.filter((interaction) => interaction
|
|
151
|
+
.filter((interaction) => isTeacherLabelerCandidateInteraction(interaction))
|
|
149
152
|
.sort((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt))
|
|
150
153
|
.map((interaction) => {
|
|
151
154
|
const decision = matchServeTimeDecision(interaction);
|
|
@@ -258,6 +258,169 @@ function buildDerivedAttributionCoverage(db) {
|
|
|
258
258
|
: `completed_without_evaluation=${completedWithoutEvaluationCount}; ready=${readyCount}, delayed=${delayedCount}, budget_deferred=${budgetDeferredCount}`
|
|
259
259
|
};
|
|
260
260
|
}
|
|
261
|
+
function loadJsonFile(pathname) {
|
|
262
|
+
if (!existsSync(pathname)) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
return JSON.parse(readFileSync(pathname, "utf8"));
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function resolveActivePackPaths(activationRoot) {
|
|
273
|
+
const pointers = toRecord(loadJsonFile(path.join(path.resolve(activationRoot), "activation-pointers.json")));
|
|
274
|
+
const active = toRecord(pointers?.active);
|
|
275
|
+
const packRootDir = normalizeOptionalString(active?.packRootDir)
|
|
276
|
+
?? (normalizeOptionalString(active?.packId) === null
|
|
277
|
+
? null
|
|
278
|
+
: path.join(path.resolve(activationRoot), "packs", String(active.packId)));
|
|
279
|
+
const manifestPath = normalizeOptionalString(active?.manifestPath)
|
|
280
|
+
?? (packRootDir === null ? null : path.join(packRootDir, "manifest.json"));
|
|
281
|
+
return {
|
|
282
|
+
packRootDir,
|
|
283
|
+
manifestPath
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function buildActivePackFeedbackSummary(activationRoot) {
|
|
287
|
+
const active = resolveActivePackPaths(activationRoot);
|
|
288
|
+
if (active.packRootDir === null || active.manifestPath === null) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
const manifest = toRecord(loadJsonFile(active.manifestPath));
|
|
292
|
+
const runtimeAssets = toRecord(manifest?.runtimeAssets);
|
|
293
|
+
const router = toRecord(runtimeAssets?.router);
|
|
294
|
+
const routerArtifactPath = normalizeOptionalString(router?.artifactPath);
|
|
295
|
+
if (routerArtifactPath === null) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const routerPath = path.isAbsolute(routerArtifactPath)
|
|
299
|
+
? routerArtifactPath
|
|
300
|
+
: path.join(active.packRootDir, routerArtifactPath);
|
|
301
|
+
const routerArtifact = toRecord(loadJsonFile(routerPath));
|
|
302
|
+
const traces = Array.isArray(routerArtifact?.traces) ? routerArtifact.traces : [];
|
|
303
|
+
const verdictCounts = {
|
|
304
|
+
helpfulCount: 0,
|
|
305
|
+
irrelevantCount: 0,
|
|
306
|
+
harmfulCount: 0
|
|
307
|
+
};
|
|
308
|
+
for (const trace of traces) {
|
|
309
|
+
const traceRecord = toRecord(trace);
|
|
310
|
+
if (normalizeOptionalString(traceRecord?.supervisionKind) === "route_trace") {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const verdict = classifyContextFeedbackVerdict(Number(traceRecord?.reward ?? 0));
|
|
314
|
+
if (verdict === "helpful") {
|
|
315
|
+
verdictCounts.helpfulCount += 1;
|
|
316
|
+
}
|
|
317
|
+
else if (verdict === "harmful") {
|
|
318
|
+
verdictCounts.harmfulCount += 1;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
verdictCounts.irrelevantCount += 1;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const routeTraceCount = normalizeCount(routerArtifact?.training?.routeTraceCount) || traces.length;
|
|
325
|
+
const supervisedTraceCount = verdictCounts.helpfulCount + verdictCounts.irrelevantCount + verdictCounts.harmfulCount;
|
|
326
|
+
if (routeTraceCount === 0 && supervisedTraceCount === 0) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
visible: true,
|
|
331
|
+
...verdictCounts,
|
|
332
|
+
supervisedTraceCount,
|
|
333
|
+
routeTraceCount,
|
|
334
|
+
latestAgentIdentity: null,
|
|
335
|
+
latestLabel: null,
|
|
336
|
+
detail: routeTraceCount === 0
|
|
337
|
+
? "no active-pack traced routes are visible"
|
|
338
|
+
: `${verdictCounts.helpfulCount} helpful, ${verdictCounts.irrelevantCount} irrelevant, ${verdictCounts.harmfulCount} harmful; ${supervisedTraceCount}/${routeTraceCount} active-pack traced routes are supervised`
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function readIntegerNote(notes, prefix) {
|
|
342
|
+
if (!Array.isArray(notes)) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const entry = notes.find((candidate) => typeof candidate === "string" && candidate.startsWith(prefix));
|
|
346
|
+
if (typeof entry !== "string") {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
const parsed = Number.parseInt(entry.slice(prefix.length), 10);
|
|
350
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
351
|
+
}
|
|
352
|
+
function buildWatchSnapshotAttributionCoverage(activationRoot) {
|
|
353
|
+
const snapshot = toRecord(loadJsonFile(path.join(path.resolve(activationRoot), "watch", "teacher-snapshot.json")));
|
|
354
|
+
const notes = Array.isArray(snapshot?.notes)
|
|
355
|
+
? snapshot.notes
|
|
356
|
+
: Array.isArray(snapshot?.snapshot?.diagnostics?.notes)
|
|
357
|
+
? snapshot.snapshot.diagnostics.notes
|
|
358
|
+
: Array.isArray(snapshot?.diagnostics?.notes)
|
|
359
|
+
? snapshot.diagnostics.notes
|
|
360
|
+
: [];
|
|
361
|
+
const readyCount = readIntegerNote(notes, "teacher_feedback_eligible=");
|
|
362
|
+
const delayedCount = readIntegerNote(notes, "teacher_feedback_delayed=");
|
|
363
|
+
const budgetDeferredCount = readIntegerNote(notes, "teacher_feedback_budgeted_out=");
|
|
364
|
+
const budgetPerTick = readIntegerNote(notes, "teacher_budget=");
|
|
365
|
+
const delayMs = readIntegerNote(notes, "teacher_delay_ms=");
|
|
366
|
+
if (readyCount === null && delayedCount === null && budgetDeferredCount === null && budgetPerTick === null && delayMs === null) {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
visible: true,
|
|
371
|
+
gatingVisible: budgetPerTick !== null || delayMs !== null,
|
|
372
|
+
completedWithoutEvaluationCount: 0,
|
|
373
|
+
readyCount: normalizeCount(readyCount),
|
|
374
|
+
delayedCount: normalizeCount(delayedCount),
|
|
375
|
+
budgetDeferredCount: normalizeCount(budgetDeferredCount),
|
|
376
|
+
detail: `watch sparse-feedback queue: completed_without_evaluation=0, ready=${normalizeCount(readyCount)}, delayed=${normalizeCount(delayedCount)}, budget_deferred=${normalizeCount(budgetDeferredCount)}`
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function shouldPreferActivationFeedbackSummary(current, fallback) {
|
|
380
|
+
if (fallback === null) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
if (current.visible !== true) {
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
return normalizeCount(current.supervisedTraceCount) === 0 && normalizeCount(fallback.supervisedTraceCount) > 0;
|
|
387
|
+
}
|
|
388
|
+
function shouldPreferWatchAttributionCoverage(current, fallback) {
|
|
389
|
+
if (fallback === null) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
if (current.visible !== true || current.gatingVisible !== true) {
|
|
393
|
+
return normalizeCount(fallback.readyCount) > 0
|
|
394
|
+
|| normalizeCount(fallback.delayedCount) > 0
|
|
395
|
+
|| normalizeCount(fallback.budgetDeferredCount) > 0;
|
|
396
|
+
}
|
|
397
|
+
const currentKnown = normalizeCount(current.completedWithoutEvaluationCount)
|
|
398
|
+
+ normalizeCount(current.readyCount)
|
|
399
|
+
+ normalizeCount(current.delayedCount)
|
|
400
|
+
+ normalizeCount(current.budgetDeferredCount);
|
|
401
|
+
const fallbackKnown = normalizeCount(fallback.completedWithoutEvaluationCount)
|
|
402
|
+
+ normalizeCount(fallback.readyCount)
|
|
403
|
+
+ normalizeCount(fallback.delayedCount)
|
|
404
|
+
+ normalizeCount(fallback.budgetDeferredCount);
|
|
405
|
+
return currentKnown === 0 && fallbackKnown > 0;
|
|
406
|
+
}
|
|
407
|
+
function enrichBridgeWithActivationTruth(activationRoot, bridge) {
|
|
408
|
+
const feedbackSummary = buildActivePackFeedbackSummary(activationRoot);
|
|
409
|
+
const attributionCoverage = buildWatchSnapshotAttributionCoverage(activationRoot);
|
|
410
|
+
if (!shouldPreferActivationFeedbackSummary(bridge.feedbackSummary, feedbackSummary)
|
|
411
|
+
&& !shouldPreferWatchAttributionCoverage(bridge.attributionCoverage, attributionCoverage)) {
|
|
412
|
+
return bridge;
|
|
413
|
+
}
|
|
414
|
+
return normalizeBridgePayload({
|
|
415
|
+
...bridge,
|
|
416
|
+
feedbackSummary: shouldPreferActivationFeedbackSummary(bridge.feedbackSummary, feedbackSummary)
|
|
417
|
+
? feedbackSummary
|
|
418
|
+
: bridge.feedbackSummary,
|
|
419
|
+
attributionCoverage: shouldPreferWatchAttributionCoverage(bridge.attributionCoverage, attributionCoverage)
|
|
420
|
+
? attributionCoverage
|
|
421
|
+
: bridge.attributionCoverage
|
|
422
|
+
});
|
|
423
|
+
}
|
|
261
424
|
function normalizeLastInterruptionSummary(value) {
|
|
262
425
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
263
426
|
return null;
|
|
@@ -995,12 +1158,12 @@ export function buildTracedLearningStatusSurface(activationRoot, options = {}) {
|
|
|
995
1158
|
const persisted = loadBrainStoreTracedLearningBridge(options);
|
|
996
1159
|
const runtime = loadTracedLearningBridge(activationRoot);
|
|
997
1160
|
if (persisted.bridge !== null) {
|
|
998
|
-
return buildStatusSurface(persisted.path, mergeCanonicalStatusBridge(persisted.bridge, runtime), {
|
|
1161
|
+
return buildStatusSurface(persisted.path, enrichBridgeWithActivationTruth(activationRoot, mergeCanonicalStatusBridge(persisted.bridge, runtime)), {
|
|
999
1162
|
runtimeState: describeBridgeRuntimeState(runtime)
|
|
1000
1163
|
});
|
|
1001
1164
|
}
|
|
1002
1165
|
if (runtime.bridge !== null) {
|
|
1003
|
-
return buildStatusSurface(runtime.path, runtime.bridge);
|
|
1166
|
+
return buildStatusSurface(runtime.path, enrichBridgeWithActivationTruth(activationRoot, runtime.bridge));
|
|
1004
1167
|
}
|
|
1005
1168
|
if (persisted.error !== null) {
|
|
1006
1169
|
return defaultSurface(persisted.path, "brain_store_unreadable", persisted.error);
|
package/package.json
CHANGED