#!/usr/bin/env bash set -euo pipefail CONF="/home/node/.openclaw/openclaw.json" CONTRACT="/home/node/.openclaw/workspace/memory/discord-routing-contract.json" python3 - <<'PY' import json,sys from pathlib import Path conf=json.loads(Path('/home/node/.openclaw/openclaw.json').read_text()) contract=json.loads(Path('/home/node/.openclaw/workspace/memory/discord-routing-contract.json').read_text()) errors=[] warn=[] bindings=conf.get('bindings',[]) discord_cfg=((conf.get('channels') or {}).get('discord') or {}) guilds=(discord_cfg.get('guilds') or {}) gid=contract.get('guildId') guild_cfg=(guilds.get(gid) or {}) guild_channels=(guild_cfg.get('channels') or {}) # index bindings by (agent, kind, id) def has_binding(agent,kind,cid): for b in bindings: if b.get('agentId')!=agent: continue m=b.get('match') or {} if m.get('channel')!='discord': continue p=m.get('peer') or {} if p.get('kind')==kind and p.get('id')==cid: return True return False # validate channel contracts for cid,meta in (contract.get('channels') or {}).items(): agent=meta.get('expectedAgent') kinds=meta.get('peerKinds') or [] for k in kinds: if not has_binding(agent,k,cid): errors.append(f"Missing binding: agent={agent} peer={k}:{cid}") # allowlist presence if cid not in guild_channels: errors.append(f"Channel {cid} missing from channels.discord.guilds.{gid}.channels allowlist") else: req=(guild_channels.get(cid) or {}).get('requireMention') exp=meta.get('requireMention') if exp is not None and req!=exp: errors.append(f"requireMention mismatch for {cid}: expected {exp}, got {req}") # validate guild fallback fb=((contract.get('guildFallback') or {}).get('expectedAgent')) if fb: ok=False for b in bindings: if b.get('agentId')!=fb: continue m=b.get('match') or {} if m.get('channel')=='discord' and m.get('guildId')==gid: ok=True break if not ok: errors.append(f"Missing guild fallback binding for guild {gid} -> {fb}") # Note: binding index order does not override match-tier precedence (peer beats guild). # So we intentionally do not fail on peer-after-guild placement. if errors: print('DISCORD ROUTING VERIFICATION: FAIL') for e in errors: print('-',e) sys.exit(1) print('DISCORD ROUTING VERIFICATION: OK') PY