@openclawbrain/cli 0.4.15 → 0.4.16
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 +6 -4
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.js +170 -6
- package/dist/src/install-converge.js +4 -3
- package/dist/src/local-learner.js +4 -2
- package/dist/src/proof-command.js +55 -3
- package/dist/src/teacher-labeler.d.ts +12 -0
- package/dist/src/teacher-labeler.js +42 -0
- package/package.json +1 -1
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 } 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, writeScannedEventExportBundle } from "./index.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";
|
|
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";
|
|
@@ -682,14 +682,14 @@ const LEARNING_WARNING_MESSAGES = {
|
|
|
682
682
|
passive_backfill_pending: "passive backfill remains queued",
|
|
683
683
|
teacher_queue_full: "teacher queue is full",
|
|
684
684
|
teacher_labels_stale: "teacher labels are stale",
|
|
685
|
-
teacher_no_artifacts: "
|
|
685
|
+
teacher_no_artifacts: "latest no-op cycle had teachable material but no new teacher artifact",
|
|
686
686
|
teacher_snapshot_unavailable: "teacher snapshot is unavailable"
|
|
687
687
|
};
|
|
688
688
|
const TEACHER_NO_OP_MESSAGES = {
|
|
689
689
|
none: "the latest processed export produced teacher artifacts",
|
|
690
690
|
duplicate_export: "the latest cycle was a no-op because the export was already seen",
|
|
691
691
|
queue_full: "the latest cycle was a no-op because the teacher queue was full",
|
|
692
|
-
no_teacher_artifacts: "the latest cycle
|
|
692
|
+
no_teacher_artifacts: "the latest cycle produced no new teacher artifacts",
|
|
693
693
|
empty_scan: "the latest cycle was a no-op because the scanner did not produce any events",
|
|
694
694
|
unavailable: "the latest cycle is not visible from the current operator snapshot"
|
|
695
695
|
};
|
|
@@ -1089,7 +1089,9 @@ function summarizeStatusTeacher(report, providerConfig, localLlm) {
|
|
|
1089
1089
|
const healthy = report.teacherLoop.failureMode === "none" &&
|
|
1090
1090
|
stale === false &&
|
|
1091
1091
|
report.teacherLoop.watchState !== "not_visible";
|
|
1092
|
-
const cycleDetail =
|
|
1092
|
+
const cycleDetail = report.teacherLoop.lastNoOpReason === "no_teacher_artifacts"
|
|
1093
|
+
? summarizeTeacherNoArtifactCycle(report.teacherLoop.notes).detail
|
|
1094
|
+
: TEACHER_NO_OP_MESSAGES[report.teacherLoop.lastNoOpReason] ?? "the latest teacher cycle detail is unavailable";
|
|
1093
1095
|
if (report.teacherLoop.failureMode !== "none" && report.teacherLoop.failureMode !== "unavailable") {
|
|
1094
1096
|
return {
|
|
1095
1097
|
model: providerConfig.teacher.model,
|
package/dist/src/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { type AdvanceAlwaysOnLearningRuntimeInput, type AlwaysOnLearningCadenceV
|
|
|
5
5
|
import { type ActivationInspection, type ActivationObservabilityReport, type GraphEvolutionLogV1, type LearningSpineServeRouteBreadcrumbsV1, type ActivationSlotInspection, type InitHandoffState, type LearningSpineServeRouteDecisionLogEntryV1 } from "@openclawbrain/pack-format";
|
|
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
|
-
export { createHttpOllamaTeacherLabelerClient, createOllamaTeacherLabeler, createTeacherLabeler, type AsyncTeacherLabelerConfigV1, type AsyncTeacherNoopLabelerConfigV1, type AsyncTeacherOllamaLabelerConfigV1, type OllamaTeacherLabelerClient, type TeacherLabeler, type TeacherLabelerResultV1, type TeacherLabelerRunInputV1 } from "./teacher-labeler.js";
|
|
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
9
|
export declare const DEFAULT_ASYNC_TEACHER_QUEUE_CAPACITY = 8;
|
|
10
10
|
declare const RECORDED_SESSION_TRACE_CONTRACT: "recorded_session_trace.v1";
|
|
11
11
|
declare const RECORDED_SESSION_FIXTURE_CONTRACT: "recorded_session_replay_fixture.v1";
|
|
@@ -401,6 +401,10 @@ export interface AsyncTeacherLiveLoopInput extends Pick<AdvanceAlwaysOnLearningR
|
|
|
401
401
|
persistUpdatedBaseline?: (state: BaselineStateV1) => void;
|
|
402
402
|
teacherLabeler?: AsyncTeacherLabelerConfigV1 | null;
|
|
403
403
|
}
|
|
404
|
+
export interface TeacherNoArtifactCycleSummaryV1 {
|
|
405
|
+
shouldWarn: boolean;
|
|
406
|
+
detail: string;
|
|
407
|
+
}
|
|
404
408
|
export interface AsyncTeacherQueuedExportJobV1 {
|
|
405
409
|
jobId: string;
|
|
406
410
|
exportDigest: string;
|
|
@@ -681,6 +685,7 @@ export declare const WATCH_STATE_DIRNAME = "watch";
|
|
|
681
685
|
export declare const WATCH_SESSION_TAIL_CURSOR_BASENAME = "session-tail-cursor.json";
|
|
682
686
|
export declare const WATCH_TEACHER_SNAPSHOT_BASENAME = "teacher-snapshot.json";
|
|
683
687
|
export declare const DEFAULT_WATCH_POLL_INTERVAL_SECONDS = 30;
|
|
688
|
+
export declare function summarizeTeacherNoArtifactCycle(notes: readonly string[] | null | undefined): TeacherNoArtifactCycleSummaryV1;
|
|
684
689
|
export interface WatchTeacherSnapshotFailureV1 {
|
|
685
690
|
mode: "materialization_failed" | "teacher_fail_open";
|
|
686
691
|
detail: string;
|
package/dist/src/index.js
CHANGED
|
@@ -12,8 +12,8 @@ import { inspectOpenClawBrainHookStatus, summarizeOpenClawBrainHookLoad } from "
|
|
|
12
12
|
import { appendLearningUpdateLogs, appendServeTimeRouteDecisionLog } from "./learning-spine.js";
|
|
13
13
|
import { buildFeedbackSemanticMetadata, buildInteractionSemanticMetadata } from "./semantic-metadata.js";
|
|
14
14
|
export { clearOpenClawProfileRuntimeLoadProof, listOpenClawProfileRuntimeLoadProofs, recordOpenClawProfileRuntimeLoadProof, resolveAttachmentRuntimeLoadProofsPath } from "./attachment-truth.js";
|
|
15
|
-
import { createTeacherLabeler } from "./teacher-labeler.js";
|
|
16
|
-
export { createHttpOllamaTeacherLabelerClient, createOllamaTeacherLabeler, createTeacherLabeler } from "./teacher-labeler.js";
|
|
15
|
+
import { createTeacherLabeler, summarizeTeacherLabelerOpportunity } from "./teacher-labeler.js";
|
|
16
|
+
export { createHttpOllamaTeacherLabelerClient, createOllamaTeacherLabeler, createTeacherLabeler, summarizeTeacherLabelerOpportunity } from "./teacher-labeler.js";
|
|
17
17
|
const DEFAULT_AGENT_ID = "openclaw-runtime";
|
|
18
18
|
const FEEDBACK_KINDS = new Set(["correction", "teaching", "approval", "suppression"]);
|
|
19
19
|
export const DEFAULT_ASYNC_TEACHER_QUEUE_CAPACITY = 8;
|
|
@@ -250,9 +250,45 @@ function buildAsyncTeacherLoopNotes(input) {
|
|
|
250
250
|
`teacher_noop=${input.noOpReason}`,
|
|
251
251
|
`teacher_labeler=${input.teacherLabeler?.status ?? "disabled"}`,
|
|
252
252
|
`teacher_labeler_detail=${input.teacherLabeler?.detail ?? "disabled"}`,
|
|
253
|
+
`teacher_last_cycle_deterministic_artifacts=${input.lastCycle?.deterministicArtifactCount ?? "unknown"}`,
|
|
254
|
+
`teacher_last_cycle_new_deterministic_artifacts=${input.lastCycle?.newDeterministicArtifactCount ?? "unknown"}`,
|
|
255
|
+
`teacher_last_cycle_labeler_candidates=${input.lastCycle?.labelerCandidateCount ?? "unknown"}`,
|
|
256
|
+
`teacher_last_cycle_labeler_budgeted_candidates=${input.lastCycle?.labelerBudgetedCandidateCount ?? "unknown"}`,
|
|
257
|
+
`teacher_last_cycle_labeler_status=${input.lastCycle?.labelerStatus ?? "unknown"}`,
|
|
258
|
+
`teacher_last_cycle_labeler_detail=${input.lastCycle?.labelerDetail ?? "unknown"}`,
|
|
253
259
|
input.materialization === null ? "teacher_materialization=noop" : `teacher_materialized_pack=${input.materialization.candidate.summary.packId}`
|
|
254
260
|
];
|
|
255
261
|
}
|
|
262
|
+
function parseAsyncTeacherLastCycleNotes(notes) {
|
|
263
|
+
const values = new Map();
|
|
264
|
+
for (const note of notes) {
|
|
265
|
+
const separator = note.indexOf("=");
|
|
266
|
+
if (separator <= 0) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
values.set(note.slice(0, separator), note.slice(separator + 1));
|
|
270
|
+
}
|
|
271
|
+
const readNullableNumber = (key) => {
|
|
272
|
+
const raw = values.get(key);
|
|
273
|
+
if (raw === undefined || raw === "unknown") {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
const parsed = Number.parseInt(raw, 10);
|
|
277
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
278
|
+
};
|
|
279
|
+
const readNullableString = (key) => {
|
|
280
|
+
const raw = values.get(key);
|
|
281
|
+
return raw === undefined || raw === "unknown" ? null : raw;
|
|
282
|
+
};
|
|
283
|
+
return {
|
|
284
|
+
deterministicArtifactCount: readNullableNumber("teacher_last_cycle_deterministic_artifacts"),
|
|
285
|
+
newDeterministicArtifactCount: readNullableNumber("teacher_last_cycle_new_deterministic_artifacts"),
|
|
286
|
+
labelerCandidateCount: readNullableNumber("teacher_last_cycle_labeler_candidates"),
|
|
287
|
+
labelerBudgetedCandidateCount: readNullableNumber("teacher_last_cycle_labeler_budgeted_candidates"),
|
|
288
|
+
labelerStatus: readNullableString("teacher_last_cycle_labeler_status"),
|
|
289
|
+
labelerDetail: readNullableString("teacher_last_cycle_labeler_detail")
|
|
290
|
+
};
|
|
291
|
+
}
|
|
256
292
|
function cloneAlwaysOnLearningMaterializationJobOrNull(value) {
|
|
257
293
|
return value === null ? null : structuredClone(value);
|
|
258
294
|
}
|
|
@@ -565,6 +601,14 @@ export class AsyncTeacherLiveLoop {
|
|
|
565
601
|
learnerState = createAlwaysOnLearningRuntimeState();
|
|
566
602
|
lastMaterialization = null;
|
|
567
603
|
lastTeacherLabelerResult = null;
|
|
604
|
+
lastCycle = {
|
|
605
|
+
deterministicArtifactCount: null,
|
|
606
|
+
newDeterministicArtifactCount: null,
|
|
607
|
+
labelerCandidateCount: null,
|
|
608
|
+
labelerBudgetedCandidateCount: null,
|
|
609
|
+
labelerStatus: null,
|
|
610
|
+
labelerDetail: null
|
|
611
|
+
};
|
|
568
612
|
diagnostics = {
|
|
569
613
|
acceptedExportCount: 0,
|
|
570
614
|
processedExportCount: 0,
|
|
@@ -584,7 +628,8 @@ export class AsyncTeacherLiveLoop {
|
|
|
584
628
|
sparseFeedback: this.learnerState.sparseFeedback,
|
|
585
629
|
noOpReason: "none",
|
|
586
630
|
materialization: null,
|
|
587
|
-
teacherLabeler: null
|
|
631
|
+
teacherLabeler: null,
|
|
632
|
+
lastCycle: this.lastCycle
|
|
588
633
|
})
|
|
589
634
|
};
|
|
590
635
|
constructor(input) {
|
|
@@ -612,6 +657,7 @@ export class AsyncTeacherLiveLoop {
|
|
|
612
657
|
...structuredClone(resumedSnapshot.diagnostics),
|
|
613
658
|
notes: [...resumedSnapshot.diagnostics.notes]
|
|
614
659
|
};
|
|
660
|
+
this.lastCycle = parseAsyncTeacherLastCycleNotes(this.diagnostics.notes);
|
|
615
661
|
for (const exportDigest of resumedSnapshot.state?.seenExportDigests ?? []) {
|
|
616
662
|
this.seenExportDigests.add(exportDigest);
|
|
617
663
|
}
|
|
@@ -858,6 +904,19 @@ export class AsyncTeacherLiveLoop {
|
|
|
858
904
|
feedbackEvents: this.feedbackEvents
|
|
859
905
|
});
|
|
860
906
|
const learnedRoutingState = this.input.resolveLearnedRoutingState?.() ?? {};
|
|
907
|
+
const currentDedupIds = new Set(this.teacherArtifacts.map((artifact) => artifact.dedupId));
|
|
908
|
+
const currentCycleBuiltArtifacts = buildTeacherSupervisionArtifactsFromNormalizedEventExport({
|
|
909
|
+
normalizedEventExport: job.normalizedEventExport,
|
|
910
|
+
observedAt: job.observedAt,
|
|
911
|
+
staleAfterMs: this.staleAfterMs,
|
|
912
|
+
...(this.input.sparseFeedback !== undefined ? { sparseFeedback: this.input.sparseFeedback } : {})
|
|
913
|
+
});
|
|
914
|
+
const currentCycleOpportunity = summarizeTeacherLabelerOpportunity({
|
|
915
|
+
normalizedEventExport: job.normalizedEventExport,
|
|
916
|
+
...(learnedRoutingState.serveTimeDecisions !== undefined
|
|
917
|
+
? { serveTimeDecisions: learnedRoutingState.serveTimeDecisions }
|
|
918
|
+
: {})
|
|
919
|
+
}, this.input.teacherLabeler ?? null);
|
|
861
920
|
const builtArtifacts = buildTeacherSupervisionArtifactsFromNormalizedEventExport({
|
|
862
921
|
normalizedEventExport: mergedNormalizedEventExport,
|
|
863
922
|
observedAt: job.observedAt,
|
|
@@ -887,10 +946,21 @@ export class AsyncTeacherLiveLoop {
|
|
|
887
946
|
}
|
|
888
947
|
}
|
|
889
948
|
const nextBuiltArtifacts = mergeTeacherArtifacts([], [...builtArtifacts, ...generatedTeacherArtifacts]);
|
|
890
|
-
const currentDedupIds = new Set(this.teacherArtifacts.map((artifact) => artifact.dedupId));
|
|
891
949
|
const nextTeacherArtifacts = mergeTeacherArtifacts(this.teacherArtifacts, nextBuiltArtifacts);
|
|
892
950
|
const emittedArtifactCount = nextBuiltArtifacts.filter((artifact) => !currentDedupIds.has(artifact.dedupId)).length;
|
|
893
951
|
const dedupedArtifactCount = nextBuiltArtifacts.length - emittedArtifactCount;
|
|
952
|
+
this.lastCycle = {
|
|
953
|
+
deterministicArtifactCount: currentCycleBuiltArtifacts.length,
|
|
954
|
+
newDeterministicArtifactCount: currentCycleBuiltArtifacts.filter((artifact) => !currentDedupIds.has(artifact.dedupId)).length,
|
|
955
|
+
labelerCandidateCount: currentCycleOpportunity.candidateCount,
|
|
956
|
+
labelerBudgetedCandidateCount: currentCycleOpportunity.budgetedCandidateCount,
|
|
957
|
+
labelerStatus: currentCycleOpportunity.candidateCount === 0
|
|
958
|
+
? currentCycleOpportunity.status
|
|
959
|
+
: this.lastTeacherLabelerResult?.status ?? (currentCycleOpportunity.enabled ? "unknown" : "disabled"),
|
|
960
|
+
labelerDetail: currentCycleOpportunity.candidateCount === 0
|
|
961
|
+
? currentCycleOpportunity.detail
|
|
962
|
+
: this.lastTeacherLabelerResult?.detail ?? currentCycleOpportunity.detail
|
|
963
|
+
};
|
|
894
964
|
this.teacherArtifacts = nextTeacherArtifacts;
|
|
895
965
|
const learnerResult = advanceAlwaysOnLearningRuntime({
|
|
896
966
|
packLabel: this.input.packLabel,
|
|
@@ -952,7 +1022,8 @@ export class AsyncTeacherLiveLoop {
|
|
|
952
1022
|
sparseFeedback: this.learnerState.sparseFeedback,
|
|
953
1023
|
noOpReason: this.diagnostics.lastNoOpReason,
|
|
954
1024
|
materialization: this.lastMaterialization,
|
|
955
|
-
teacherLabeler: this.lastTeacherLabelerResult
|
|
1025
|
+
teacherLabeler: this.lastTeacherLabelerResult,
|
|
1026
|
+
lastCycle: this.lastCycle
|
|
956
1027
|
});
|
|
957
1028
|
}
|
|
958
1029
|
}
|
|
@@ -6981,11 +7052,104 @@ function summarizeLearningWarningStates(input) {
|
|
|
6981
7052
|
if (input.teacherSnapshot.diagnostics.latestFreshness === "stale" && input.teacherSnapshot.diagnostics.lastNoOpReason !== "no_teacher_artifacts") {
|
|
6982
7053
|
warnings.add("teacher_labels_stale");
|
|
6983
7054
|
}
|
|
6984
|
-
if (input.teacherSnapshot.diagnostics.lastNoOpReason === "no_teacher_artifacts"
|
|
7055
|
+
if (input.teacherSnapshot.diagnostics.lastNoOpReason === "no_teacher_artifacts" &&
|
|
7056
|
+
summarizeTeacherNoArtifactCycle(input.teacherSnapshot.diagnostics.notes).shouldWarn) {
|
|
6985
7057
|
warnings.add("teacher_no_artifacts");
|
|
6986
7058
|
}
|
|
6987
7059
|
return [...warnings];
|
|
6988
7060
|
}
|
|
7061
|
+
export function summarizeTeacherNoArtifactCycle(notes) {
|
|
7062
|
+
const values = new Map();
|
|
7063
|
+
for (const note of notes ?? []) {
|
|
7064
|
+
const separator = note.indexOf("=");
|
|
7065
|
+
if (separator <= 0) {
|
|
7066
|
+
continue;
|
|
7067
|
+
}
|
|
7068
|
+
values.set(note.slice(0, separator), note.slice(separator + 1));
|
|
7069
|
+
}
|
|
7070
|
+
const readNullableNumber = (key) => {
|
|
7071
|
+
const raw = values.get(key);
|
|
7072
|
+
if (raw === undefined || raw === "unknown") {
|
|
7073
|
+
return null;
|
|
7074
|
+
}
|
|
7075
|
+
const parsed = Number.parseInt(raw, 10);
|
|
7076
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
7077
|
+
};
|
|
7078
|
+
const readNullableString = (key) => {
|
|
7079
|
+
const raw = values.get(key);
|
|
7080
|
+
return raw === undefined || raw === "unknown" ? null : raw;
|
|
7081
|
+
};
|
|
7082
|
+
const deterministicArtifactCount = readNullableNumber("teacher_last_cycle_deterministic_artifacts");
|
|
7083
|
+
const newDeterministicArtifactCount = readNullableNumber("teacher_last_cycle_new_deterministic_artifacts");
|
|
7084
|
+
const labelerCandidateCount = readNullableNumber("teacher_last_cycle_labeler_candidates");
|
|
7085
|
+
const labelerBudgetedCandidateCount = readNullableNumber("teacher_last_cycle_labeler_budgeted_candidates");
|
|
7086
|
+
const labelerStatus = readNullableString("teacher_last_cycle_labeler_status");
|
|
7087
|
+
const labelerDetail = readNullableString("teacher_last_cycle_labeler_detail");
|
|
7088
|
+
if (deterministicArtifactCount === null && labelerCandidateCount === null) {
|
|
7089
|
+
return {
|
|
7090
|
+
shouldWarn: true,
|
|
7091
|
+
detail: "the latest cycle produced no new teacher artifacts, and the snapshot did not say whether any teachable material was present"
|
|
7092
|
+
};
|
|
7093
|
+
}
|
|
7094
|
+
if ((deterministicArtifactCount ?? 0) === 0 && (labelerCandidateCount ?? 0) === 0) {
|
|
7095
|
+
return {
|
|
7096
|
+
shouldWarn: false,
|
|
7097
|
+
detail: "the latest cycle produced no new teacher artifacts because the current export had no eligible feedback, operator overrides, or matched interaction text"
|
|
7098
|
+
};
|
|
7099
|
+
}
|
|
7100
|
+
if ((deterministicArtifactCount ?? 0) > 0 &&
|
|
7101
|
+
(newDeterministicArtifactCount ?? 0) === 0 &&
|
|
7102
|
+
(labelerCandidateCount ?? 0) === 0) {
|
|
7103
|
+
return {
|
|
7104
|
+
shouldWarn: false,
|
|
7105
|
+
detail: "the latest cycle produced no new teacher artifacts because the current export only repeated supervision that was already captured"
|
|
7106
|
+
};
|
|
7107
|
+
}
|
|
7108
|
+
if ((labelerCandidateCount ?? 0) > 0) {
|
|
7109
|
+
if ((labelerBudgetedCandidateCount ?? labelerCandidateCount) === 0) {
|
|
7110
|
+
return {
|
|
7111
|
+
shouldWarn: true,
|
|
7112
|
+
detail: "the latest cycle produced no new teacher artifacts because candidate interactions exceeded the teacher labeler prompt budget"
|
|
7113
|
+
};
|
|
7114
|
+
}
|
|
7115
|
+
if (labelerStatus === "disabled") {
|
|
7116
|
+
return {
|
|
7117
|
+
shouldWarn: false,
|
|
7118
|
+
detail: "the latest cycle produced no new teacher artifacts because candidate interactions existed, but the background teacher labeler is disabled"
|
|
7119
|
+
};
|
|
7120
|
+
}
|
|
7121
|
+
if (labelerStatus === "ok") {
|
|
7122
|
+
return {
|
|
7123
|
+
shouldWarn: false,
|
|
7124
|
+
detail: "the latest cycle produced no new teacher artifacts because candidate interactions were evaluated but did not add a new reusable label"
|
|
7125
|
+
};
|
|
7126
|
+
}
|
|
7127
|
+
if (labelerStatus === "fail_open") {
|
|
7128
|
+
return {
|
|
7129
|
+
shouldWarn: true,
|
|
7130
|
+
detail: labelerDetail === null
|
|
7131
|
+
? "the latest cycle produced no new teacher artifacts because the teacher labeler failed open while candidate interactions were present"
|
|
7132
|
+
: `the latest cycle produced no new teacher artifacts because the teacher labeler failed open while candidate interactions were present: ${labelerDetail}`
|
|
7133
|
+
};
|
|
7134
|
+
}
|
|
7135
|
+
if (labelerDetail === "no_labels_emitted") {
|
|
7136
|
+
return {
|
|
7137
|
+
shouldWarn: true,
|
|
7138
|
+
detail: "the latest cycle produced no new teacher artifacts even though candidate interactions were present; the teacher labeler emitted no reusable labels"
|
|
7139
|
+
};
|
|
7140
|
+
}
|
|
7141
|
+
return {
|
|
7142
|
+
shouldWarn: true,
|
|
7143
|
+
detail: labelerDetail === null
|
|
7144
|
+
? "the latest cycle produced no new teacher artifacts even though candidate interactions were present"
|
|
7145
|
+
: `the latest cycle produced no new teacher artifacts even though candidate interactions were present: ${labelerDetail}`
|
|
7146
|
+
};
|
|
7147
|
+
}
|
|
7148
|
+
return {
|
|
7149
|
+
shouldWarn: true,
|
|
7150
|
+
detail: "the latest cycle produced no new teacher artifacts even though teachable material was present"
|
|
7151
|
+
};
|
|
7152
|
+
}
|
|
6989
7153
|
function summarizeAlwaysOnLearning(input, active) {
|
|
6990
7154
|
const unavailableLag = {
|
|
6991
7155
|
activeEventRangeEnd: active?.eventRange.end ?? null,
|
|
@@ -142,9 +142,10 @@ export function classifyOpenClawBrainConvergeVerification(input) {
|
|
|
142
142
|
if (displayedStatus === "fail") {
|
|
143
143
|
blockingReasons.push("status still reports fail");
|
|
144
144
|
}
|
|
145
|
-
const runtimeTruthAlreadyProven =
|
|
146
|
-
&&
|
|
147
|
-
&&
|
|
145
|
+
const runtimeTruthAlreadyProven = runtimeLoad === "proven"
|
|
146
|
+
&& loadProof === "status_probe_ready"
|
|
147
|
+
&& installState === "installed"
|
|
148
|
+
&& loadability === "loadable";
|
|
148
149
|
if (input.restartRequired === true && input.restartPerformed !== true && !runtimeTruthAlreadyProven) {
|
|
149
150
|
blockingReasons.push("restart is still required before runtime load can be trusted");
|
|
150
151
|
}
|
|
@@ -4854,8 +4854,10 @@ function isCarryForwardSeedBlock(block) {
|
|
|
4854
4854
|
if (typeof block.text !== "string" || block.text.trim().length === 0) {
|
|
4855
4855
|
return false;
|
|
4856
4856
|
}
|
|
4857
|
-
|
|
4858
|
-
|
|
4857
|
+
// Only true seed-session evidence should survive prefix-changing promotions.
|
|
4858
|
+
// Ordinary runtime-turn feedback is re-materialized from learnedEventExport;
|
|
4859
|
+
// carrying it forward under the old runtime-graph id duplicates evidence.
|
|
4860
|
+
return block.semantic?.sourceKind === "recorded_session_seed" ||
|
|
4859
4861
|
block.source.includes("/seed:");
|
|
4860
4862
|
}
|
|
4861
4863
|
function carryForwardSeedBlockScore(block) {
|
|
@@ -398,8 +398,10 @@ function buildVerdict({ steps, gatewayStatus, pluginInspect, statusSignals, brea
|
|
|
398
398
|
const runtimeProofMatched = Array.isArray(runtimeLoadProofSnapshot?.value?.profiles)
|
|
399
399
|
&& runtimeLoadProofSnapshot.value.profiles.some((profile) => canonicalizeExistingProofPath(profile?.openclawHome ?? "") === canonicalizeExistingProofPath(openclawHome));
|
|
400
400
|
const runtimeTruthGaps = [];
|
|
401
|
-
|
|
402
|
-
|
|
401
|
+
const strongRuntimeTruth = statusSignals.loadProofReady
|
|
402
|
+
&& statusSignals.runtimeProven
|
|
403
|
+
&& statusSignals.serveActivePack
|
|
404
|
+
&& statusSignals.routeFnAvailable;
|
|
403
405
|
if (!statusSignals.loadProofReady)
|
|
404
406
|
runtimeTruthGaps.push("load_proof");
|
|
405
407
|
if (!statusSignals.runtimeProven)
|
|
@@ -410,6 +412,15 @@ function buildVerdict({ steps, gatewayStatus, pluginInspect, statusSignals, brea
|
|
|
410
412
|
runtimeTruthGaps.push("route_fn");
|
|
411
413
|
const warningCodes = [];
|
|
412
414
|
const warnings = [];
|
|
415
|
+
if (!statusSignals.statusOk) {
|
|
416
|
+
if (strongRuntimeTruth) {
|
|
417
|
+
warningCodes.push("status_warn");
|
|
418
|
+
warnings.push("detailed status did not return STATUS ok, but loadProof/runtime/serve/routeFn proofs stayed healthy");
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
runtimeTruthGaps.push("status_ok");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
413
424
|
if (!gatewayHealthy) {
|
|
414
425
|
warningCodes.push("gateway_health");
|
|
415
426
|
warnings.push("gateway status did not confirm runtime running and RPC probe ok");
|
|
@@ -597,6 +608,17 @@ function buildGatewayArgs(action, profileName) {
|
|
|
597
608
|
: ["gateway", action, "--profile", profileName];
|
|
598
609
|
}
|
|
599
610
|
|
|
611
|
+
function buildGatewayStatusArgs(profileName, gatewayUrl, gatewayToken) {
|
|
612
|
+
const args = buildGatewayArgs("status", profileName);
|
|
613
|
+
if (gatewayUrl !== null) {
|
|
614
|
+
args.push("--url", gatewayUrl);
|
|
615
|
+
}
|
|
616
|
+
if (gatewayToken !== null) {
|
|
617
|
+
args.push("--token", gatewayToken);
|
|
618
|
+
}
|
|
619
|
+
return args;
|
|
620
|
+
}
|
|
621
|
+
|
|
600
622
|
export function buildProofCommandForOpenClawHome(openclawHome) {
|
|
601
623
|
return `openclawbrain proof --openclaw-home ${quoteShellArg(path.resolve(openclawHome))}`;
|
|
602
624
|
}
|
|
@@ -609,6 +631,8 @@ export function buildProofCommandHelpSection() {
|
|
|
609
631
|
" --skip-install Capture proof without rerunning install first (proof only).",
|
|
610
632
|
" --skip-restart Capture proof without restarting OpenClaw first (proof only).",
|
|
611
633
|
` --plugin-id <id> Plugin id for \`openclaw plugins inspect\` (proof only; default: ${DEFAULT_OPERATOR_PROOF_PLUGIN_ID}).`,
|
|
634
|
+
" --gateway-url <url> Override the gateway-status probe target for proof capture (proof only).",
|
|
635
|
+
" --gateway-token <token> Gateway token to use with --gateway-url or other non-default proof probes.",
|
|
612
636
|
` --timeout-ms <ms> Per-step timeout in ms for proof capture (proof only; default: ${DEFAULT_OPERATOR_PROOF_TIMEOUT_MS}).`,
|
|
613
637
|
],
|
|
614
638
|
lifecycle: " 5. proof openclawbrain proof --openclaw-home <path> - capture one durable operator proof bundle after install/restart/status",
|
|
@@ -624,6 +648,8 @@ export function parseProofCliArgs(argv, options = {}) {
|
|
|
624
648
|
let skipInstall = false;
|
|
625
649
|
let skipRestart = false;
|
|
626
650
|
let pluginId = DEFAULT_OPERATOR_PROOF_PLUGIN_ID;
|
|
651
|
+
let gatewayUrl = null;
|
|
652
|
+
let gatewayToken = null;
|
|
627
653
|
let timeoutMs = DEFAULT_OPERATOR_PROOF_TIMEOUT_MS;
|
|
628
654
|
let json = false;
|
|
629
655
|
let help = false;
|
|
@@ -681,6 +707,24 @@ export function parseProofCliArgs(argv, options = {}) {
|
|
|
681
707
|
index += 1;
|
|
682
708
|
continue;
|
|
683
709
|
}
|
|
710
|
+
if (arg === "--gateway-url") {
|
|
711
|
+
const next = argv[index + 1];
|
|
712
|
+
if (next === undefined) {
|
|
713
|
+
throw new Error("--gateway-url requires a value");
|
|
714
|
+
}
|
|
715
|
+
gatewayUrl = next;
|
|
716
|
+
index += 1;
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
if (arg === "--gateway-token") {
|
|
720
|
+
const next = argv[index + 1];
|
|
721
|
+
if (next === undefined) {
|
|
722
|
+
throw new Error("--gateway-token requires a value");
|
|
723
|
+
}
|
|
724
|
+
gatewayToken = next;
|
|
725
|
+
index += 1;
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
684
728
|
if (arg === "--timeout-ms") {
|
|
685
729
|
const next = argv[index + 1];
|
|
686
730
|
if (next === undefined) {
|
|
@@ -705,6 +749,8 @@ export function parseProofCliArgs(argv, options = {}) {
|
|
|
705
749
|
skipInstall,
|
|
706
750
|
skipRestart,
|
|
707
751
|
pluginId,
|
|
752
|
+
gatewayUrl,
|
|
753
|
+
gatewayToken,
|
|
708
754
|
timeoutMs,
|
|
709
755
|
json,
|
|
710
756
|
help
|
|
@@ -725,6 +771,8 @@ export function parseProofCliArgs(argv, options = {}) {
|
|
|
725
771
|
skipInstall,
|
|
726
772
|
skipRestart,
|
|
727
773
|
pluginId,
|
|
774
|
+
gatewayUrl,
|
|
775
|
+
gatewayToken,
|
|
728
776
|
timeoutMs,
|
|
729
777
|
json,
|
|
730
778
|
help
|
|
@@ -783,7 +831,11 @@ export function captureOperatorProofBundle(options) {
|
|
|
783
831
|
}
|
|
784
832
|
addStep("01-install", "install", cliInvocation.command, [...cliInvocation.args, "install", "--openclaw-home", options.openclawHome], { skipped: options.skipInstall === true });
|
|
785
833
|
addStep("02-restart", "gateway restart", "openclaw", buildGatewayArgs("restart", gatewayProfile), { skipped: options.skipRestart === true });
|
|
786
|
-
const gatewayStatusCapture = addStep("03-gateway-status", "gateway status", "openclaw",
|
|
834
|
+
const gatewayStatusCapture = addStep("03-gateway-status", "gateway status", "openclaw", buildGatewayStatusArgs(
|
|
835
|
+
gatewayProfile,
|
|
836
|
+
normalizeOptionalCliString(options.gatewayUrl ?? null),
|
|
837
|
+
normalizeOptionalCliString(options.gatewayToken ?? null),
|
|
838
|
+
));
|
|
787
839
|
const pluginInspectCapture = addStep("04-plugin-inspect", "plugin inspect", "openclaw", ["plugins", "inspect", options.pluginId]);
|
|
788
840
|
const statusCapture = addStep("05-detailed-status", "detailed status", cliInvocation.command, [...cliInvocation.args, "status", "--openclaw-home", options.openclawHome, "--detailed"]);
|
|
789
841
|
const gatewayLogPath = extractGatewayLogPath(gatewayStatusCapture.stdout);
|
|
@@ -15,6 +15,17 @@ export interface TeacherLabelerResultV1 {
|
|
|
15
15
|
export interface TeacherLabeler {
|
|
16
16
|
label(input: TeacherLabelerRunInputV1): Promise<TeacherLabelerResultV1>;
|
|
17
17
|
}
|
|
18
|
+
export interface TeacherLabelerOpportunityInputV1 {
|
|
19
|
+
normalizedEventExport: NormalizedEventExportV1;
|
|
20
|
+
serveTimeDecisions?: readonly LearningSpineServeRouteDecisionLogEntryV1[];
|
|
21
|
+
}
|
|
22
|
+
export interface TeacherLabelerOpportunityV1 {
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
candidateCount: number;
|
|
25
|
+
budgetedCandidateCount: number;
|
|
26
|
+
status: "disabled" | "ready" | "skipped";
|
|
27
|
+
detail: string;
|
|
28
|
+
}
|
|
18
29
|
export interface OllamaTeacherLabelerGenerateInputV1 {
|
|
19
30
|
model: string;
|
|
20
31
|
prompt: string;
|
|
@@ -47,4 +58,5 @@ export interface AsyncTeacherNoopLabelerConfigV1 {
|
|
|
47
58
|
export type AsyncTeacherLabelerConfigV1 = AsyncTeacherNoopLabelerConfigV1 | AsyncTeacherOllamaLabelerConfigV1;
|
|
48
59
|
export declare function createHttpOllamaTeacherLabelerClient(baseUrl?: string): OllamaTeacherLabelerClient;
|
|
49
60
|
export declare function createOllamaTeacherLabeler(config: AsyncTeacherOllamaLabelerConfigV1): TeacherLabeler;
|
|
61
|
+
export declare function summarizeTeacherLabelerOpportunity(input: TeacherLabelerOpportunityInputV1, config?: AsyncTeacherLabelerConfigV1 | null): TeacherLabelerOpportunityV1;
|
|
50
62
|
export declare function createTeacherLabeler(config: AsyncTeacherLabelerConfigV1 | null | undefined): TeacherLabeler | null;
|
|
@@ -246,6 +246,48 @@ function normalizeOllamaTeacherLabelerConfig(config) {
|
|
|
246
246
|
client: config.client ?? createHttpOllamaTeacherLabelerClient(normalizeBaseUrl(config.baseUrl))
|
|
247
247
|
};
|
|
248
248
|
}
|
|
249
|
+
export function summarizeTeacherLabelerOpportunity(input, config) {
|
|
250
|
+
const normalized = config === undefined || config === null || config.provider === "none"
|
|
251
|
+
? {
|
|
252
|
+
enabled: false,
|
|
253
|
+
maxPromptChars: DEFAULT_OLLAMA_MAX_PROMPT_CHARS,
|
|
254
|
+
maxArtifactsPerExport: DEFAULT_OLLAMA_MAX_ARTIFACTS_PER_EXPORT,
|
|
255
|
+
maxInteractionsPerExport: DEFAULT_OLLAMA_MAX_INTERACTIONS,
|
|
256
|
+
maxUserMessageChars: DEFAULT_OLLAMA_MAX_USER_MESSAGE_CHARS,
|
|
257
|
+
maxContextIdsPerDecision: DEFAULT_OLLAMA_MAX_CONTEXT_IDS
|
|
258
|
+
}
|
|
259
|
+
: {
|
|
260
|
+
enabled: true,
|
|
261
|
+
...normalizeOllamaTeacherLabelerConfig(config)
|
|
262
|
+
};
|
|
263
|
+
const candidates = collectCandidates(input, normalized);
|
|
264
|
+
if (candidates.length === 0) {
|
|
265
|
+
return {
|
|
266
|
+
enabled: normalized.enabled,
|
|
267
|
+
candidateCount: 0,
|
|
268
|
+
budgetedCandidateCount: 0,
|
|
269
|
+
status: normalized.enabled ? "skipped" : "disabled",
|
|
270
|
+
detail: "no_matching_interaction_text"
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const budgetedCandidates = fitCandidatesToPromptBudget(candidates, normalized);
|
|
274
|
+
if (budgetedCandidates.length === 0) {
|
|
275
|
+
return {
|
|
276
|
+
enabled: normalized.enabled,
|
|
277
|
+
candidateCount: candidates.length,
|
|
278
|
+
budgetedCandidateCount: 0,
|
|
279
|
+
status: normalized.enabled ? "skipped" : "disabled",
|
|
280
|
+
detail: "prompt_budget_exhausted"
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
enabled: normalized.enabled,
|
|
285
|
+
candidateCount: candidates.length,
|
|
286
|
+
budgetedCandidateCount: budgetedCandidates.length,
|
|
287
|
+
status: normalized.enabled ? "ready" : "disabled",
|
|
288
|
+
detail: `candidates=${budgetedCandidates.length}`
|
|
289
|
+
};
|
|
290
|
+
}
|
|
249
291
|
class HttpOllamaTeacherLabelerClient {
|
|
250
292
|
baseUrl;
|
|
251
293
|
constructor(baseUrl) {
|
package/package.json
CHANGED