@openclawbrain/cli 0.4.25 → 0.4.26

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 CHANGED
@@ -17,7 +17,7 @@ import { inspectOpenClawBrainHookStatus, inspectOpenClawBrainPluginAllowlist } f
17
17
  import { describeOpenClawBrainInstallIdentity, describeOpenClawBrainInstallLayout, findInstalledOpenClawBrainPlugin, getOpenClawBrainKnownPluginIds, normalizeOpenClawBrainPluginsConfig, pinInstalledOpenClawBrainPluginActivationRoot, resolveOpenClawBrainInstallTarget } from "./openclaw-plugin-install.js";
18
18
  import { buildOpenClawBrainConvergeRestartPlan, classifyOpenClawBrainConvergeVerification, describeOpenClawBrainConvergeChangeReasons, diffOpenClawBrainConvergeRuntimeFingerprint, finalizeOpenClawBrainConvergeResult, planOpenClawBrainConvergePluginAction, shouldReplaceOpenClawBrainInstallBeforeConverge } from "./install-converge.js";
19
19
  import { loadAttachmentPolicyDeclaration, resolveEffectiveAttachmentPolicyTruth, writeAttachmentPolicyDeclaration } from "./attachment-policy-truth.js";
20
- import { DEFAULT_WATCH_POLL_INTERVAL_SECONDS, buildNormalizedEventExportFromScannedEvents, bootstrapRuntimeAttach, buildOperatorSurfaceReport, clearOpenClawProfileRuntimeLoadProof, compileRuntimeContext, createAsyncTeacherLiveLoop, createOpenClawLocalSessionTail, createRuntimeEventExportScanner, describeCurrentProfileBrainStatus, formatOperatorRollbackReport, listOpenClawProfileRuntimeLoadProofs, loadRuntimeEventExportBundle, loadWatchTeacherSnapshotState, persistWatchTeacherSnapshot, rollbackRuntimeAttach, resolveAttachmentRuntimeLoadProofsPath, resolveOperatorTeacherSnapshotPath, resolveAsyncTeacherLiveLoopSnapshotPath, resolveWatchSessionTailCursorPath, resolveWatchStateRoot, resolveWatchTeacherSnapshotPath, scanLiveEventExport, scanRecordedSession, summarizeLearningPathFromMaterialization, summarizeNormalizedEventExportLabelFlow, summarizeTeacherNoArtifactCycle, writeScannedEventExportBundle } from "./index.js";
20
+ import { DEFAULT_WATCH_POLL_INTERVAL_SECONDS, buildNormalizedEventExportFromScannedEvents, bootstrapRuntimeAttach, clearOpenClawProfileRuntimeLoadProof, compileRuntimeContext, createAsyncTeacherLiveLoop, createOpenClawLocalSessionTail, createRuntimeEventExportScanner, describeCurrentProfileBrainStatusWithReport, formatOperatorRollbackReport, listOpenClawProfileRuntimeLoadProofs, loadRuntimeEventExportBundle, loadWatchTeacherSnapshotState, persistWatchTeacherSnapshot, rollbackRuntimeAttach, resolveAttachmentRuntimeLoadProofsPath, resolveOperatorTeacherSnapshotPath, resolveAsyncTeacherLiveLoopSnapshotPath, resolveWatchSessionTailCursorPath, resolveWatchStateRoot, resolveWatchTeacherSnapshotPath, scanLiveEventExport, scanRecordedSession, summarizeLearningPathFromMaterialization, summarizeNormalizedEventExportLabelFlow, summarizeTeacherNoArtifactCycle, writeScannedEventExportBundle } from "./index.js";
21
21
  import { appendLearningUpdateLogs } from "./learning-spine.js";
22
22
  import { buildPassiveLearningSessionExportFromOpenClawSessionStore } from "./local-session-passive-learning.js";
23
23
  import { reindexMaterializationCandidateWithEmbedder } from "./materialization-embedder.js";
@@ -1692,8 +1692,7 @@ function inspectInstallConvergeVerification(parsed) {
1692
1692
  openclawHome: parsed.openclawHome,
1693
1693
  ...(targetInspection.profileId === null ? {} : { profileId: targetInspection.profileId })
1694
1694
  };
1695
- const status = describeCurrentProfileBrainStatus(operatorInput);
1696
- const report = buildOperatorSurfaceReport(operatorInput);
1695
+ const { status, report } = describeCurrentProfileBrainStatusWithReport(operatorInput);
1697
1696
  const normalizedStatusAndReport = applyAttachmentPolicyTruth(status, report);
1698
1697
  const installHook = summarizeStatusInstallHook(parsed.openclawHome);
1699
1698
  const attachmentTruth = summarizeStatusAttachmentTruth({
@@ -6364,9 +6363,10 @@ export function runOperatorCli(argv = process.argv.slice(2)) {
6364
6363
  : { profileId: targetInspection.profileId }),
6365
6364
  teacherSnapshotPath: resolveOperatorTeacherSnapshotPath(activationRoot, statusOrRollback.input.teacherSnapshotPath)
6366
6365
  };
6367
- const status = describeCurrentProfileBrainStatus(operatorInput);
6366
+ const statusWithReport = describeCurrentProfileBrainStatusWithReport(operatorInput);
6367
+ const status = statusWithReport.status;
6368
6368
  const tracedLearning = buildTracedLearningStatusSurface(activationRoot);
6369
- const normalizedStatusAndReport = applyAttachmentPolicyTruth(status, statusOrRollback.json ? null : buildOperatorSurfaceReport(operatorInput));
6369
+ const normalizedStatusAndReport = applyAttachmentPolicyTruth(status, statusOrRollback.json ? null : statusWithReport.report);
6370
6370
  if (statusOrRollback.json) {
6371
6371
  console.log(JSON.stringify({
6372
6372
  ...normalizedStatusAndReport.status,
package/dist/src/index.js CHANGED
@@ -8031,9 +8031,15 @@ export function buildOperatorSurfaceReport(input) {
8031
8031
  findings
8032
8032
  };
8033
8033
  }
8034
- export function describeCurrentProfileBrainStatus(input) {
8034
+ export function describeCurrentProfileBrainStatusWithReport(input) {
8035
8035
  const report = buildOperatorSurfaceReport(input);
8036
- return buildCurrentProfileBrainStatusFromReport(report, report.manyProfile.declaredAttachmentPolicy, normalizeOptionalString(input.profileId) ?? null);
8036
+ return {
8037
+ report,
8038
+ status: buildCurrentProfileBrainStatusFromReport(report, report.manyProfile.declaredAttachmentPolicy, normalizeOptionalString(input.profileId) ?? null)
8039
+ };
8040
+ }
8041
+ export function describeCurrentProfileBrainStatus(input) {
8042
+ return describeCurrentProfileBrainStatusWithReport(input).status;
8037
8043
  }
8038
8044
  export function formatOperatorRollbackReport(result) {
8039
8045
  const header = result.allowed ? (result.dryRun ? "ROLLBACK ready" : "ROLLBACK ok") : "ROLLBACK blocked";
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclawbrain/cli",
3
- "version": "0.4.25",
3
+ "version": "0.4.26",
4
4
  "description": "OpenClawBrain operator CLI package with install/status helpers, daemon controls, and import/export tooling.",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",