Skip to content

Config: preserve implicit main route bindings#89490

Closed
dahifi wants to merge 1 commit into
openclaw:mainfrom
dahifi:seraphel/issue-89412-main-binding
Closed

Config: preserve implicit main route bindings#89490
dahifi wants to merge 1 commit into
openclaw:mainfrom
dahifi:seraphel/issue-89412-main-binding

Conversation

@dahifi

@dahifi dahifi commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Treat the implicit default agent main as an allowed route binding target during config validation, even when agents.list is populated.
  • Preserve main route bindings during doctor compatibility pruning while continuing to prune genuinely missing agent ids.
  • Add regression coverage for the documented ACP multi-agent shape with codex/claude in agents.list and fallback bindings to main.

Fixes #89412

Test plan

  • RED: node scripts/run-vitest.mjs src/config/config.schema-regressions.test.ts --run failed on the new main binding validation regression.
  • RED: node scripts/run-vitest.mjs src/commands/doctor/shared/legacy-config-migrate.test.ts --run failed on the new doctor preservation regression.
  • GREEN: node scripts/run-vitest.mjs src/config/config.schema-regressions.test.ts src/commands/doctor/shared/legacy-config-migrate.test.ts --run passed: 2 Vitest shards, 137 tests.
  • pnpm check passed.
  • pnpm build passed.

— Seraphel

@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 2, 2026
@clawsweeper

clawsweeper Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 15, 2026, 5:20 AM ET / 09:20 UTC.

Summary
The PR adds DEFAULT_AGENT_ID to route-binding allowed sets in config validation and doctor compatibility pruning, with regression tests for preserving main bindings when agents.list is populated.

PR surface: Source +6, Tests +52. Total +58 across 4 files.

Reproducibility: yes. source-level. A non-empty agents.list plus agentId: "main" hits the current schema/doctor predicates, and the PR head still leaves runtime routing through pickFirstExistingAgentId.

Review metrics: 1 noteworthy metric.

  • Route-binding predicates: 2 changed, 0 new config options. Both load-time validation and doctor pruning decide whether existing route bindings survive startup or upgrade.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Fix runtime main route resolution and configured binding compilation, then add focused route regression coverage.
  • [P1] Add redacted real config-load, doctor, gateway, or route-resolution proof showing agentId: "main" remains main after the patch.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body lists tests/check/build output only; before merge, add redacted after-fix config-load, doctor, gateway, or route-resolution output and update the PR body for re-review.

Risk before merge

  • [P1] Accepted explicit main route bindings can still resolve to the first/default listed agent at runtime because route consumers continue to call pickFirstExistingAgentId.
  • [P1] The diff changes upgrade-sensitive config validation and doctor pruning for existing bindings[], but the PR body has no after-fix real config-load, doctor, gateway, or route-resolution proof.

Maintainer options:

  1. Fix Runtime Main Semantics (recommended)
    Update route resolution and configured binding compilation so accepted explicit main remains the implicit main agent when it is absent from agents.list, with focused regression coverage.
  2. Accept Staged Validation Repair
    Maintainers could knowingly land only the validation and doctor preservation change, but they would own the remaining wrong-agent delivery risk until follow-up work lands.
  3. Pause For Replacement
    If this branch will not cover runtime semantics and proof, pause it in favor of a narrow replacement that fixes the full binding path.

Next step before merge

  • [P1] Contributor or maintainer revision is needed for runtime semantics and real behavior proof; the proof gate cannot be satisfied by an automated repair lane for this external PR.

Security
Cleared: No concrete security or supply-chain concern was found; the diff is limited to config validation, doctor pruning, and tests.

Review findings

  • [P1] Preserve explicit main in route resolution — src/config/zod-schema.ts:1286-1289
Review details

Best possible solution:

Make exact main consistent across schema validation, doctor pruning, route resolution, and configured binding compilation, then add focused route/doctor regressions plus redacted real behavior proof.

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

Yes, source-level. A non-empty agents.list plus agentId: "main" hits the current schema/doctor predicates, and the PR head still leaves runtime routing through pickFirstExistingAgentId.

Is this the best way to solve the issue?

No. Preserving main in schema and doctor is necessary, but the best fix must also preserve the same target in route resolution and configured binding compilation.

