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

12 KiB
Raw Blame History

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:


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:


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

Додати:


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-методи:


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

Додати:


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:


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:


@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

Додати:


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. Розбити на секції:


<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 (щоб він сам крок-за-кроком виконав усе з цього таска).