feat(config): add canonical group-policy scope-tree resolver#106819
feat(config): add canonical group-policy scope-tree resolver#106819steipete wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d8a7307cee
ℹ️ 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".
| senderName: params.senderName, | ||
| senderUsername: params.senderUsername, | ||
| senderE164: params.senderE164, | ||
| messageProvider: params.messageProvider, |
There was a problem hiding this comment.
Add a channel fallback for sender policy
When a channel migrates its groups.resolveToolPolicy adapter to this new public resolver and passes the existing ChannelGroupContext fields, channel-scoped toolsBySender entries like channel:discord:<senderId> or channel:whatsapp:<senderId> never match because ChannelGroupContext has no messageProvider field and resolveToolsBySender only checks channel: buckets when that value is present. The existing resolveChannelGroupToolsPolicy avoids this by defaulting messageProvider to params.channel, so this resolver should accept a channel/provider parameter and apply the same fallback; otherwise it silently falls through to generic id: or wildcard policies during the advertised channel migrations.
Useful? React with 👍 / 👎.
|
Codex review: needs real behavior proof before merge. Reviewed July 13, 2026, 7:22 PM ET / 23:22 UTC. Summary PR surface: Source +117, Tests +296, Generated 0, Other +1. Total +414 across 5 files. Reproducibility: not applicable. This PR introduces a new canonical resolver and public SDK surface rather than fixing a demonstrated current-main failure. Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Use one canonical landing path, preferably #106846, make provider identity mandatory or preserve the existing channel fallback, keep the SDK surface no broader than required, and attach redacted live migration proof before closing the stacked PRs. Do we have a high-confidence way to reproduce the issue? Not applicable: this PR introduces a new canonical resolver and public SDK surface rather than fixing a demonstrated current-main failure. Is this the best way to solve the issue? Unclear: centralizing duplicated policy resolution is directionally sound, but the best landing is one provider-safe canonical change with real channel migrations rather than an unproven standalone public API slice. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 8da737858d62. Label changesLabel justifications:
Evidence reviewedPR surface: Source +117, Tests +296, Generated 0, Other +1. Total +414 across 5 files. View PR surface stats
Security concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (3 earlier review cycles)
|
d8a7307 to
2ccd5bf
Compare
2ccd5bf to
d38f5b4
Compare
What Problem This Solves
16 channel plugins register a
groupsadapter answering the same questions — effectiverequireMention, tool policy (including sender-scoped tools), group intro hints — but only 9 delegate to the shared resolver insrc/config/group-policy.ts. The rest ship private walkers over channel-specific config nests (discord guild→channel, telegram group→topic, msteams team→channel with cross-team scan, slack/matrix/zalouser candidate matching): same decision, many implementations, measurable drift (e.g. adapter paths that can never matchchannel:-prefixedtoolsBySenderkeys while the core fallback can).Why This Change Was Made
Stage 1 of the group-policy scope normalization design (load-time canonical model, zero user-visible config change): a
ScopeTreeof flat keyed scope nodes plus channel-ordered scope paths, with core-owned resolvers for requireMention (most-specific-wins, override-order semantics identical toresolveChannelGroupRequireMention), tool policy (per-leveltoolsBySender→tools, whole-object override, reusingresolveToolsBySenderverbatim as the sender engine), and intro hints. Flat keys instead of a nested tree are deliberate: telegram's real precedence lets a wildcard-group topic node outrank an exact-group scalar, which a nested walk cannot express; channels encode precedence in the path they emit. Runtime overrides stay resolver parameters, never tree data. Follow-up PRs migrate channels in parity-tested batches and delete the per-channel walkers (~600 LOC across 11 files).User Impact
None yet — no callers are wired in this PR; behavior is unchanged. The new resolvers are exported via
openclaw/plugin-sdk/channel-policy(surface budgets bumped by the exact delta with a citation comment) so channel migrations can adopt them.Evidence
pnpm test src/config/group-scope-tree.test.ts src/config/group-policy.test.ts src/plugin-sdkgreen;pnpm check:changedgreen through all lanes with the regenerated Plugin SDK API baseline hash committed.true), the telegram-shaped ordering case, msteams-shaped two-level cascade, typed-sender key integration incl.messageProvidergating, before-/after-config override parity withgroup-policy.ts,configuredScopeDefaultsToNoMention, and narrowest-first intro hints.