Files
microdao-daarion/docs/tasks/TASK_PHASE_MICRODAO_DASHBOARD_v1.md
Apple fca48b3eb0 feat(node2): Complete NODE2 setup - guardian, agents, swapper models
- Node-guardian running on MacBook and updating metrics
- NODE2 agents (Atlas, Greeter, Oracle, Builder Bot) assigned to node-2-macbook-m4max
- Swapper models displaying correctly (8 models)
- DAGI Router agents showing with correct status (3 active, 1 stale)
- Router health check using node_cache for remote nodes
2025-12-02 07:07:58 -08:00

479 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TASK_PHASE_MICRODAO_DASHBOARD_v1
Статус: PLANNED
Пріоритет: High (презентація MVP)
## 1. Ціль
Зробити повноцінний **кабінет MicroDAO** (спочатку для `DAARION DAO`), який показує:
- базові метрики DAO (кімнати, громадяни, агенти);
- стрічку активності (новини/апдейти);
- кімнати DAO + кнопки створення кімнати;
- команду DAO (ключові агенти/громадяни);
- підготовлені секції під проєкти/задачі/файли/інтеграції.
Архітектурна вимога: **цей самий дашборд** повинен працювати для будь-якого MicroDAO (`slug`-залежний), щоб його можна було фрактально клонувати.
---
## 2. Поточний стан
Є:
- /microdao — список MicroDAO (з лого, тегами, pinned-сортуванням).
- /microdao/[slug] — сторінка MicroDAO з:
- Branding (лого, банер),
- visibility (public / platform),
- MicroDAO Rooms section,
- базовою статистикою (rooms count).
- /city — кімнати міста (мапа + список).
- /citizens — публічні агенти (громадяни).
- /agents — Agent Console (63 агентів, фільтри по нодах, кнопка "Новий агент").
- API для кімнат і агентів уже працює.
Немає:
- окремого **Dashboard API** для MicroDAO;
- таблиць для **активності (новин)** и **DAO-level метрик**;
- явної прив'язки громадян до конкретного MicroDAO (лише district/room mapping).
---
## 3. Архітектура рішення
### 3.1. База даних (PostgreSQL)
#### 3.1.1. Таблиця активності MicroDAO
Створити міграцію `migrations/041_microdao_activity.sql`:
```sql
CREATE TABLE microdao_activity (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
microdao_slug TEXT NOT NULL REFERENCES city_microdao(slug) ON DELETE CASCADE,
kind TEXT NOT NULL CHECK (kind IN ('post', 'event', 'update')),
title TEXT,
body TEXT NOT NULL,
author_agent_id UUID NULL REFERENCES city_agent(id),
author_name TEXT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_microdao_activity_microdao_created_at
ON microdao_activity (microdao_slug, created_at DESC);
```
#### 3.1.2. Розширити `city_microdao` під метрики (опціонально, але корисно)
Міграція `migrations/042_microdao_stats.sql`:
```sql
ALTER TABLE city_microdao
ADD COLUMN IF NOT EXISTS citizens_count INTEGER NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS rooms_count INTEGER NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS agents_count INTEGER NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS last_update_at TIMESTAMPTZ;
```
> На етапі MVP значення можна просто перераховувати на льоту в репозиторії й не оновлювати ці поля — але стовпці потрібні для майбутнього кешування.
---
### 3.2. Backend: FastAPI (city-service)
#### 3.2.1. Repo-рівень (Python)
Файл: `services/city-service/repo_city.py`
Додати:
```python
async def get_microdao_dashboard(conn, slug: str) -> MicrodaoDashboard:
"""
Aggregates:
- microdao summary
- last 5 activity items
- up to 5 rooms
- up to 6 citizens (agents) linked to this microdao
"""
```
Використати існуючі репо-методи:
* `get_microdao_by_slug`
* `get_microdao_rooms(slug)`
* `get_agents_by_microdao(slug)` або аналог (якщо немає — додати простий SELECT по district/slug mapping).
Нові helper-методи:
```python
async def get_microdao_activity(conn, slug: str, limit: int = 10) -> list[MicrodaoActivity]:
...
async def insert_microdao_activity(conn, activity: CreateMicrodaoActivity) -> MicrodaoActivity:
...
```
#### 3.2.2. Pydantic-моделі
Файл: `services/city-service/models_city.py`
Додати:
```python
class MicrodaoActivity(BaseModel):
id: UUID
microdao_slug: str
kind: str
title: str | None
body: str
author_agent_id: UUID | None
author_name: str | None
created_at: datetime
class CreateMicrodaoActivity(BaseModel):
kind: str = Field(pattern="^(post|event|update)$")
title: str | None = None
body: str
author_agent_id: UUID | None = None
author_name: str | None = None
class MicrodaoDashboard(BaseModel):
microdao: MicrodaoSummary
stats: MicrodaoStats
recent_activity: list[MicrodaoActivity]
rooms: list[RoomSummary]
citizens: list[PublicCitizenSummary]
```
`MicrodaoStats`:
```python
class MicrodaoStats(BaseModel):
rooms_count: int
citizens_count: int
agents_count: int
last_update_at: datetime | None
```
#### 3.2.3. Routes (FastAPI)
Файл: `services/city-service/routes_city.py`
Додати endpoints:
```python
@router.get("/microdao/{slug}/dashboard", response_model=MicrodaoDashboard)
async def get_microdao_dashboard(slug: str, conn=Depends(get_conn)):
return await repo_city.get_microdao_dashboard(conn, slug)
@router.get("/microdao/{slug}/activity", response_model=list[MicrodaoActivity])
async def list_microdao_activity(slug: str, limit: int = 20, conn=Depends(get_conn)):
return await repo_city.get_microdao_activity(conn, slug, limit)
@router.post("/microdao/{slug}/activity", response_model=MicrodaoActivity, status_code=201)
async def create_microdao_activity(
slug: str,
payload: CreateMicrodaoActivity,
conn=Depends(get_conn),
# TODO: optional auth / orchestrator check
):
return await repo_city.create_microdao_activity(conn, slug, payload)
```
Для MVP можна не чіпати авторизацію — припустити, що виклик робить orchestrator через адмін-UI.
---
### 3.3. Frontend: Next.js (apps/web)
#### 3.3.1. API-клієнт
Файл: `apps/web/src/lib/api.ts`
Додати:
```ts
export async function fetchMicrodaoDashboard(slug: string): Promise<MicrodaoDashboard> {
const res = await fetch(`${CITY_API_BASE_URL}/microdao/${slug}/dashboard`, { cache: "no-store" });
if (!res.ok) throw new Error("Failed to load microdao dashboard");
return res.json();
}
export async function fetchMicrodaoActivity(slug: string): Promise<MicrodaoActivity[]> {
const res = await fetch(`${CITY_API_BASE_URL}/microdao/${slug}/activity?limit=20`, { cache: "no-store" });
if (!res.ok) throw new Error("Failed to load microdao activity");
return res.json();
}
```
Типи `MicrodaoDashboard` / `MicrodaoActivity` додати до `apps/web/src/lib/types.ts`.
---
#### 3.3.2. Структура сторінки `/microdao/[slug]`
Файл (вже існує):
`apps/web/src/app/microdao/[slug]/page.tsx`
Перетворити на **Dashboard Layout**:
1. На сервері викликати `fetchMicrodaoDashboard(slug)`.
2. Розбити на секції:
```tsx
<MicrodaoHeaderCard dashboard={dashboard} /> // hero
<MicrodaoDashboardGrid>
<MicrodaoActivitySection activity={dashboard.recent_activity} />
<MicrodaoRoomsSection rooms={dashboard.rooms} slug={slug} />
<MicrodaoTeamSection citizens={dashboard.citizens} />
<MicrodaoProjectsSection microdao={dashboard.microdao} /> // placeholder
<MicrodaoTasksSection microdao={dashboard.microdao} /> // placeholder
</MicrodaoDashboardGrid>
```
Нові компоненти:
* `apps/web/src/components/microdao/MicrodaoHeaderCard.tsx`
* `apps/web/src/components/microdao/MicrodaoActivitySection.tsx`
* `apps/web/src/components/microdao/MicrodaoTeamSection.tsx`
* `apps/web/src/components/microdao/MicrodaoProjectsSection.tsx` (stub)
* `apps/web/src/components/microdao/MicrodaoTasksSection.tsx` (stub)
##### MicrodaoHeaderCard
Показати:
* Лого (через `normalizeAssetUrl`)
* Назву, теги (Platform / Core / Active)
* Метрики:
* `{stats.rooms_count} Кімнат`
* `{stats.citizens_count} Громадян`
* `{stats.agents_count} Агентів`
* кнопки:
* "Поспілкуватися з DAARWIZZ" → `href="/city?room=city-lobby"`
* "Створити кімнату" → прокрутка до секції кімнат або модалка.
##### MicrodaoActivitySection
* Заголовок "Новини DAARION" (або назва DAO).
* Список останніх 510 записів:
* заголовок / перші рядки body,
* дата,
* автор (агент або author_name).
* Якщо немає записів — показати `Empty state: "Поки що немає новин"`.
---
### 3.4. Зв'язок з існуючими розділами
* MicroDAO Rooms: у компоненті `MicrodaoRoomsSection` використати вже існуючу логіку створення/видалення кімнат.
* Citizens: `MicrodaoTeamSection` повинна показувати тільки тих громадян, у яких `home_microdao_slug` або district/room mapping вказує на цей MicroDAO. На етапі MVP можна вибрати фіксований набір (наприклад, 6 ключових агентів DAARION) через простий SQL.
---
## 4. План виконання (для Cursor)
### Крок 1. DB міграції
1. Створити `migrations/041_microdao_activity.sql` і `042_microdao_stats.sql`.
2. Запустити міграції локально й на NODE1 (MVP DB).
### Крок 2. Backend
1. Оновити `models_city.py` — додати моделі `MicrodaoActivity`, `CreateMicrodaoActivity`, `MicrodaoStats`, `MicrodaoDashboard`.
2. Оновити `repo_city.py` — реалізувати aggregation для `get_microdao_dashboard` та CRUD для activity.
3. Оновити `routes_city.py` — додати `/microdao/{slug}/dashboard` та `/microdao/{slug}/activity`.
### Крок 3. Frontend
1. Оновити `apps/web/src/lib/types.ts` та `api.ts` (типи й API-клієнт).
2. Переписати `apps/web/src/app/microdao/[slug]/page.tsx`, щоб вона використовувала `fetchMicrodaoDashboard`.
3. Створити компоненти:
* `MicrodaoHeaderCard.tsx`
* `MicrodaoActivitySection.tsx`
* `MicrodaoTeamSection.tsx`
* (stubs) `MicrodaoProjectsSection.tsx`, `MicrodaoTasksSection.tsx`
### Крок 4. DAARION DAO як демо
1. Заповнити хоча б **510 записів `microdao_activity`** для `slug='daarion'` (через SQL або простий admin-endpoint /seed).
2. Прив'язати ключових агентів DAARION до цього MicroDAO (update в таблиці citizens/agents).
3. Перевірити сторінку `/microdao/daarion`:
* лого + title;
* метрики не ламаються (0 — ок, NaN — ні);
* відображаються кімнати DAARION;
* видно список 6+ громадян DAARION;
* CTA "Поспілкуватися з DAARWIZZ" працює.
---
## 7. Що показувати на презентації
1. **МікроDAO список** — DAARION, Energy Union, GreenFood, Soul наверху (pin).
2. **DAARION DAO сторінка**:
* красивий hero-блок як "панель керування DAO";
* блок "Новини DAARION";
* блок "Кімнати DAARION";
* блок "Команда DAARION".
3. **City Rooms** — показати, що одна з кімнат — головний публічний чат (DAARION City Lobby) з DAARWIZZ.
4. **Citizens / Agents** — як реєстр агентів, які прив'язані до DAARION.
Це вже виглядає як **живий кабінет DAO**, а не просто сайт.
---
Якщо хочеш, наступним кроком можу згенерувати окремий `TASK_PHASE_MICRODAO_DASHBOARD_v1_CURSOR_PROMPT.md` з готовим промтом для Cursor (щоб він сам крок-за-кроком виконав усе з цього таска).