Add is_past_trade_deadline property to Current model and guard /trade initiate,
submit, and finalize flows. All checks fail-closed (block if API unreachable).
981 tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The data/ volume was mounted :ro to protect Google Sheets credentials,
but this also prevented all state trackers from persisting JSON files
(scorecards, voice channels, trade channels, soak data), causing silent
save failures and stale data accumulating across restarts.
- Mount only the credentials file as :ro (file-level mount)
- Add a separate :rw storage/ volume for runtime state files
- Move all tracker default paths from data/ to storage/
- Add STATE_HOST_PATH env var (defaults to ./storage)
- Update SHEETS_CREDENTIALS_HOST_PATH semantics: now a file path
(e.g. ./data/major-domo-service-creds.json) instead of a directory
- Add storage/ to .gitignore
Closes#85
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
/trade add-player hardcoded from_roster=MAJOR_LEAGUE for all players,
causing incorrect transaction records when trading MiL/IL players. This
cascaded into false roster validation errors for other teams' /dropadd
commands because pre-existing transaction processing misidentified which
roster a player was leaving from.
Now looks up the player's actual team and calls roster_type() to determine
the correct source roster. Same fix applied to /trade supplementary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ran `ruff check --select F401 --fix` to auto-remove 221 unused imports,
manually removed 4 unused `import discord` from package __init__.py files,
and fixed test import for DISAPPOINTMENT_TIERS to reference canonical location.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents players who are already claimed in another team's pending
transaction (frozen=false, cancelled=false) from being added to a new
transaction for the same week.
Changes:
- Add is_player_in_pending_transaction() to TransactionService
- Make TransactionBuilder.add_move() async with validation
- Add check_pending_transactions flag (default True for /dropadd)
- Skip validation for /ilmove and trades (check_pending_transactions=False)
- Add tests/conftest.py for proper test isolation
- Add 4 new tests for pending transaction validation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change sWAR formatting from 1 decimal to 2 decimal places across all displays
- Draft on-clock announcements now ping team role (via team.lname) instead of GM
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document trade acceptance workflow added in v2.22.0
- Add trade transaction logging documentation
- Update workflow steps to include Accept/Reject UI
- Move completed features from Future to Recent Enhancements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add multi-team trade acceptance system requiring all GMs to approve
- TradeBuilder tracks accepted_teams with accept_trade/reject_trade methods
- TradeAcceptanceView with Accept/Reject buttons validates GM permissions
- Create transactions when all teams accept (frozen=false for immediate effect)
- Add post_trade_to_log() for rich trade embeds in #transaction-log
- Trade embeds show grouped player moves by receiving team with sWAR
- Add 10 comprehensive tests for acceptance tracking methods
- All 36 trade builder tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, only the trade initiator could access the trade builder
because lookups used their Discord user ID. Now any GM whose team
participates in a trade can add players, view, and manage the trade.
Changes:
- Add _team_to_trade_key secondary index mapping team IDs to trade keys
- Add get_trade_builder_by_team() for team-based lookups
- Add clear_trade_builder_by_team() for team-based clearing
- Update add_team/remove_team to maintain secondary index
- Refactor 5 trade commands to use team-based lookups
- Add 9 new tests for multi-GM access functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove redundant sba_current_season and pd_current_season config values.
All code now uses sba_season and pd_season, which properly read from
environment variables. Fixes /team command defaulting to Season 12.
- Remove duplicate *_current_season constants from config.py
- Update 100+ references across commands, services, and utils
- sba_season defaults to 13, pd_season defaults to 10
- Environment variables SBA_SEASON/PD_SEASON now work correctly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements decorator-based permission system to support bot scaling across
multiple Discord servers with different command access requirements.
Key Features:
- @global_command() - Available in all servers
- @league_only() - Restricted to league server only
- @requires_team() - Requires user to have a league team
- @admin_only() - Requires server admin permissions
- @league_admin_only() - Requires admin in league server
Implementation:
- utils/permissions.py - Core permission decorators and validation
- utils/permissions_examples.py - Comprehensive usage examples
- Automatic caching via TeamService.get_team_by_owner() (30-min TTL)
- User-friendly error messages for permission failures
Applied decorators to:
- League commands (league, standings, schedule, team, roster)
- Admin commands (management, league management, users)
- Draft system commands
- Transaction commands (dropadd, ilmove, management)
- Injury management
- Help system
- Custom commands
- Voice channels
- Gameplay (scorebug)
- Utilities (weather)
Benefits:
- Maximum flexibility - easy to change command scopes
- Built-in caching - ~80% reduction in API calls
- Combinable decorators for complex permissions
- Clean migration path for existing commands
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed all diagnostic logging statements added for transaction bug tracking
from INFO level to DEBUG level. This reduces log noise during normal operations
while preserving detailed diagnostics when needed.
Changes:
- All 🔍 DIAGNOSTIC messages changed to DEBUG level
- All ✅ player found messages changed to DEBUG level
- All roster validation tracking changed to DEBUG level
- WARNING (⚠️) and ERROR (❌) messages preserved at their levels
Files modified:
- commands/transactions/dropadd.py - Player roster detection diagnostics
- commands/transactions/ilmove.py - Player roster detection diagnostics
- services/transaction_builder.py - Transaction validation tracking
- views/transaction_embed.py - Submission handler mode tracking
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhancement: Allow releasing players to Free Agency via /ilmove
Changes:
- Added "Free Agency" as destination choice in command options
- Updated destination_map to include "fa" -> RosterType.FREE_AGENCY
- Added logic to fetch FA team from config (free_agent_team_id: 498)
- Set to_team correctly: FA team when releasing, user team otherwise
This allows users to immediately release players to Free Agency for current week,
complementing the existing ML/MiL/IL destination options.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Bug: /dropadd was incorrectly rejecting players from Minor League affiliates
Root Cause: Ownership check used team.id comparison instead of organizational check
Fix: Use team.is_same_organization() to properly handle ML/MiL/IL affiliates
Before: player.team.id != builder.team.id (fails for WVMiL when user owns WV)
After: not builder.team.is_same_organization(player.team) (correctly identifies same org)
This brings /dropadd in line with /ilmove implementation which already used
the correct organizational check pattern.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adding 17 CLAUDE.md files across the project to provide detailed context
and implementation guidelines for AI development agents:
Root Documentation:
- CLAUDE.md - Main project guide with Git workflow requirements
Component Documentation:
- commands/CLAUDE.md - Command architecture and patterns
- models/CLAUDE.md - Pydantic models and validation
- services/CLAUDE.md - Service layer and API interactions
- tasks/CLAUDE.md - Background tasks and automation
- tests/CLAUDE.md - Testing strategies and patterns
- utils/CLAUDE.md - Utility functions and decorators
- views/CLAUDE.md - Discord UI components and embeds
Command Package Documentation:
- commands/help/CLAUDE.md - Help system implementation
- commands/injuries/CLAUDE.md - Injury management commands
- commands/league/CLAUDE.md - League-wide commands
- commands/players/CLAUDE.md - Player information commands
- commands/profile/CLAUDE.md - User profile commands
- commands/teams/CLAUDE.md - Team information commands
- commands/transactions/CLAUDE.md - Transaction management
- commands/utilities/CLAUDE.md - Utility commands
- commands/voice/CLAUDE.md - Voice channel management
Key Updates:
- Updated .gitignore to track CLAUDE.md files in version control
- Added Git Workflow section requiring branch-based development
- Documented all architectural patterns and best practices
- Included comprehensive command/service implementation guides
These files provide essential context for AI agents working on the codebase,
ensuring consistent patterns, proper error handling, and maintainable code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive /ilmove command system for immediate roster changes (IL moves,
activations, etc.) that execute instantly for the current week, complementing the existing
/dropadd system which schedules moves for next week.
New Features:
- /ilmove command: Interactive transaction builder for THIS week (immediate execution)
- /clearilmove command: Clear current IL move transaction builder
- Dual-mode transaction system: Scheduled (/dropadd) vs Immediate (/ilmove)
Key Fixes:
- Organizational team matching: Minor League players (WVMiL) now correctly recognized as
valid targets for their Major League organization (WV)
- Transaction POST format: Fixed to use correct batch API format with count/moves structure
- RosterType to team affiliate mapping: Moves to IL now correctly assign players to WVIL
instead of WV, and moves from MiL correctly reference WVMiL as source team
- Player team updates: Added update_player_team() method for immediate team assignments
Technical Changes:
- commands/transactions/ilmove.py: New command with organizational validation
- commands/transactions/__init__.py: Register ILMoveCommands cog
- services/transaction_service.py: create_transaction_batch() with correct batch format
- services/player_service.py: update_player_team() for immediate updates
- services/transaction_builder.py: RosterType affiliate resolution with async team lookups
- views/transaction_embed.py: Dual-mode support with context-aware instructions
Code Reuse:
- 95% code sharing between /dropadd and /ilmove via shared TransactionBuilder
- Same validation, UI, and move tracking - only submission differs
- Context-aware command_name parameter for dynamic UI instructions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Standardize data file locations to data/ directory and improve command organization with better UI for team rosters, pagination for team lists, and refactored chart commands into logical command groups.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix transaction count bug by filtering transactions >= current week
- Add TransactionPaginationView with "Show Move IDs" button
- Implement intelligent message chunking for long transaction lists
- Remove emojis from individual transaction lines (kept in headers)
- Display 10 transactions per page with navigation buttons
- Show move IDs on demand via ephemeral button (stays under 2000 char limit)
- Update all tests to validate pagination and chunking behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add /weather command with smart team resolution and D20 rolling system
- Add /charts command with autocomplete and category organization
- Implement ChartService for JSON-based chart management
- Add comprehensive test coverage for new commands
- Update test factories with complete model fixtures
- Enhance voice channel tracker with improved logging
- Update PRE_LAUNCH_ROADMAP.md to reflect completed features
- Minor improvements to imports and service initialization
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit fixes two critical bugs in the trade system and adds a new
feature for automatic channel updates.
## Bug Fixes
### 1. Trade Channel Creation Permission Error (Discord API 50013)
**Issue**: Trade channels failed to create with "Missing Permissions" error
**Root Cause**: Bot was attempting to grant itself manage_channels and
manage_permissions in channel-specific overwrites. Discord prohibits bots
from self-granting elevated permissions in channel overwrites.
**Fix**: Removed manage_channels and manage_permissions from bot's
channel-specific overwrites in trade_channels.py. Server-level permissions
are sufficient for all channel management operations.
**Files Changed**:
- commands/transactions/trade_channels.py (lines 74-77)
### 2. TeamService Method Name AttributeError
**Issue**: Bot crashed with AttributeError when adding players to trades
**Root Cause**: Code called non-existent method team_service.get_team_by_id()
The correct method name is team_service.get_team()
**Fix**: Updated method call in trade_builder.py and all test mocks
**Files Changed**:
- services/trade_builder.py (line 201)
- tests/test_services_trade_builder.py (all test mocks)
## New Features
### Smart Trade Channel Updates
**Feature**: When trade commands are executed outside the dedicated trade
channel, the trade embed is automatically posted to the trade channel
(non-ephemeral) for visibility to all participants.
**Behavior**:
- Commands in trade channel: Only ephemeral response to user
- Commands outside trade channel: Ephemeral response + public post to channel
- Applies to: /trade add-team, /trade add-player, /trade supplementary, /trade view
**Implementation**:
- Added _get_trade_channel() helper method
- Added _is_in_trade_channel() helper method
- Added _post_to_trade_channel() helper method
- Updated 4 trade commands to use smart posting logic
**Files Changed**:
- commands/transactions/trade.py (new helper methods + 4 command updates)
## Documentation Updates
Updated comprehensive documentation for:
- Trade channel permission requirements and troubleshooting
- TeamService correct method names with examples
- Smart channel update feature and behavior
- Bug fix details and prevention strategies
**Files Changed**:
- commands/transactions/README.md
- services/README.md
## Testing
- All 18 trade builder tests pass
- Updated test assertions to match new error message format
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major fixes and improvements:
Trade System Fixes:
- Fix duplicate player moves in trade embed Player Exchanges section
- Resolve "WVMiL not participating" error for Minor League destinations
- Implement organizational authority model for ML/MiL/IL team relationships
- Update Trade.cross_team_moves to deduplicate using moves_giving only
Team Model Enhancements:
- Rewrite roster_type() method using sname as definitive source per spec
- Fix edge cases like "BHMIL" (Birmingham IL) vs "BHMMIL"
- Update _get_base_abbrev() to use consistent sname-based logic
- Add organizational lookup support in trade participation
Autocomplete System:
- Fix major_league_team_autocomplete invalid roster_type parameter
- Implement client-side filtering using Team.roster_type() method
- Add comprehensive test coverage for all autocomplete functions
- Centralize autocomplete logic to shared utils functions
Test Infrastructure:
- Add 25 new tests for trade models and trade builder
- Add 13 autocomplete function tests with error handling
- Fix existing test failures with proper mocking patterns
- Update dropadd tests to use shared autocomplete functions
Documentation Updates:
- Document trade model enhancements and deduplication fix
- Add autocomplete function documentation with usage examples
- Document organizational authority model and edge case handling
- Update README files with recent fixes and implementation notes
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit implements significant improvements to the transaction management system:
**Major Changes:**
1. Enhanced /dropadd command workflow:
- All responses are now ephemeral for better user privacy
- Every call now shows the transaction builder (not just first move)
- Improved autocomplete with team context prioritization (user's players first)
2. Added team ownership validation:
- Prevents adding players from other teams (except Free Agents with abbrev='FA')
- Enhanced error messages with specific team information
- Changed _add_quick_move return type to tuple[bool, str] for better error handling
3. Removed redundant /transactionstatus command:
- Command functionality fully replaced by /dropadd without parameters
- Simplified workflow reduces user confusion
- All related tests updated accordingly
**Technical Improvements:**
- Enhanced player autocomplete with team prioritization and better formatting
- Improved roster detection logic checking actual roster data vs team_id
- Better error handling with specific, actionable error messages
- Updated all test cases to handle new tuple return types
- Added comprehensive test coverage for team ownership validation
**Test Coverage:**
- All 30 tests passing (17 dropadd + 13 transaction embed tests)
- New tests for team ownership validation scenarios
- Updated existing tests for new return type patterns
The /dropadd command now serves as the single point of entry for all transaction operations while providing a cleaner, more intuitive user experience.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>