docs: document doctor stale warning helpers

This commit is contained in:
Peter Steinberger
2026-06-04 11:53:40 -04:00
parent 3e6978770a
commit 3e2d56469b
7 changed files with 31 additions and 0 deletions

View File

@@ -1,3 +1,4 @@
// Doctor warnings for plugin allowlists that make configured tool policies ineffective.
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import { isRecord as hasRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
@@ -573,6 +574,7 @@ function addIssue(issues: Map<string, Set<string>>, key: string, sourceLabel: st
issues.set(key, sources);
}
/** Collect warnings when plugin allowlists block tools referenced by active tool policies. */
export function collectPluginToolAllowlistWarnings(params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;

View File

@@ -1,3 +1,4 @@
// Doctor preview warning aggregation for config that can surprise users before repair.
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import { isRecord as hasRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
@@ -305,6 +306,7 @@ function formatTargets(targets: string[]): string {
return `${targets.slice(0, 2).join(", ")}, and ${targets.length - 2} more`;
}
/** Warn when visible-reply policy selects message_tool but message is unavailable. */
export function collectVisibleReplyToolPolicyWarnings(cfg: OpenClawConfig): string[] {
const groupPolicy = resolveGroupVisibleReplyProvenance(cfg);
const warnings: string[] = [];
@@ -345,6 +347,7 @@ function formatChannelList(channels: string[]): string {
.join(", ")}, and ${channels.length - 2} more`;
}
/** Warn when routed channel agents lack the message tool required for channel actions. */
export function collectChannelBoundMessageToolPolicyWarnings(cfg: OpenClawConfig): string[] {
return collectChannelRouteTargets(cfg).flatMap((target) => {
const agentTools = resolveAgentConfig(cfg, target.agentId)?.tools;
@@ -686,6 +689,7 @@ function collectInheritedByProviderConfiguredToolSectionWarnings(params: {
});
}
/** Warn when configured tool sections no longer widen restrictive tool profiles. */
export function collectProfileConfiguredToolSectionWarnings(cfg: OpenClawConfig): string[] {
const warnings: string[] = [];
const globalTools = hasRecord(cfg.tools) ? cfg.tools : undefined;
@@ -754,10 +758,13 @@ export function collectProfileConfiguredToolSectionWarnings(cfg: OpenClawConfig)
}
export type DoctorPreviewNotes = {
/** Non-warning doctor notes shown during preview. */
infoNotes: string[];
/** Warning notes shown during preview. */
warningNotes: string[];
};
/** Collect info and warning notes for doctor preview mode. */
export async function collectDoctorPreviewNotes(params: {
cfg: OpenClawConfig;
doctorFixCommand: string;
@@ -959,6 +966,7 @@ export async function collectDoctorPreviewNotes(params: {
return { infoNotes, warningNotes: warnings };
}
/** Collect warning notes only for callers that do not display info notes. */
export async function collectDoctorPreviewWarnings(params: {
cfg: OpenClawConfig;
doctorFixCommand: string;

View File

@@ -1,3 +1,4 @@
// Release-era repair for configs that imply official plugin installs before install records existed.
import { collectConfiguredModelRefs } from "@openclaw/model-catalog-core/configured-model-refs";
import { normalizeNullableString as normalizeId } from "@openclaw/normalization-core/string-coerce";
import { collectConfiguredAgentHarnessRuntimes } from "../../../agents/harness-runtimes.js";
@@ -256,6 +257,7 @@ function addEligiblePluginId(cfg: OpenClawConfig, pluginIds: Set<string>, plugin
pluginIds.add(normalized);
}
/** Return true when this config has not yet crossed the configured-plugin install release gate. */
export function shouldRunConfiguredPluginInstallReleaseStep(params: {
currentVersion?: string | null;
touchedVersion?: string | null;
@@ -273,6 +275,7 @@ export function shouldRunConfiguredPluginInstallReleaseStep(params: {
return touchedComparedToRelease === null || touchedComparedToRelease < 0;
}
/** Collect plugin/channel ids implied by config for the release install backfill step. */
export function collectReleaseConfiguredPluginIds(params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;
@@ -327,6 +330,7 @@ export function collectReleaseConfiguredPluginIds(params: {
};
}
/** Run the configured-plugin install release backfill when the config still needs it. */
export async function maybeRunConfiguredPluginInstallReleaseStep(params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;

View File

@@ -1,3 +1,4 @@
// Doctor cleanup for per-agent OAuth profiles shadowing fresher main-agent credentials.
import fs from "node:fs/promises";
import path from "node:path";
import { isRecord } from "@openclaw/normalization-core/record-coerce";
@@ -106,6 +107,7 @@ function shouldRemoveLocalOAuthShadow(params: {
return mainExpires >= localExpires;
}
/** Find local OAuth profiles that safely inherit fresher main-agent credentials instead. */
export async function scanStaleOAuthProfileShadows(params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;
@@ -263,6 +265,7 @@ async function repairStaleOAuthProfilesForAgent(params: {
: { status: "unchanged" };
}
/** Format warnings for stale per-agent OAuth profile shadows. */
export function collectStaleOAuthProfileShadowWarnings(params: {
hits: StaleOAuthProfileShadow[];
doctorFixCommand: string;
@@ -273,6 +276,7 @@ export function collectStaleOAuthProfileShadowWarnings(params: {
);
}
/** Remove stale per-agent OAuth profile shadows after rechecking each locked store. */
export async function repairStaleOAuthProfileShadows(params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;

View File

@@ -1,3 +1,4 @@
// Doctor scanner and repair for plugin/channel config that references missing plugins.
import { sanitizeForLog } from "../../../../packages/terminal-core/src/ansi.js";
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../agents/agent-scope.js";
import { CHANNEL_IDS } from "../../../channels/ids.js";
@@ -79,6 +80,7 @@ function collectPluginRegistryState(
};
}
/** Return true when plugin discovery errors should pause stale-plugin auto-removal. */
export function isStalePluginAutoRepairBlocked(
cfg: OpenClawConfig,
env?: NodeJS.ProcessEnv,
@@ -89,6 +91,7 @@ export function isStalePluginAutoRepairBlocked(
return collectPluginRegistryState(cfg, env).hasDiscoveryErrors;
}
/** Scan plugin/channel config surfaces for ids no longer present in manifests or installs. */
export function scanStalePluginConfig(
cfg: OpenClawConfig,
env?: NodeJS.ProcessEnv,
@@ -305,6 +308,7 @@ function formatStalePluginHitWarning(hit: StalePluginConfigHit): string {
return `- ${hit.pathLabel}: model override references missing channel plugin "${hit.pluginId}".`;
}
/** Format warnings for stale plugin config hits. */
export function collectStalePluginConfigWarnings(params: {
hits: StalePluginConfigHit[];
doctorFixCommand: string;
@@ -326,6 +330,7 @@ export function collectStalePluginConfigWarnings(params: {
return lines.map((line) => sanitizeForLog(line));
}
/** Remove stale plugin ids and dangling channel references when discovery is healthy. */
export function maybeRepairStalePluginConfig(
cfg: OpenClawConfig,
env?: NodeJS.ProcessEnv,

View File

@@ -1,11 +1,15 @@
// Doctor scanner and repair for subagent allowlists that reference missing agents.
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { listAgentIds } from "../../../agents/agent-scope-config.js";
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
import { normalizeAgentId } from "../../../routing/session-key.js";
export type StaleSubagentAllowlistHit = {
/** Config path containing the stale allowAgents entry. */
pathLabel: string;
/** Original configured agent id. */
agentId: string;
/** Normalized agent id used for matching configured targets. */
normalizedAgentId: string;
};
@@ -80,6 +84,7 @@ function collectStaleAllowlistEntries(params: {
return hits;
}
/** Find subagent allowlist entries not backed by configured agent or ACP targets. */
export function scanStaleSubagentAllowlistReferences(
cfg: OpenClawConfig,
): StaleSubagentAllowlistHit[] {
@@ -105,6 +110,7 @@ export function scanStaleSubagentAllowlistReferences(
return hits;
}
/** Format warnings for stale subagent allowlist entries. */
export function collectStaleSubagentAllowlistWarnings(params: {
hits: readonly StaleSubagentAllowlistHit[];
doctorFixCommand: string;
@@ -131,6 +137,7 @@ function filterAllowAgents(params: {
});
}
/** Remove stale subagent allowlist entries while preserving valid targets and wildcards. */
export function maybeRepairStaleSubagentAllowlists(cfg: OpenClawConfig): {
config: OpenClawConfig;
changes: string[];

View File

@@ -1,3 +1,4 @@
// Update-phase helpers that gate doctor repairs during package swaps and convergence.
import { isTruthyEnvValue } from "../../../infra/env.js";
export const UPDATE_IN_PROGRESS_ENV = "OPENCLAW_UPDATE_IN_PROGRESS";