Repository navigation
Conversation
Adds async list_channel_members(channel_id) to discord-bridge.py. Queries all guild members who have VIEW_CHANNEL permission for the specified channel — enables accurate allowFrom population without manual ID guessing. Requires GUILD_MEMBERS privileged intent in Discord Dev Portal (already enabled per owner, 2026-06-06). Enables intents.members in bridge code. Stand: Echo Act IV Pro
…ied mention Adds skills/fleet-roster/ skill: - mention(name, platform) — name→ID lookup from builtin dict; platform param for Discord/ag2.space future cutover - mention_verified(name, channel_id) — live membership check via discord-bridge list_channel_members() at post-time; prevents mentions to channels where the target bot can't see; falls back to unverified with warning if GUILD_MEMBERS intent unavailable (avoids false-negative refusals) - No roster data file in workspace (IDs stay private; builtin dict is the source) - FLEET_ROSTER_PATH override for migration safety Closes the "posted where Lucy can't see it" class of bugs. 8 tests, all passing. Dependency direction: skill → discord-bridge, never reverse. Stand: Echo Act IV Pro
Per Air's corrected design review: IDs-in-.py is the same leak as IDs-in-JSON. fleet_roster.py now ships with ZERO IDs. Privacy contract: - fleet_roster.py: NO IDs (safe to share/review/commit) - ~/.claude/fleet-roster.local.json: per-host private file (NOT committed, NOT memory-synced) Each host installs its own name→ID map at ~/.claude/fleet-roster.local.json. mention() raises FileNotFoundError if not installed (explicit error > silent drift). mention_verified() + channel-verified lookup unchanged. 9 tests passing. Stand: Echo Act IV Pro
Per Air's call (2026-06-06): the data file lives in the Memory space ($SUTANDO_MEMORY_DIR) so it migrates correctly with the workspace-revamp. Default path: $SUTANDO_MEMORY_DIR/fleet-roster.local.json. Override: FLEET_ROSTER_PATH env var (unchanged). The data file itself is DEFERRED until the Memory-space migration settles (#1449, #1454, #1490). This commit ships the resolver logic only. Stand: Echo Act IV Pro
Owner
Author
|
Closing to scrub leaked IDs from SKILL.md and tests. Reopening with clean history. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
skills/fleet-roster/— the cross-host substrate that fixes the «posted where Lucy can't see it» / wrong-mention class of bugs.Privacy contract: The code ships with ZERO Discord IDs. IDs live in
$SUTANDO_MEMORY_DIR/fleet-roster.local.json(per-host private file, NOT committed, NOT memory-synced). The committed code contains only resolution logic.What this PR does
1.
src/discord-bridge.py— GUILD_MEMBERS intent +list_channel_members()intents.members = True(requires GUILD_MEMBERS privileged intent in Discord Dev Portal — already granted per owner)async def list_channel_members(channel_id) → list[dict]— live guild membership query used bymention_verified()2.
skills/fleet-roster/scripts/fleet_roster.py— canonical name→ID skillmention(name, platform)— reads private local roster at runtime; raisesFileNotFoundErrorif not installed (explicit error > silent drift); platform param for Discord/ag2.space cutovermention_verified(name, channel_id)— live membership check viadiscord-bridge.list_channel_members()at post-time; falls back to unverified with warning if GUILD_MEMBERS unavailable (avoids false-negative refusals)$SUTANDO_MEMORY_DIR/fleet-roster.local.json(follows Memory-space after workspace-revamp); override viaFLEET_ROSTER_PATHenv var.sutando/workspacenamespace across resolvers, helpers, docs (8 commits) #1490)3.
tests/fleet-roster.test.py— 9 teststest_no_hardcoded_ids: verifies no Discord snowflake IDs in committed source (CI enforcement)test_private_roster_path_default,test_configurable_pathtest_raises_without_roster,test_mention_with_private_rostertest_no_synced_data_file: verifies fleet-roster.json absent from workspace/data/test_mention_verified_defined,test_dependency_direction,test_platform_paramScope check
The discord-bridge change exists solely to serve
mention_verified(). Nothing unrelated rode along — the diff isintents.members = True+ the new async function. Test coverage is intests/discord-list-members.test.py(4 tests).What's NOT in this PR
fleet-roster.local.json) — deferred until workspace revamp landsReview checklist for Air + Mini
list_channel_members()dependency direction: skill → bridge, never reversemention_verified()fallback behavior is correct (drift > refusal)$SUTANDO_MEMORY_DIRat runtimeStand: Echo Act IV Pro