Skip to content

refactor(config): config-surface reduction tranche 2 — purge tuning knobs behind built-in defaults#111382

Merged
steipete merged 1 commit into
mainfrom
claude/openclaw-config-phase3
Jul 19, 2026
Merged

refactor(config): config-surface reduction tranche 2 — purge tuning knobs behind built-in defaults#111382
steipete merged 1 commit into
mainfrom
claude/openclaw-config-phase3

Conversation

@steipete

Copy link
Copy Markdown
Contributor

What Problem This Solves

OpenClaw exposed a large set of internal numeric tuning knobs as public configuration even though their unset behavior already had stable built-in defaults. That widened the schema, docs, generated metadata, tests, and long-term compatibility surface without giving most operators a meaningful product choice.

This tranche removes 209 generated config paths after rebasing onto current main:

Surface Current main This PR Delta
Core 3008 2851 -157
Channel 3732 3680 -52
Plugin 3537 3537 0

ClawSweeper config-surface metric: 209 config/default paths removed. The committed baseline on main still reports core 3007 because the newly added ui.prefs.sidebarLiveActivity path had not yet been regenerated there; measuring the current schema gives the 3008 pre-change value above.

Removed keys by subtree

Authentication, secrets, browser, and tools

  • auth.cooldowns and all children: billingBackoffHours, billingBackoffHoursByProvider, billingMaxHours, authPermanentBackoffMinutes, authPermanentMaxMinutes, failureWindowHours, overloadedProfileRotations, overloadedBackoffMs, and rateLimitedProfileRotations.
  • secrets.resolution and maxProviderConcurrency, maxRefsPerProvider, and maxBatchBytes.
  • browser.remoteCdpTimeoutMs, remoteCdpHandshakeTimeoutMs, localLaunchTimeoutMs, localCdpReadyTimeoutMs, actionTimeoutMs, and cdpPortRangeStart.
  • browser.tabCleanup.idleMinutes, maxTabsPerSession, and sweepMinutes; enabled remains.
  • Root and per-agent tools.loopDetection: genericRepeat, knownPollNoProgress, pingPong, windowSize, historySize, warningThreshold, unknownToolThreshold, criticalThreshold, globalCircuitBreakerThreshold, detectors, and postCompactionGuard; enabled remains.

Agent defaults and agent-list echoes

  • compaction.reserveTokens, reserveTokensFloor, and maxHistoryShare.
  • contextPruning.keepLastAssistants, softTrimRatio, hardClearRatio, minPrunableToolChars, plus softTrim.maxChars, headChars, and tailChars.
  • memorySearch.chunking.tokens and overlap; memorySearch.sync.watchDebounceMs and intervalMinutes.
  • memorySearch.query.hybrid.vectorWeight, textWeight, and candidateMultiplier; mmr.lambda; temporalDecay.halfLifeDays.
  • memorySearch.cache.maxEntries.
  • cliBackends.*.reliability.outputLimits.maxTurnRawChars and maxTurnLines; watchdog.fresh.noOutputTimeoutMs and watchdog.resume.noOutputTimeoutMs.
  • runRetries.base, perProfile, min, and max.

These paths are removed from both agents.defaults and agents.list[] wherever those scopes support them.

Gateway, sessions, cron, diagnostics, web, and messages

  • gateway.channelHealthCheckMinutes, channelStaleEventThresholdMinutes, channelMaxRestartsPerHour, and config-level handshakeTimeoutMs.
  • gateway.reload.debounceMs and deferralTimeoutMs.
  • gateway.http.endpoints.chatCompletions.maxBodyBytes, maxImageParts, and maxTotalImageBytes; gateway.http.endpoints.responses.maxBodyBytes.
  • session.typingIntervalSeconds, session.agentToAgent.maxPingPongTurns, and session.writeLock.acquireTimeoutMs, staleMs, and maxHoldMs.
  • cron.maxConcurrentRuns, cron.triggers.minIntervalMs, and cron.retry.maxAttempts, backoffMs, and retryOn.
  • diagnostics.stuckSessionWarnMs, stuckSessionAbortMs, and memoryPressureSnapshot; doctor also removes legacy memoryPressureBundle.
  • web.heartbeatSeconds, web.reconnect.initialMs, maxMs, factor, jitter, and maxAttempts, plus web.whatsapp.keepAliveIntervalMs, connectTimeoutMs, and defaultQueryTimeoutMs.
  • messages.queue.debounceMs and messages.statusReactions.timing.debounceMs, stallSoftMs, stallHardMs, doneHoldMs, and errorHoldMs.

