Skip to content

fix(doctor): preserve unknown web search records#83315

Merged
giodl73-repo merged 9 commits into
mainfrom
fix-legacy-web-search-preserve-records-83287
May 20, 2026
Merged

fix(doctor): preserve unknown web search records#83315
giodl73-repo merged 9 commits into
mainfrom
fix-legacy-web-search-preserve-records-83287

Conversation

@giodl73-repo

@giodl73-repo giodl73-repo commented May 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • preserve unrelated record-valued tools.web.search entries during legacy web search migration
  • align tools.web.search validation with its extensible config type so doctor writes do not drop extension-owned settings, while still rejecting known legacy provider-scoped records
  • continue removing only positively identified legacy provider records and dangerous prototype keys
  • add regression coverage for custom record-valued web search config next to a legacy apiKey

Fixes #83287.

Real behavior proof

Behavior addressed: legacy web search migration should move known provider-owned settings while preserving unrelated extension-owned tools.web.search records.
Real environment tested: WSL Ubuntu OpenClaw source checkout at PR head 154550b971d0 on branch tmp-pr-83315-proof.
Exact steps or command run after this patch: OPENCLAW_CONFIG_PATH="$cfg" node --import tsx src/entry.ts doctor --fix --non-interactive --no-workspace-suggestions.
Evidence after fix: the command below migrated the legacy Brave key while preserving unrelated record-valued search settings in the written config.

before tools.web.search:
{
  "apiKey": "brave-key",
  "customSearch": {
    "endpoint": "https://search.example.test",
    "mode": "strict"
  },
  "openaiCodex": {
    "enabled": true
  }
}
command: OPENCLAW_CONFIG_PATH=/tmp/openclaw-83315-config.NyMROQ.json node --import tsx src/entry.ts doctor --fix --non-interactive --no-workspace-suggestions
Doctor changes:
  Moved tools.web.search.apiKey → plugins.entries.brave.config.webSearch.apiKey.
Updated config: /tmp/openclaw-83315-config.NyMROQ.json

after tools.web.search and migrated plugin config:
{
  "customSearch": {
    "endpoint": "https://search.example.test",
    "mode": "strict"
  },
  "openaiCodex": {
    "enabled": true
  }
}
plugins.entries.brave.config.webSearch = {"apiKey":"brave-key"}

Observed result after fix: doctor --fix migrated the legacy global search key to plugins.entries.brave.config.webSearch.apiKey, removed tools.web.search.apiKey, and preserved both tools.web.search.customSearch and tools.web.search.openaiCodex in the written config.
What was not tested: a live web search call using the preserved custom provider record; this proof covers the on-disk doctor migration/write path.

Root Cause

  • Root cause: normalization treated all record-valued unknown keys as removable unless they were in a small modern allowlist, and schema validation was stricter than the config type.
  • Missing detection / guardrail: no regression test covered an unrelated record-valued key beside a migrated legacy provider key through config validation, or the schema boundary that keeps known legacy provider records invalid.
  • Contributing context: the migration needs to remove legacy provider records, but that removal condition was broader than the set of known legacy providers.

Regression Test Plan

  • Coverage level that should have caught this: unit plus config validation test.
  • Target tests or files: src/commands/doctor/shared/legacy-web-search-migrate.test.ts, src/config/web-search-codex-config.test.ts, src/config/config.web-search-provider.test.ts.
  • Scenario the tests should lock in: known legacy provider config is migrated/rejected while unrelated record-valued config remains under tools.web.search and survives validation.
  • Why this is the smallest reliable guardrail: the behavior is isolated to config normalization and schema validation before broader doctor plumbing.

Validation

  • node node_modules/vitest/vitest.mjs run src/config/config.web-search-provider.test.ts src/config/web-search-codex-config.test.ts src/commands/doctor/shared/legacy-web-search-migrate.test.ts --reporter=dot in WSL: 3 files, 41 tests passed.
  • node node_modules/@typescript/native-preview/bin/tsgo.js --noEmit --pretty false -p tsconfig.json in WSL.
  • git diff --check.

@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations size: XS maintainer Maintainer-authored PR labels May 17, 2026
@clawsweeper

clawsweeper Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

