feat: Rooms Layer restore - seed City/MicroDAO/Node rooms + fix Citizens

TASK_PHASE_ROOMS_LAYER_RESTORE_AND_MATRIX_INTEGRATION (partial):

Backend:
- Seed 8 City Rooms (general, welcome, leadership-hall, etc.)
- Seed 5 MicroDAO Rooms for DAARION (lobby, governance, news, builders, help)
- Seed 2 Node Support Rooms (node1, node2)
- Update agents is_public for Citizens Layer
- Fix get_public_citizens query (less strict filtering)
- Add get_city_rooms_for_list function

This fixes:
- City Rooms list = 0 -> now 8 rooms
- MicroDAO Rooms = 0 -> now 5 rooms
- Citizens = 0 -> now shows public agents
This commit is contained in:
Apple
2025-11-30 09:48:37 -08:00
parent d264e7efc5
commit a1baedfc94
2 changed files with 104 additions and 9 deletions

View File

@@ -81,6 +81,73 @@ async def run_migrations():
""")
logger.info("Migration: Inserted/updated NODE1 and NODE2 in nodes table.")
# =========================================================================
# ROOMS LAYER RESTORE (TASK_PHASE_ROOMS_LAYER_RESTORE_AND_MATRIX_INTEGRATION)
# =========================================================================
# Seed City Rooms (8 standard rooms)
await conn.execute("""
INSERT INTO city_rooms (id, slug, name, description, room_type, owner_type, owner_id, space_scope, visibility, is_public, sort_order, created_at, updated_at)
VALUES
(gen_random_uuid(), 'general', 'General', 'Main city chat room for all citizens', 'chat', 'city', 'daarion', 'city', 'public-city', true, 1, NOW(), NOW()),
(gen_random_uuid(), 'welcome', 'Welcome', 'Welcome new citizens to DAARION City', 'chat', 'city', 'daarion', 'city', 'public-city', true, 2, NOW(), NOW()),
(gen_random_uuid(), 'leadership-hall', 'Leadership Hall', 'City governance and leadership discussions', 'chat', 'city', 'daarion', 'city', 'public-city', true, 3, NOW(), NOW()),
(gen_random_uuid(), 'builders', 'Builders', 'Builders and developers community', 'chat', 'city', 'daarion', 'city', 'public-city', true, 4, NOW(), NOW()),
(gen_random_uuid(), 'science-lab', 'Science Lab', 'Research, AI, and innovation discussions', 'chat', 'city', 'daarion', 'city', 'public-city', true, 5, NOW(), NOW()),
(gen_random_uuid(), 'security-bureau', 'Security Bureau', 'Security and safety discussions', 'chat', 'city', 'daarion', 'city', 'public-city', true, 6, NOW(), NOW()),
(gen_random_uuid(), 'economics-square', 'Economics Square', 'Economics, tokenomics, and finance', 'chat', 'city', 'daarion', 'city', 'public-city', true, 7, NOW(), NOW()),
(gen_random_uuid(), 'announcements', 'Announcements', 'Official city announcements', 'broadcast', 'city', 'daarion', 'city', 'public-city', true, 8, NOW(), NOW())
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
room_type = EXCLUDED.room_type,
is_public = EXCLUDED.is_public,
sort_order = EXCLUDED.sort_order,
updated_at = NOW();
""")
logger.info("Migration: Seeded 8 City Rooms.")
# Seed MicroDAO Rooms for DAARION root DAO
await conn.execute("""
INSERT INTO city_rooms (id, slug, name, description, room_type, owner_type, owner_id, space_scope, visibility, is_public, room_role, sort_order, created_at, updated_at)
VALUES
(gen_random_uuid(), 'daarion-lobby', 'DAARION Lobby', 'Main lobby for DAARION DAO', 'chat', 'microdao', 'dao_daarion', 'microdao', 'public-city', true, 'primary', 1, NOW(), NOW()),
(gen_random_uuid(), 'daarion-governance', 'DAARION Governance', 'Governance and voting discussions', 'chat', 'microdao', 'dao_daarion', 'microdao', 'members', false, 'governance', 2, NOW(), NOW()),
(gen_random_uuid(), 'daarion-news', 'DAARION News', 'News and updates from DAARION', 'broadcast', 'microdao', 'dao_daarion', 'microdao', 'public-city', true, 'news', 3, NOW(), NOW()),
(gen_random_uuid(), 'daarion-builders', 'DAARION Builders', 'Development and technical discussions', 'chat', 'microdao', 'dao_daarion', 'microdao', 'members', false, 'builders', 4, NOW(), NOW()),
(gen_random_uuid(), 'daarion-help', 'DAARION Help', 'Help and support for DAARION members', 'chat', 'microdao', 'dao_daarion', 'microdao', 'public-city', true, 'help', 5, NOW(), NOW())
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
room_role = EXCLUDED.room_role,
is_public = EXCLUDED.is_public,
sort_order = EXCLUDED.sort_order,
updated_at = NOW();
""")
logger.info("Migration: Seeded 5 MicroDAO Rooms for DAARION.")
# Seed Node Support Rooms
await conn.execute("""
INSERT INTO city_rooms (id, slug, name, description, room_type, owner_type, owner_id, space_scope, visibility, is_public, room_role, created_at, updated_at)
VALUES
(gen_random_uuid(), 'node-support-node1', 'NODE1 Support', 'Support room for Hetzner GEX44 Production node', 'node-support', 'node', 'node-1-hetzner-gex44', 'node', 'members', false, 'support', NOW(), NOW()),
(gen_random_uuid(), 'node-support-node2', 'NODE2 Support', 'Support room for MacBook Pro M4 Max node', 'node-support', 'node', 'node-2-macbook-m4max', 'node', 'members', false, 'support', NOW(), NOW())
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
room_role = EXCLUDED.room_role,
updated_at = NOW();
""")
logger.info("Migration: Seeded 2 Node Support Rooms.")
# Update public agents to be visible as citizens
await conn.execute("""
UPDATE agents SET is_public = true
WHERE gov_level IN ('city_governance', 'district_lead', 'orchestrator', 'core_team')
OR kind IN ('civic', 'governance', 'orchestrator');
""")
logger.info("Migration: Updated public agents for Citizens Layer.")
except Exception as e:
logger.error(f"Error running migrations: {e}")
raise

View File

@@ -61,14 +61,21 @@ def _normalize_capabilities(value: Any) -> List[str]:
# =============================================================================
async def get_all_rooms(limit: int = 100, offset: int = 0) -> List[dict]:
"""Отримати всі кімнати"""
"""Отримати всі кімнати з додатковими полями"""
pool = await get_pool()
query = """
SELECT id, slug, name, description, is_default, created_at, created_by,
matrix_room_id, matrix_room_alias, logo_url, banner_url
FROM city_rooms
ORDER BY is_default DESC, created_at DESC
SELECT
cr.id, cr.slug, cr.name, cr.description,
cr.room_type, cr.owner_type, cr.owner_id, cr.space_scope, cr.visibility,
cr.is_default, cr.is_public, cr.sort_order,
cr.created_at, cr.created_by,
cr.matrix_room_id, cr.matrix_room_alias,
cr.logo_url, cr.banner_url,
cr.room_role
FROM city_rooms cr
WHERE cr.is_public = true OR cr.space_scope = 'city'
ORDER BY cr.sort_order ASC, cr.is_default DESC, cr.created_at DESC
LIMIT $1 OFFSET $2
"""
@@ -76,6 +83,29 @@ async def get_all_rooms(limit: int = 100, offset: int = 0) -> List[dict]:
return [dict(row) for row in rows]
async def get_city_rooms_for_list(limit: int = 100) -> List[dict]:
"""Отримати City Rooms для відображення у списку"""
pool = await get_pool()
query = """
SELECT
cr.id, cr.slug, cr.name, cr.description,
cr.room_type, cr.owner_type, cr.owner_id, cr.space_scope, cr.visibility,
cr.is_public, cr.sort_order,
cr.matrix_room_id, cr.matrix_room_alias,
cr.logo_url, cr.banner_url,
cr.room_role,
cr.created_at
FROM city_rooms cr
WHERE cr.space_scope = 'city' AND cr.is_public = true
ORDER BY cr.sort_order ASC, cr.name ASC
LIMIT $1
"""
rows = await pool.fetch(query, limit)
return [dict(row) for row in rows]
async def get_room_by_id(room_id: str) -> Optional[dict]:
"""Отримати кімнату по ID"""
pool = await get_pool()
@@ -994,13 +1024,11 @@ async def get_public_citizens(
params: List[Any] = []
where_clauses = [
"a.is_public = true",
"a.public_slug IS NOT NULL",
"COALESCE(a.is_archived, false) = false",
"COALESCE(a.is_test, false) = false",
"a.deleted_at IS NULL",
# TASK 037A: Stricter filtering for Citizens Layer
"a.node_id IS NOT NULL",
"EXISTS (SELECT 1 FROM microdao_agents ma WHERE ma.agent_id = a.id)"
# ROOMS_LAYER_RESTORE: Include agents with gov_level or specific kinds as citizens
"(a.public_slug IS NOT NULL OR a.gov_level IN ('city_governance', 'district_lead', 'orchestrator', 'core_team') OR a.kind IN ('civic', 'governance', 'orchestrator'))"
]
if district: