docs: add critical TASK_PHASE_ROOMS_LAYER_RESTORE_AND_MATRIX_INTEGRATION.md
Comprehensive task to fix Rooms Layer issues: - City Rooms not loading in list view - MicroDAO Rooms = 0 - Agent/Node Chat Rooms missing - Citizens Layer = 0 citizens Includes SQL seeds, API fixes, Matrix integration steps.
This commit is contained in:
@@ -0,0 +1,392 @@
|
||||
# TASK_PHASE_ROOMS_LAYER_RESTORE_AND_MATRIX_INTEGRATION
|
||||
|
||||
Version: 1.0
|
||||
Status: Ready
|
||||
Priority: **Critical** (MVP breaking issue)
|
||||
|
||||
---
|
||||
|
||||
# 1. МЕТА
|
||||
|
||||
Повністю відновити та інтегрувати Rooms Layer у MVP згідно з:
|
||||
|
||||
- `Rooms_Layer_Architecture_v1.md`
|
||||
- `District_Interface_Architecture_v1.md`
|
||||
- `MicroDAO_Interface_Architecture_v1.md`
|
||||
- Matrix federation & gateway design
|
||||
- Agent Governance Protocol
|
||||
|
||||
Цей таск виправляє критичні проблеми:
|
||||
- City Rooms не вантажаться у "список"
|
||||
- MicroDAO Rooms = 0
|
||||
- Agent Chat Rooms = missing
|
||||
- Node Chat Rooms = missing
|
||||
- Citizens Layer = 0 citizens
|
||||
- `/city/map` показує кімнати, але API `/rooms/list` — порожній
|
||||
|
||||
---
|
||||
|
||||
# 2. ВИМОГИ (архітектурні інваріанти)
|
||||
|
||||
## 2.1. Кімната існує у трьох шарах одночасно:
|
||||
|
||||
1. **База даних (city-service):**
|
||||
`city_rooms` + `matrix_room_id` + `room_agents`
|
||||
|
||||
2. **Matrix (Synapse):**
|
||||
кімната повинна бути створена на сервері matrix
|
||||
|
||||
3. **Gateway (matrix-gateway):**
|
||||
API `/internal/matrix/room/create` та `/internal/matrix/agent-join`
|
||||
|
||||
---
|
||||
|
||||
# 3. СКОП РОБОТИ
|
||||
|
||||
## 3.1. Відновити City Rooms (8 кімнат)
|
||||
|
||||
Згідно з `Rooms_Layer_Architecture_v1.md`:
|
||||
|
||||
| Slug | Name | Owner | Agents |
|
||||
|------|------|-------|--------|
|
||||
| `general` | General | city | DARIO, DARIA |
|
||||
| `welcome` | Welcome | city | Greeter |
|
||||
| `leadership-hall` | Leadership Hall | city | DAARWIZZ |
|
||||
| `builders` | Builders | city | Builder agents |
|
||||
| `science-lab` | Science Lab | city | Research agents |
|
||||
| `security-bureau` | Security Bureau | city | Security agent |
|
||||
| `economics-square` | Economics Square | city | Finance agent |
|
||||
| `announcements` | Announcements | city | DAARWIZZ |
|
||||
|
||||
### Завдання
|
||||
|
||||
1. Створити SQL seed у city-service для `city_rooms`
|
||||
2. Створити matrix room для кожної кімнати через gateway
|
||||
3. Записати `matrix_room_id` у таблицю `city_rooms`
|
||||
4. Підключити public agent до кожної кімнати
|
||||
|
||||
### SQL Seed
|
||||
|
||||
```sql
|
||||
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', 'chat', 'city', 'daarion', 'city', 'public-city', true, 1, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'welcome', 'Welcome', 'Welcome new citizens', 'chat', 'city', 'daarion', 'city', 'public-city', true, 2, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'leadership-hall', 'Leadership Hall', 'City governance discussions', 'chat', 'city', 'daarion', 'city', 'public-city', true, 3, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'builders', 'Builders', 'Builders community', 'chat', 'city', 'daarion', 'city', 'public-city', true, 4, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'science-lab', 'Science Lab', 'Research and AI discussions', 'chat', 'city', 'daarion', 'city', 'public-city', true, 5, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'security-bureau', 'Security Bureau', 'Security discussions', 'chat', 'city', 'daarion', 'city', 'public-city', true, 6, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'economics-square', 'Economics Square', 'Economics and tokenomics', 'chat', 'city', 'daarion', 'city', 'public-city', true, 7, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'announcements', 'Announcements', 'Official announcements', 'broadcast', 'city', 'daarion', 'city', 'public-city', true, 8, NOW(), NOW())
|
||||
ON CONFLICT (slug) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
description = EXCLUDED.description,
|
||||
updated_at = NOW();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.2. Відновити MicroDAO Rooms
|
||||
|
||||
Кожне MicroDAO повинно мати:
|
||||
|
||||
| Room Slug Pattern | Name | Role |
|
||||
|-------------------|------|------|
|
||||
| `{slug}-lobby` | Lobby | Primary public room |
|
||||
| `{slug}-governance` | Governance | Voting & proposals |
|
||||
| `{slug}-news` | News | Announcements |
|
||||
| `{slug}-builders` | Builders | Development |
|
||||
| `{slug}-help` | Help | Support |
|
||||
|
||||
### Завдання
|
||||
|
||||
1. **Backend**: auto-generate rooms when MicroDAO created
|
||||
2. **Matrix**: auto-create matrix rooms via gateway
|
||||
3. **UI**: підключити список кімнат до `/microdao/:slug`
|
||||
|
||||
### API Endpoint
|
||||
|
||||
```python
|
||||
@router.post("/microdao/{slug}/rooms/ensure")
|
||||
async def ensure_microdao_rooms(slug: str):
|
||||
"""
|
||||
Ensure all standard rooms exist for a MicroDAO.
|
||||
Creates missing rooms in DB and Matrix.
|
||||
"""
|
||||
dao = await repo_city.get_microdao_by_slug(slug)
|
||||
if not dao:
|
||||
raise HTTPException(404, "MicroDAO not found")
|
||||
|
||||
standard_rooms = [
|
||||
{"suffix": "lobby", "name": "Lobby", "role": "primary"},
|
||||
{"suffix": "governance", "name": "Governance", "role": "governance"},
|
||||
{"suffix": "news", "name": "News", "role": "news"},
|
||||
{"suffix": "builders", "name": "Builders", "role": "builders"},
|
||||
{"suffix": "help", "name": "Help", "role": "help"},
|
||||
]
|
||||
|
||||
created = []
|
||||
for room_def in standard_rooms:
|
||||
room_slug = f"{slug}-{room_def['suffix']}"
|
||||
existing = await repo_city.get_room_by_slug(room_slug)
|
||||
if not existing:
|
||||
room = await create_room_with_matrix(
|
||||
slug=room_slug,
|
||||
name=f"{dao['name']} {room_def['name']}",
|
||||
owner_type="microdao",
|
||||
owner_id=dao["id"],
|
||||
room_role=room_def["role"]
|
||||
)
|
||||
created.append(room_slug)
|
||||
|
||||
return {"created": created, "total": len(standard_rooms)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.3. Відновити Agent Chat Rooms
|
||||
|
||||
### Правило
|
||||
|
||||
Кожен агент має **власну консольну кімнату** з метаданими:
|
||||
|
||||
- `room_type = "agent-console"`
|
||||
- `owner_type = "agent"`
|
||||
- `owner_id = agent_id`
|
||||
|
||||
### Завдання
|
||||
|
||||
1. **Backend**: при `GET /agents/{id}/chat-room`
|
||||
- якщо кімната не існує → створити автоматично
|
||||
2. **Matrix**: створити приватну кімнату
|
||||
3. **Gateway**: додати агента у кімнату
|
||||
4. **Frontend**: оновити widget (грузити messages через gateway)
|
||||
|
||||
### Auto-Create Logic
|
||||
|
||||
```python
|
||||
async def ensure_agent_chat_room(agent_id: str):
|
||||
"""Ensure agent has a chat room, create if missing."""
|
||||
agent = await repo_city.get_agent_by_id(agent_id)
|
||||
if not agent:
|
||||
raise HTTPException(404, "Agent not found")
|
||||
|
||||
room_slug = f"agent-console-{agent.get('public_slug') or agent_id}"
|
||||
room = await repo_city.get_room_by_slug(room_slug)
|
||||
|
||||
if not room:
|
||||
# Create room in DB
|
||||
room = await repo_city.create_room({
|
||||
"slug": room_slug,
|
||||
"name": f"{agent['display_name']} Console",
|
||||
"room_type": "agent-console",
|
||||
"owner_type": "agent",
|
||||
"owner_id": agent_id,
|
||||
"space_scope": "agent",
|
||||
"visibility": "private",
|
||||
"is_public": False
|
||||
})
|
||||
|
||||
# Create Matrix room via gateway
|
||||
matrix_room = await create_matrix_room(room_slug, agent['display_name'])
|
||||
if matrix_room:
|
||||
await repo_city.update_room_matrix_id(room["id"], matrix_room["room_id"])
|
||||
|
||||
return room
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.4. Відновити Node Chat Rooms
|
||||
|
||||
### Правило
|
||||
|
||||
Кожна нода має кімнату підтримки:
|
||||
|
||||
- `room_slug = "node-support-{node_slug}"`
|
||||
- `room_type = "node-support"`
|
||||
- Учасники: GuardianOS, Steward, користувачі
|
||||
|
||||
### Завдання
|
||||
|
||||
1. **Backend**: generate + seed node support rooms
|
||||
2. **Gateway**: ensure node guardian is room admin
|
||||
3. **Matrix**: join guardian + steward agents
|
||||
|
||||
### SQL Seed for NODE1 and NODE2
|
||||
|
||||
```sql
|
||||
INSERT INTO city_rooms (id, slug, name, description, room_type, owner_type, owner_id, space_scope, visibility, is_public, created_at, updated_at)
|
||||
VALUES
|
||||
(gen_random_uuid(), 'node-support-node1', 'NODE1 Support', 'Support room for Hetzner GEX44 Production', 'node-support', 'node', 'node-1-hetzner-gex44', 'node', 'members', false, NOW(), NOW()),
|
||||
(gen_random_uuid(), 'node-support-node2', 'NODE2 Support', 'Support room for MacBook Pro M4 Max', 'node-support', 'node', 'node-2-macbook-m4max', 'node', 'members', false, NOW(), NOW())
|
||||
ON CONFLICT (slug) DO NOTHING;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.5. Виправити Citizens Layer
|
||||
|
||||
Public Agents = "Citizens of DAARION City"
|
||||
|
||||
### Правило
|
||||
|
||||
Агент є "громадянином" якщо:
|
||||
- `is_public = true`
|
||||
- `status = 'online' OR status = 'offline'` (не archived)
|
||||
- Має `city_visibility = 'public'` або `gov_level IN ('city_governance', 'district_lead', 'orchestrator')`
|
||||
|
||||
### Завдання
|
||||
|
||||
1. **Backend**: Оновити фільтр у `/public/citizens`
|
||||
2. **UI**: Виводити список усіх public agents у `/citizens`
|
||||
3. **Matrix**: Публічні агенти автоматично додаються до `general` room
|
||||
|
||||
### Updated Query
|
||||
|
||||
```python
|
||||
async def list_public_citizens(limit: int = 100):
|
||||
"""List all public agents as city citizens."""
|
||||
query = """
|
||||
SELECT a.*, nc.node_name
|
||||
FROM agents a
|
||||
LEFT JOIN node_cache nc ON a.node_id = nc.node_id
|
||||
WHERE a.is_public = true
|
||||
AND a.status != 'archived'
|
||||
AND (
|
||||
a.gov_level IN ('city_governance', 'district_lead', 'orchestrator', 'core_team')
|
||||
OR a.kind IN ('civic', 'governance', 'orchestrator')
|
||||
)
|
||||
ORDER BY a.display_name
|
||||
LIMIT $1
|
||||
"""
|
||||
return await db.fetch(query, limit)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.6. Виправити API /rooms/list
|
||||
|
||||
### Проблема
|
||||
|
||||
`/city/rooms` API повертає порожній список або помилку.
|
||||
|
||||
### Завдання
|
||||
|
||||
1. Перевірити endpoint у `city-service/routes_city.py`
|
||||
2. Забезпечити повернення:
|
||||
- rooms list
|
||||
- occupancy (online count)
|
||||
- agents list per room
|
||||
- matrix room mapping
|
||||
|
||||
### Expected Response
|
||||
|
||||
```json
|
||||
{
|
||||
"rooms": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"slug": "general",
|
||||
"name": "General",
|
||||
"room_type": "chat",
|
||||
"owner_type": "city",
|
||||
"matrix_room_id": "!abc:matrix.daarion.space",
|
||||
"online_count": 5,
|
||||
"agents": [
|
||||
{"id": "dario", "display_name": "DARIO", "role": "primary"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total": 8
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.7. Перевірка Gateway
|
||||
|
||||
### Завдання
|
||||
|
||||
1. Перевірити health matrix-gateway (`/health`)
|
||||
2. Перевірити NATS підключення
|
||||
3. Перевірити Matrix credentials
|
||||
4. Перезапустити якщо потрібно
|
||||
|
||||
### Health Check Commands
|
||||
|
||||
```bash
|
||||
# Check gateway health
|
||||
curl http://localhost:9300/health
|
||||
|
||||
# Check Matrix connection
|
||||
curl http://localhost:9300/internal/matrix/status
|
||||
|
||||
# Check NATS connection
|
||||
docker logs gateway | grep -i nats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 4. ЧЕКЛІСТ ВПРОВАДЖЕННЯ
|
||||
|
||||
Після завершення цього таска:
|
||||
|
||||
- [ ] `/city/map` — показує кімнати ✅
|
||||
- [ ] `/city` (список view) — працює
|
||||
- [ ] У кожного MicroDAO є свої кімнати (5+)
|
||||
- [ ] У кожного агента є своя чат-кімната
|
||||
- [ ] У кожної ноди є своя чат-кімната
|
||||
- [ ] Matrix кімнати реально існують
|
||||
- [ ] Gateway виконує join + send
|
||||
- [ ] Citizens Layer показує публічних агентів (5+)
|
||||
- [ ] Всі сторінки мають агентів + чат-віджет працює
|
||||
|
||||
---
|
||||
|
||||
# 5. ПОРЯДОК ВИКОНАННЯ
|
||||
|
||||
1. **Seed City Rooms** → SQL migration
|
||||
2. **Create Matrix Rooms** → gateway API calls
|
||||
3. **Update city_rooms** → set matrix_room_id
|
||||
4. **Fix /rooms/list API** → return proper data
|
||||
5. **Seed MicroDAO Rooms** → for DAARION root
|
||||
6. **Fix Citizens Layer** → update query
|
||||
7. **Test Agent Chat** → ensure auto-create works
|
||||
8. **Test Node Chat** → ensure rooms exist
|
||||
9. **Verify UI** → all pages show rooms
|
||||
|
||||
---
|
||||
|
||||
# 6. ВИХІДНІ АРТЕФАКТИ
|
||||
|
||||
Після виконання:
|
||||
|
||||
- `docs/debug/rooms_layer_restore_report_<DATE>.md`
|
||||
- SQL migration file
|
||||
- Updated API endpoints
|
||||
- UI verification screenshots
|
||||
|
||||
---
|
||||
|
||||
# 7. ІНСТРУКЦІЯ ДЛЯ CURSOR
|
||||
|
||||
```
|
||||
Виконай TASK_PHASE_ROOMS_LAYER_RESTORE_AND_MATRIX_INTEGRATION.md.
|
||||
|
||||
Працюй у модулях:
|
||||
1) city-service (FastAPI) — routes_city.py, repo_city.py, migrations.py
|
||||
2) matrix-gateway — room creation API
|
||||
3) apps/web (Next.js) — rooms list, citizens page
|
||||
|
||||
Дотримуйся документації у /docs/foundation/.
|
||||
Після кожного сектора — роби git commit.
|
||||
Не змінюй інші частини системи.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Target Date**: Immediate
|
||||
**Priority**: Critical
|
||||
**Dependencies**: Matrix gateway running, PostgreSQL accessible
|
||||
|
||||
Reference in New Issue
Block a user