@openclawbrain/cli 0.4.31 → 0.4.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/cli.js
CHANGED
|
@@ -1738,6 +1738,19 @@ function readInstallRuntimeFingerprint(openclawHome) {
|
|
|
1738
1738
|
function runOpenClawBrainConvergePluginStep(openclawHome) {
|
|
1739
1739
|
const before = readInstallRuntimeFingerprint(openclawHome);
|
|
1740
1740
|
const plan = planOpenClawBrainConvergePluginAction(before);
|
|
1741
|
+
if (plan.action === "noop") {
|
|
1742
|
+
return {
|
|
1743
|
+
plan,
|
|
1744
|
+
command: null,
|
|
1745
|
+
changed: false,
|
|
1746
|
+
changeReasons: [],
|
|
1747
|
+
detail: "Skipped the OpenClaw plugin manager because the authoritative split-package plugin is already present and a no-op refresh would only churn volatile install metadata.",
|
|
1748
|
+
warning: null,
|
|
1749
|
+
capture: null,
|
|
1750
|
+
before,
|
|
1751
|
+
after: before
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1741
1754
|
let uninstallCapture = null;
|
|
1742
1755
|
if (plan.action === "install" && shouldReplaceOpenClawBrainInstallBeforeConverge(before)) {
|
|
1743
1756
|
uninstallCapture = runCapturedExternalCommand("openclaw", ["plugins", "uninstall", plan.pluginId]);
|
|
@@ -4761,13 +4774,13 @@ function resolveServeTimeLearningRuntimeInput(activationRoot, normalizedEventExp
|
|
|
4761
4774
|
: readHistoricalServeTimeDecisions(logPath, collectServeTimeDecisionRecoveryTargets(normalizedEventExport));
|
|
4762
4775
|
const serveTimeDecisions = mergeHistoricalServeTimeDecisions(historicalRecovery.decisions, boundedServeTimeDecisions);
|
|
4763
4776
|
const decisionLogCount = serveTimeDecisions.length;
|
|
4764
|
-
const pgVersion =
|
|
4777
|
+
const pgVersion = "v2";
|
|
4765
4778
|
const resolvedFallbackReason = combineServeTimeLearningFallbackReasons(fallbackReason, historicalRecovery.scanFailed ? "historical_recovery_scan_failed" : null);
|
|
4766
4779
|
return {
|
|
4767
4780
|
pgVersion,
|
|
4768
4781
|
serveTimeDecisions,
|
|
4769
4782
|
decisionLogCount,
|
|
4770
|
-
baselineState:
|
|
4783
|
+
baselineState: loadOrInitBaseline(activationRoot),
|
|
4771
4784
|
fallbackReason: resolvedFallbackReason === null ? null : `serve_time_decision_log_${resolvedFallbackReason}`
|
|
4772
4785
|
};
|
|
4773
4786
|
}
|
|
@@ -103,10 +103,10 @@ export function planOpenClawBrainConvergePluginAction(fingerprint) {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
return {
|
|
106
|
-
action: "
|
|
106
|
+
action: "noop",
|
|
107
107
|
packageSpec: "@openclawbrain/openclaw",
|
|
108
108
|
pluginId: "openclawbrain",
|
|
109
|
-
reason: "
|
|
109
|
+
reason: "the authoritative split-package plugin is already installed, so converge should preserve the current plugin-manager record instead of rewriting volatile install metadata",
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -384,11 +384,15 @@ function buildCoverageSnapshot({ attachedSetLine, runtimeLoadProofSnapshot, open
|
|
|
384
384
|
profiles
|
|
385
385
|
};
|
|
386
386
|
}
|
|
387
|
-
function buildHardeningSnapshot({ attachTruthLine, serveLine, routeFnLine, surfaceLine, verdict, statusSignals }) {
|
|
387
|
+
function buildHardeningSnapshot({ attachTruthLine, serveLine, routeFnLine, surfaceLine, brainLine, routeLine, learningLine, learningPathLine, verdict, statusSignals }) {
|
|
388
388
|
const attachTruth = extractKeyValuePairs(attachTruthLine);
|
|
389
389
|
const serve = extractKeyValuePairs(serveLine);
|
|
390
390
|
const routeFn = extractKeyValuePairs(routeFnLine);
|
|
391
391
|
const surface = extractKeyValuePairs(surfaceLine);
|
|
392
|
+
const brain = extractKeyValuePairs(brainLine);
|
|
393
|
+
const route = extractKeyValuePairs(routeLine);
|
|
394
|
+
const learning = extractKeyValuePairs(learningLine);
|
|
395
|
+
const learningPath = extractKeyValuePairs(learningPathLine);
|
|
392
396
|
return {
|
|
393
397
|
contract: "openclaw_operator_hardening_snapshot.v1",
|
|
394
398
|
generatedAt: new Date().toISOString(),
|
|
@@ -427,6 +431,27 @@ function buildHardeningSnapshot({ attachTruthLine, serveLine, routeFnLine, surfa
|
|
|
427
431
|
available: routeFn.available ?? null,
|
|
428
432
|
freshness: routeFn.freshness ?? null,
|
|
429
433
|
},
|
|
434
|
+
routeLayer: {
|
|
435
|
+
activePackId: brain.pack ?? null,
|
|
436
|
+
routerIdentity: brain.router ?? route.router ?? null,
|
|
437
|
+
routeFreshness: brain.routeFreshness ?? null,
|
|
438
|
+
routeFingerprint: route.freshness ?? null,
|
|
439
|
+
lastPromotionAt: brain.lastPromotion ?? null,
|
|
440
|
+
brainState: brain.state ?? null,
|
|
441
|
+
initMode: brain.init ?? null,
|
|
442
|
+
serveState: serve.state ?? null,
|
|
443
|
+
usedLearnedRouteFn: serve.usedRouteFn ?? null,
|
|
444
|
+
routeFnAvailable: routeFn.available ?? null,
|
|
445
|
+
routeFnFreshness: routeFn.freshness ?? null,
|
|
446
|
+
learningState: learning.state ?? null,
|
|
447
|
+
learningMode: learning.mode ?? null,
|
|
448
|
+
learningPathSource: learningPath.source ?? null,
|
|
449
|
+
learningPathPg: learningPath.pg ?? null,
|
|
450
|
+
learningPathMethod: learningPath.method ?? null,
|
|
451
|
+
learningPathTarget: learningPath.target ?? null,
|
|
452
|
+
learningPathConnect: learningPath.connect ?? null,
|
|
453
|
+
learningPathTrajectories: learningPath.trajectories ?? null,
|
|
454
|
+
},
|
|
430
455
|
verdict: {
|
|
431
456
|
verdict: verdict.verdict,
|
|
432
457
|
severity: verdict.severity,
|
|
@@ -576,7 +601,7 @@ function buildVerdict({ steps, gatewayStatus, pluginInspect, statusSignals, brea
|
|
|
576
601
|
};
|
|
577
602
|
}
|
|
578
603
|
|
|
579
|
-
function buildSummary({ options, steps, verdict, gatewayStatusText, pluginInspectText, statusSignals, breadcrumbs, runtimeLoadProofSnapshot, surfaceLine, surfacesLine, surfaceNoteLine, hotfixLine, guardLine, feedbackLine, attributionLine, attributionCoverageLine, learningPathLine, learningFlowLine, learningHealthLine, coverageSnapshot, hardeningSnapshot }) {
|
|
604
|
+
function buildSummary({ options, steps, verdict, gatewayStatusText, pluginInspectText, statusSignals, breadcrumbs, runtimeLoadProofSnapshot, surfaceLine, surfacesLine, surfaceNoteLine, hotfixLine, guardLine, brainLine, routeLine, learningLine, feedbackLine, attributionLine, attributionCoverageLine, learningPathLine, learningFlowLine, learningHealthLine, coverageSnapshot, hardeningSnapshot }) {
|
|
580
605
|
const passed = [];
|
|
581
606
|
const missing = [];
|
|
582
607
|
const warnings = Array.isArray(verdict.warnings) ? verdict.warnings : [];
|
|
@@ -660,6 +685,21 @@ function buildSummary({ options, steps, verdict, gatewayStatusText, pluginInspec
|
|
|
660
685
|
? ["- runtime guard line not reported by detailed status"]
|
|
661
686
|
: [`- ${guardLine}`]),
|
|
662
687
|
"",
|
|
688
|
+
"## Route Layer Truth",
|
|
689
|
+
...(brainLine === null
|
|
690
|
+
? ["- brain line not reported by detailed status"]
|
|
691
|
+
: [`- ${brainLine}`]),
|
|
692
|
+
...(routeLine === null
|
|
693
|
+
? ["- route line not reported by detailed status"]
|
|
694
|
+
: [`- ${routeLine}`]),
|
|
695
|
+
...(learningLine === null
|
|
696
|
+
? ["- learning line not reported by detailed status"]
|
|
697
|
+
: [`- ${learningLine}`]),
|
|
698
|
+
...(learningPathLine === null
|
|
699
|
+
? ["- path line not reported by detailed status"]
|
|
700
|
+
: [`- ${learningPathLine}`]),
|
|
701
|
+
`- derived: activePack=${hardeningSnapshot.routeLayer.activePackId ?? "none"} router=${hardeningSnapshot.routeLayer.routerIdentity ?? "none"} routeFreshness=${hardeningSnapshot.routeLayer.routeFreshness ?? "none"} routeFingerprint=${hardeningSnapshot.routeLayer.routeFingerprint ?? "none"} usedLearnedRouteFn=${hardeningSnapshot.routeLayer.usedLearnedRouteFn ?? "none"}`,
|
|
702
|
+
"",
|
|
663
703
|
"## Learning Flow",
|
|
664
704
|
...(learningPathLine === null
|
|
665
705
|
? ["- learning path line not reported by detailed status"]
|
|
@@ -988,6 +1028,9 @@ export function captureOperatorProofBundle(options) {
|
|
|
988
1028
|
const serveLine = extractDetailedStatusLine(statusCapture.stdout, "serve");
|
|
989
1029
|
const routeFnLine = extractDetailedStatusLine(statusCapture.stdout, "routeFn");
|
|
990
1030
|
const guardLine = extractDetailedStatusLine(statusCapture.stdout, "guard");
|
|
1031
|
+
const brainLine = extractDetailedStatusLine(statusCapture.stdout, "brain");
|
|
1032
|
+
const routeLine = extractDetailedStatusLine(statusCapture.stdout, "route");
|
|
1033
|
+
const learningLine = extractDetailedStatusLine(statusCapture.stdout, "learning");
|
|
991
1034
|
const learningFlowLine = extractDetailedStatusLine(statusCapture.stdout, "learnFlow");
|
|
992
1035
|
const learningHealthLine = extractDetailedStatusLine(statusCapture.stdout, "health");
|
|
993
1036
|
const feedbackLine = extractDetailedStatusLine(statusCapture.stdout, "feedback");
|
|
@@ -1024,6 +1067,10 @@ export function captureOperatorProofBundle(options) {
|
|
|
1024
1067
|
serveLine,
|
|
1025
1068
|
routeFnLine,
|
|
1026
1069
|
surfaceLine,
|
|
1070
|
+
brainLine,
|
|
1071
|
+
routeLine,
|
|
1072
|
+
learningLine,
|
|
1073
|
+
learningPathLine,
|
|
1027
1074
|
verdict,
|
|
1028
1075
|
statusSignals,
|
|
1029
1076
|
});
|
|
@@ -1053,6 +1100,9 @@ export function captureOperatorProofBundle(options) {
|
|
|
1053
1100
|
surfaceNoteLine,
|
|
1054
1101
|
hotfixLine,
|
|
1055
1102
|
guardLine,
|
|
1103
|
+
brainLine,
|
|
1104
|
+
routeLine,
|
|
1105
|
+
learningLine,
|
|
1056
1106
|
learningFlowLine,
|
|
1057
1107
|
learningHealthLine,
|
|
1058
1108
|
feedbackLine,
|
|
@@ -1075,6 +1125,9 @@ export function captureOperatorProofBundle(options) {
|
|
|
1075
1125
|
surfaceNoteLine,
|
|
1076
1126
|
hotfixLine,
|
|
1077
1127
|
guardLine,
|
|
1128
|
+
brainLine,
|
|
1129
|
+
routeLine,
|
|
1130
|
+
learningLine,
|
|
1078
1131
|
learningFlowLine,
|
|
1079
1132
|
learningHealthLine,
|
|
1080
1133
|
feedbackLine,
|
|
@@ -3,6 +3,7 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { describeOpenClawBrainInstallLayout, findInstalledOpenClawBrainPlugin } from "./openclaw-plugin-install.js";
|
|
6
|
+
import { inspectOpenClawBrainHookStatus } from "./openclaw-hook-truth.js";
|
|
6
7
|
const REQUIRED_RUNTIME_GUARD_EXPORTS = [
|
|
7
8
|
"createBeforePromptBuildHandler",
|
|
8
9
|
"isActivationRootPlaceholder",
|
|
@@ -70,6 +71,10 @@ export function inspectInstalledOpenClawBrainExtension(openclawHome, extensionId
|
|
|
70
71
|
}
|
|
71
72
|
export async function proveInstalledOpenClawBrainExtensionLoad(openclawHome, extensionId = "openclawbrain") {
|
|
72
73
|
const inspected = inspectInstalledOpenClawBrainExtension(openclawHome, extensionId);
|
|
74
|
+
const hookStatus = inspectOpenClawBrainHookStatus(openclawHome);
|
|
75
|
+
if (hookStatus.loadability !== "loadable") {
|
|
76
|
+
throw new Error(`[shadow-extension-load-proof] Installed hook is not loadable enough to prove its loader: ${hookStatus.detail}`);
|
|
77
|
+
}
|
|
73
78
|
const runtimeGuardModule = await importWithHelpfulError(inspected.runtimeGuardPath, `runtime-guard.js (${describeOpenClawBrainInstallLayout(inspected.installLayout)})`);
|
|
74
79
|
const runtimeGuardExportNames = Object.keys(runtimeGuardModule).sort((left, right) => left.localeCompare(right));
|
|
75
80
|
const missingRuntimeGuardExports = REQUIRED_RUNTIME_GUARD_EXPORTS.filter((exportName) => !runtimeGuardExportNames.includes(exportName));
|
|
@@ -272,13 +272,15 @@ function loadJsonFile(pathname) {
|
|
|
272
272
|
function resolveActivePackPaths(activationRoot) {
|
|
273
273
|
const pointers = toRecord(loadJsonFile(path.join(path.resolve(activationRoot), "activation-pointers.json")));
|
|
274
274
|
const active = toRecord(pointers?.active);
|
|
275
|
+
const packId = normalizeOptionalString(active?.packId);
|
|
275
276
|
const packRootDir = normalizeOptionalString(active?.packRootDir)
|
|
276
|
-
?? (
|
|
277
|
+
?? (packId === null
|
|
277
278
|
? null
|
|
278
|
-
: path.join(path.resolve(activationRoot), "packs", String(
|
|
279
|
+
: path.join(path.resolve(activationRoot), "packs", String(packId)));
|
|
279
280
|
const manifestPath = normalizeOptionalString(active?.manifestPath)
|
|
280
281
|
?? (packRootDir === null ? null : path.join(packRootDir, "manifest.json"));
|
|
281
282
|
return {
|
|
283
|
+
packId,
|
|
282
284
|
packRootDir,
|
|
283
285
|
manifestPath
|
|
284
286
|
};
|
|
@@ -376,6 +378,38 @@ function buildWatchSnapshotAttributionCoverage(activationRoot) {
|
|
|
376
378
|
detail: `watch sparse-feedback queue: completed_without_evaluation=0, ready=${normalizeCount(readyCount)}, delayed=${normalizeCount(delayedCount)}, budget_deferred=${normalizeCount(budgetDeferredCount)}`
|
|
377
379
|
};
|
|
378
380
|
}
|
|
381
|
+
function readWatchTeacherSnapshotPackTruth(activationRoot) {
|
|
382
|
+
const snapshot = toRecord(loadJsonFile(path.join(path.resolve(activationRoot), "watch", "teacher-snapshot.json")));
|
|
383
|
+
const learning = toRecord(snapshot?.learning);
|
|
384
|
+
const nestedSnapshot = toRecord(snapshot?.snapshot);
|
|
385
|
+
const nestedLearning = toRecord(nestedSnapshot?.learning);
|
|
386
|
+
return {
|
|
387
|
+
lastHandledMaterializationPackId: normalizeOptionalString(snapshot?.lastHandledMaterializationPackId)
|
|
388
|
+
?? normalizeOptionalString(learning?.lastHandledMaterializationPackId)
|
|
389
|
+
?? normalizeOptionalString(nestedLearning?.lastHandledMaterializationPackId),
|
|
390
|
+
lastMaterializationPackId: normalizeOptionalString(snapshot?.lastMaterializationPackId)
|
|
391
|
+
?? normalizeOptionalString(learning?.lastMaterializationPackId)
|
|
392
|
+
?? normalizeOptionalString(nestedLearning?.lastMaterializationPackId)
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function buildActivationPackTruth(activationRoot) {
|
|
396
|
+
const active = resolveActivePackPaths(activationRoot);
|
|
397
|
+
const activePackId = active.packId;
|
|
398
|
+
if (activePackId === null) {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
const watchTruth = readWatchTeacherSnapshotPackTruth(activationRoot);
|
|
402
|
+
const handledPackId = watchTruth.lastHandledMaterializationPackId ?? watchTruth.lastMaterializationPackId;
|
|
403
|
+
if (handledPackId === null) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
activePackId,
|
|
408
|
+
handledPackId,
|
|
409
|
+
materializedPackId: handledPackId,
|
|
410
|
+
promoted: handledPackId === activePackId
|
|
411
|
+
};
|
|
412
|
+
}
|
|
379
413
|
function shouldPreferActivationFeedbackSummary(current, fallback) {
|
|
380
414
|
if (fallback === null) {
|
|
381
415
|
return false;
|
|
@@ -407,18 +441,35 @@ function shouldPreferWatchAttributionCoverage(current, fallback) {
|
|
|
407
441
|
function enrichBridgeWithActivationTruth(activationRoot, bridge) {
|
|
408
442
|
const feedbackSummary = buildActivePackFeedbackSummary(activationRoot);
|
|
409
443
|
const attributionCoverage = buildWatchSnapshotAttributionCoverage(activationRoot);
|
|
410
|
-
|
|
411
|
-
|
|
444
|
+
const packTruth = buildActivationPackTruth(activationRoot);
|
|
445
|
+
const preferFeedbackSummary = shouldPreferActivationFeedbackSummary(bridge.feedbackSummary, feedbackSummary);
|
|
446
|
+
const preferAttributionCoverage = shouldPreferWatchAttributionCoverage(bridge.attributionCoverage, attributionCoverage);
|
|
447
|
+
const preferPackTruth = packTruth !== null
|
|
448
|
+
&& (bridge.materializedPackId === null || (bridge.promoted !== true && packTruth.promoted === true))
|
|
449
|
+
&& (packTruth.promoted === true || bridge.materializedPackId === null);
|
|
450
|
+
if (!preferFeedbackSummary && !preferAttributionCoverage && !preferPackTruth) {
|
|
412
451
|
return bridge;
|
|
413
452
|
}
|
|
414
453
|
return normalizeBridgePayload({
|
|
415
454
|
...bridge,
|
|
416
|
-
|
|
455
|
+
materializedPackId: preferPackTruth ? packTruth.materializedPackId : bridge.materializedPackId,
|
|
456
|
+
promoted: preferPackTruth ? packTruth.promoted : bridge.promoted,
|
|
457
|
+
feedbackSummary: preferFeedbackSummary
|
|
417
458
|
? feedbackSummary
|
|
418
459
|
: bridge.feedbackSummary,
|
|
419
|
-
attributionCoverage:
|
|
460
|
+
attributionCoverage: preferAttributionCoverage
|
|
420
461
|
? attributionCoverage
|
|
421
|
-
: bridge.attributionCoverage
|
|
462
|
+
: bridge.attributionCoverage,
|
|
463
|
+
source: preferPackTruth
|
|
464
|
+
? {
|
|
465
|
+
...(bridge.source ?? {}),
|
|
466
|
+
activationPackTruth: {
|
|
467
|
+
activePackId: packTruth.activePackId,
|
|
468
|
+
handledPackId: packTruth.handledPackId,
|
|
469
|
+
source: "active_pack_plus_watch_snapshot"
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
: bridge.source
|
|
422
473
|
});
|
|
423
474
|
}
|
|
424
475
|
function normalizeLastInterruptionSummary(value) {
|
|
@@ -865,6 +916,21 @@ export function persistBrainStoreTracedLearningBridge(payload, options = {}) {
|
|
|
865
916
|
try {
|
|
866
917
|
db = new sqlite.DatabaseSync(dbPath);
|
|
867
918
|
const summary = normalizePersistedStatusSurface(payload);
|
|
919
|
+
const existingSummaryLoaded = loadTrainingStateJson(db, TRACED_LEARNING_STATUS_SURFACE_STATE_KEY);
|
|
920
|
+
if (existingSummaryLoaded.value !== null) {
|
|
921
|
+
const existingSummary = normalizePersistedStatusSurface(existingSummaryLoaded.value);
|
|
922
|
+
if (JSON.stringify(existingSummary) === JSON.stringify(summary)) {
|
|
923
|
+
return {
|
|
924
|
+
path: dbPath,
|
|
925
|
+
bridge: buildPersistedStatusSurfaceBridge(existingSummary, {
|
|
926
|
+
brainRoot,
|
|
927
|
+
dbPath
|
|
928
|
+
}),
|
|
929
|
+
persisted: false,
|
|
930
|
+
error: null
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
}
|
|
868
934
|
writeTrainingStateJson(db, TRACED_LEARNING_STATUS_SURFACE_STATE_KEY, summary);
|
|
869
935
|
return {
|
|
870
936
|
path: dbPath,
|
package/package.json
CHANGED