ACP, MCP, worktrees, transcripts, hooks, and update

  • acp.stream.coalesceIdleMs, maxChunkChars, maxOutputChars, maxSessionUpdateChars, and hiddenBoundarySeparator; delivery mode, repeat suppression, and tag visibility remain.
  • acp.maxConcurrentSessions and acp.runtime.ttlMinutes.
  • mcp.sessionIdleTtlMs.
  • worktrees.cleanup.maxCount and maxTotalSizeGb, then the empty worktrees parent.
  • transcripts.maxUtterances.
  • hooks.maxBodyBytes.
  • update.auto.stableDelayHours, stableJitterHours, and betaCheckIntervalHours; channel, check-on-start, and auto-enabled settings remain.

Bundled channels

  • Telegram at root/account and applicable nested policy scopes: timeoutSeconds, mediaGroupFlushMs, pollingStallThresholdMs, retry.attempts, retry.minDelayMs, retry.maxDelayMs, retry.jitter, and errorCooldownMs.
  • Discord at root/account scope: gatewayInfoTimeoutMs, gatewayReadyTimeoutMs, gatewayRuntimeReadyTimeoutMs, eventQueue.listenerTimeout, eventQueue.maxQueueSize, eventQueue.maxConcurrency, and retry.attempts, minDelayMs, maxDelayMs, and jitter. Doctor intentionally does not recurse into arbitrary provider settings.
  • ClickClack at root/account scope: timeoutSeconds.
  • Other bundled-channel schemas had no equivalent timeout/retry tuning surface to remove.

Kept, with reason

  • skills.limits.*: documented mainstream operator control.
  • gateway.auth.rateLimit.*: optional security policy without one universal default.
  • messages.inbound.* debounce values: unset disables debounce, so removal would change the default behavior.
  • agents.*.compaction.keepRecentTokens: configured values change the runtime checkpoint cut point.
  • media.ttlHours: unset disables cleanup, so a built-in positive TTL would change retention.
  • Telegram network.autoSelectFamily, network.dnsResultOrder, and dangerouslyAllowPrivateNetwork: policy/selection controls, not numeric tuning defaults.
  • agents.defaults typing controls: explicitly deferred to Phase 4.
  • OPENCLAW_HANDSHAKE_TIMEOUT_MS: the config knob is removed, but the environment override remains.

Why This Change Was Made

Runtime readers now use named built-in constants or their prior unset defaults. Current schemas, types, labels, help, docs, and generated metadata expose only the canonical surface, while legacy cleanup remains owned by doctor rather than steady-state runtime compatibility branches.

One global migration, runtime.tuning-knobs-purge, strips root, agents.defaults, and agents.list[] echoes. Telegram, Discord, and ClickClack cleanup stays in their channel doctor contracts. The matching compatibility record is doctor-runtime-tuning-knobs-purge, with a removal window ending 2026-09-18.

User Impact

Named tradeoff: operators who explicitly tuned these tuning-only keys revert to the built-in defaults after running openclaw doctor --fix. Behavior is unchanged for everyone who never set them.

Strict current schemas intentionally reject the retired aliases; doctor is the sole migration owner. Mainstream feature switches, security policies, and settings whose unset state changes behavior remain available.

