* feat(config): give shared channel settings help text
* fix(ui): space the settings tiers and stop repeating help on list items
* feat(ui): link each channel detail to its docs page
* test(ui): mirror production channel hints in the mock dev server
* docs: note the shared channel help inheritance for plugin authors
* fix(config): let a channel suppress shared help with an empty string
* chore(config): regenerate bundled channel metadata for the new WhatsApp hints
* fix(ci): check bundled channel metadata locally
* chore(release): keep changelog release-owned
* chore(release): keep changelog release-owned
* fix(ui): keep shared channel help contract-neutral
* feat(ui): repair settings titles, scope form-unsafe banner, consolidate advanced tier
- Advanced/Notifications settings headers rendered raw i18n keys
(tabs.advanced/tabs.notifications); configPageTitle now resolves through
the nav registry titleForRoute, deleting the drifting key map.
- Form-unsafe banner is value-aware (only when the user's config has a value
at a form-unsupported path in the active scope), names the paths, offers an
Open Raw editor action, and sits in the content column instead of full-bleed.
- Advanced tier collapses to one synced toggle: hidden advanced fields render
a ghost row that enables the toggle; the Advanced page always reveals and
hides the toggle; per-section details state and the controlled-open dance
are deleted; toggle visibility mirrors the renderer's tier split.
- schema.tags no longer tags facet-less paths as "advanced" (common fields
like update.channel wore a lying chip); the chip is no longer rendered in
form rows while tag:advanced search keeps working.
* fix(config): dev bootstrap writes canonical agents.entries; finish stale agents.list sweep
- openclaw gateway run --dev failed on a fresh state dir: the bootstrap wrote
the retired agents.list array and validation rejected its own config
(Unrecognized key: list). It now writes the keyed agents.entries record;
new dev.test.ts validates the written shape against the zod schema.
- Revive the dead gateway hot-reload rule: prefix agents.list never matched
canonical config diffs, so per-agent heartbeat edits fell through to the
agents:none tail rule; the rule now matches agents.entries.
- config set replacement protection moves from the dead agents.list array
to the agents.entries map (joins plugins.entries/auth.profiles family).
- Sweep remaining stale agents.list config-path strings in hints, fix-it
messages, elevated gates, doctor hints, audit text, and type docs to
agents.entries.*; RPC ids, the internal list projection, and doctor
legacy-migration references intentionally keep the old name.
* test(ui): derive nav i18n audit from route registry; fix stale bootstrap hint assertion
- Knip flagged navigationCopyEntries (test-only export); the audit now walks
ALL_ROUTES through prod titleForRoute/subtitleForRoute and rejects raw
dotted-key output, so no export exists solely for the test.
- commands-context-report expected the retired agents.list[] hint wording.
* fix(config): align rebase resolution with main's roster-aware diagnostic
- tool-policy-diagnostic: keep main's test expectations (dotted
agents.entries.<id> paths from the roster-aware implementation); our
pre-rebase bracket-style assertions no longer match any code.
- Reapply the placeholder sweep the conflict resolution dropped:
generic agents.list[] fallbacks in tool-policy-diagnostic and the audit
sandbox-mode hint now say agents.entries.*.