# Graph Report - .  (2026-05-13)

## Corpus Check
- cluster-only mode — file stats not available

## Summary
- 1886 nodes · 3876 edges · 141 communities (89 shown, 52 thin omitted)
- Extraction: 90% EXTRACTED · 10% INFERRED · 0% AMBIGUOUS · INFERRED: 393 edges (avg confidence: 0.62)
- Token cost: 0 input · 0 output

## Graph Freshness
- Built from commit: `6085fd66`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).

## Community Hubs (Navigation)
- [[_COMMUNITY_Community 0|Community 0]]
- [[_COMMUNITY_Community 1|Community 1]]
- [[_COMMUNITY_Community 2|Community 2]]
- [[_COMMUNITY_Community 3|Community 3]]
- [[_COMMUNITY_Community 4|Community 4]]
- [[_COMMUNITY_Community 5|Community 5]]
- [[_COMMUNITY_Community 6|Community 6]]
- [[_COMMUNITY_Community 7|Community 7]]
- [[_COMMUNITY_Community 8|Community 8]]
- [[_COMMUNITY_Community 9|Community 9]]
- [[_COMMUNITY_Community 10|Community 10]]
- [[_COMMUNITY_Community 11|Community 11]]
- [[_COMMUNITY_Community 12|Community 12]]
- [[_COMMUNITY_Community 13|Community 13]]
- [[_COMMUNITY_Community 14|Community 14]]
- [[_COMMUNITY_Community 15|Community 15]]
- [[_COMMUNITY_Community 16|Community 16]]
- [[_COMMUNITY_Community 17|Community 17]]
- [[_COMMUNITY_Community 18|Community 18]]
- [[_COMMUNITY_Community 19|Community 19]]
- [[_COMMUNITY_Community 20|Community 20]]
- [[_COMMUNITY_Community 21|Community 21]]
- [[_COMMUNITY_Community 22|Community 22]]
- [[_COMMUNITY_Community 23|Community 23]]
- [[_COMMUNITY_Community 24|Community 24]]
- [[_COMMUNITY_Community 25|Community 25]]
- [[_COMMUNITY_Community 26|Community 26]]
- [[_COMMUNITY_Community 27|Community 27]]
- [[_COMMUNITY_Community 28|Community 28]]
- [[_COMMUNITY_Community 29|Community 29]]
- [[_COMMUNITY_Community 30|Community 30]]
- [[_COMMUNITY_Community 31|Community 31]]
- [[_COMMUNITY_Community 32|Community 32]]
- [[_COMMUNITY_Community 33|Community 33]]
- [[_COMMUNITY_Community 34|Community 34]]
- [[_COMMUNITY_Community 35|Community 35]]
- [[_COMMUNITY_Community 36|Community 36]]
- [[_COMMUNITY_Community 37|Community 37]]
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 40|Community 40]]
- [[_COMMUNITY_Community 41|Community 41]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 47|Community 47]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 49|Community 49]]
- [[_COMMUNITY_Community 50|Community 50]]
- [[_COMMUNITY_Community 51|Community 51]]
- [[_COMMUNITY_Community 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
- [[_COMMUNITY_Community 54|Community 54]]
- [[_COMMUNITY_Community 55|Community 55]]
- [[_COMMUNITY_Community 56|Community 56]]
- [[_COMMUNITY_Community 57|Community 57]]
- [[_COMMUNITY_Community 58|Community 58]]
- [[_COMMUNITY_Community 59|Community 59]]
- [[_COMMUNITY_Community 60|Community 60]]
- [[_COMMUNITY_Community 61|Community 61]]
- [[_COMMUNITY_Community 62|Community 62]]
- [[_COMMUNITY_Community 63|Community 63]]
- [[_COMMUNITY_Community 64|Community 64]]
- [[_COMMUNITY_Community 65|Community 65]]
- [[_COMMUNITY_Community 66|Community 66]]
- [[_COMMUNITY_Community 67|Community 67]]
- [[_COMMUNITY_Community 68|Community 68]]
- [[_COMMUNITY_Community 69|Community 69]]
- [[_COMMUNITY_Community 70|Community 70]]
- [[_COMMUNITY_Community 71|Community 71]]
- [[_COMMUNITY_Community 72|Community 72]]
- [[_COMMUNITY_Community 73|Community 73]]
- [[_COMMUNITY_Community 76|Community 76]]
- [[_COMMUNITY_Community 77|Community 77]]
- [[_COMMUNITY_Community 78|Community 78]]
- [[_COMMUNITY_Community 79|Community 79]]
- [[_COMMUNITY_Community 80|Community 80]]
- [[_COMMUNITY_Community 81|Community 81]]
- [[_COMMUNITY_Community 82|Community 82]]
- [[_COMMUNITY_Community 83|Community 83]]
- [[_COMMUNITY_Community 84|Community 84]]
- [[_COMMUNITY_Community 85|Community 85]]
- [[_COMMUNITY_Community 86|Community 86]]
- [[_COMMUNITY_Community 87|Community 87]]
- [[_COMMUNITY_Community 88|Community 88]]
- [[_COMMUNITY_Community 89|Community 89]]
- [[_COMMUNITY_Community 90|Community 90]]
- [[_COMMUNITY_Community 91|Community 91]]
- [[_COMMUNITY_Community 92|Community 92]]
- [[_COMMUNITY_Community 93|Community 93]]
- [[_COMMUNITY_Community 94|Community 94]]
- [[_COMMUNITY_Community 95|Community 95]]
- [[_COMMUNITY_Community 96|Community 96]]
- [[_COMMUNITY_Community 97|Community 97]]
- [[_COMMUNITY_Community 98|Community 98]]
- [[_COMMUNITY_Community 101|Community 101]]
- [[_COMMUNITY_Community 102|Community 102]]
- [[_COMMUNITY_Community 103|Community 103]]
- [[_COMMUNITY_Community 104|Community 104]]
- [[_COMMUNITY_Community 105|Community 105]]
- [[_COMMUNITY_Community 106|Community 106]]
- [[_COMMUNITY_Community 107|Community 107]]
- [[_COMMUNITY_Community 108|Community 108]]
- [[_COMMUNITY_Community 109|Community 109]]
- [[_COMMUNITY_Community 110|Community 110]]
- [[_COMMUNITY_Community 111|Community 111]]
- [[_COMMUNITY_Community 112|Community 112]]
- [[_COMMUNITY_Community 113|Community 113]]
- [[_COMMUNITY_Community 114|Community 114]]
- [[_COMMUNITY_Community 115|Community 115]]
- [[_COMMUNITY_Community 116|Community 116]]
- [[_COMMUNITY_Community 117|Community 117]]
- [[_COMMUNITY_Community 118|Community 118]]
- [[_COMMUNITY_Community 119|Community 119]]
- [[_COMMUNITY_Community 120|Community 120]]
- [[_COMMUNITY_Community 121|Community 121]]
- [[_COMMUNITY_Community 122|Community 122]]
- [[_COMMUNITY_Community 123|Community 123]]
- [[_COMMUNITY_Community 124|Community 124]]
- [[_COMMUNITY_Community 125|Community 125]]

## God Nodes (most connected - your core abstractions)
1. `_make_siege()` - 124 edges
2. `_make_member()` - 92 edges
3. `_make_position()` - 85 edges
4. `SiegeMember` - 78 edges
5. `_make_building()` - 64 edges
6. `_make_group()` - 60 edges
7. `BoardPage()` - 55 edges
8. `makeSiegeMember()` - 55 edges
9. `PostsPage()` - 37 edges
10. `_session_with_siege_and_configs()` - 35 edges

## Surprising Connections (you probably didn't know these)
- `PostPriorityResponse` --uses--> `PostPriorityConfig`  [INFERRED]
  backend/app/api/post_priority_config.py → frontend/src/api/posts.ts
- `PostPriorityUpdate` --uses--> `PostPriorityConfig`  [INFERRED]
  backend/app/api/post_priority_config.py → frontend/src/api/posts.ts
- `TestStartupValidation` --uses--> `MemberRole`  [INFERRED]
  backend/tests/test_auth.py → frontend/src/api/types.ts
- `AuthError` --uses--> `Member`  [INFERRED]
  backend/app/api/auth.py → frontend/src/api/types.ts
- `import_file()` --calls--> `seed_post_priority_config()`  [INFERRED]
  scripts/excel-import/import_excel.py → backend/app/db/seeds.py

## Communities (141 total, 52 thin omitted)

### Community 0 - "Community 0"
Cohesion: 0.05
Nodes (84): BuildingUpdate, _make_group(), _make_config(), Service-layer tests for update_building — focus on unbreak restoration., A Mana Shrine at level 5 has 13 teams = 4 full groups + 1 slot last group     (4, Stronghold level 6: 10 groups × 3 slots.     Break → reduces to base config (4 g, Adding a post-type building must use PostPriorityConfig to set the Post     prio, Return a MagicMock shaped like scalars().all() → items. (+76 more)

### Community 1 - "Community 1"
Cohesion: 0.05
Nodes (45): Carousel(), CarouselProps, CarouselSlide, dot0, renderCarousel(), track, viewport, renderDropdown() (+37 more)

### Community 2 - "Community 2"
Cohesion: 0.07
Nodes (61): makeBoard(), _build_assignments_html(), _build_reserves_html(), generate_assignments_image(), generate_reserves_image(), Image generation service — renders HTML/CSS to PNG via Playwright., Build the reserves/members list HTML string.      Args:         members: Siege m, Render an HTML string to PNG bytes using headless Chromium. (+53 more)

### Community 3 - "Community 3"
Cohesion: 0.05
Nodes (41): activateSiege(), applyAttackDay(), cloneSiege(), completeSiege(), deleteSiege(), getSiege(), getSiegeMembers(), reopenSiege() (+33 more)

### Community 4 - "Community 4"
Cohesion: 0.06
Nodes (60): build_member_notification_message(), _build_section(), _position_label(), _position_sort_key(), PositionInfo, _positions_from_keys(), _positions_to_key_set(), Build rich per-member Discord DM messages for siege assignment notifications. (+52 more)

### Community 5 - "Community 5"
Cohesion: 0.05
Nodes (54): lifespan(), main(), FastAPI application factory and middleware wiring., Run the FastAPI/uvicorn HTTP sidecar on port 8001., Connect and run the Discord client., Start both the Discord client and HTTP server concurrently., Application lifespan — runs startup guards before serving requests., run_discord_client() (+46 more)

### Community 6 - "Community 6"
Cohesion: 0.08
Nodes (53): _make_member(), Return a minimal Member-like namespace., _preview(), Regression for #381.      Setup: one member matches a condition that is active o, Invoke preview_post_suggestions with a mocked session., AC: single post with one matching member → suggestion targets that member., AC #6: post with no matching member → skip_reason='no_match'., Charge #1: is_reserve=True on the position → skip_reason='reserve'. (+45 more)

### Community 7 - "Community 7"
Cohesion: 0.09
Nodes (40): compareSiegesSpecific(), createSiege(), getSieges(), CONFIDENCE_LABEL, ConfidenceVariant, ComparisonPage(), formatPosition(), PositionTag() (+32 more)

### Community 8 - "Community 8"
Cohesion: 0.07
Nodes (40): getBoard(), PostPriorityResponse, PostPriorityUpdate, SiegeMemberCreate, AutofillApplyResult, AutofillAssignment, AutofillPreviewResult, BuildingGroupResponse (+32 more)

### Community 9 - "Community 9"
Cohesion: 0.05
Nodes (43): _make_mock_bot_with_guild(), _make_mock_member(), patch_guild_id(), Tests for GET /api/members/{discord_user_id} — guild member lookup endpoint., The @everyone role must never appear in the roles list., When Discord returns NotFound, respond 200 with is_member=false., When Discord raises an unexpected HTTPException, respond 503., When get_guild() returns None (bot not in guild), respond 503. (+35 more)

### Community 10 - "Community 10"
Cohesion: 0.05
Nodes (20): get_config(), Public config endpoint — exposes non-sensitive runtime flags to the frontend., Return public runtime configuration flags.      This endpoint is intentionally u, Settings, BaseSettings, Tests for the /api/config public endpoint and startup guards.  Covers:   - /api/, Backend must refuse to start when SESSION_SECRET is missing and auth is enabled., GET /api/config returns the current auth_disabled flag. (+12 more)

### Community 11 - "Community 11"
Cohesion: 0.06
Nodes (42): Tests for the attack day auto-assign algorithm., Heavy hitters and advanced always get Day 2 regardless of threshold., Medium members are promoted to Day 2 (by power desc) when count < 10., Novice promoted by power desc after medium if still < 10., Overridden Day 2 members count toward the 10-threshold., attack_day_override=True members keep their existing attack_day., Exactly 10 HH/ADV → all remaining go to Day 1., Apply reads stored preview and updates siege_member attack_day values. (+34 more)

### Community 12 - "Community 12"
Cohesion: 0.08
Nodes (42): makeSiegeMember(), _make_batch(), _make_batch_result(), _make_db_session(), Endpoint tests for notification and post-to-channel routes., POST /notify must return 400 with a clear message when siege.date is None., POST /post-to-channel must return 400 with a clear message when siege.date is No, Build a mock DB session that returns the given objects. (+34 more)

### Community 13 - "Community 13"
Cohesion: 0.05
Nodes (43): Endpoints for Discord guild member ↔ clan member sync., Return proposed Discord ↔ clan member matches without writing to the DB., Apply accepted sync matches, updating discord_username and discord_id., applyDiscordSync(), previewDiscordSync(), SyncApply, SyncApplyResponse, Service logic for Discord guild member → clan member matching. (+35 more)

### Community 14 - "Community 14"
Cohesion: 0.06
Nodes (31): PostSuggestionStaleEntry, ChangeCell(), Classification, classify(), ExpiryCountdown, OutcomeFilter, Pill(), PRIORITY_META (+23 more)

### Community 15 - "Community 15"
Cohesion: 0.08
Nodes (30): createMember(), getMember(), getMemberRoles(), getPostConditions(), updateMember(), updateMemberPreferences(), MemberRoleInfo, SyncApplyItem (+22 more)

### Community 16 - "Community 16"
Cohesion: 0.17
Nodes (35): PostPriorityConfig, Building, Member, Post, PostCondition, Siege, SiegeStatus, Base (+27 more)

### Community 17 - "Community 17"
Cohesion: 0.09
Nodes (23): _cors_headers(), _make_app(), Integration tests for the CORS middleware wired in app/main.py.  The middleware, Entries that are only whitespace after stripping must be dropped., A request from an explicitly allowed origin must get CORS response headers., The echoed origin must match the request, not be a wildcard., allow_credentials=True means the vary/credentials header is set., The default value from Settings must allow the dev frontend. (+15 more)

### Community 18 - "Community 18"
Cohesion: 0.05
Nodes (24): Tests for backend/app/telemetry.py.  Verifies: - configure_telemetry() is a no-o, If configure_azure_monitor raises, the exception is swallowed., Regression tests: FastAPIInstrumentor.instrument_app() must be called.      Issu, FastAPIInstrumentor.instrument_app() is called with the FastAPI app.          Wh, When APPLICATIONINSIGHTS_CONNECTION_STRING is absent, nothing should happen., configure_azure_monitor() is called when both env vars are present.          Reg, No exception and configure_azure_monitor is never imported or called., FastAPIInstrumentor.instrument_app() is NOT called when app argument is None. (+16 more)

### Community 19 - "Community 19"
Cohesion: 0.08
Nodes (36): _get(), Tests for rate limiting on the Discord OAuth2 auth endpoints.  Covers: - /api/au, 3rd rapid request to /api/auth/login returns 429 when limit is 2/minute.      Th, Two different X-Forwarded-For IPs have independent rate-limit buckets., 3rd rapid request to /api/auth/callback returns 429 when limit is 2/minute., When AUTH_DISABLED=true, 50 rapid requests to /login never return 429., Pathologically long X-Forwarded-For header is handled without error.      Constr, Garbage XFF value falls back to the ASGI remote-address bucket.      Sending ``X (+28 more)

### Community 20 - "Community 20"
Cohesion: 0.12
Nodes (34): _make_position(), _apply(), _entry_dict(), _preview_data(), Unit tests for the Suggest Post Assignments service.  All tests use SimpleNamesp, Null suggested_member_id entries are skipped; no error raised., Position disabled since preview → 409 with reason position_disabled., Position set to reserve since preview → 409 with reason position_reserve. (+26 more)

### Community 21 - "Community 21"
Cohesion: 0.09
Nodes (31): build_group_structure(), compute_building_group_structure(), create_building_with_groups_and_positions(), import_file(), infer_building_level(), map_building_alias(), map_role(), parse_assignments_sheet() (+23 more)

### Community 22 - "Community 22"
Cohesion: 0.1
Nodes (17): apiClient, AppConfig, fetchConfig(), Layout(), navLinkClass(), renderLayout(), RequireAuth(), postsLink (+9 more)

### Community 23 - "Community 23"
Cohesion: 0.1
Nodes (17): downgrade(), initial schema  Revision ID: 0001 Revises: Create Date: 2026-03-16, upgrade(), add autofill and attack day preview columns to siege  Revision ID: 0002 Revises:, make siege date nullable  Revision ID: 0003 Revises: 0002 Create Date: 2026-03-1, Add post_priority_config table, Add description to post_priority_config, Replace power with power_level, drop sort_value (+9 more)

### Community 24 - "Community 24"
Cohesion: 0.1
Nodes (24): API router for the Suggest Post Assignments feature.  Routes:     POST /sieges/{, Generate a greedy post-assignment suggestion preview.      Args:         siege_i, Apply a caller-filtered subset of the stored preview atomically.      Uses SELEC, applyAutofill(), applyPostSuggestions(), previewAttackDay(), previewPostSuggestions(), AttackDayApplyResult (+16 more)

### Community 25 - "Community 25"
Cohesion: 0.1
Nodes (24): compareSieges(), get_most_recent_completed(), _load_assignments(), _load_member_names(), Return {member_id: [PositionKey, ...]} for non-reserve, non-disabled assigned po, _build_siege_assignments(), Tests for siege comparison service and endpoints., Build (Position, BuildingGroup, Building) rows for mock execute results. (+16 more)

### Community 26 - "Community 26"
Cohesion: 0.1
Nodes (24): AuthError, callback(), _check_guild_membership(), _error_redirect(), _exchange_code_for_token(), _get_discord_user(), login(), logout() (+16 more)

### Community 27 - "Community 27"
Cohesion: 0.13
Nodes (22): _async_client_that_raises(), _async_client_that_returns(), _make_ok_response(), Tests for bot HTTP client graceful degradation., get_member() returns the member dict when sidecar responds 200., get_member() returns the dict as-is when sidecar responds with is_member=False., get_member() raises httpx.HTTPError when the sidecar is unreachable., get_member() raises httpx.HTTPStatusError when sidecar returns 503. (+14 more)

### Community 28 - "Community 28"
Cohesion: 0.09
Nodes (9): Tests for scripts/import_excel.py parsing logic.  All tests are pure-function te, Stronghold: 4 groups all with 3 slots., Only assignments for the specified (type, number) pair are counted., Returns None when the extracted date components don't form a valid date., 1 total position in a post -> level 1., test_build_group_structure_stronghold(), test_compute_building_group_structure_filters_by_building_number(), test_infer_building_level_post() (+1 more)

### Community 29 - "Community 29"
Cohesion: 0.09
Nodes (22): Tests for GET /api/version endpoint and _read_backend_version helper., GET /api/version responds 200 with all required fields., backend_version includes build metadata when env vars are present., backend_version is bare semver when BUILD_NUMBER/GIT_SHA are absent., git_sha top-level field is still returned for backward compatibility., Force re-import of version module so env-var reads pick up monkeypatches., bot_version is null when the bot sidecar is unreachable., When BUILD_NUMBER / GIT_SHA are absent, return bare semver. (+14 more)

### Community 30 - "Community 30"
Cohesion: 0.1
Nodes (16): get_team_count(), Return the theoretical total team slots for a building type at a given level., compute_scroll_count(), Compute total scroll count from the theoretical capacity of every building., Enable SQLite foreign key enforcement (no-op on PostgreSQL)., _enable_sqlite_fk(), Enable SQLite foreign key enforcement., compute_scroll_count returns the sum of _LEVEL_TEAMS capacities for all building (+8 more)

### Community 31 - "Community 31"
Cohesion: 0.11
Nodes (21): _make_mock_db(), A correct Bearer token grants access as the bot-service principal., Full valid callback flow issues a session cookie and redirects to /., Guild member WITH the required role passes the role check and proceeds normally., Return an AsyncMock session whose db.get() returns `member`., test_callback_happy_path(), test_callback_with_required_role_proceeds_to_member_lookup(), test_valid_service_token_allows_access() (+13 more)

### Community 32 - "Community 32"
Cohesion: 0.15
Nodes (20): PostSuggestionApplyRequest, Request body for POST /post-suggestions/apply.      Attributes:         apply_po, engine(), Integration tests for the Suggest Post Assignments feature.  These tests use a r, Charge #12: selectinload chain works against real DB.      Verifies that no Miss, Second preview within TTL overwrites first in the DB JSON column.      Asserts b, Charge #17: apply → re-read position from DB → matched_condition_id set.      Wi, Charge #22: member_changed reason fires when position written between preview an (+12 more)

### Community 33 - "Community 33"
Cohesion: 0.1
Nodes (17): _make_expired_jwt(), Tests for Discord OAuth2 auth middleware and endpoints., A wrong Bearer token is rejected with 401., An expired JWT cookie is rejected with 401., /api/version is accessible without any credentials., Mismatched OAuth state redirects to /login?error=invalid_state., Guild member response without role_names key is treated as no roles (rejected)., Bot sidecar connection error redirects to /login?error=service_unavailable. (+9 more)

### Community 34 - "Community 34"
Cohesion: 0.22
Nodes (17): generate_images(), Image generation endpoints., Generate PNG images for siege assignments and members list., getNotificationBatch(), notifySiegeMembers(), postToChannel(), Notification endpoints — send DMs and post images to Discord., Send DM notifications to all siege members asynchronously. (+9 more)

### Community 35 - "Community 35"
Cohesion: 0.12
Nodes (17): apiAddBuilding(), apiCreateMember(), apiCreateSiege(), autofillBtn, buildingsTab, chevron, firstPositionSpan, positionCell (+9 more)

### Community 36 - "Community 36"
Cohesion: 0.11
Nodes (13): PostSuggestionPreviewResult, applyBtn, board, btn, chip, labels, makePostBoard(), makeTwoPostBoard() (+5 more)

### Community 37 - "Community 37"
Cohesion: 0.15
Nodes (14): Send DMs for each member and record results in a fresh DB session., _send_dms(), Find member by username in the guild, open DM, send message., Find text channel by name, post message., Find text channel by name, post image as Discord file attachment.          Retur, Discord client for the Siege Assignment System., SiegeBot, _get_bot() (+6 more)

### Community 38 - "Community 38"
Cohesion: 0.14
Nodes (13): getPostPriorities(), getPosts(), updatePostPriority(), getSiegeMemberPreferences(), DuplicateConditionMap, MemberWithMatches, postsTab, priorityBadgeColor() (+5 more)

### Community 39 - "Community 39"
Cohesion: 0.19
Nodes (15): bulk_update_positions(), list_posts(), Build a PostResponse-compatible dict, denormalizing building_number from the rel, _serialize_post(), setPostConditions(), updatePost(), Update a single position's assignment.      Raises:         404 if position not, Apply multiple position updates in a single transaction.      Each update dict m (+7 more)

### Community 40 - "Community 40"
Cohesion: 0.17
Nodes (14): VersionInfo, _fetch_bot_version(), getVersion(), Return a version string for the backend.      When both BUILD_NUMBER and GIT_SHA, Call the bot sidecar's /version endpoint. Returns None if unreachable., Return version information for all components., _read_backend_version(), useVersion() (+6 more)

### Community 41 - "Community 41"
Cohesion: 0.15
Nodes (11): ChangelogStatus, fetchChangelogStatus(), DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioItem, DropdownMenuSeparator (+3 more)

### Community 42 - "Community 42"
Cohesion: 0.16
Nodes (14): list_buildings(), list_members(), list_post_priorities(), list_siege_members(), delete_siege(), get_siege(), list_sieges(), previewAutofill() (+6 more)

### Community 43 - "Community 43"
Cohesion: 0.13
Nodes (14): db_session(), Schema constraint and seed data tests using in-memory SQLite., seed_building_type_config populates exactly 5 rows., Inserting a duplicate (siege_id, member_id) pair raises IntegrityError., Inserting two members with the same name must raise IntegrityError., The check constraint preventing is_reserve=True with a member_id is defined., slot_count check constraints (1–3) are declared on the table., seed_post_conditions populates exactly 36 rows. (+6 more)

### Community 44 - "Community 44"
Cohesion: 0.14
Nodes (13): Schema-aware tests for Member.last_seen_changelog_at (issue #295, AC 1).  These, Mapped type annotation allows a datetime value.      Assigning a real datetime m, Member mapper exposes last_seen_changelog_at as a mapped attribute., last_seen_changelog_at column is defined nullable=True.      Null is the sentine, last_seen_changelog_at has no server-side default.      Null is the intentional, last_seen_changelog_at uses SQLAlchemy DateTime (no timezone).      Matches the, Mapped type annotation allows None (datetime | None).      Constructing a Member, test_last_seen_changelog_at_accepts_datetime_at_python_level() (+5 more)

### Community 45 - "Community 45"
Cohesion: 0.23
Nodes (13): add_building(), add_group(), delete_group(), deleteBuilding(), getBuildings(), updateBuilding(), _create_groups_and_positions(), _get_building_type_config() (+5 more)

### Community 46 - "Community 46"
Cohesion: 0.2
Nodes (11): _make_post_priority_config(), _make_post_ns(), _make_src_building_ns(), _make_src_group_ns(), _make_src_position_ns(), Endpoint tests for siege lifecycle transitions: activate, complete, clone., Cloning a siege with stale priority=0 posts must use PostPriorityConfig.priority, test_activate_planning_siege() (+3 more)

### Community 47 - "Community 47"
Cohesion: 0.36
Nodes (12): _make_bot(), _make_guild(), _make_text_channel(), Unit tests for SiegeBot Discord client methods using mock guild/member objects., Create a SiegeBot instance with a pre-loaded guild (bypasses Discord connect)., test_get_members_returns_correct_dict_format(), test_post_image_returns_cdn_url(), test_post_message_finds_channel_and_sends() (+4 more)

### Community 48 - "Community 48"
Cohesion: 0.15
Nodes (13): _make_worksheet(), Create a mock openpyxl worksheet that yields the given rows., Parses name, power_level bucket, and role from correct column positions., Column E is parsed as a slash-separated list of keyword strings., Empty or None column E results in an empty list., test_parse_members_sheet_basic(), test_parse_members_sheet_post_preferences(), test_parse_members_sheet_skips_empty_rows() (+5 more)

### Community 49 - "Community 49"
Cohesion: 0.25
Nodes (10): get_changelog_status(), markChangelogSeen(), Changelog status and mark-seen endpoints.  These endpoints let the frontend trac, Raise HTTP 400 if the caller is a service principal.      Args:         current_, Return the authenticated user's last-seen changelog timestamp.      Args:, Set the authenticated user's last-seen changelog timestamp to now.      Idempote, _require_member_session(), ChangelogStatusResponse (+2 more)

### Community 50 - "Community 50"
Cohesion: 0.18
Nodes (9): health(), get_guild_member(), NotifyRequest, PostMessageRequest, Look up a single guild member by Discord user ID.      Returns ``{"is_member": f, Validate the Bearer token against the configured bot API key., Health check — no authentication required., set_bot() (+1 more)

### Community 51 - "Community 51"
Cohesion: 0.2
Nodes (8): Exception, disable_auth_for_tests(), _FakeClient, _FakeHTTPException, _FakeNotFound, _FakeTextChannel, Shared pytest configuration for backend tests.  Sets required environment variab, Bypass auth middleware for all tests by default.      Individual tests that exer

### Community 52 - "Community 52"
Cohesion: 0.33
Nodes (9): MemberRole, SyncMatch, SyncPreviewResponse, PowerLevel, MemberBase, MemberCreate, MemberPreferencesUpdate, MemberResponse (+1 more)

### Community 53 - "Community 53"
Cohesion: 0.24
Nodes (9): _get_client_ip(), _parse_retry_after_seconds(), rate_limit_exceeded_handler(), _rate_limit_key(), Rate-limiting utilities shared across the application.  This module owns the sin, Composite key function that honours the AUTH_DISABLED bypass.      When ``AUTH_D, Parse a slowapi rate-limit detail string into a window size in seconds.      slo, Return a JSON 429 response with a ``Retry-After`` header.      Replaces slowapi' (+1 more)

### Community 54 - "Community 54"
Cohesion: 0.24
Nodes (9): _build_valid_siege_graph(), Integration test: full siege lifecycle — create → validate → assign → activate →, Build a siege with exactly the right building counts and assigned active members, Return a mock async session that serves the siege + configs across multiple exec, Happy-path: validate (errors) → assign → validate (0 errors) → activate → comple, test_full_siege_lifecycle(), _make_session(), Return a minimal AsyncSession mock that scalar_one_or_none returns siege. (+1 more)

### Community 55 - "Community 55"
Cohesion: 0.2
Nodes (10): _make_jwt(), A valid JWT session cookie with an existing member grants access., A JWT signed with a different secret is rejected with 401., A valid JWT whose member no longer exists in the DB returns 401., GET /api/auth/me returns member info when authenticated via session cookie., test_jwt_with_deleted_member_returns_401(), test_jwt_with_wrong_secret_returns_401(), test_me_with_valid_session() (+2 more)

### Community 56 - "Community 56"
Cohesion: 0.22
Nodes (10): _make_empty_worksheet(), _make_session_mock(), _make_workbook_mock(), Worksheet that yields no rows., Minimal openpyxl workbook mock.      Members / Assignments / Reserves are empty, AsyncMock session whose execute() returns a result whose scalars().all() is []., When is_most_recent=False, section 3c must not run even if the Posts sheet     p, When is_most_recent=True and the DB has no PostPriorityConfig rows yet,     sect (+2 more)

### Community 57 - "Community 57"
Cohesion: 0.32
Nodes (6): get_member(), getMemberPreferences(), Return list of guild members as dicts with id, username, and display_name., Retrieve guild member list., Check guild membership via bot sidecar.         Returns the member dict (includi, deactivate_member()

### Community 58 - "Community 58"
Cohesion: 0.25
Nodes (8): _make_assignments_worksheet(), Build a mock assignments worksheet with the proper two header rows prepended., Rows with a None group cell are skipped., Whitespace-only cell values normalise to None., test_parse_assignments_sheet_empty_value_is_none(), test_parse_assignments_sheet_member_assignment(), test_parse_assignments_sheet_skips_incomplete_rows(), test_parse_assignments_sheet_skips_unknown_building_type()

### Community 59 - "Community 59"
Cohesion: 0.25
Nodes (8): _make_posts_config_worksheet(), Create a mock worksheet for parse_posts_sheet_config.      The function calls ws, One high-priority section with two posts: both get priority=3 and correct descri, Rows before any priority header default to priority=1 (Low)., Posts fall into the correct priority section based on their position., test_parse_posts_sheet_config_basic(), test_parse_posts_sheet_config_default_priority(), test_parse_posts_sheet_config_multiple_sections()

### Community 60 - "Community 60"
Cohesion: 0.29
Nodes (3): test_create_member_returns_201(), test_delete_member_returns_204(), Endpoint tests for /api/sieges — mocks the service layer directly.

### Community 61 - "Community 61"
Cohesion: 0.4
Nodes (5): notify(), Send a DM notification to a guild member., BotClient, HTTP client for the Discord bot sidecar API., Send DM via bot. Returns True on success, False on error.

### Community 63 - "Community 63"
Cohesion: 0.33
Nodes (5): Tests for enum definitions and associated constants in app.models.enums., BUILDING_TYPE_LABELS values must be non-empty title-cased display strings., Every BuildingType member must have an entry in BUILDING_TYPE_LABELS.      This, test_building_type_labels_are_friendly_strings(), test_building_type_labels_covers_all_values()

### Community 64 - "Community 64"
Cohesion: 0.33
Nodes (6): _make_posts_conditions_worksheet(), Create a mock worksheet for parse_posts_sheet_conditions.      The function enum, Three post rows with 1–3 keywords each are parsed correctly., A row with all-None cells is not included in the result., test_parse_posts_sheet_conditions_basic(), test_parse_posts_sheet_conditions_skips_empty()

### Community 65 - "Community 65"
Cohesion: 0.4
Nodes (3): _make_post_condition(), Endpoint tests for /api reference data endpoints., test_get_post_conditions_returns_list()

### Community 67 - "Community 67"
Cohesion: 0.4
Nodes (5): Mana shrine with 2 groups: position 3 is an empty trailing sheet column for grou, Stronghold level 2 = 16 total slots = 5 full groups (3 slots each) + 1 last grou, Stronghold level 4 = 22 total slots = 7 full groups + 1 last group with 1 slot., Defense Tower level 4 = 6 total slots = 2 full groups × 3 slots each.     At lev, test_compute_building_group_structure_basic()

### Community 69 - "Community 69"
Cohesion: 0.5
Nodes (3): configure_telemetry(), Application Insights / OpenTelemetry initialisation for the backend.  Call ``con, Initialise Azure Monitor OpenTelemetry and instrument the app.      The ``azure-

### Community 71 - "Community 71"
Cohesion: 0.5
Nodes (4): Magic tower (base_last_slots=2): position 3 is a trailing empty sheet column and, Magic tower at a higher level where position 3 is genuinely filled:     slot_cou, Magic Tower level 3 = 4 total slots = 1 full group (3 slots) + 1 last group with, test_compute_building_group_structure_magic_tower_level3()

### Community 72 - "Community 72"
Cohesion: 0.67
Nodes (3): Mana Shrine level 2 = 7 total slots = 2 full groups + 1 last group with 1 slot., Mana Shrine level 4 = 11 total slots = 3 full groups + 1 last group with 2 slots, test_compute_building_group_structure_mana_shrine_level2()

### Community 73 - "Community 73"
Cohesion: 0.67
Nodes (3): Returns None for a filename that does not match the pattern., Returns None for a completely unrelated filename., test_parse_filename_invalid_random()

## Knowledge Gaps
- **752 isolated node(s):** `initial schema  Revision ID: 0001 Revises: Create Date: 2026-03-16`, `add autofill and attack day preview columns to siege  Revision ID: 0002 Revises:`, `make siege date nullable  Revision ID: 0003 Revises: 0002 Create Date: 2026-03-1`, `Add post_priority_config table`, `Add description to post_priority_config` (+747 more)
  These have ≤1 connection - possible missing edges or undocumented components.
- **52 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.

## Suggested Questions
_Questions this graph is uniquely positioned to answer:_

- **Why does `_make_siege()` connect `Community 12` to `Community 0`, `Community 1`, `Community 3`, `Community 36`, `Community 6`, `Community 11`, `Community 46`, `Community 20`, `Community 54`, `Community 22`, `Community 25`, `Community 30`?**
  _High betweenness centrality (0.183) - this node is a cross-community bridge._
- **Why does `SiegeMember` connect `Community 3` to `Community 1`, `Community 34`, `Community 35`, `Community 36`, `Community 6`, `Community 38`, `Community 8`, `Community 7`, `Community 42`, `Community 12`, `Community 14`, `Community 15`, `Community 16`, `Community 22`, `Community 24`, `Community 57`?**
  _High betweenness centrality (0.167) - this node is a cross-community bridge._
- **Why does `list` connect `Community 42` to `Community 0`, `Community 1`, `Community 56`, `Community 5`, `Community 6`, `Community 39`, `Community 38`, `Community 45`, `Community 13`, `Community 15`, `Community 21`, `Community 24`, `Community 57`, `Community 58`?**
  _High betweenness centrality (0.089) - this node is a cross-community bridge._
- **Are the 17 inferred relationships involving `SiegeMember` (e.g. with `Base` and `TestSeedDemoMembers`) actually correct?**
  _`SiegeMember` has 17 INFERRED edges - model-reasoned connections that need verification._
- **What connects `initial schema  Revision ID: 0001 Revises: Create Date: 2026-03-16`, `add autofill and attack day preview columns to siege  Revision ID: 0002 Revises:`, `make siege date nullable  Revision ID: 0003 Revises: 0002 Create Date: 2026-03-1` to the rest of the system?**
  _752 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
  _Cohesion score 0.05 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
  _Cohesion score 0.05 - nodes in this community are weakly interconnected._