Evidence

  • Focused schema/dead-key/migration/doctor tests: src/config/dead-config-keys.test.ts, src/config/config.schema-regressions.test.ts, src/commands/doctor/shared/legacy-config-migrations.runtime.retired.test.ts, and Telegram/Discord/ClickClack doctor tests — all green after the final rebase.
  • Changed reader/regression coverage includes gateway worktree handlers and Worktrees UI tests — green.
  • pnpm config:docs:check — green; generated docs baseline, channel metadata, and docs map regenerated.
  • pnpm tsgo:core, pnpm tsgo:extensions:test, and pnpm check:test-types — green.
  • Changed-surface oxlint lanes, pnpm deadcode:dependencies, pnpm deadcode:exports, and pnpm plugin-sdk:surface:check — green.
  • pnpm format <changed files> and git diff --check — green.
  • Autoreview covered the production/config/doctor/generator bundle in three bounded passes, found two actionable doctor-scope issues that were fixed and retested, and left no accepted/actionable findings.
  • CHANGELOG.md is intentionally untouched.

@steipete
steipete requested a review from a team as a code owner July 19, 2026 12:17
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord channel: signal Channel integration: signal channel: slack Channel integration: slack channel: telegram Channel integration: telegram channel: whatsapp-web Channel integration: whatsapp-web app: web-ui App: web-ui gateway Gateway runtime extensions: memory-core Extension: memory-core cli CLI command changes scripts Repository scripts commands Command implementations agents Agent runtime and tooling extensions: qa-lab extensions: codex size: XL maintainer Maintainer-authored PR labels Jul 19, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8e072ae6eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 121 to 124
mode: z
.union([z.literal("off"), z.literal("restart"), z.literal("hot"), z.literal("hybrid")])
.optional(),
debounceMs: z.number().int().min(0).optional(),
deferralTimeoutMs: z.number().int().min(0).optional(),
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove retired reload knobs from the config reference

After these properties are removed from the strict gateway.reload schema, the example and field descriptions in docs/gateway/configuration-reference.md:738-758 still instruct operators to set debounceMs and deferralTimeoutMs. Copying that documented configuration now causes validation to reject openclaw.json, so the gateway may not start until the advertised keys are removed.

Useful? React with 👍 / 👎.

Comment on lines 162 to 165
mode: z.union([z.literal("default"), z.literal("safeguard")]).optional(),
provider: z.string().optional(),
thinkingLevel: AgentThinkingLevelSchema.optional(),
reserveTokens: z.number().int().nonnegative().optional(),
keepRecentTokens: z.number().int().positive().optional(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the compaction QA scenario before rejecting its knobs

When the goal-context-survives-compaction QA scenario runs, qa/scenarios/goals/goal-context-survives-compaction.yaml:19-25 still injects reserveTokens and reserveTokensFloor through gatewayConfigPatch; extensions/qa-lab/src/suite.ts:1771-1773 writes that patch into the gateway config. Since this object is strict, the gateway now rejects the scenario config during startup instead of exercising compaction, breaking that experiment until the scenario is rewritten to use supported controls.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the claude/openclaw-config-phase3 branch from 8e072ae to 4c00afa Compare July 19, 2026 14:05
@steipete steipete closed this Jul 19, 2026
@steipete steipete reopened this Jul 19, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c00afa4bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 220 to 221
richMessages: z.boolean().optional(),
timeoutSeconds: z.number().int().positive().optional(),
mediaGroupFlushMs: z
.number()
.int()
.min(10)
.max(60_000)
.optional()
.describe(
"Buffer window in milliseconds for Telegram media groups/albums before dispatching them as one inbound message. Default: 500.",
),
pollingStallThresholdMs: z.number().int().min(30_000).max(600_000).optional(),
retry: RetryConfigSchema,
network: z

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove retired retry blocks from channel docs

After retry is removed from both strict account schemas, docs/gateway/config-channels.md:200-205 and :333-338 plus docs/concepts/retry.md:44-69 still instruct operators to configure channels.telegram.retry and channels.discord.retry. Copying either documented example now makes config validation reject openclaw.json, potentially preventing Gateway startup.

Useful? React with 👍 / 👎.

Comment on lines 253 to 256
tabCleanup: z
.strictObject({
enabled: z.boolean().optional(),
idleMinutes: z.number().int().nonnegative().optional(),
maxTabsPerSession: z.number().int().nonnegative().optional(),
sweepMinutes: z.number().int().positive().optional(),
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove retired browser cleanup fields from the reference

The strict browser.tabCleanup schema now accepts only enabled, but docs/gateway/configuration-reference.md:415-420 still presents idleMinutes, maxTabsPerSession, and sweepMinutes in its main browser example. Operators copying that reference receive unknown-key validation errors and may be unable to start the Gateway until those advertised fields are removed.

Useful? React with 👍 / 👎.

Comment on lines 370 to 373
triggers: z
.strictObject({
enabled: z.boolean().optional(),
minIntervalMs: z.number().int().positive().optional(),
})
.optional(),
retry: z
.strictObject({
maxAttempts: z.number().int().min(0).max(10).optional(),
backoffMs: z.array(z.number().int().nonnegative()).min(1).max(10).optional(),
retryOn: z
.array(z.enum(["rate_limit", "overloaded", "network", "timeout", "server_error"]))
.min(1)
.optional(),
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the cron condition-watcher QA scenario

When cron-condition-watcher runs, qa/scenarios/scheduling/cron-condition-watcher.yaml:23-27 still injects cron.triggers.minIntervalMs: 250 through gatewayConfigPatch, which extensions/qa-lab/src/suite.ts:1771-1773 merges into the Gateway config. Because cron.triggers is strict and no longer accepts this key, the scenario now fails config validation instead of exercising quiet trigger ticks.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the claude/openclaw-config-phase3 branch from 4c00afa to c847403 Compare July 19, 2026 14:20
@steipete
steipete force-pushed the claude/openclaw-config-phase3 branch from c847403 to 9ab967c Compare July 19, 2026 14:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ab967cfb7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 75 to 76
sendPolicy: SessionSendPolicySchema.optional(),
writeLock: z
.object({
acquireTimeoutMs: z.number().int().positive().optional(),
staleMs: z.number().int().positive().optional(),
maxHoldMs: z.number().int().positive().optional(),
})
.strict()
.optional(),
agentToAgent: z
.object({
maxPingPongTurns: z.number().int().min(0).max(20).optional(),
})
.strict()
.optional(),
threadBindings: z

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the A2A mirror-dedupe QA scenario

When a2a-message-tool-mirror-dedupe runs, qa/scenarios/channels/a2a-message-tool-mirror-dedupe.yaml:13-19 still adds session.agentToAgent.maxPingPongTurns: 0 through gatewayConfigPatch, and extensions/qa-lab/src/suite.ts:1771-1773 writes that patch into the Gateway config. Because SessionSchema is strict and no longer accepts agentToAgent, Gateway startup fails validation before this channel-delivery scenario can exercise mirror deduplication.

Useful? React with 👍 / 👎.

Comment on lines 904 to 908
temporalDecay: z
.object({
enabled: z.boolean().optional(),
halfLifeDays: z.number().int().positive().optional(),
})
.strict()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the session-memory ranking QA scenario

During session-memory-ranking, qa/scenarios/memory/session-memory-ranking.yaml:63-78 calls config.patch with agents.defaults.memorySearch.query.hybrid.temporalDecay.halfLifeDays: 1; extensions/qa-lab/src/suite-runtime-gateway.ts:344-365 sends that mutation to the Gateway. The now-strict temporalDecay object accepts only enabled, so the patch is rejected and the scenario stops before proving that temporal decay ranks the current memory above the stale one.

Useful? React with 👍 / 👎.

@steipete
steipete merged commit 783a5d2 into main Jul 19, 2026
120 checks passed
@steipete
steipete deleted the claude/openclaw-config-phase3 branch July 19, 2026 14:35
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui channel: discord Channel integration: discord channel: signal Channel integration: signal channel: slack Channel integration: slack channel: telegram Channel integration: telegram channel: whatsapp-web Channel integration: whatsapp-web cli CLI command changes commands Command implementations docs Improvements or additions to documentation extensions: codex extensions: memory-core Extension: memory-core extensions: qa-lab gateway Gateway runtime maintainer Maintainer-authored PR scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant