@openclawbrain/cli 0.4.22 → 0.4.24

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
@@ -818,10 +818,14 @@ function summarizeStatusHookFilesState(installHook) {
818
818
  return "unverified";
819
819
  }
820
820
  function summarizeStatusAttachmentWatcher(status) {
821
- if (status.passiveLearning.watchState === "watching") {
821
+ const watchState = status.passiveLearning.watch?.state ?? status.passiveLearning.watchState;
822
+ if (watchState === "watching") {
822
823
  return "alive";
823
824
  }
824
- if (status.passiveLearning.watchState === "stale_snapshot") {
825
+ if (watchState === "lagging") {
826
+ return "lagging";
827
+ }
828
+ if (watchState === "stale_snapshot") {
825
829
  return "stale";
826
830
  }
827
831
  return "not_visible";
@@ -1150,13 +1154,14 @@ function summarizeStatusTeacher(report, providerConfig, localLlm) {
1150
1154
  detail: `${providerConfig.teacher.model} is enabled on Ollama, but no watch teacher snapshot is visible yet`
1151
1155
  };
1152
1156
  }
1153
- const stale = report.teacherLoop.watchState === "stale_snapshot" || (report.teacherLoop.latestFreshness === "stale" && report.teacherLoop.lastNoOpReason !== "no_teacher_artifacts");
1157
+ const watchState = report.teacherLoop.watch?.state ?? report.teacherLoop.watchState ?? "not_visible";
1158
+ const stale = watchState === "stale_snapshot" || (report.teacherLoop.latestFreshness === "stale" && report.teacherLoop.lastNoOpReason !== "no_teacher_artifacts");
1154
1159
  const idle = report.teacherLoop.running === false &&
1155
1160
  (report.teacherLoop.queueDepth ?? 0) === 0 &&
1156
1161
  report.teacherLoop.failureMode === "none";
1157
1162
  const healthy = report.teacherLoop.failureMode === "none" &&
1158
1163
  stale === false &&
1159
- report.teacherLoop.watchState !== "not_visible";
1164
+ watchState === "watching";
1160
1165
  const cycleDetail = report.teacherLoop.lastNoOpReason === "no_teacher_artifacts"
1161
1166
  ? summarizeTeacherNoArtifactCycle(report.teacherLoop.notes).detail
1162
1167
  : TEACHER_NO_OP_MESSAGES[report.teacherLoop.lastNoOpReason] ?? "the latest teacher cycle detail is unavailable";
@@ -1180,7 +1185,9 @@ function summarizeStatusTeacher(report, providerConfig, localLlm) {
1180
1185
  stale,
1181
1186
  idle,
1182
1187
  latestCycle,
1183
- detail: `${providerConfig.teacher.model} is enabled on Ollama; ${cycleDetail}`
1188
+ detail: watchState === "lagging"
1189
+ ? `${providerConfig.teacher.model} is enabled on Ollama, but the watch heartbeat is lagging; ${cycleDetail}`
1190
+ : `${providerConfig.teacher.model} is enabled on Ollama; ${cycleDetail}`
1184
1191
  };
1185
1192
  }
1186
1193
  function summarizeStatusEmbedder(embeddings) {
@@ -1334,7 +1341,7 @@ function summarizeStatusAlerts(report, providerConfig, embeddings, localLlm) {
1334
1341
  return buckets;
1335
1342
  }
1336
1343
  function summarizeStatusWatchState(status) {
1337
- return status.passiveLearning.watchState;
1344
+ return status.passiveLearning.watch?.state ?? status.passiveLearning.watchState;
1338
1345
  }
1339
1346
  function summarizeStatusServeReality(status) {
1340
1347
  if (status.brainStatus.serveState === "serving_active_pack") {
@@ -1483,7 +1490,7 @@ function formatCurrentProfileStatusSummary(status, report, targetInspection, opt
1483
1490
  `budget requested=${report.servePath.requestedBudgetStrategy ?? "none"} resolved=${report.servePath.resolvedBudgetStrategy ?? "none"} maxBlocks=${report.servePath.resolvedMaxContextBlocks ?? "none"} source=${report.servePath.structuralBudgetSource ?? "none"} origin=${status.brainStatus.structuralDecision.origin} basis=${status.brainStatus.structuralDecision.basis}`,
1484
1491
  `decision ${status.brainStatus.structuralDecision.detail}`,
1485
1492
  `principal latest=${formatPrincipalLatest(report)} pending=${report.principal.pendingCount ?? report.learning.pendingPrincipalCount ?? "none"} checkpoint=${formatPrincipalCheckpointFrontier(report)} downstream=${yesNo(report.principal.servingDownstreamOfLatestCorrection)} lag=${report.learning.principalLagToPromotion.sequenceLag ?? "none"}`,
1486
- `passive learner=${yesNo(status.passiveLearning.learnerRunning)} firstExport=${yesNo(status.passiveLearning.firstExportOccurred)} watch=${status.passiveLearning.watchState} export=${status.passiveLearning.exportState} backlog=${status.passiveLearning.backlogState} pending=${formatStatusNullableNumber(status.passiveLearning.pendingLive)}/${formatStatusNullableNumber(status.passiveLearning.pendingBackfill)} detail=${status.passiveLearning.detail}`,
1493
+ `passive learner=${yesNo(status.passiveLearning.learnerRunning)} firstExport=${yesNo(status.passiveLearning.firstExportOccurred)} watch=${summarizeStatusWatchState(status)} export=${status.passiveLearning.exportState} backlog=${status.passiveLearning.backlogState} pending=${formatStatusNullableNumber(status.passiveLearning.pendingLive)}/${formatStatusNullableNumber(status.passiveLearning.pendingBackfill)} detail=${status.passiveLearning.detail}`,
1487
1494
  `delta observed=${status.passiveLearning.lastObservedDelta.observedAt ?? "none"} exported=${formatStatusNullableYesNo(status.passiveLearning.lastObservedDelta.exported)} labeled=${formatStatusNullableYesNo(status.passiveLearning.lastObservedDelta.labeled)} promoted=${formatStatusNullableYesNo(status.passiveLearning.lastObservedDelta.promoted)} served=${formatStatusNullableYesNo(status.passiveLearning.lastObservedDelta.served)} transition=${formatStatusObservedDeltaTransition(status.passiveLearning.lastObservedDelta)} detail=${status.passiveLearning.lastObservedDelta.explanation}`,
1488
1495
  `scanner flowing=${yesNo(report.supervision.flowing)} scan=${report.supervision.scanPolicy ?? "none"} surfaces=${formatScannerSurfaces(report)} labels=${report.supervision.humanLabelCount ?? "none"}/${report.supervision.selfLabelCount ?? "none"} attributable=${report.supervision.attributedEventCount ?? "none"}/${report.supervision.totalEventCount ?? "none"} digests=${report.supervision.selectionDigestCount ?? "none"}`,
1489
1496
  `labels ${formatLabelFlowSummary(report.labelFlow)}`,
@@ -6,6 +6,16 @@ import { type ActivationInspection, type ActivationObservabilityReport, type Gra
6
6
  export { clearOpenClawProfileRuntimeLoadProof, listOpenClawProfileRuntimeLoadProofs, recordOpenClawProfileRuntimeLoadProof, resolveAttachmentRuntimeLoadProofsPath, type OpenClawProfileRuntimeLoadProofRecordV1, type OpenClawProfileRuntimeLoadProofSetV1, type OpenClawProfileRuntimeLoadProofsV1 } from "./attachment-truth.js";
7
7
  import { type AsyncTeacherLabelerConfigV1 } from "./teacher-labeler.js";
8
8
  export { createHttpOllamaTeacherLabelerClient, createOllamaTeacherLabeler, createTeacherLabeler, summarizeTeacherLabelerOpportunity, type AsyncTeacherLabelerConfigV1, type AsyncTeacherNoopLabelerConfigV1, type AsyncTeacherOllamaLabelerConfigV1, type OllamaTeacherLabelerClient, type TeacherLabeler, type TeacherLabelerOpportunityInputV1, type TeacherLabelerOpportunityV1, type TeacherLabelerResultV1, type TeacherLabelerRunInputV1 } from "./teacher-labeler.js";
9
+ export type OperatorPassiveLearningWatchState = CurrentProfilePassiveLearningWatchStateV1 | "lagging";
10
+ export interface OperatorPassiveLearningWatchSummary {
11
+ state: OperatorPassiveLearningWatchState;
12
+ detail: string;
13
+ lastHeartbeatAt: string | null;
14
+ lagSeconds: number | null;
15
+ intervalSeconds: number | null;
16
+ healthyWithinSeconds: number | null;
17
+ staleAfterSeconds: number | null;
18
+ }
9
19
  export declare const DEFAULT_ASYNC_TEACHER_QUEUE_CAPACITY = 8;
10
20
  declare const RECORDED_SESSION_TRACE_CONTRACT: "recorded_session_trace.v1";
11
21
  declare const RECORDED_SESSION_FIXTURE_CONTRACT: "recorded_session_replay_fixture.v1";
@@ -1687,7 +1697,8 @@ export interface OperatorTeacherLoopSummary {
1687
1697
  lastHeartbeatAt: string | null;
1688
1698
  lastScanAt: string | null;
1689
1699
  pollIntervalSeconds: number | null;
1690
- watchState: CurrentProfilePassiveLearningWatchStateV1;
1700
+ watchState: OperatorPassiveLearningWatchState;
1701
+ watch: OperatorPassiveLearningWatchSummary;
1691
1702
  lastProcessedAt: string | null;
1692
1703
  artifactCount: number | null;
1693
1704
  queueDepth: number | null;
package/dist/src/index.js CHANGED
@@ -6646,11 +6646,18 @@ function loadTeacherSurfaceFromInput(input) {
6646
6646
  }
6647
6647
  function summarizeTeacherLoopWatchState(input) {
6648
6648
  if (input.sourceKind !== "watch_snapshot" || input.watchSnapshot === null) {
6649
+ const watchState = input.sourceKind === "async_snapshot" ? "snapshot_only" : "not_visible";
6649
6650
  return {
6650
6651
  snapshotUpdatedAt: null,
6651
6652
  lastWatchHeartbeatAt: null,
6652
6653
  pollIntervalSeconds: null,
6653
- watchState: input.sourceKind === "async_snapshot" ? "snapshot_only" : "not_visible"
6654
+ watchState,
6655
+ watch: buildTeacherLoopWatchSummary({
6656
+ state: watchState,
6657
+ detail: watchState === "snapshot_only"
6658
+ ? "only a saved watcher snapshot is visible; no live heartbeat is available"
6659
+ : "no watcher snapshot is visible from the current activation root"
6660
+ })
6654
6661
  };
6655
6662
  }
6656
6663
  const lastWatchHeartbeatAt = input.watchSnapshot.snapshot.runtime?.lastHeartbeatAt ?? input.watchSnapshot.lastRunAt;
@@ -6660,16 +6667,55 @@ function summarizeTeacherLoopWatchState(input) {
6660
6667
  snapshotUpdatedAt: input.watchSnapshot.updatedAt,
6661
6668
  lastWatchHeartbeatAt: null,
6662
6669
  pollIntervalSeconds,
6663
- watchState: "snapshot_only"
6670
+ watchState: "snapshot_only",
6671
+ watch: buildTeacherLoopWatchSummary({
6672
+ state: "snapshot_only",
6673
+ detail: "only a saved watcher snapshot is visible; no live heartbeat is available",
6674
+ intervalSeconds: pollIntervalSeconds
6675
+ })
6664
6676
  };
6665
6677
  }
6666
- const lagMs = Date.parse(input.observedAt) - Date.parse(lastWatchHeartbeatAt);
6667
- const staleAfterMs = pollIntervalSeconds * 2000 + 15_000;
6678
+ const rawLagMs = Date.parse(input.observedAt) - Date.parse(lastWatchHeartbeatAt);
6679
+ const lagMs = Number.isFinite(rawLagMs) ? Math.max(0, rawLagMs) : null;
6680
+ const healthyWithinMs = pollIntervalSeconds * 2000 + 15_000;
6681
+ const staleAfterMs = healthyWithinMs + Math.max(15_000, pollIntervalSeconds * 1000);
6682
+ const watchState = lagMs !== null && lagMs <= healthyWithinMs
6683
+ ? "watching"
6684
+ : lagMs !== null && lagMs <= staleAfterMs
6685
+ ? "lagging"
6686
+ : "stale_snapshot";
6668
6687
  return {
6669
6688
  snapshotUpdatedAt: input.watchSnapshot.updatedAt,
6670
6689
  lastWatchHeartbeatAt,
6671
6690
  pollIntervalSeconds,
6672
- watchState: Number.isFinite(lagMs) && lagMs >= 0 && lagMs <= staleAfterMs ? "watching" : "stale_snapshot"
6691
+ watchState,
6692
+ watch: buildTeacherLoopWatchSummary({
6693
+ state: watchState,
6694
+ detail: watchState === "watching"
6695
+ ? "watch heartbeat is inside the healthy window"
6696
+ : watchState === "lagging"
6697
+ ? "watch heartbeat missed the healthy window but has not crossed the stale snapshot threshold"
6698
+ : "watch heartbeat is older than the stale snapshot threshold",
6699
+ lastHeartbeatAt: lastWatchHeartbeatAt,
6700
+ lagMs,
6701
+ intervalSeconds: pollIntervalSeconds,
6702
+ healthyWithinMs,
6703
+ staleAfterMs
6704
+ })
6705
+ };
6706
+ }
6707
+ function buildTeacherLoopWatchSummary(input) {
6708
+ const lagSeconds = Number.isFinite(input.lagMs) ? Math.round((input.lagMs / 1000) * 100) / 100 : null;
6709
+ const healthyWithinSeconds = Number.isFinite(input.healthyWithinMs) ? Math.round((input.healthyWithinMs / 1000) * 100) / 100 : null;
6710
+ const staleAfterSeconds = Number.isFinite(input.staleAfterMs) ? Math.round((input.staleAfterMs / 1000) * 100) / 100 : null;
6711
+ return {
6712
+ state: input.state,
6713
+ detail: input.detail,
6714
+ lastHeartbeatAt: input.lastHeartbeatAt ?? null,
6715
+ lagSeconds,
6716
+ intervalSeconds: input.intervalSeconds ?? null,
6717
+ healthyWithinSeconds,
6718
+ staleAfterSeconds
6673
6719
  };
6674
6720
  }
6675
6721
  function emptyOperatorLearningAttribution(source, snapshotKind, detail) {
@@ -6798,6 +6844,10 @@ function summarizeTeacherLoop(input) {
6798
6844
  const teacherSnapshotPath = resolveOperatorTeacherSnapshotPath(input.activationRoot, normalizeOptionalString(input.teacherSnapshotPath) ?? null);
6799
6845
  const unavailableFromMissing = buildUnavailableLastObservedDelta("no watch teacher snapshot is visible for the latest observed cycle");
6800
6846
  const unavailableFromAsync = buildUnavailableLastObservedDelta("raw async teacher snapshots do not record the last observed export/label/promotion delta");
6847
+ const notVisibleWatch = buildTeacherLoopWatchSummary({
6848
+ state: "not_visible",
6849
+ detail: "no watcher snapshot is visible from the current activation root"
6850
+ });
6801
6851
  if (loaded === null && teacherSnapshotPath === null) {
6802
6852
  return {
6803
6853
  available: false,
@@ -6812,6 +6862,7 @@ function summarizeTeacherLoop(input) {
6812
6862
  lastScanAt: null,
6813
6863
  pollIntervalSeconds: null,
6814
6864
  watchState: "not_visible",
6865
+ watch: notVisibleWatch,
6815
6866
  lastProcessedAt: null,
6816
6867
  artifactCount: null,
6817
6868
  queueDepth: null,
@@ -6852,6 +6903,7 @@ function summarizeTeacherLoop(input) {
6852
6903
  lastScanAt: null,
6853
6904
  pollIntervalSeconds: null,
6854
6905
  watchState: "not_visible",
6906
+ watch: notVisibleWatch,
6855
6907
  lastProcessedAt: null,
6856
6908
  artifactCount: null,
6857
6909
  queueDepth: null,
@@ -6898,6 +6950,7 @@ function summarizeTeacherLoop(input) {
6898
6950
  lastScanAt: snapshot.runtime?.lastScanAt ?? null,
6899
6951
  pollIntervalSeconds: watchState.pollIntervalSeconds,
6900
6952
  watchState: watchState.watchState,
6953
+ watch: watchState.watch,
6901
6954
  lastProcessedAt: snapshot.diagnostics.lastProcessedAt,
6902
6955
  artifactCount: watchSnapshot?.teacher.artifactCount ?? snapshot.teacher.artifactCount,
6903
6956
  queueDepth: snapshot.queue.depth,
@@ -7486,6 +7539,13 @@ function didCurrentProfileFirstExportOccur(report) {
7486
7539
  }
7487
7540
  function summarizeCurrentProfilePassiveLearning(report, activePackId) {
7488
7541
  const firstExportOccurred = didCurrentProfileFirstExportOccur(report);
7542
+ const watch = report.teacherLoop.watch ?? buildTeacherLoopWatchSummary({
7543
+ state: report.teacherLoop.watchState,
7544
+ detail: "watch state came from the legacy passive-learning surface",
7545
+ lastHeartbeatAt: report.teacherLoop.lastHeartbeatAt,
7546
+ intervalSeconds: report.teacherLoop.pollIntervalSeconds
7547
+ });
7548
+ const watchState = watch.state ?? report.teacherLoop.watchState;
7489
7549
  const exportState = !firstExportOccurred
7490
7550
  ? "awaiting_first_export"
7491
7551
  : report.supervision.exportedAt !== null
@@ -7495,28 +7555,33 @@ function summarizeCurrentProfilePassiveLearning(report, activePackId) {
7495
7555
  ? report.learning.backlogState
7496
7556
  : "unknown";
7497
7557
  const detail = !firstExportOccurred
7498
- ? report.teacherLoop.watchState === "watching"
7558
+ ? watchState === "watching"
7499
7559
  ? "watch heartbeat is fresh, but this activation root has not observed its first export yet"
7560
+ : watchState === "lagging"
7561
+ ? "watch heartbeat is lagging, and this activation root is still waiting for the first export before passive learning can advance"
7500
7562
  : "this activation root is still waiting for the first export before passive learning can advance"
7501
7563
  : backlogState === "unknown"
7502
7564
  ? "first export is proven, but passive backlog state is not visible from the current local artifacts"
7503
- : report.teacherLoop.watchState === "watching"
7565
+ : watchState === "watching"
7504
7566
  ? `watch heartbeat is fresh; passive backlog is ${backlogState} with live=${report.learning.pendingLive ?? 0} and backfill=${report.learning.pendingBackfill ?? 0}`
7505
- : report.teacherLoop.watchState === "stale_snapshot"
7567
+ : watchState === "lagging"
7568
+ ? `watch heartbeat is lagging; latest known passive backlog is ${backlogState} with live=${report.learning.pendingLive ?? 0} and backfill=${report.learning.pendingBackfill ?? 0}`
7569
+ : watchState === "stale_snapshot"
7506
7570
  ? `last saved watch snapshot is stale; latest known passive backlog is ${backlogState}`
7507
- : report.teacherLoop.watchState === "snapshot_only"
7571
+ : watchState === "snapshot_only"
7508
7572
  ? `passive backlog is visible from the last saved snapshot: ${backlogState}`
7509
7573
  : `passive backlog is visible from the last known learner state: ${backlogState}`;
7510
7574
  return {
7511
- learnerRunning: report.teacherLoop.watchState === "watching",
7575
+ learnerRunning: watchState === "watching",
7512
7576
  firstExportOccurred,
7513
- watchState: report.teacherLoop.watchState,
7577
+ watchState,
7578
+ watch,
7514
7579
  exportState,
7515
7580
  backlogState,
7516
7581
  pendingLive: report.learning.available ? report.learning.pendingLive : null,
7517
7582
  pendingBackfill: report.learning.available ? report.learning.pendingBackfill : null,
7518
- lastWatchHeartbeatAt: report.teacherLoop.lastHeartbeatAt,
7519
- watchIntervalSeconds: report.teacherLoop.pollIntervalSeconds,
7583
+ lastWatchHeartbeatAt: watch.lastHeartbeatAt ?? report.teacherLoop.lastHeartbeatAt,
7584
+ watchIntervalSeconds: watch.intervalSeconds ?? report.teacherLoop.pollIntervalSeconds,
7520
7585
  lastExportAt: report.supervision.exportedAt,
7521
7586
  lastPromotionAt: report.promotion.lastPromotion.at,
7522
7587
  currentServingPackId: activePackId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclawbrain/cli",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
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",