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