Workflow note: Future ClawSweeper reviews update this same comment in place.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Summary
The PR changes doctor migration and config validation so unknown record-valued tools.web.search entries survive legacy web-search repair while legacy provider records and blocked prototype keys remain rejected.

Reproducibility: yes. from source inspection: current main only preserves openaiCodex or non-record unknown search keys during legacy migration, so a custom record-valued key beside a migrated legacy key is dropped. I did not execute tests in the read-only checkout, but the failing path is clear from the migration loop.

PR rating
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Summary: Focused patch with sufficient terminal proof and no blocking findings; remaining readiness is ordinary maintainer review.

Rank-up moves:

  • none
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Real behavior proof
Sufficient (terminal): The PR body includes terminal proof from a real WSL doctor --fix run showing the legacy Brave key migrated while custom record-valued search settings were preserved in the written config.

Next step before merge
The protected maintainer label and clean review leave this for explicit maintainer review and normal merge gates; no ClawSweeper repair is indicated.

Security
Cleared: The diff only changes local config validation, doctor migration logic, and tests; it adds no dependencies, workflows, network calls, or new execution surfaces and preserves prototype-key blocking.

Review details

Best possible solution:

Land this PR or an equivalent narrow fix after maintainer review so doctor preserves extension-owned web-search records without weakening legacy-provider migration or prototype-key safety.

Do we have a high-confidence way to reproduce the issue?

Yes, from source inspection: current main only preserves openaiCodex or non-record unknown search keys during legacy migration, so a custom record-valued key beside a migrated legacy key is dropped. I did not execute tests in the read-only checkout, but the failing path is clear from the migration loop.

Is this the best way to solve the issue?

Yes. Updating both the migration normalization and the schema boundary is the narrow maintainable fix because the config type is already extensible, while known legacy provider records and blocked prototype keys remain explicitly guarded.

Label justifications:

  • P2: This is a focused doctor/config data-preservation bug fix with limited blast radius and targeted regression coverage.
  • rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🦞 diamond lobster, patch quality is 🐚 platinum hermit, and Focused patch with sufficient terminal proof and no blocking findings; remaining readiness is ordinary maintainer review.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes terminal proof from a real WSL doctor --fix run showing the legacy Brave key migrated while custom record-valued search settings were preserved in the written config.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes terminal proof from a real WSL doctor --fix run showing the legacy Brave key migrated while custom record-valued search settings were preserved in the written config.

What I checked:

  • Current main drops custom record-valued search config: On current main, normalizeLegacyWebSearchConfigRecord skips apiKey and legacy provider records, then only preserves openaiCodex or non-record values, so an unrelated record-valued key is omitted during migration. (src/commands/doctor/shared/legacy-web-search-migrate.ts:203, 6048cd43a5ab)
  • Config type is extensible but current schema is strict: The TypeScript config type allows tools.web.search to carry Record<string, unknown> extension-owned fields, while current main's Zod schema is .strict(), which explains the PR's schema-side fix. (src/config/types.tools.ts:571, 6048cd43a5ab)
  • PR diff addresses migration and validation together: The PR removes the narrow modern-key allowlist, preserves non-legacy/non-blocked keys, adds blocked prototype-key handling, changes ToolsWebSearchSchema to accept unknown extension fields, and rejects known legacy provider records. (src/config/zod-schema.agent-runtime.ts:343, 064b20669a1d)
  • Regression coverage targets the reported path: The PR adds tests for preserving unrelated record-valued web-search config, dropping dangerous keys, and validating extension-owned tools.web.search records while rejecting blocked keys. (src/commands/doctor/shared/legacy-web-search-migrate.test.ts:62, 064b20669a1d)
  • Contributor real behavior proof is present: The PR body includes a WSL doctor --fix run showing tools.web.search.apiKey migrated to plugins.entries.brave.config.webSearch.apiKey while customSearch and openaiCodex remained in the written config. (064b20669a1d)
  • Current line provenance: git blame in this checkout points the current migration and strict schema lines to commit e2c8e7c; older feature history also shows legacy migration refactoring and native web-search config work in adjacent commits. (src/commands/doctor/shared/legacy-web-search-migrate.ts:203, e2c8e7c8ae65)