Full review comments:

  • [P1] Preserve explicit main in route resolution — src/config/zod-schema.ts:1286-1289
    Adding DEFAULT_AGENT_ID here lets documented agentId: "main" bindings load, but matched route bindings still call pickFirstExistingAgentId(). With agents.list containing only entries like codex and claude, main is absent from the lookup map and resolves to the configured default listed agent instead of the implicit main session, so add the runtime fix and route regression before merge.
    Confidence: 0.93

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 233b48daaab4.

Label changes

Label justifications:

  • P1: The PR targets a documented startup/config-loss regression but can still produce wrong-agent channel delivery after relaxing validation.
  • merge-risk: 🚨 compatibility: The diff changes config load and doctor repair behavior for existing bindings[] entries during upgrade.
  • merge-risk: 🚨 message-delivery: Accepted main route bindings can still resolve to a listed agent instead of the implicit main agent.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body lists tests/check/build output only; before merge, add redacted after-fix config-load, doctor, gateway, or route-resolution output and update the PR body for re-review.
Evidence reviewed

PR surface:

Source +6, Tests +52. Total +58 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 10 4 +6
Tests 2 52 0 +52
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 62 4 +58

What I checked:

  • PR diff scope: The branch changes schema validation, doctor compatibility pruning, and tests only; it does not change route resolution or configured binding compilation. (src/config/zod-schema.ts:1286, 5177472ea93c)
  • Runtime route consumer still remaps binding targets: resolveAgentRoute passes matched binding targets through pickFirstExistingAgentId, so accepting agentId: "main" in schema does not preserve that target at runtime. (src/routing/resolve-route.ts:663, 233b48daaab4)
  • Missing main falls back to configured default listed agent: When agents.list is non-empty and the requested normalized id is absent, pickFirstExistingAgentId returns the fallback default agent id. (src/routing/resolve-route.ts:168, 233b48daaab4)
  • Default agent can be the first listed ACP agent: resolveDefaultAgentId chooses the first/default agents.list entry when the list is non-empty, which can turn an explicit main fallback binding into codex or another listed agent. (src/agents/agent-scope-config.ts:92, 233b48daaab4)
  • Configured binding compiler shares the same helper: Configured binding compilation also calls pickFirstExistingAgentId, so the runtime target-preservation issue is not limited to direct route resolution. (src/channels/plugins/configured-binding-compiler.ts:83, 233b48daaab4)
  • Documented affected config shape: The ACP docs show agents.list with codex and claude plus route bindings targeting agentId: "main" for Discord and Telegram fallback routing. Public docs: docs/tools/acp-agents.md. (docs/tools/acp-agents.md:423, 233b48daaab4)

Likely related people:

  • yetval: Commit bbdff39b6a3f added normalized binding-agent validation and doctor pruning for missing agents.list ids in the central files touched by this PR. (role: introduced current validation and doctor behavior; confidence: high; commits: bbdff39b6a3f; files: src/config/zod-schema.ts, src/commands/doctor/shared/legacy-config-core-migrate.ts)
  • Squirbie: PR history for a1cb8d50ba8d shows focused work on route binding behavior and resolve-route.ts, adjacent to the runtime path that still needs main preservation. (role: recent routing contributor; confidence: medium; commits: a1cb8d50ba8d; files: src/routing/resolve-route.ts)
  • steipete: Recent history includes documentation/refactor touches around doctor compatibility helpers, routing helpers, and config schema normalization in the affected area. (role: recent adjacent contributor; confidence: medium; commits: 4fcc7537ffec, 9b30ff181c14, 00d8d7ead059; files: src/commands/doctor/shared/legacy-config-core-migrate.ts, src/routing/resolve-route.ts, src/config/zod-schema.ts)
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.

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.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 2, 2026
@openclaw-clownfish

Copy link
Copy Markdown
Contributor

Thanks @dahifi for the focused fix and proof notes. I am closing this as superseded by #89419 (#89419) because both PRs target the same #89412 route-binding bug, and #89419 is the current canonical path with the stricter exact-main guard plus expanded schema and doctor regression coverage.

Clownfish will keep credit and source PR attribution for this work from #89490 (#89490) in the canonical thread/context. If your branch has a different reproduction path or still catches behavior after the canonical fix lands, please reply and we can reopen or split it back out.

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

Labels

clownfish Tracked by Clownfish automation commands Command implementations merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: binding to the implicit default agent "main" is rejected at config load and deleted by doctor --fix when agents.list is non-empty

1 participant