@openclawbrain/cli 0.4.32 → 0.4.34

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,10 @@ function readInstallRuntimeFingerprint(openclawHome) {
1738
1738
  function runOpenClawBrainConvergePluginStep(openclawHome) {
1739
1739
  const before = readInstallRuntimeFingerprint(openclawHome);
1740
1740
  const plan = planOpenClawBrainConvergePluginAction(before);
1741
+ const pluginManagerEnv = {
1742
+ ...process.env,
1743
+ OPENCLAW_HOME: openclawHome
1744
+ };
1741
1745
  if (plan.action === "noop") {
1742
1746
  return {
1743
1747
  plan,
@@ -1753,7 +1757,7 @@ function runOpenClawBrainConvergePluginStep(openclawHome) {
1753
1757
  }
1754
1758
  let uninstallCapture = null;
1755
1759
  if (plan.action === "install" && shouldReplaceOpenClawBrainInstallBeforeConverge(before)) {
1756
- uninstallCapture = runCapturedExternalCommand("openclaw", ["plugins", "uninstall", plan.pluginId]);
1760
+ uninstallCapture = runCapturedExternalCommand("openclaw", ["plugins", "uninstall", plan.pluginId], { env: pluginManagerEnv });
1757
1761
  if (uninstallCapture.error !== null || uninstallCapture.exitCode !== 0) {
1758
1762
  throw new Error(`OpenClaw plugin-manager uninstall failed while migrating ${path.resolve(openclawHome)} onto the canonical plugin lane. Tried \`${uninstallCapture.shellCommand}\`. Detail: ${summarizeCapturedCommandFailure(uninstallCapture)}`);
1759
1763
  }
@@ -1761,7 +1765,7 @@ function runOpenClawBrainConvergePluginStep(openclawHome) {
1761
1765
  const commandArgs = plan.action === "install"
1762
1766
  ? ["plugins", "install", plan.packageSpec]
1763
1767
  : ["plugins", "update", plan.pluginId];
1764
- const capture = runCapturedExternalCommand("openclaw", commandArgs);
1768
+ const capture = runCapturedExternalCommand("openclaw", commandArgs, { env: pluginManagerEnv });
1765
1769
  if (capture.error !== null || capture.exitCode !== 0) {
1766
1770
  const hasAuthoritativeNativePlugin = before.selectedInstall !== null && before.installLayout === "native_package_plugin";
1767
1771
  if (plan.action === "update" && hasAuthoritativeNativePlugin) {
@@ -3375,7 +3379,11 @@ function readOpenClawRuntimePackageMetadata() {
3375
3379
  function buildExtensionIndexTs(activationRoot) {
3376
3380
  const templatePath = resolveExtensionTemplatePath();
3377
3381
  const template = readFileSync(templatePath, "utf8");
3378
- return template.replace(/const ACTIVATION_ROOT = "__ACTIVATION_ROOT__";/, `const ACTIVATION_ROOT = ${JSON.stringify(activationRoot)};`);
3382
+ const activationRootTemplateLinePattern = /^const ACTIVATION_ROOT = "__ACTIVATION_ROOT__";$/m;
3383
+ if (!activationRootTemplateLinePattern.test(template)) {
3384
+ throw new Error(`Extension template ${templatePath} does not expose a patchable ACTIVATION_ROOT line`);
3385
+ }
3386
+ return template.replace(activationRootTemplateLinePattern, `const ACTIVATION_ROOT = ${JSON.stringify(activationRoot)};`);
3379
3387
  }
3380
3388
  function buildExtensionPackageJson() {
3381
3389
  const packageMetadata = readOpenClawPackageMetadata();
@@ -4774,13 +4782,13 @@ function resolveServeTimeLearningRuntimeInput(activationRoot, normalizedEventExp
4774
4782
  : readHistoricalServeTimeDecisions(logPath, collectServeTimeDecisionRecoveryTargets(normalizedEventExport));
4775
4783
  const serveTimeDecisions = mergeHistoricalServeTimeDecisions(historicalRecovery.decisions, boundedServeTimeDecisions);
4776
4784
  const decisionLogCount = serveTimeDecisions.length;
4777
- const pgVersion = decisionLogCount > 0 ? "v2" : "v1";
4785
+ const pgVersion = "v2";
4778
4786
  const resolvedFallbackReason = combineServeTimeLearningFallbackReasons(fallbackReason, historicalRecovery.scanFailed ? "historical_recovery_scan_failed" : null);
4779
4787
  return {
4780
4788
  pgVersion,
4781
4789
  serveTimeDecisions,
4782
4790
  decisionLogCount,
4783
- baselineState: pgVersion === "v2" ? loadOrInitBaseline(activationRoot) : undefined,
4791
+ baselineState: loadOrInitBaseline(activationRoot),
4784
4792
  fallbackReason: resolvedFallbackReason === null ? null : `serve_time_decision_log_${resolvedFallbackReason}`
4785
4793
  };
4786
4794
  }
@@ -366,7 +366,7 @@ export function resolveOpenClawBrainInstallTarget(openclawHome) {
366
366
  }
367
367
  export function pinInstalledOpenClawBrainPluginActivationRoot(loaderEntryPath, activationRoot) {
368
368
  const loaderSource = readFileSync(loaderEntryPath, "utf8");
369
- const activationRootPattern = /const\s+ACTIVATION_ROOT\s*=\s*["'`][^"'`]*["'`];/;
369
+ const activationRootPattern = /^const\s+ACTIVATION_ROOT\s*=\s*["'`][^"'`]*["'`];$/m;
370
370
  const pinnedActivationRoot = `const ACTIVATION_ROOT = ${JSON.stringify(activationRoot)};`;
371
371
  const matchedActivationRoot = loaderSource.match(activationRootPattern)?.[0] ?? null;
372
372
  if (matchedActivationRoot === null) {
@@ -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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclawbrain/cli",
3
- "version": "0.4.32",
3
+ "version": "0.4.34",
4
4
  "description": "OpenClawBrain operator CLI package with install/status helpers, daemon controls, and import/export tooling.",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",