@openclawbrain/openclaw 0.2.3 → 0.3.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.
- package/dist/extension/index.d.ts +1 -0
- package/dist/extension/index.js +73 -0
- package/dist/extension/index.js.map +1 -0
- package/dist/extension/runtime-guard.d.ts +61 -0
- package/dist/extension/runtime-guard.js +230 -0
- package/dist/extension/runtime-guard.js.map +1 -0
- package/dist/src/cli.d.ts +8 -4
- package/dist/src/cli.js +501 -154
- package/dist/src/cli.js.map +1 -1
- package/dist/src/daemon.d.ts +7 -4
- package/dist/src/daemon.js +275 -47
- package/dist/src/daemon.js.map +1 -1
- package/dist/src/index.d.ts +150 -2
- package/dist/src/index.js +769 -139
- package/dist/src/index.js.map +1 -1
- package/dist/src/learning-spine.d.ts +2 -1
- package/dist/src/learning-spine.js +8 -0
- package/dist/src/learning-spine.js.map +1 -1
- package/dist/src/ollama-client.d.ts +46 -0
- package/dist/src/ollama-client.js +231 -0
- package/dist/src/ollama-client.js.map +1 -0
- package/dist/src/provider-config.d.ts +28 -0
- package/dist/src/provider-config.js +150 -0
- package/dist/src/provider-config.js.map +1 -0
- package/dist/src/resolve-activation-root.d.ts +3 -3
- package/dist/src/resolve-activation-root.js +68 -21
- package/dist/src/resolve-activation-root.js.map +1 -1
- package/dist/src/shadow-extension-proof.d.ts +40 -0
- package/dist/src/shadow-extension-proof.js +214 -0
- package/dist/src/shadow-extension-proof.js.map +1 -0
- package/dist/src/teacher-labeler.d.ts +50 -0
- package/dist/src/teacher-labeler.js +424 -0
- package/dist/src/teacher-labeler.js.map +1 -0
- package/extension/index.ts +5 -1
- package/extension/runtime-guard.ts +17 -2
- package/package.json +8 -7
package/dist/src/index.js
CHANGED
|
@@ -8,6 +8,8 @@ import { classifyFeedbackSignalContent, describeNormalizedEventExportObservabili
|
|
|
8
8
|
import { DEFAULT_TEACHER_SUPERVISION_STALE_AFTER_MS, advanceAlwaysOnLearningRuntime, buildTeacherSupervisionArtifactsFromNormalizedEventExport, createAlwaysOnLearningRuntimeState, describeAlwaysOnLearningRuntimeState, materializeAlwaysOnLearningCandidatePack, materializeCandidatePackFromNormalizedEventExport } from "@openclawbrain/learner";
|
|
9
9
|
import { LEARNING_SPINE_LOG_LAYOUT, activatePack, describeActivationObservability, describeActivationTarget, describePackCompileTarget, inspectActivationState, loadPackFromActivation, promoteCandidatePack, readLearningSpineLogEntries, rollbackActivePack, stageCandidatePack } from "@openclawbrain/pack-format";
|
|
10
10
|
import { appendLearningUpdateLogs, appendServeTimeRouteDecisionLog } from "./learning-spine.js";
|
|
11
|
+
import { createTeacherLabeler } from "./teacher-labeler.js";
|
|
12
|
+
export { createHttpOllamaTeacherLabelerClient, createOllamaTeacherLabeler, createTeacherLabeler } from "./teacher-labeler.js";
|
|
11
13
|
const DEFAULT_AGENT_ID = "openclaw-runtime";
|
|
12
14
|
const FEEDBACK_KINDS = new Set(["correction", "teaching", "approval", "suppression"]);
|
|
13
15
|
export const DEFAULT_ASYNC_TEACHER_QUEUE_CAPACITY = 8;
|
|
@@ -220,6 +222,8 @@ function buildAsyncTeacherLoopNotes(input) {
|
|
|
220
222
|
`teacher_feedback_budgeted_out=${input.sparseFeedback.budgetedOutFeedbackCount}`,
|
|
221
223
|
`teacher_background_amplified=${input.sparseFeedback.amplifiedBackgroundLabelCount}`,
|
|
222
224
|
`teacher_noop=${input.noOpReason}`,
|
|
225
|
+
`teacher_labeler=${input.teacherLabeler?.status ?? "disabled"}`,
|
|
226
|
+
`teacher_labeler_detail=${input.teacherLabeler?.detail ?? "disabled"}`,
|
|
223
227
|
input.materialization === null ? "teacher_materialization=noop" : `teacher_materialized_pack=${input.materialization.candidate.summary.packId}`
|
|
224
228
|
];
|
|
225
229
|
}
|
|
@@ -233,10 +237,13 @@ function cloneAsyncTeacherSnapshotState(value) {
|
|
|
233
237
|
if (value === undefined) {
|
|
234
238
|
return undefined;
|
|
235
239
|
}
|
|
240
|
+
const interactionEvents = Array.isArray(value.interactionEvents) ? value.interactionEvents : [];
|
|
241
|
+
const feedbackEvents = Array.isArray(value.feedbackEvents) ? value.feedbackEvents : [];
|
|
242
|
+
const seenExportDigests = Array.isArray(value.seenExportDigests) ? value.seenExportDigests : [];
|
|
236
243
|
return {
|
|
237
|
-
interactionEvents: [...structuredClone(
|
|
238
|
-
feedbackEvents: [...structuredClone(
|
|
239
|
-
seenExportDigests: [...
|
|
244
|
+
interactionEvents: [...structuredClone(interactionEvents)],
|
|
245
|
+
feedbackEvents: [...structuredClone(feedbackEvents)],
|
|
246
|
+
seenExportDigests: [...seenExportDigests]
|
|
240
247
|
};
|
|
241
248
|
}
|
|
242
249
|
function cloneAsyncTeacherSnapshotRuntime(value) {
|
|
@@ -521,6 +528,7 @@ export class AsyncTeacherLiveLoop {
|
|
|
521
528
|
input;
|
|
522
529
|
queueCapacity;
|
|
523
530
|
staleAfterMs;
|
|
531
|
+
teacherLabeler;
|
|
524
532
|
queuedExportDigests = new Set();
|
|
525
533
|
seenExportDigests = new Set();
|
|
526
534
|
queue = [];
|
|
@@ -530,6 +538,7 @@ export class AsyncTeacherLiveLoop {
|
|
|
530
538
|
teacherArtifacts = [];
|
|
531
539
|
learnerState = createAlwaysOnLearningRuntimeState();
|
|
532
540
|
lastMaterialization = null;
|
|
541
|
+
lastTeacherLabelerResult = null;
|
|
533
542
|
diagnostics = {
|
|
534
543
|
acceptedExportCount: 0,
|
|
535
544
|
processedExportCount: 0,
|
|
@@ -548,13 +557,15 @@ export class AsyncTeacherLiveLoop {
|
|
|
548
557
|
dedupedArtifactCount: 0,
|
|
549
558
|
sparseFeedback: this.learnerState.sparseFeedback,
|
|
550
559
|
noOpReason: "none",
|
|
551
|
-
materialization: null
|
|
560
|
+
materialization: null,
|
|
561
|
+
teacherLabeler: null
|
|
552
562
|
})
|
|
553
563
|
};
|
|
554
564
|
constructor(input) {
|
|
555
565
|
this.input = input;
|
|
556
566
|
this.queueCapacity = input.maxQueuedExports ?? DEFAULT_ASYNC_TEACHER_QUEUE_CAPACITY;
|
|
557
567
|
this.staleAfterMs = input.staleAfterMs ?? DEFAULT_TEACHER_SUPERVISION_STALE_AFTER_MS;
|
|
568
|
+
this.teacherLabeler = createTeacherLabeler(input.teacherLabeler);
|
|
558
569
|
if (!Number.isInteger(this.queueCapacity) || this.queueCapacity <= 0) {
|
|
559
570
|
throw new Error("maxQueuedExports must be a positive integer");
|
|
560
571
|
}
|
|
@@ -621,7 +632,9 @@ export class AsyncTeacherLiveLoop {
|
|
|
621
632
|
this.queuedExportDigests.add(exportDigest);
|
|
622
633
|
this.diagnostics.acceptedExportCount += 1;
|
|
623
634
|
this.refreshNotes();
|
|
624
|
-
void this.ensureDrain()
|
|
635
|
+
void this.ensureDrain().catch(() => {
|
|
636
|
+
// Explicit flush()/ingest callers observe the failure; the background kickoff must not leak an unhandled rejection.
|
|
637
|
+
});
|
|
625
638
|
return {
|
|
626
639
|
accepted: true,
|
|
627
640
|
exportDigest,
|
|
@@ -800,57 +813,106 @@ export class AsyncTeacherLiveLoop {
|
|
|
800
813
|
while (this.queue.length > 0) {
|
|
801
814
|
const job = this.queue.shift();
|
|
802
815
|
this.queuedExportDigests.delete(job.exportDigest);
|
|
803
|
-
this.
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
816
|
+
const previousInteractionEvents = [...structuredClone(this.interactionEvents)];
|
|
817
|
+
const previousFeedbackEvents = [...structuredClone(this.feedbackEvents)];
|
|
818
|
+
const previousTeacherArtifacts = cloneTeacherSupervisionArtifacts(this.teacherArtifacts);
|
|
819
|
+
const previousLearnerState = structuredClone(this.learnerState);
|
|
820
|
+
const previousLastMaterialization = cloneAlwaysOnLearningMaterializationJobOrNull(this.lastMaterialization);
|
|
821
|
+
const previousDiagnostics = {
|
|
822
|
+
...structuredClone(this.diagnostics),
|
|
823
|
+
notes: [...this.diagnostics.notes]
|
|
824
|
+
};
|
|
825
|
+
const previousSeenExportDigests = [...this.seenExportDigests];
|
|
826
|
+
try {
|
|
827
|
+
this.seenExportDigests.add(job.exportDigest);
|
|
828
|
+
this.interactionEvents = mergeUniqueEvents(this.interactionEvents, job.normalizedEventExport.interactionEvents);
|
|
829
|
+
this.feedbackEvents = mergeUniqueEvents(this.feedbackEvents, job.normalizedEventExport.feedbackEvents);
|
|
830
|
+
const mergedNormalizedEventExport = buildNormalizedEventExport({
|
|
831
|
+
interactionEvents: this.interactionEvents,
|
|
832
|
+
feedbackEvents: this.feedbackEvents
|
|
833
|
+
});
|
|
834
|
+
const learnedRoutingState = this.input.resolveLearnedRoutingState?.() ?? {};
|
|
835
|
+
const builtArtifacts = buildTeacherSupervisionArtifactsFromNormalizedEventExport({
|
|
836
|
+
normalizedEventExport: mergedNormalizedEventExport,
|
|
837
|
+
observedAt: job.observedAt,
|
|
838
|
+
staleAfterMs: this.staleAfterMs,
|
|
839
|
+
...(this.input.sparseFeedback !== undefined ? { sparseFeedback: this.input.sparseFeedback } : {})
|
|
840
|
+
});
|
|
841
|
+
let generatedTeacherArtifacts = [];
|
|
842
|
+
if (this.teacherLabeler !== null) {
|
|
843
|
+
try {
|
|
844
|
+
this.lastTeacherLabelerResult = await this.teacherLabeler.label({
|
|
845
|
+
normalizedEventExport: mergedNormalizedEventExport,
|
|
846
|
+
observedAt: job.observedAt,
|
|
847
|
+
staleAfterMs: this.staleAfterMs,
|
|
848
|
+
existingArtifacts: [...this.teacherArtifacts, ...builtArtifacts],
|
|
849
|
+
...(learnedRoutingState.serveTimeDecisions !== undefined
|
|
850
|
+
? { serveTimeDecisions: learnedRoutingState.serveTimeDecisions }
|
|
851
|
+
: {})
|
|
852
|
+
});
|
|
853
|
+
generatedTeacherArtifacts = this.lastTeacherLabelerResult.artifacts;
|
|
854
|
+
}
|
|
855
|
+
catch (error) {
|
|
856
|
+
this.lastTeacherLabelerResult = {
|
|
857
|
+
artifacts: [],
|
|
858
|
+
status: "fail_open",
|
|
859
|
+
detail: toErrorMessage(error)
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
const nextBuiltArtifacts = mergeTeacherArtifacts([], [...builtArtifacts, ...generatedTeacherArtifacts]);
|
|
864
|
+
const currentDedupIds = new Set(this.teacherArtifacts.map((artifact) => artifact.dedupId));
|
|
865
|
+
const nextTeacherArtifacts = mergeTeacherArtifacts(this.teacherArtifacts, nextBuiltArtifacts);
|
|
866
|
+
const emittedArtifactCount = nextBuiltArtifacts.filter((artifact) => !currentDedupIds.has(artifact.dedupId)).length;
|
|
867
|
+
const dedupedArtifactCount = nextBuiltArtifacts.length - emittedArtifactCount;
|
|
868
|
+
this.teacherArtifacts = nextTeacherArtifacts;
|
|
869
|
+
const learnerResult = advanceAlwaysOnLearningRuntime({
|
|
870
|
+
packLabel: this.input.packLabel,
|
|
871
|
+
workspace: this.input.workspace,
|
|
872
|
+
interactionEvents: this.interactionEvents,
|
|
873
|
+
feedbackEvents: this.feedbackEvents,
|
|
874
|
+
teacherSupervisionArtifacts: this.teacherArtifacts,
|
|
875
|
+
learnedRouting: this.input.learnedRouting,
|
|
876
|
+
state: this.learnerState,
|
|
877
|
+
builtAt: this.input.builtAt ?? job.observedAt,
|
|
878
|
+
...(this.input.offlineArtifacts !== undefined ? { offlineArtifacts: this.input.offlineArtifacts } : {}),
|
|
879
|
+
...(this.input.structuralOps !== undefined ? { structuralOps: this.input.structuralOps } : {}),
|
|
880
|
+
...(this.input.sparseFeedback !== undefined ? { sparseFeedback: this.input.sparseFeedback } : {}),
|
|
881
|
+
...(this.input.liveSliceSize !== undefined ? { liveSliceSize: this.input.liveSliceSize } : {}),
|
|
882
|
+
...(this.input.backfillSliceSize !== undefined ? { backfillSliceSize: this.input.backfillSliceSize } : {}),
|
|
883
|
+
...(this.input.cadence !== undefined ? { cadence: this.input.cadence } : {}),
|
|
884
|
+
...(learnedRoutingState.pgVersion !== undefined ? { pgVersion: learnedRoutingState.pgVersion } : {}),
|
|
885
|
+
...(learnedRoutingState.serveTimeDecisions !== undefined ? { serveTimeDecisions: learnedRoutingState.serveTimeDecisions } : {}),
|
|
886
|
+
...(learnedRoutingState.baselineState !== undefined ? { baselineState: learnedRoutingState.baselineState } : {})
|
|
887
|
+
});
|
|
888
|
+
this.learnerState = structuredClone(learnerResult.state);
|
|
889
|
+
this.lastMaterialization = cloneAlwaysOnLearningMaterializationJobOrNull(learnerResult.materialization);
|
|
890
|
+
const updatedBaseline = learnerResult.materialization?.candidate.routingBuild.updatedBaseline ?? null;
|
|
891
|
+
if (updatedBaseline !== null) {
|
|
892
|
+
this.input.persistUpdatedBaseline?.(structuredClone(updatedBaseline));
|
|
893
|
+
}
|
|
894
|
+
this.diagnostics.processedExportCount += 1;
|
|
895
|
+
this.diagnostics.emittedArtifactCount += emittedArtifactCount;
|
|
896
|
+
this.diagnostics.dedupedArtifactCount += dedupedArtifactCount;
|
|
897
|
+
this.diagnostics.lastProcessedAt = job.observedAt;
|
|
898
|
+
this.diagnostics.latestFreshness = latestTeacherFreshness(this.teacherArtifacts);
|
|
899
|
+
this.diagnostics.lastNoOpReason = emittedArtifactCount === 0 ? "no_teacher_artifacts" : "none";
|
|
900
|
+
this.refreshNotes();
|
|
901
|
+
}
|
|
902
|
+
catch (error) {
|
|
903
|
+
this.interactionEvents = previousInteractionEvents;
|
|
904
|
+
this.feedbackEvents = previousFeedbackEvents;
|
|
905
|
+
this.teacherArtifacts = previousTeacherArtifacts;
|
|
906
|
+
this.learnerState = previousLearnerState;
|
|
907
|
+
this.lastMaterialization = previousLastMaterialization;
|
|
908
|
+
this.diagnostics = previousDiagnostics;
|
|
909
|
+
this.seenExportDigests.clear();
|
|
910
|
+
for (const exportDigest of previousSeenExportDigests) {
|
|
911
|
+
this.seenExportDigests.add(exportDigest);
|
|
912
|
+
}
|
|
913
|
+
this.refreshNotes();
|
|
914
|
+
throw error;
|
|
846
915
|
}
|
|
847
|
-
this.diagnostics.processedExportCount += 1;
|
|
848
|
-
this.diagnostics.emittedArtifactCount += emittedArtifactCount;
|
|
849
|
-
this.diagnostics.dedupedArtifactCount += dedupedArtifactCount;
|
|
850
|
-
this.diagnostics.lastProcessedAt = job.observedAt;
|
|
851
|
-
this.diagnostics.latestFreshness = latestTeacherFreshness(this.teacherArtifacts);
|
|
852
|
-
this.diagnostics.lastNoOpReason = emittedArtifactCount === 0 ? "no_teacher_artifacts" : "none";
|
|
853
|
-
this.refreshNotes();
|
|
854
916
|
}
|
|
855
917
|
}
|
|
856
918
|
refreshNotes() {
|
|
@@ -862,7 +924,8 @@ export class AsyncTeacherLiveLoop {
|
|
|
862
924
|
dedupedArtifactCount: this.diagnostics.dedupedArtifactCount,
|
|
863
925
|
sparseFeedback: this.learnerState.sparseFeedback,
|
|
864
926
|
noOpReason: this.diagnostics.lastNoOpReason,
|
|
865
|
-
materialization: this.lastMaterialization
|
|
927
|
+
materialization: this.lastMaterialization,
|
|
928
|
+
teacherLabeler: this.lastTeacherLabelerResult
|
|
866
929
|
});
|
|
867
930
|
}
|
|
868
931
|
}
|
|
@@ -968,7 +1031,8 @@ export function scanLiveEventExport(input) {
|
|
|
968
1031
|
dedupedArtifactCount: 0,
|
|
969
1032
|
sparseFeedback: learnerResult.state.sparseFeedback,
|
|
970
1033
|
noOpReason: lastNoOpReason,
|
|
971
|
-
materialization: learnerResult.materialization
|
|
1034
|
+
materialization: learnerResult.materialization,
|
|
1035
|
+
teacherLabeler: null
|
|
972
1036
|
})
|
|
973
1037
|
}
|
|
974
1038
|
};
|
|
@@ -991,8 +1055,270 @@ function readJsonFile(filePath) {
|
|
|
991
1055
|
export function resolveAsyncTeacherLiveLoopSnapshotPath(activationRoot) {
|
|
992
1056
|
return path.join(path.resolve(normalizeNonEmptyString(activationRoot, "activationRoot")), "async-teacher-live-loop.snapshot.json");
|
|
993
1057
|
}
|
|
994
|
-
export
|
|
995
|
-
|
|
1058
|
+
export const WATCH_STATE_DIRNAME = "watch";
|
|
1059
|
+
export const WATCH_SESSION_TAIL_CURSOR_BASENAME = "session-tail-cursor.json";
|
|
1060
|
+
export const WATCH_TEACHER_SNAPSHOT_BASENAME = "teacher-snapshot.json";
|
|
1061
|
+
function isAsyncTeacherLiveLoopSnapshot(value) {
|
|
1062
|
+
if (value === null || typeof value !== "object") {
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
const candidate = value;
|
|
1066
|
+
return (candidate.runtimeOwner === "openclaw" &&
|
|
1067
|
+
candidate.queue !== undefined &&
|
|
1068
|
+
candidate.teacher !== undefined &&
|
|
1069
|
+
candidate.learner !== undefined &&
|
|
1070
|
+
candidate.diagnostics !== undefined);
|
|
1071
|
+
}
|
|
1072
|
+
function isWatchTeacherSnapshot(value) {
|
|
1073
|
+
if (value === null || typeof value !== "object") {
|
|
1074
|
+
return false;
|
|
1075
|
+
}
|
|
1076
|
+
const candidate = value;
|
|
1077
|
+
return (candidate.contract === "openclaw_watch_teacher_snapshot.v1" &&
|
|
1078
|
+
candidate.runtimeOwner === "openclaw" &&
|
|
1079
|
+
isAsyncTeacherLiveLoopSnapshot(candidate.snapshot));
|
|
1080
|
+
}
|
|
1081
|
+
function cloneWatchTeacherSnapshotFailure(value) {
|
|
1082
|
+
if (value === null ||
|
|
1083
|
+
value === undefined ||
|
|
1084
|
+
!["materialization_failed", "teacher_fail_open"].includes(value.mode) ||
|
|
1085
|
+
typeof value.detail !== "string" ||
|
|
1086
|
+
typeof value.at !== "string") {
|
|
1087
|
+
return null;
|
|
1088
|
+
}
|
|
1089
|
+
return {
|
|
1090
|
+
mode: value.mode,
|
|
1091
|
+
detail: value.detail,
|
|
1092
|
+
at: value.at
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
function cloneRuntimeEventExportScannerCheckpoint(value) {
|
|
1096
|
+
return structuredClone(value);
|
|
1097
|
+
}
|
|
1098
|
+
function buildWatchTeacherSnapshotTeacherSummary(snapshot) {
|
|
1099
|
+
return {
|
|
1100
|
+
artifactCount: snapshot.teacher.artifactCount,
|
|
1101
|
+
latestFreshness: snapshot.teacher.latestFreshness,
|
|
1102
|
+
acceptedExportCount: snapshot.diagnostics.acceptedExportCount,
|
|
1103
|
+
processedExportCount: snapshot.diagnostics.processedExportCount,
|
|
1104
|
+
duplicateExportCount: snapshot.diagnostics.duplicateExportCount,
|
|
1105
|
+
droppedExportCount: snapshot.diagnostics.droppedExportCount,
|
|
1106
|
+
emittedArtifactCount: snapshot.diagnostics.emittedArtifactCount,
|
|
1107
|
+
dedupedArtifactCount: snapshot.diagnostics.dedupedArtifactCount,
|
|
1108
|
+
lastProcessedAt: snapshot.diagnostics.lastProcessedAt,
|
|
1109
|
+
lastNoOpReason: snapshot.diagnostics.lastNoOpReason,
|
|
1110
|
+
queueDepth: snapshot.queue.depth,
|
|
1111
|
+
queueCapacity: snapshot.queue.capacity,
|
|
1112
|
+
running: snapshot.queue.running,
|
|
1113
|
+
lastAppliedMaterializationJobId: snapshot.runtime?.lastAppliedMaterializationJobId ?? snapshot.learner.lastMaterialization?.jobId ?? null,
|
|
1114
|
+
lastMaterializedPackId: snapshot.learner.lastMaterialization?.candidate.summary.packId ?? null
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
function buildWatchTeacherSnapshotLearningSummary(snapshot, lastHandledMaterializationPackId) {
|
|
1118
|
+
const plan = describeAlwaysOnLearningRuntimeState(snapshot.learner.state, snapshot.learner.lastMaterialization);
|
|
1119
|
+
return {
|
|
1120
|
+
bootstrapped: plan.bootstrapped,
|
|
1121
|
+
mode: plan.mode,
|
|
1122
|
+
nextPriorityLane: plan.nextPriorityLane,
|
|
1123
|
+
nextPriorityBucket: plan.nextPriorityBucket,
|
|
1124
|
+
pendingLive: plan.pending.live,
|
|
1125
|
+
pendingBackfill: plan.pending.backfill,
|
|
1126
|
+
pendingTotal: plan.pending.total,
|
|
1127
|
+
pendingByBucket: { ...plan.pending.byBucket },
|
|
1128
|
+
materializationCount: plan.materialization.count,
|
|
1129
|
+
lastMaterializedAt: plan.materialization.lastMaterializedAt,
|
|
1130
|
+
lastMaterializationReason: plan.materialization.lastReason,
|
|
1131
|
+
lastMaterializationLane: plan.materialization.lastLane,
|
|
1132
|
+
lastMaterializedPackId: snapshot.learner.lastMaterialization?.candidate.summary.packId ?? null,
|
|
1133
|
+
lastHandledMaterializationPackId
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
function buildWatchTeacherSnapshotLabelingSummary(snapshot) {
|
|
1137
|
+
const learningSurface = snapshot.learner.lastMaterialization?.candidate.summary.learningSurface ??
|
|
1138
|
+
snapshot.learner.state.learnedEventExport?.provenance.learningSurface ??
|
|
1139
|
+
null;
|
|
1140
|
+
return {
|
|
1141
|
+
learningCadence: learningSurface?.learningCadence ?? "passive_background",
|
|
1142
|
+
scanPolicy: learningSurface?.scanPolicy ?? "always_on",
|
|
1143
|
+
liveSlicesPerCycle: 1,
|
|
1144
|
+
backfillSlicesPerCycle: 1,
|
|
1145
|
+
teacherBudget: snapshot.learner.state.sparseFeedback.teacherBudget,
|
|
1146
|
+
teacherDelayMs: snapshot.learner.state.sparseFeedback.teacherDelayMs,
|
|
1147
|
+
backgroundLabelAmplification: snapshot.learner.state.sparseFeedback.backgroundLabelAmplification
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
function normalizeWatchTeacherSnapshotFromValue(value, snapshot, sourcePath) {
|
|
1151
|
+
const activationRoot = path.dirname(path.dirname(sourcePath));
|
|
1152
|
+
const defaultScanRoot = path.join(activationRoot, "event-exports");
|
|
1153
|
+
return {
|
|
1154
|
+
contract: "openclaw_watch_teacher_snapshot.v1",
|
|
1155
|
+
runtimeOwner: "openclaw",
|
|
1156
|
+
updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : new Date(0).toISOString(),
|
|
1157
|
+
lastRunAt: typeof value.lastRunAt === "string"
|
|
1158
|
+
? value.lastRunAt
|
|
1159
|
+
: typeof value.updatedAt === "string"
|
|
1160
|
+
? value.updatedAt
|
|
1161
|
+
: snapshot.diagnostics.lastProcessedAt ?? new Date(0).toISOString(),
|
|
1162
|
+
scanRoot: typeof value.scanRoot === "string" ? value.scanRoot : defaultScanRoot,
|
|
1163
|
+
sessionTailCursorPath: typeof value.sessionTailCursorPath === "string"
|
|
1164
|
+
? value.sessionTailCursorPath
|
|
1165
|
+
: resolveWatchSessionTailCursorPath(activationRoot),
|
|
1166
|
+
sessionTailCursorUpdatedAt: typeof value.sessionTailCursorUpdatedAt === "string"
|
|
1167
|
+
? value.sessionTailCursorUpdatedAt
|
|
1168
|
+
: typeof value.updatedAt === "string"
|
|
1169
|
+
? value.updatedAt
|
|
1170
|
+
: new Date(0).toISOString(),
|
|
1171
|
+
sessionTailSessionsTracked: typeof value.sessionTailSessionsTracked === "number" ? value.sessionTailSessionsTracked : 0,
|
|
1172
|
+
sessionTailBridgedEventCount: typeof value.sessionTailBridgedEventCount === "number" ? value.sessionTailBridgedEventCount : 0,
|
|
1173
|
+
scannerCheckpointPath: typeof value.scannerCheckpointPath === "string"
|
|
1174
|
+
? value.scannerCheckpointPath
|
|
1175
|
+
: path.join(typeof value.scanRoot === "string" ? value.scanRoot : defaultScanRoot, ".openclawbrain-scanner-checkpoint.json"),
|
|
1176
|
+
scannerCheckpoint: value.scannerCheckpoint !== undefined
|
|
1177
|
+
? cloneRuntimeEventExportScannerCheckpoint(value.scannerCheckpoint)
|
|
1178
|
+
: createRuntimeEventExportScannerCheckpoint({
|
|
1179
|
+
scanRoot: typeof value.scanRoot === "string" ? value.scanRoot : defaultScanRoot
|
|
1180
|
+
}),
|
|
1181
|
+
replayedBundleCount: typeof value.replayedBundleCount === "number" ? value.replayedBundleCount : 0,
|
|
1182
|
+
replayedEventCount: typeof value.replayedEventCount === "number" ? value.replayedEventCount : 0,
|
|
1183
|
+
exportedBundleCount: typeof value.exportedBundleCount === "number" ? value.exportedBundleCount : 0,
|
|
1184
|
+
exportedEventCount: typeof value.exportedEventCount === "number" ? value.exportedEventCount : 0,
|
|
1185
|
+
startupWarnings: Array.isArray(value.startupWarnings)
|
|
1186
|
+
? value.startupWarnings.filter((warning) => typeof warning === "string")
|
|
1187
|
+
: [],
|
|
1188
|
+
lastTeacherError: typeof value.lastTeacherError === "string"
|
|
1189
|
+
? value.lastTeacherError
|
|
1190
|
+
: null,
|
|
1191
|
+
localSessionTailNoopReason: typeof value.localSessionTailNoopReason === "string" ? value.localSessionTailNoopReason : null,
|
|
1192
|
+
lastHandledMaterializationPackId: typeof value.lastHandledMaterializationPackId === "string" ? value.lastHandledMaterializationPackId : null,
|
|
1193
|
+
teacher: value.teacher ?? buildWatchTeacherSnapshotTeacherSummary(snapshot),
|
|
1194
|
+
learning: value.learning ?? buildWatchTeacherSnapshotLearningSummary(snapshot, typeof value.lastHandledMaterializationPackId === "string" ? value.lastHandledMaterializationPackId : null),
|
|
1195
|
+
labeling: value.labeling ?? buildWatchTeacherSnapshotLabelingSummary(snapshot),
|
|
1196
|
+
failure: cloneWatchTeacherSnapshotFailure(value.failure),
|
|
1197
|
+
snapshot
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
export function resolveWatchStateRoot(activationRoot) {
|
|
1201
|
+
return path.resolve(normalizeNonEmptyString(activationRoot, "activationRoot"), WATCH_STATE_DIRNAME);
|
|
1202
|
+
}
|
|
1203
|
+
export function resolveWatchSessionTailCursorPath(activationRoot) {
|
|
1204
|
+
return path.join(resolveWatchStateRoot(activationRoot), WATCH_SESSION_TAIL_CURSOR_BASENAME);
|
|
1205
|
+
}
|
|
1206
|
+
export function resolveWatchTeacherSnapshotPath(activationRoot) {
|
|
1207
|
+
return path.join(resolveWatchStateRoot(activationRoot), WATCH_TEACHER_SNAPSHOT_BASENAME);
|
|
1208
|
+
}
|
|
1209
|
+
export function resolveOperatorTeacherSnapshotPath(activationRoot, explicitPath) {
|
|
1210
|
+
if (explicitPath !== null && explicitPath !== undefined) {
|
|
1211
|
+
return explicitPath;
|
|
1212
|
+
}
|
|
1213
|
+
const canonicalWatchSnapshotPath = resolveWatchTeacherSnapshotPath(activationRoot);
|
|
1214
|
+
if (existsSync(canonicalWatchSnapshotPath)) {
|
|
1215
|
+
return canonicalWatchSnapshotPath;
|
|
1216
|
+
}
|
|
1217
|
+
const asyncSnapshotPath = resolveAsyncTeacherLiveLoopSnapshotPath(activationRoot);
|
|
1218
|
+
return existsSync(asyncSnapshotPath) ? asyncSnapshotPath : null;
|
|
1219
|
+
}
|
|
1220
|
+
export function loadTeacherSurface(snapshotPath) {
|
|
1221
|
+
const resolvedPath = path.resolve(snapshotPath);
|
|
1222
|
+
let parsed;
|
|
1223
|
+
try {
|
|
1224
|
+
parsed = readJsonFile(resolvedPath);
|
|
1225
|
+
}
|
|
1226
|
+
catch {
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
if (isWatchTeacherSnapshot(parsed)) {
|
|
1230
|
+
const snapshot = loadAsyncTeacherLiveLoopSnapshotFromValue(parsed.snapshot);
|
|
1231
|
+
return {
|
|
1232
|
+
sourcePath: resolvedPath,
|
|
1233
|
+
sourceKind: "watch_snapshot",
|
|
1234
|
+
snapshot,
|
|
1235
|
+
watchSnapshot: normalizeWatchTeacherSnapshotFromValue(parsed, snapshot, resolvedPath)
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
if (isAsyncTeacherLiveLoopSnapshot(parsed)) {
|
|
1239
|
+
return {
|
|
1240
|
+
sourcePath: resolvedPath,
|
|
1241
|
+
sourceKind: "async_snapshot",
|
|
1242
|
+
snapshot: loadAsyncTeacherLiveLoopSnapshotFromValue(parsed),
|
|
1243
|
+
watchSnapshot: null
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
return null;
|
|
1247
|
+
}
|
|
1248
|
+
export function loadWatchTeacherSnapshotState(snapshotPath) {
|
|
1249
|
+
const resolvedPath = path.resolve(snapshotPath);
|
|
1250
|
+
if (!existsSync(resolvedPath)) {
|
|
1251
|
+
return {
|
|
1252
|
+
lastHandledMaterializationPackId: null,
|
|
1253
|
+
snapshot: null,
|
|
1254
|
+
error: null
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
let parsed;
|
|
1258
|
+
try {
|
|
1259
|
+
parsed = readJsonFile(resolvedPath);
|
|
1260
|
+
}
|
|
1261
|
+
catch (error) {
|
|
1262
|
+
return {
|
|
1263
|
+
lastHandledMaterializationPackId: null,
|
|
1264
|
+
snapshot: null,
|
|
1265
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
if (isWatchTeacherSnapshot(parsed)) {
|
|
1269
|
+
return {
|
|
1270
|
+
lastHandledMaterializationPackId: parsed.lastHandledMaterializationPackId,
|
|
1271
|
+
snapshot: loadAsyncTeacherLiveLoopSnapshotFromValue(parsed.snapshot),
|
|
1272
|
+
error: null
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
if (isAsyncTeacherLiveLoopSnapshot(parsed)) {
|
|
1276
|
+
return {
|
|
1277
|
+
lastHandledMaterializationPackId: null,
|
|
1278
|
+
snapshot: loadAsyncTeacherLiveLoopSnapshotFromValue(parsed),
|
|
1279
|
+
error: null
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
return {
|
|
1283
|
+
lastHandledMaterializationPackId: null,
|
|
1284
|
+
snapshot: null,
|
|
1285
|
+
error: `watch teacher snapshot is invalid: ${resolvedPath}`
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
export function persistWatchTeacherSnapshot(snapshotPath, input) {
|
|
1289
|
+
const persistedAt = new Date().toISOString();
|
|
1290
|
+
const canonicalSnapshot = loadAsyncTeacherLiveLoopSnapshotFromValue(input.snapshot);
|
|
1291
|
+
const payload = {
|
|
1292
|
+
contract: "openclaw_watch_teacher_snapshot.v1",
|
|
1293
|
+
runtimeOwner: "openclaw",
|
|
1294
|
+
updatedAt: persistedAt,
|
|
1295
|
+
lastRunAt: input.lastRunAt,
|
|
1296
|
+
scanRoot: path.resolve(input.scanRoot),
|
|
1297
|
+
sessionTailCursorPath: path.resolve(input.sessionTailCursorPath),
|
|
1298
|
+
sessionTailCursorUpdatedAt: input.sessionTailCursorUpdatedAt,
|
|
1299
|
+
sessionTailSessionsTracked: input.sessionTailSessionsTracked,
|
|
1300
|
+
sessionTailBridgedEventCount: input.sessionTailBridgedEventCount,
|
|
1301
|
+
scannerCheckpointPath: path.resolve(input.scannerCheckpointPath),
|
|
1302
|
+
scannerCheckpoint: cloneRuntimeEventExportScannerCheckpoint(input.scannerCheckpoint),
|
|
1303
|
+
replayedBundleCount: input.replayedBundleCount,
|
|
1304
|
+
replayedEventCount: input.replayedEventCount,
|
|
1305
|
+
exportedBundleCount: input.exportedBundleCount,
|
|
1306
|
+
exportedEventCount: input.exportedEventCount,
|
|
1307
|
+
startupWarnings: [...input.startupWarnings],
|
|
1308
|
+
lastTeacherError: input.lastTeacherError,
|
|
1309
|
+
localSessionTailNoopReason: input.localSessionTailNoopReason,
|
|
1310
|
+
lastHandledMaterializationPackId: input.lastHandledMaterializationPackId,
|
|
1311
|
+
teacher: buildWatchTeacherSnapshotTeacherSummary(canonicalSnapshot),
|
|
1312
|
+
learning: buildWatchTeacherSnapshotLearningSummary(canonicalSnapshot, input.lastHandledMaterializationPackId),
|
|
1313
|
+
labeling: buildWatchTeacherSnapshotLabelingSummary(canonicalSnapshot),
|
|
1314
|
+
failure: cloneWatchTeacherSnapshotFailure(input.failure),
|
|
1315
|
+
snapshot: canonicalSnapshot
|
|
1316
|
+
};
|
|
1317
|
+
mkdirSync(path.dirname(snapshotPath), { recursive: true });
|
|
1318
|
+
writeFileSync(snapshotPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
1319
|
+
return payload;
|
|
1320
|
+
}
|
|
1321
|
+
function loadAsyncTeacherLiveLoopSnapshotFromValue(snapshot) {
|
|
996
1322
|
if (snapshot.runtimeOwner !== "openclaw") {
|
|
997
1323
|
throw new Error("async teacher snapshot runtimeOwner must be openclaw");
|
|
998
1324
|
}
|
|
@@ -1019,6 +1345,17 @@ export function loadAsyncTeacherLiveLoopSnapshot(snapshotPath) {
|
|
|
1019
1345
|
}
|
|
1020
1346
|
return cloned;
|
|
1021
1347
|
}
|
|
1348
|
+
export function loadAsyncTeacherLiveLoopSnapshot(snapshotPath) {
|
|
1349
|
+
const resolvedPath = path.resolve(snapshotPath);
|
|
1350
|
+
const parsed = readJsonFile(resolvedPath);
|
|
1351
|
+
if (isWatchTeacherSnapshot(parsed)) {
|
|
1352
|
+
return loadAsyncTeacherLiveLoopSnapshotFromValue(parsed.snapshot);
|
|
1353
|
+
}
|
|
1354
|
+
if (isAsyncTeacherLiveLoopSnapshot(parsed)) {
|
|
1355
|
+
return loadAsyncTeacherLiveLoopSnapshotFromValue(parsed);
|
|
1356
|
+
}
|
|
1357
|
+
throw new Error(`async teacher snapshot is invalid: ${resolvedPath}`);
|
|
1358
|
+
}
|
|
1022
1359
|
function resolveBundlePayloadPath(rootDir, payloadPath) {
|
|
1023
1360
|
const resolved = path.resolve(rootDir, payloadPath);
|
|
1024
1361
|
const relative = path.relative(rootDir, resolved);
|
|
@@ -1653,6 +1990,18 @@ export class RuntimeEventExportScanner {
|
|
|
1653
1990
|
snapshot() {
|
|
1654
1991
|
return structuredClone(this.checkpoint);
|
|
1655
1992
|
}
|
|
1993
|
+
restoreCheckpoint(checkpoint) {
|
|
1994
|
+
const restored = structuredClone(checkpoint);
|
|
1995
|
+
const errors = validateRuntimeEventExportScannerCheckpoint(restored);
|
|
1996
|
+
if (errors.length > 0) {
|
|
1997
|
+
throw new Error(`runtime event export scanner checkpoint is invalid: ${errors.join("; ")}`);
|
|
1998
|
+
}
|
|
1999
|
+
if (restored.scanRoot !== this.scanRoot) {
|
|
2000
|
+
throw new Error(`runtime event export scanner checkpoint scanRoot mismatch: checkpoint=${restored.scanRoot} scanner=${this.scanRoot}`);
|
|
2001
|
+
}
|
|
2002
|
+
this.checkpoint = restored;
|
|
2003
|
+
writeRuntimeEventExportScannerCheckpoint(this.checkpointPath, this.checkpoint);
|
|
2004
|
+
}
|
|
1656
2005
|
scanOnce(options = {}) {
|
|
1657
2006
|
const scannedAt = normalizeIsoTimestamp(options.scannedAt, "scannedAt", new Date().toISOString());
|
|
1658
2007
|
const discovered = discoverRuntimeEventExportBundles(this.scanRoot);
|
|
@@ -2102,6 +2451,31 @@ function normalizeServeRouteChannel(value) {
|
|
|
2102
2451
|
function normalizeServeRouteMessage(value) {
|
|
2103
2452
|
return typeof value === "string" ? value.trim() : "";
|
|
2104
2453
|
}
|
|
2454
|
+
function normalizeServeRouteInstalledEntryPath(value) {
|
|
2455
|
+
if (typeof value !== "string") {
|
|
2456
|
+
return null;
|
|
2457
|
+
}
|
|
2458
|
+
const trimmed = value.trim();
|
|
2459
|
+
return trimmed.length === 0 ? null : path.resolve(trimmed);
|
|
2460
|
+
}
|
|
2461
|
+
function buildCompileServeRouteBreadcrumbs(input) {
|
|
2462
|
+
return {
|
|
2463
|
+
entrypoint: "compileRuntimeContext",
|
|
2464
|
+
invocationSurface: input._serveRouteBreadcrumbs?.invocationSurface ?? "direct_compile_call",
|
|
2465
|
+
hostEvent: input._serveRouteBreadcrumbs?.hostEvent ?? null,
|
|
2466
|
+
installedEntryPath: normalizeServeRouteInstalledEntryPath(input._serveRouteBreadcrumbs?.installedEntryPath),
|
|
2467
|
+
syntheticTurn: true
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2470
|
+
function buildRunRuntimeTurnServeRouteBreadcrumbs() {
|
|
2471
|
+
return {
|
|
2472
|
+
entrypoint: "runRuntimeTurn",
|
|
2473
|
+
invocationSurface: "runtime_turn_helper",
|
|
2474
|
+
hostEvent: null,
|
|
2475
|
+
installedEntryPath: null,
|
|
2476
|
+
syntheticTurn: false
|
|
2477
|
+
};
|
|
2478
|
+
}
|
|
2105
2479
|
function appendCompileServeRouteDecisionLog(input) {
|
|
2106
2480
|
if (input.compileInput._suppressServeLog) {
|
|
2107
2481
|
return;
|
|
@@ -2132,7 +2506,8 @@ function appendCompileServeRouteDecisionLog(input) {
|
|
|
2132
2506
|
activationRoot: input.activationRoot,
|
|
2133
2507
|
turn: syntheticTurn,
|
|
2134
2508
|
compileResult: input.compileResult,
|
|
2135
|
-
recordedAt
|
|
2509
|
+
recordedAt,
|
|
2510
|
+
breadcrumbs: buildCompileServeRouteBreadcrumbs(input.compileInput)
|
|
2136
2511
|
});
|
|
2137
2512
|
}
|
|
2138
2513
|
catch (error) {
|
|
@@ -3274,6 +3649,7 @@ export function writeScannedEventExportBundle(input) {
|
|
|
3274
3649
|
}
|
|
3275
3650
|
export function runRuntimeTurn(turn, options = {}) {
|
|
3276
3651
|
const warnings = [];
|
|
3652
|
+
const serveRouteBreadcrumbs = buildRunRuntimeTurnServeRouteBreadcrumbs();
|
|
3277
3653
|
const agentId = normalizeOptionalString(turn.agentId);
|
|
3278
3654
|
const compileInput = {
|
|
3279
3655
|
activationRoot: (options.activationRoot ?? turn.activationRoot),
|
|
@@ -3294,7 +3670,8 @@ export function runRuntimeTurn(turn, options = {}) {
|
|
|
3294
3670
|
activationRoot: compileResult.activationRoot,
|
|
3295
3671
|
turn,
|
|
3296
3672
|
compileResult,
|
|
3297
|
-
recordedAt: serveLoggedAt
|
|
3673
|
+
recordedAt: serveLoggedAt,
|
|
3674
|
+
breadcrumbs: serveRouteBreadcrumbs
|
|
3298
3675
|
});
|
|
3299
3676
|
}
|
|
3300
3677
|
catch (error) {
|
|
@@ -3312,7 +3689,8 @@ export function runRuntimeTurn(turn, options = {}) {
|
|
|
3312
3689
|
turn,
|
|
3313
3690
|
compileResult,
|
|
3314
3691
|
normalizedEventExport,
|
|
3315
|
-
recordedAt: compileEvent?.createdAt ?? serveLoggedAt
|
|
3692
|
+
recordedAt: compileEvent?.createdAt ?? serveLoggedAt,
|
|
3693
|
+
breadcrumbs: serveRouteBreadcrumbs
|
|
3316
3694
|
});
|
|
3317
3695
|
}
|
|
3318
3696
|
catch (error) {
|
|
@@ -4536,9 +4914,137 @@ function summarizeManyProfileSupport(policyMode) {
|
|
|
4536
4914
|
detail: "The Host has not declared shared-vs-dedicated attachment policy. Keep the operator read current-profile-only, do not infer profile exclusivity from activation state alone, and do not claim same-gateway many-profile proof."
|
|
4537
4915
|
};
|
|
4538
4916
|
}
|
|
4917
|
+
function summarizeRetainedActivationSlots(input) {
|
|
4918
|
+
const retained = [];
|
|
4919
|
+
if (input.candidate !== null) {
|
|
4920
|
+
retained.push(`candidate=${input.candidate.packId}`);
|
|
4921
|
+
}
|
|
4922
|
+
if (input.previous !== null) {
|
|
4923
|
+
retained.push(`previous=${input.previous.packId}`);
|
|
4924
|
+
}
|
|
4925
|
+
return retained.length === 0 ? "none" : retained.join(", ");
|
|
4926
|
+
}
|
|
4539
4927
|
function isAwaitingFirstExportSlot(slot) {
|
|
4540
4928
|
return slot !== null && slot.eventRange.count === 0;
|
|
4541
4929
|
}
|
|
4930
|
+
function summarizeOperatorActivationState(input) {
|
|
4931
|
+
if (input.inspectionError !== null) {
|
|
4932
|
+
return {
|
|
4933
|
+
state: "broken_install",
|
|
4934
|
+
detail: `activation root could not be inspected because activation pointers or pinned pack metadata are unreadable: ${input.inspectionError}`,
|
|
4935
|
+
inspectionError: input.inspectionError
|
|
4936
|
+
};
|
|
4937
|
+
}
|
|
4938
|
+
if (input.active !== null && !input.active.activationReady) {
|
|
4939
|
+
return {
|
|
4940
|
+
state: "broken_install",
|
|
4941
|
+
detail: input.active.findings.length > 0
|
|
4942
|
+
? `active pack ${input.active.packId} is pinned but not activation-ready: ${input.active.findings.join("; ")}`
|
|
4943
|
+
: `active pack ${input.active.packId} is pinned but not activation-ready`,
|
|
4944
|
+
inspectionError: null
|
|
4945
|
+
};
|
|
4946
|
+
}
|
|
4947
|
+
if (input.active === null) {
|
|
4948
|
+
if (input.candidate !== null || input.previous !== null) {
|
|
4949
|
+
return {
|
|
4950
|
+
state: "stale_incomplete",
|
|
4951
|
+
detail: `activation root has retained non-serving state but no active pack (${summarizeRetainedActivationSlots(input)})`,
|
|
4952
|
+
inspectionError: null
|
|
4953
|
+
};
|
|
4954
|
+
}
|
|
4955
|
+
return {
|
|
4956
|
+
state: "detached",
|
|
4957
|
+
detail: "activation root has no active, candidate, or previous pack pinned",
|
|
4958
|
+
inspectionError: null
|
|
4959
|
+
};
|
|
4960
|
+
}
|
|
4961
|
+
if (input.observability === null) {
|
|
4962
|
+
return {
|
|
4963
|
+
state: "broken_install",
|
|
4964
|
+
detail: `active pack ${input.active.packId} is pinned, but activation observability could not be derived`,
|
|
4965
|
+
inspectionError: null
|
|
4966
|
+
};
|
|
4967
|
+
}
|
|
4968
|
+
if (input.observability.initHandoff.handoffState === "pg_promoted_pack_authoritative") {
|
|
4969
|
+
return {
|
|
4970
|
+
state: "active_promoted",
|
|
4971
|
+
detail: `active pack ${input.active.packId} is authoritative through promotion, not the seed handoff`,
|
|
4972
|
+
inspectionError: null
|
|
4973
|
+
};
|
|
4974
|
+
}
|
|
4975
|
+
if (isAwaitingFirstExportSlot(input.active)) {
|
|
4976
|
+
return {
|
|
4977
|
+
state: "awaiting_first_export",
|
|
4978
|
+
detail: `active seed-state pack ${input.active.packId} is healthy but still waiting for the first live export`,
|
|
4979
|
+
inspectionError: null
|
|
4980
|
+
};
|
|
4981
|
+
}
|
|
4982
|
+
if (input.observability.initHandoff.handoffState === "seed_state_authoritative") {
|
|
4983
|
+
return {
|
|
4984
|
+
state: "healthy_seed",
|
|
4985
|
+
detail: `active seed-state pack ${input.active.packId} is serving beyond the first export`,
|
|
4986
|
+
inspectionError: null
|
|
4987
|
+
};
|
|
4988
|
+
}
|
|
4989
|
+
return {
|
|
4990
|
+
state: "stale_incomplete",
|
|
4991
|
+
detail: `active pack ${input.active.packId} is pinned, but init handoff truth is incomplete (${input.observability.initHandoff.handoffState})`,
|
|
4992
|
+
inspectionError: null
|
|
4993
|
+
};
|
|
4994
|
+
}
|
|
4995
|
+
function summarizeBrainStateWithoutObservability(active, activation) {
|
|
4996
|
+
return {
|
|
4997
|
+
state: active === null ? "no_active_pack" : "missing",
|
|
4998
|
+
initMode: null,
|
|
4999
|
+
runtimePlasticitySource: null,
|
|
5000
|
+
seedStateVisible: false,
|
|
5001
|
+
seedBlockCount: 0,
|
|
5002
|
+
activePackId: active?.packId ?? null,
|
|
5003
|
+
activeWorkspaceSnapshot: active?.workspaceSnapshot ?? null,
|
|
5004
|
+
activeEventExportDigest: active?.eventExportDigest ?? null,
|
|
5005
|
+
detail: activation.detail
|
|
5006
|
+
};
|
|
5007
|
+
}
|
|
5008
|
+
function summarizeGraphWithoutObservability(active, activation) {
|
|
5009
|
+
return {
|
|
5010
|
+
available: false,
|
|
5011
|
+
runtimePlasticitySource: null,
|
|
5012
|
+
structuralOps: null,
|
|
5013
|
+
changed: null,
|
|
5014
|
+
operationsApplied: [],
|
|
5015
|
+
liveBlockCount: null,
|
|
5016
|
+
prunedBlockCount: null,
|
|
5017
|
+
prePruneBlockCount: null,
|
|
5018
|
+
strongestBlockId: null,
|
|
5019
|
+
operatorSummary: null,
|
|
5020
|
+
detail: active === null
|
|
5021
|
+
? activation.detail
|
|
5022
|
+
: `active pack ${active.packId} is pinned, but graph observability is unavailable`
|
|
5023
|
+
};
|
|
5024
|
+
}
|
|
5025
|
+
function summarizeLearnedRoutingWithoutObservability(active) {
|
|
5026
|
+
return {
|
|
5027
|
+
required: active?.routePolicy === "requires_learned_routing",
|
|
5028
|
+
available: false,
|
|
5029
|
+
routerIdentity: active?.routerIdentity ?? null,
|
|
5030
|
+
routeFnVersion: null,
|
|
5031
|
+
trainingMethod: null,
|
|
5032
|
+
routerTrainedAt: null,
|
|
5033
|
+
objective: null,
|
|
5034
|
+
pgProfile: null,
|
|
5035
|
+
routerChecksum: null,
|
|
5036
|
+
objectiveChecksum: null,
|
|
5037
|
+
updateMechanism: null,
|
|
5038
|
+
updateVersion: null,
|
|
5039
|
+
updateCount: null,
|
|
5040
|
+
supervisionCount: null,
|
|
5041
|
+
collectedLabelsTotal: null,
|
|
5042
|
+
freshnessChecksum: null,
|
|
5043
|
+
handoffState: "missing",
|
|
5044
|
+
initMode: null,
|
|
5045
|
+
seedStateVisible: false
|
|
5046
|
+
};
|
|
5047
|
+
}
|
|
4542
5048
|
function summarizeBrainState(active, observability) {
|
|
4543
5049
|
if (active === null) {
|
|
4544
5050
|
return {
|
|
@@ -4692,6 +5198,11 @@ function summarizeServePath(compile) {
|
|
|
4692
5198
|
error: compile.error
|
|
4693
5199
|
};
|
|
4694
5200
|
}
|
|
5201
|
+
function probeOperatorServePath(activationRoot, observability, activePackId) {
|
|
5202
|
+
const compileInput = buildAttachStatusCompileInput(activationRoot, undefined);
|
|
5203
|
+
const compile = compileInput === null ? null : buildAttachCompileStatus(compileRuntimeContext(compileInput), observability, activePackId);
|
|
5204
|
+
return summarizeServePath(compile);
|
|
5205
|
+
}
|
|
4695
5206
|
function loadOperatorEventExport(input) {
|
|
4696
5207
|
const eventExportPath = normalizeOptionalString(input.eventExportPath);
|
|
4697
5208
|
if (eventExportPath === undefined) {
|
|
@@ -4880,70 +5391,125 @@ function summarizeSupervision(input) {
|
|
|
4880
5391
|
: "the supplied export does not yet show human supervision"
|
|
4881
5392
|
};
|
|
4882
5393
|
}
|
|
4883
|
-
function
|
|
5394
|
+
function loadTeacherSurfaceFromInput(input) {
|
|
4884
5395
|
const teacherSnapshotPath = normalizeOptionalString(input.teacherSnapshotPath);
|
|
4885
5396
|
if (teacherSnapshotPath === undefined) {
|
|
4886
5397
|
return null;
|
|
4887
5398
|
}
|
|
4888
|
-
return
|
|
5399
|
+
return loadTeacherSurface(teacherSnapshotPath);
|
|
4889
5400
|
}
|
|
4890
5401
|
function summarizeTeacherLoop(input) {
|
|
4891
|
-
const
|
|
4892
|
-
if (teacherSnapshotPath === undefined) {
|
|
5402
|
+
const loaded = loadTeacherSurfaceFromInput(input);
|
|
5403
|
+
if (loaded === null && normalizeOptionalString(input.teacherSnapshotPath) === undefined) {
|
|
4893
5404
|
return {
|
|
4894
5405
|
available: false,
|
|
4895
5406
|
sourcePath: null,
|
|
5407
|
+
sourceKind: "missing",
|
|
5408
|
+
lastRunAt: null,
|
|
4896
5409
|
lastNoOpReason: "unavailable",
|
|
4897
5410
|
latestFreshness: "unavailable",
|
|
4898
5411
|
startedAt: null,
|
|
4899
5412
|
lastHeartbeatAt: null,
|
|
4900
5413
|
lastScanAt: null,
|
|
4901
5414
|
lastProcessedAt: null,
|
|
5415
|
+
artifactCount: null,
|
|
4902
5416
|
queueDepth: null,
|
|
4903
5417
|
queueCapacity: null,
|
|
4904
5418
|
running: null,
|
|
5419
|
+
replayedBundleCount: null,
|
|
5420
|
+
replayedEventCount: null,
|
|
5421
|
+
exportedBundleCount: null,
|
|
5422
|
+
exportedEventCount: null,
|
|
5423
|
+
sessionTailSessionsTracked: null,
|
|
5424
|
+
sessionTailBridgedEventCount: null,
|
|
5425
|
+
localSessionTailNoopReason: null,
|
|
5426
|
+
learningCadence: "unavailable",
|
|
5427
|
+
scanPolicy: "unavailable",
|
|
5428
|
+
liveSlicesPerCycle: null,
|
|
5429
|
+
backfillSlicesPerCycle: null,
|
|
5430
|
+
failureMode: "unavailable",
|
|
5431
|
+
failureDetail: null,
|
|
4905
5432
|
lastAppliedMaterializationJobId: null,
|
|
4906
5433
|
lastMaterializedPackId: null,
|
|
4907
5434
|
notes: [],
|
|
4908
5435
|
detail: "no teacher snapshot path supplied"
|
|
4909
5436
|
};
|
|
4910
5437
|
}
|
|
4911
|
-
|
|
4912
|
-
|
|
5438
|
+
if (loaded === null) {
|
|
5439
|
+
const teacherSnapshotPath = normalizeOptionalString(input.teacherSnapshotPath);
|
|
4913
5440
|
return {
|
|
4914
5441
|
available: false,
|
|
4915
|
-
sourcePath: path.resolve(teacherSnapshotPath),
|
|
5442
|
+
sourcePath: teacherSnapshotPath === undefined ? null : path.resolve(teacherSnapshotPath),
|
|
5443
|
+
sourceKind: "missing",
|
|
5444
|
+
lastRunAt: null,
|
|
4916
5445
|
lastNoOpReason: "unavailable",
|
|
4917
5446
|
latestFreshness: "unavailable",
|
|
4918
5447
|
startedAt: null,
|
|
4919
5448
|
lastHeartbeatAt: null,
|
|
4920
5449
|
lastScanAt: null,
|
|
4921
5450
|
lastProcessedAt: null,
|
|
5451
|
+
artifactCount: null,
|
|
4922
5452
|
queueDepth: null,
|
|
4923
5453
|
queueCapacity: null,
|
|
4924
5454
|
running: null,
|
|
5455
|
+
replayedBundleCount: null,
|
|
5456
|
+
replayedEventCount: null,
|
|
5457
|
+
exportedBundleCount: null,
|
|
5458
|
+
exportedEventCount: null,
|
|
5459
|
+
sessionTailSessionsTracked: null,
|
|
5460
|
+
sessionTailBridgedEventCount: null,
|
|
5461
|
+
localSessionTailNoopReason: null,
|
|
5462
|
+
learningCadence: "unavailable",
|
|
5463
|
+
scanPolicy: "unavailable",
|
|
5464
|
+
liveSlicesPerCycle: null,
|
|
5465
|
+
backfillSlicesPerCycle: null,
|
|
5466
|
+
failureMode: "unavailable",
|
|
5467
|
+
failureDetail: null,
|
|
4925
5468
|
lastAppliedMaterializationJobId: null,
|
|
4926
5469
|
lastMaterializedPackId: null,
|
|
4927
5470
|
notes: [],
|
|
4928
5471
|
detail: "teacher snapshot could not be loaded"
|
|
4929
5472
|
};
|
|
4930
5473
|
}
|
|
5474
|
+
const snapshot = loaded.snapshot;
|
|
5475
|
+
const watchSnapshot = loaded.watchSnapshot;
|
|
4931
5476
|
return {
|
|
4932
5477
|
available: true,
|
|
4933
|
-
sourcePath:
|
|
5478
|
+
sourcePath: loaded.sourcePath,
|
|
5479
|
+
sourceKind: loaded.sourceKind,
|
|
5480
|
+
lastRunAt: watchSnapshot?.lastRunAt ?? snapshot.runtime?.lastHeartbeatAt ?? snapshot.diagnostics.lastProcessedAt ?? null,
|
|
4934
5481
|
lastNoOpReason: snapshot.diagnostics.lastNoOpReason,
|
|
4935
5482
|
latestFreshness: snapshot.diagnostics.latestFreshness,
|
|
4936
5483
|
startedAt: snapshot.runtime?.startedAt ?? null,
|
|
4937
5484
|
lastHeartbeatAt: snapshot.runtime?.lastHeartbeatAt ?? null,
|
|
4938
5485
|
lastScanAt: snapshot.runtime?.lastScanAt ?? null,
|
|
4939
5486
|
lastProcessedAt: snapshot.diagnostics.lastProcessedAt,
|
|
5487
|
+
artifactCount: watchSnapshot?.teacher.artifactCount ?? snapshot.teacher.artifactCount,
|
|
4940
5488
|
queueDepth: snapshot.queue.depth,
|
|
4941
5489
|
queueCapacity: snapshot.queue.capacity,
|
|
4942
5490
|
running: snapshot.queue.running,
|
|
4943
|
-
|
|
5491
|
+
replayedBundleCount: watchSnapshot?.replayedBundleCount ?? null,
|
|
5492
|
+
replayedEventCount: watchSnapshot?.replayedEventCount ?? null,
|
|
5493
|
+
exportedBundleCount: watchSnapshot?.exportedBundleCount ?? null,
|
|
5494
|
+
exportedEventCount: watchSnapshot?.exportedEventCount ?? null,
|
|
5495
|
+
sessionTailSessionsTracked: watchSnapshot?.sessionTailSessionsTracked ?? null,
|
|
5496
|
+
sessionTailBridgedEventCount: watchSnapshot?.sessionTailBridgedEventCount ?? null,
|
|
5497
|
+
localSessionTailNoopReason: watchSnapshot?.localSessionTailNoopReason ?? null,
|
|
5498
|
+
learningCadence: watchSnapshot?.labeling.learningCadence ?? "unavailable",
|
|
5499
|
+
scanPolicy: watchSnapshot?.labeling.scanPolicy ?? "unavailable",
|
|
5500
|
+
liveSlicesPerCycle: watchSnapshot?.labeling.liveSlicesPerCycle ?? null,
|
|
5501
|
+
backfillSlicesPerCycle: watchSnapshot?.labeling.backfillSlicesPerCycle ?? null,
|
|
5502
|
+
failureMode: watchSnapshot?.failure?.mode ?? "none",
|
|
5503
|
+
failureDetail: watchSnapshot?.failure?.detail ?? null,
|
|
5504
|
+
lastAppliedMaterializationJobId: watchSnapshot?.teacher.lastAppliedMaterializationJobId ??
|
|
5505
|
+
snapshot.runtime?.lastAppliedMaterializationJobId ??
|
|
5506
|
+
snapshot.learner.lastMaterialization?.jobId ??
|
|
5507
|
+
null,
|
|
4944
5508
|
lastMaterializedPackId: snapshot.learner.lastMaterialization?.candidate.summary.packId ?? null,
|
|
4945
5509
|
notes: [...snapshot.diagnostics.notes],
|
|
4946
|
-
detail:
|
|
5510
|
+
detail: loaded.sourceKind === "watch_snapshot"
|
|
5511
|
+
? "canonical watch teacher snapshot loaded"
|
|
5512
|
+
: "raw async teacher snapshot loaded"
|
|
4947
5513
|
};
|
|
4948
5514
|
}
|
|
4949
5515
|
function summarizeLearningBacklogState(plan, principalLagStatus) {
|
|
@@ -5000,8 +5566,8 @@ function summarizeAlwaysOnLearning(input, active) {
|
|
|
5000
5566
|
sequenceLag: null,
|
|
5001
5567
|
status: "unavailable"
|
|
5002
5568
|
};
|
|
5003
|
-
const
|
|
5004
|
-
if (teacherSnapshotPath === undefined) {
|
|
5569
|
+
const loadedTeacherSurface = loadTeacherSurfaceFromInput(input);
|
|
5570
|
+
if (loadedTeacherSurface === null && normalizeOptionalString(input.teacherSnapshotPath) === undefined) {
|
|
5005
5571
|
return {
|
|
5006
5572
|
available: false,
|
|
5007
5573
|
sourcePath: null,
|
|
@@ -5033,11 +5599,11 @@ function summarizeAlwaysOnLearning(input, active) {
|
|
|
5033
5599
|
detail: "no teacher snapshot path supplied"
|
|
5034
5600
|
};
|
|
5035
5601
|
}
|
|
5036
|
-
|
|
5037
|
-
|
|
5602
|
+
if (loadedTeacherSurface === null) {
|
|
5603
|
+
const teacherSnapshotPath = normalizeOptionalString(input.teacherSnapshotPath);
|
|
5038
5604
|
return {
|
|
5039
5605
|
available: false,
|
|
5040
|
-
sourcePath: path.resolve(teacherSnapshotPath),
|
|
5606
|
+
sourcePath: teacherSnapshotPath === undefined ? null : path.resolve(teacherSnapshotPath),
|
|
5041
5607
|
bootstrapped: null,
|
|
5042
5608
|
mode: "unavailable",
|
|
5043
5609
|
nextPriorityLane: "unavailable",
|
|
@@ -5066,6 +5632,7 @@ function summarizeAlwaysOnLearning(input, active) {
|
|
|
5066
5632
|
detail: "teacher snapshot could not be loaded"
|
|
5067
5633
|
};
|
|
5068
5634
|
}
|
|
5635
|
+
const snapshot = loadedTeacherSurface.snapshot;
|
|
5069
5636
|
const plan = describeAlwaysOnLearningRuntimeState(snapshot.learner.state, snapshot.learner.lastMaterialization);
|
|
5070
5637
|
const latestPrincipalSequence = plan.principalBacklog.checkpoints.reduce((latest, checkpoint) => {
|
|
5071
5638
|
const candidate = checkpoint.newestPendingSequence ?? checkpoint.learnedThroughSequence;
|
|
@@ -5091,7 +5658,7 @@ function summarizeAlwaysOnLearning(input, active) {
|
|
|
5091
5658
|
});
|
|
5092
5659
|
return {
|
|
5093
5660
|
available: true,
|
|
5094
|
-
sourcePath:
|
|
5661
|
+
sourcePath: loadedTeacherSurface.sourcePath,
|
|
5095
5662
|
bootstrapped: plan.bootstrapped,
|
|
5096
5663
|
mode: plan.mode,
|
|
5097
5664
|
nextPriorityLane: plan.nextPriorityLane,
|
|
@@ -5140,7 +5707,13 @@ function buildOperatorFindings(report) {
|
|
|
5140
5707
|
const push = (severity, code, summary, detail) => {
|
|
5141
5708
|
findings.push({ severity, code, summary, detail });
|
|
5142
5709
|
};
|
|
5143
|
-
if (report.
|
|
5710
|
+
if (report.activation.state === "broken_install") {
|
|
5711
|
+
push("fail", "activation_broken_install", "activation root is broken", report.activation.detail);
|
|
5712
|
+
}
|
|
5713
|
+
else if (report.activation.state === "stale_incomplete") {
|
|
5714
|
+
push("fail", "activation_stale_incomplete", "activation root is stale or incomplete", report.activation.detail);
|
|
5715
|
+
}
|
|
5716
|
+
else if (report.active === null) {
|
|
5144
5717
|
push("fail", "active_missing", "active slot is empty", "no active pack found; this is the pre-bootstrap state — call `bootstrapRuntimeAttach()` to activate an initial pack before compiling or serving");
|
|
5145
5718
|
}
|
|
5146
5719
|
else if (!report.active.activationReady) {
|
|
@@ -5281,12 +5854,18 @@ function summarizeCurrentProfileLogRoot(activationRoot) {
|
|
|
5281
5854
|
const logRoot = path.join(path.resolve(activationRoot), LEARNING_SPINE_LOG_LAYOUT.dir);
|
|
5282
5855
|
return existsSync(logRoot) ? logRoot : null;
|
|
5283
5856
|
}
|
|
5284
|
-
function summarizeCurrentProfileLastLearningUpdateAt(activationRoot, learning) {
|
|
5857
|
+
function summarizeCurrentProfileLastLearningUpdateAt(activationRoot, learning, teacherLoop) {
|
|
5285
5858
|
const updates = readLearningSpineLogEntries(activationRoot, "pgRouteUpdates");
|
|
5286
|
-
return updates.at(-1)?.recordedAt ?? learning.lastMaterializedAt ?? null;
|
|
5859
|
+
return updates.at(-1)?.recordedAt ?? teacherLoop.lastRunAt ?? learning.lastMaterializedAt ?? null;
|
|
5287
5860
|
}
|
|
5288
5861
|
function summarizeCurrentProfileBrainSummary(input) {
|
|
5289
5862
|
const packId = input.activePackId ?? "unknown";
|
|
5863
|
+
if (input.activationState === "broken_install") {
|
|
5864
|
+
return "Brain activation is broken and needs repair before serve-path truth can be trusted.";
|
|
5865
|
+
}
|
|
5866
|
+
if (input.activationState === "stale_incomplete") {
|
|
5867
|
+
return "Brain activation has retained stale/incomplete state and no serving active pack.";
|
|
5868
|
+
}
|
|
5290
5869
|
if (!input.attached) {
|
|
5291
5870
|
return "Brain is not attached to the current Profile.";
|
|
5292
5871
|
}
|
|
@@ -5322,6 +5901,7 @@ function summarizeCurrentProfileBrainStatusLevel(input) {
|
|
|
5322
5901
|
function buildCurrentProfileBrainStatusFromReport(report, policyMode, profileId) {
|
|
5323
5902
|
const attached = report.active !== null;
|
|
5324
5903
|
const awaitingFirstExport = isAwaitingFirstExportSlot(report.active);
|
|
5904
|
+
const activationState = report.activation.state;
|
|
5325
5905
|
const routerIdentity = report.servePath.routerIdentity ?? report.learnedRouting.routerIdentity ?? report.active?.routerIdentity ?? null;
|
|
5326
5906
|
const routeFreshness = report.servePath.refreshStatus === "updated" || report.servePath.refreshStatus === "no_supervision"
|
|
5327
5907
|
? report.servePath.refreshStatus
|
|
@@ -5360,16 +5940,20 @@ function buildCurrentProfileBrainStatusFromReport(report, policyMode, profileId)
|
|
|
5360
5940
|
routerIdentity,
|
|
5361
5941
|
routerChecksum: report.learnedRouting.routerChecksum,
|
|
5362
5942
|
lastExportAt: report.supervision.exportedAt,
|
|
5363
|
-
lastLearningUpdateAt: summarizeCurrentProfileLastLearningUpdateAt(report.activationRoot, report.learning),
|
|
5943
|
+
lastLearningUpdateAt: summarizeCurrentProfileLastLearningUpdateAt(report.activationRoot, report.learning, report.teacherLoop),
|
|
5364
5944
|
lastPromotionAt: report.promotion.lastPromotion.at,
|
|
5365
5945
|
summary: summarizeCurrentProfileBrainSummary({
|
|
5946
|
+
activationState,
|
|
5366
5947
|
attached,
|
|
5367
5948
|
serveState: report.servePath.state,
|
|
5368
5949
|
brainState: report.brain.state,
|
|
5369
5950
|
awaitingFirstExport,
|
|
5370
|
-
activePackId
|
|
5951
|
+
activePackId,
|
|
5952
|
+
activationDetail: report.activation.detail
|
|
5371
5953
|
}),
|
|
5372
|
-
detail:
|
|
5954
|
+
detail: activationState === "broken_install" || activationState === "stale_incomplete" || activationState === "detached"
|
|
5955
|
+
? report.activation.detail
|
|
5956
|
+
: report.brain.detail
|
|
5373
5957
|
},
|
|
5374
5958
|
attachment: attached
|
|
5375
5959
|
? {
|
|
@@ -5398,21 +5982,28 @@ function buildCurrentProfileBrainStatusFromReport(report, policyMode, profileId)
|
|
|
5398
5982
|
status,
|
|
5399
5983
|
brainState: report.brain.state,
|
|
5400
5984
|
serveState: report.servePath.state,
|
|
5985
|
+
activationState,
|
|
5401
5986
|
usedLearnedRouteFn: report.servePath.usedLearnedRouteFn,
|
|
5402
5987
|
failOpen: report.servePath.fallbackToStaticContext,
|
|
5403
5988
|
awaitingFirstExport,
|
|
5404
5989
|
structuralDecision: report.servePath.structuralDecision,
|
|
5405
|
-
detail:
|
|
5406
|
-
?
|
|
5407
|
-
|
|
5408
|
-
: report.
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5990
|
+
detail: activationState === "broken_install"
|
|
5991
|
+
? `current profile activation is broken: ${report.activation.detail}`
|
|
5992
|
+
: activationState === "stale_incomplete"
|
|
5993
|
+
? `current profile activation is stale/incomplete: ${report.activation.detail}`
|
|
5994
|
+
: activationState === "detached"
|
|
5995
|
+
? "current profile has no attached active pack at the activation boundary"
|
|
5996
|
+
: report.servePath.state === "serving_active_pack"
|
|
5997
|
+
? awaitingFirstExport
|
|
5998
|
+
? `current profile is serving seed-state pack ${activePackId ?? "unknown"} while awaiting the first exported turn`
|
|
5999
|
+
: report.brain.state === "pg_promoted_pack_authoritative"
|
|
6000
|
+
? `current profile is serving promoted pack ${activePackId ?? "unknown"}; serve-visible change came from activation promotion, not hot-path mutation`
|
|
6001
|
+
: `current profile is serving active pack ${activePackId ?? "unknown"}; learned routing is active, but authority is still seed-state`
|
|
6002
|
+
: report.servePath.state === "fail_open_static_context"
|
|
6003
|
+
? "current profile would fail open to static context because no serving pack is available"
|
|
6004
|
+
: report.servePath.state === "hard_fail"
|
|
6005
|
+
? "current profile cannot serve because the learned-route or activation requirement hard-failed"
|
|
6006
|
+
: "current profile serve state has not been compile-probed yet"
|
|
5416
6007
|
},
|
|
5417
6008
|
currentTurnAttribution: null
|
|
5418
6009
|
};
|
|
@@ -5421,62 +6012,100 @@ export function buildOperatorSurfaceReport(input) {
|
|
|
5421
6012
|
const activationRoot = path.resolve(normalizeNonEmptyString(input.activationRoot, "activationRoot"));
|
|
5422
6013
|
const updatedAt = normalizeIsoTimestamp(input.updatedAt, "updatedAt", new Date().toISOString());
|
|
5423
6014
|
const brainAttachmentPolicy = normalizeBrainAttachmentPolicy(input.brainAttachmentPolicy);
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
6015
|
+
let inspection = null;
|
|
6016
|
+
let observability = null;
|
|
6017
|
+
let inspectionError = null;
|
|
6018
|
+
try {
|
|
6019
|
+
inspection = inspectActivationState(activationRoot, updatedAt);
|
|
6020
|
+
}
|
|
6021
|
+
catch (error) {
|
|
6022
|
+
inspectionError = toErrorMessage(error);
|
|
6023
|
+
}
|
|
6024
|
+
const active = inspection === null ? null : summarizeOperatorSlot(inspection.active, inspection.pointers.active?.updatedAt ?? null);
|
|
6025
|
+
const candidate = inspection === null ? null : summarizeOperatorSlot(inspection.candidate, inspection.pointers.candidate?.updatedAt ?? null);
|
|
6026
|
+
const previous = inspection === null ? null : summarizeOperatorSlot(inspection.previous, inspection.pointers.previous?.updatedAt ?? null);
|
|
6027
|
+
if (inspection !== null && inspection.active !== null) {
|
|
6028
|
+
try {
|
|
6029
|
+
observability = describeActivationObservability(activationRoot, "active", {
|
|
6030
|
+
updatedAt
|
|
6031
|
+
});
|
|
6032
|
+
}
|
|
6033
|
+
catch (error) {
|
|
6034
|
+
inspectionError ??= `activation observability failed: ${toErrorMessage(error)}`;
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
const activation = summarizeOperatorActivationState({
|
|
6038
|
+
inspection,
|
|
6039
|
+
observability,
|
|
6040
|
+
active,
|
|
6041
|
+
candidate,
|
|
6042
|
+
previous,
|
|
6043
|
+
inspectionError
|
|
5427
6044
|
});
|
|
5428
|
-
const
|
|
5429
|
-
|
|
5430
|
-
|
|
6045
|
+
const activeObservability = inspectionError === null
|
|
6046
|
+
? summarizeActivePackObservability(activationRoot, active)
|
|
6047
|
+
: {
|
|
6048
|
+
labelFlow: buildMissingLabelFlowSummary(`activation observability is unavailable: ${inspectionError}`),
|
|
6049
|
+
learningPath: buildMissingLearningPathSummary(`activation observability is unavailable: ${inspectionError}`)
|
|
6050
|
+
};
|
|
6051
|
+
const servePath = probeOperatorServePath(activationRoot, observability, active?.packId ?? null);
|
|
5431
6052
|
const reportBase = {
|
|
5432
6053
|
generatedAt: updatedAt,
|
|
5433
6054
|
activationRoot,
|
|
6055
|
+
activation,
|
|
5434
6056
|
active,
|
|
5435
|
-
candidate
|
|
5436
|
-
previous
|
|
6057
|
+
candidate,
|
|
6058
|
+
previous,
|
|
5437
6059
|
freshness: {
|
|
5438
|
-
activeBehindPromotionReadyCandidate: observability
|
|
5439
|
-
candidateAheadBy: summarizeCandidateAheadBy(observability
|
|
6060
|
+
activeBehindPromotionReadyCandidate: observability?.promotionFreshness.activeBehindPromotionReadyCandidate ?? false,
|
|
6061
|
+
candidateAheadBy: summarizeCandidateAheadBy(observability?.promotionFreshness.candidateAheadBy ?? null)
|
|
5440
6062
|
},
|
|
5441
|
-
brain: summarizeBrainState(active, observability),
|
|
5442
|
-
graph: summarizeGraphObservability(active, observability),
|
|
6063
|
+
brain: observability === null ? summarizeBrainStateWithoutObservability(active, activation) : summarizeBrainState(active, observability),
|
|
6064
|
+
graph: observability === null ? summarizeGraphWithoutObservability(active, activation) : summarizeGraphObservability(active, observability),
|
|
5443
6065
|
labelFlow: activeObservability.labelFlow,
|
|
5444
6066
|
learningPath: activeObservability.learningPath,
|
|
5445
|
-
learnedRouting:
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
6067
|
+
learnedRouting: observability === null
|
|
6068
|
+
? summarizeLearnedRoutingWithoutObservability(active)
|
|
6069
|
+
: {
|
|
6070
|
+
required: observability.learnedRouteFn.required,
|
|
6071
|
+
available: observability.learnedRouteFn.available,
|
|
6072
|
+
routerIdentity: observability.learnedRouteFn.routerIdentity,
|
|
6073
|
+
routeFnVersion: observability.learnedRouteFn.routeFnVersion,
|
|
6074
|
+
trainingMethod: observability.learnedRouteFn.trainingMethod,
|
|
6075
|
+
routerTrainedAt: observability.learnedRouteFn.routerTrainedAt,
|
|
6076
|
+
objective: observability.learnedRouteFn.objective,
|
|
6077
|
+
pgProfile: observability.learnedRouteFn.pgProfile,
|
|
6078
|
+
routerChecksum: observability.learnedRouteFn.routerChecksum,
|
|
6079
|
+
objectiveChecksum: observability.learnedRouteFn.objectiveChecksum,
|
|
6080
|
+
updateMechanism: observability.learnedRouteFn.updateMechanism,
|
|
6081
|
+
updateVersion: observability.learnedRouteFn.updateVersion,
|
|
6082
|
+
updateCount: observability.learnedRouteFn.updateCount,
|
|
6083
|
+
supervisionCount: observability.learnedRouteFn.supervisionCount,
|
|
6084
|
+
collectedLabelsTotal: observability.learnedRouteFn.collectedLabels?.total ?? null,
|
|
6085
|
+
freshnessChecksum: observability.learnedRouteFn.freshnessChecksum,
|
|
6086
|
+
handoffState: observability.initHandoff.handoffState,
|
|
6087
|
+
initMode: observability.initHandoff.initMode,
|
|
6088
|
+
seedStateVisible: observability.initHandoff.seedStateVisible
|
|
6089
|
+
},
|
|
6090
|
+
servePath,
|
|
5467
6091
|
promotion: {
|
|
5468
|
-
allowed: inspection
|
|
5469
|
-
findings: [...inspection
|
|
5470
|
-
lastPromotion:
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
6092
|
+
allowed: inspection?.promotion.allowed ?? false,
|
|
6093
|
+
findings: [...(inspection?.promotion.findings ?? [])],
|
|
6094
|
+
lastPromotion: inspection === null ? {
|
|
6095
|
+
known: false,
|
|
6096
|
+
at: null,
|
|
6097
|
+
confidence: "unknown_from_local_pointers",
|
|
6098
|
+
note: activation.detail
|
|
6099
|
+
} : summarizeLastPromotion(inspection),
|
|
6100
|
+
activeUpdatedAt: inspection?.pointers.active?.updatedAt ?? null,
|
|
6101
|
+
candidateUpdatedAt: inspection?.pointers.candidate?.updatedAt ?? null,
|
|
6102
|
+
previousUpdatedAt: inspection?.pointers.previous?.updatedAt ?? null
|
|
5474
6103
|
},
|
|
5475
6104
|
rollback: {
|
|
5476
|
-
allowed: inspection
|
|
5477
|
-
findings: [...inspection
|
|
5478
|
-
previousPackId: inspection
|
|
5479
|
-
state: inspection.rollback.allowed ? "ready" : inspection.active === null ? "unknown" : "blocked"
|
|
6105
|
+
allowed: inspection?.rollback.allowed ?? false,
|
|
6106
|
+
findings: [...(inspection?.rollback.findings ?? [])],
|
|
6107
|
+
previousPackId: inspection?.previous?.packId ?? inspection?.pointers.previous?.packId ?? null,
|
|
6108
|
+
state: inspection === null ? "unknown" : inspection.rollback.allowed ? "ready" : inspection.active === null ? "unknown" : "blocked"
|
|
5480
6109
|
},
|
|
5481
6110
|
supervision: summarizeSupervision(input),
|
|
5482
6111
|
learning: summarizeAlwaysOnLearning(input, active),
|
|
@@ -5564,6 +6193,7 @@ export { describeActivationObservability, inspectActivationState, rollbackActive
|
|
|
5564
6193
|
export { createOpenClawLocalSessionTail, OpenClawLocalSessionTail } from "./session-tail.js";
|
|
5565
6194
|
export { discoverOpenClawMainSessionStores, discoverOpenClawSessionStores, loadOpenClawSessionIndex, readOpenClawAcpStreamFile, readOpenClawSessionFile } from "./session-store.js";
|
|
5566
6195
|
export { buildPassiveLearningSessionExportFromOpenClawSessionStore, buildPassiveLearningStoreExportFromOpenClawSessionIndex } from "./local-session-passive-learning.js";
|
|
6196
|
+
export { DEFAULT_OLLAMA_BASE_URL, DEFAULT_OLLAMA_TIMEOUT_MS, OllamaClient, OllamaClientError, createOllamaClient } from "./ollama-client.js";
|
|
5567
6197
|
export { resolveActivationRoot } from "./resolve-activation-root.js";
|
|
5568
6198
|
export { runDaemonCommand, parseDaemonArgs } from "./daemon.js";
|
|
5569
6199
|
//# sourceMappingURL=index.js.map
|