c2-core
- discord_streams/discord_leases wired in: POST /discord/streams,
POST /discord/guilds/{id}/stop, GET /discord/guilds/{id}/overview,
GET /discord/streams/{id}, PUT /discord/guilds/{id}/link (admin),
GET /discord/node/{node}/tokens/{id} (node key, lease holder only).
- Retained nodes/{id}/discord/desired (token ids, never token strings),
nodes/+/discord/actual subscribed and handled; per-node publish lock keeps
the retained list the newest; failed publishes retried by the reconciler.
- Tokens freed only after the node acks logout (or offline past
discord_lease_offline_release_seconds) - sweeper and C2 startup no longer
release leases.
- /nodes/{id}/command discord_join/leave map onto streams; CommandPayload
keeps preferred_token_id. /tokens: admin-only list, validate on add against
Discord, refresh, flush via transactional force release.
- Guild -> org via discord_guilds, unlinked guilds fall back to
DISCORD_UNLINKED_GUILD_ORG_ID (default "founding").
- tests/fake_firestore.py: optimistic-transaction fake; 27 lease/race tests.
discord bot
- /join, /leave, /status, autocomplete scoped to the calling guild; /leave
never touches another server; Manage Channels default permission;
/join edits its reply with the node's real result; /help copy fixed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Trip-level tags: admins configure available tags in the trip header (inline add/remove pills). The AI can also create new tags via the add_tag tool.
Event tags: selectable in the Add Event modal, shown as colored pills on event cards in the timeline, and on AI suggestion cards.
AI integration: sees available tags in its system prompt, applies them when proposing events, can create new ones with add_tag.
Discord: tags shown as inline code blocks under each event in /trip view.
Colors: auto-assigned from an 8-color palette by tag index, consistent everywhere.
New /trips router with full CRUD, attendee management, and nested
events. Events validate date is within parent trip range and inherit
trip location when not explicitly set. Leaving a trip cascades
removal from all its events.
New TripCommands cog with /trip create, list, view, delete, join,
leave and /trip event add, remove, join, leave. Event autocomplete
is scoped to the selected trip. Enforces must-be-on-trip rule for
event joins with a clear error message.