Likely related people:

  • hcl: Current checkout blame attributes the legacy web-search migration and schema lines involved in this bug to commit e2c8e7c. (role: current line owner / recent area contributor; confidence: medium; commits: e2c8e7c8ae65; files: src/commands/doctor/shared/legacy-web-search-migrate.ts, src/config/zod-schema.agent-runtime.ts)
  • Peter Steinberger: Commit b169b2c moved legacy config migrations under doctor and touched the web-search migration surface. (role: legacy migration refactor author; confidence: medium; commits: b169b2c9772b; files: src/commands/doctor/shared/legacy-config-migrations.web-search.ts, src/commands/doctor/shared/legacy-web-search-migrate.ts)
  • Christof Salis: Commit 797a70f added native web-search config surfaces including openaiCodex, which is part of the affected tools.web.search schema boundary. (role: adjacent feature contributor; confidence: medium; commits: 797a70fd95f0; files: src/config/types.tools.ts, src/config/zod-schema.agent-runtime.ts, src/config/web-search-codex-config.test.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 6048cd43a5ab.

@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. impact:data-loss Can lose, corrupt, or silently drop user/session/config data. impact:auth-provider Auth, provider routing, model choice, or SecretRef resolution may break. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels May 17, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. impact:security Security boundary, credential, authz, sandbox, or sensitive-data risk. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels May 18, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

Reviewed and fixed the prototype-key blocker from the prior ClawSweeper pass.

Change in 4e2e711ff5b3d3e19c4ba466917e184e28e6e48d:

  • Mirrors the adjacent legacy web-fetch migration guard for __proto__, prototype, and constructor.
  • Adds a focused regression that preserves unrelated record-valued web-search config while dropping dangerous keys.

Verification:

  • git diff --check
  • node node_modules/vitest/vitest.mjs run src/commands/doctor/shared/legacy-web-search-migrate.test.ts --reporter verbose -> 4 tests passed

Note: WSL codex review --uncommitted timed out without output, so I used manual review plus focused test proof for this small follow-up.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed impact:data-loss Can lose, corrupt, or silently drop user/session/config data. impact:security Security boundary, credential, authz, sandbox, or sensitive-data risk. impact:auth-provider Auth, provider routing, model choice, or SecretRef resolution may break. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels May 18, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated the patch and PR body after real doctor --fix proof exposed an end-to-end schema/write gap. The PR now preserves extension-owned tools.web.search records through migration, validation, and config write.

Verification:

  • WSL real doctor run: OPENCLAW_CONFIG_PATH="$cfg" node --import tsx src/entry.ts doctor --fix --non-interactive --no-workspace-suggestions, preserving customSearch and migrating apiKey to plugins.entries.brave.config.webSearch.apiKey.
  • node node_modules/vitest/vitest.mjs run src/commands/doctor/shared/legacy-web-search-migrate.test.ts src/config/web-search-codex-config.test.ts --reporter=dot
  • node node_modules/@typescript/native-preview/bin/tsgo.js --noEmit --pretty false -p tsconfig.json
  • git diff --check

@clawsweeper

clawsweeper Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels May 18, 2026
@giodl73-repo giodl73-repo force-pushed the fix-legacy-web-search-preserve-records-83287 branch from 6e8f873 to 1dec7e0 Compare May 19, 2026 16:11
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

✨ Hatched: 🥚 common Velvet Review Wisp

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 🥚 common.
Trait: keeps receipts.
Image traits: location branch lighthouse; accessory lint brush; palette seafoam, black, and opal; mood proud; pose balancing on a branch marker; shell matte ceramic shell; lighting calm overcast light; background small green status lights.
Share on X: post this hatch
Copy: My PR egg hatched a 🥚 common Velvet Review Wisp in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@giodl73-repo giodl73-repo merged commit 70e51b8 into main May 20, 2026
99 checks passed
@giodl73-repo giodl73-repo deleted the fix-legacy-web-search-preserve-records-83287 branch May 20, 2026 01:35
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 25, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
* fix(doctor): preserve unknown web search records

* fix(doctor): filter dangerous web search keys

* fix(config): preserve extensible web search settings

* fix(config): keep legacy web search validation strict

* fix(config): reject blocked web search keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations maintainer Maintainer-authored PR P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: legacy web search migration drops unrelated record-valued config

1 participant