Skip to content

feat(skill): fleet-roster — zero-ID skill + channel-verified mention + GUILD_MEMBERS intent - #1492

Closed
sonichi wants to merge 4 commits into
mainfrom
feat/fleet-roster-skill
Closed

sonichi wants to merge 4 commits into
mainfrom
feat/fleet-roster-skill

Conversation

@sonichi

@sonichi sonichi commented Jun 6, 2026

Copy link
Copy Markdown
Owner

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)
  • Adds async def list_channel_members(channel_id) → list[dict] — live guild membership query used by mention_verified()

2. skills/fleet-roster/scripts/fleet_roster.py — canonical name→ID skill

3. tests/fleet-roster.test.py — 9 tests

  • test_no_hardcoded_ids: verifies no Discord snowflake IDs in committed source (CI enforcement)
  • test_private_roster_path_default, test_configurable_path
  • test_raises_without_roster, test_mention_with_private_roster
  • test_no_synced_data_file: verifies fleet-roster.json absent from workspace/data/
  • test_mention_verified_defined, test_dependency_direction, test_platform_param

Scope check

The discord-bridge change exists solely to serve mention_verified(). Nothing unrelated rode along — the diff is intents.members = True + the new async function. Test coverage is in tests/discord-list-members.test.py (4 tests).

What's NOT in this PR

  • Fleet-roster data file (fleet-roster.local.json) — deferred until workspace revamp lands
  • CLA/access.json changes
  • Any hardcoded IDs

Review checklist for Air + Mini

  • No Discord snowflake IDs anywhere in the diff (test enforces, but verify manually)
  • list_channel_members() dependency direction: skill → bridge, never reverse
  • mention_verified() fallback behavior is correct (drift > refusal)
  • Path resolution uses $SUTANDO_MEMORY_DIR at runtime

Stand: Echo Act IV Pro

sonichi added 4 commits June 6, 2026 12:19
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
@sonichi

sonichi commented Jun 6, 2026

Copy link
Copy Markdown
Owner Author

Closing to scrub leaked IDs from SKILL.md and tests. Reopening with clean history.

@sonichi sonichi closed this Jun 6, 2026
@sonichi
sonichi deleted the feat/fleet-roster-skill branch June 6, 2026 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant