Files
Apple ef3473db21 snapshot: NODE1 production state 2026-02-09
Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.

Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles

Excluded from snapshot: venv/, .env, data/, backups, .tgz archives

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 08:46:46 -08:00

1039 lines
47 KiB
HTML
Raw Permalink 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.
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://IvanTytar.github.io/microdao-daarion/tasks/TASK_PHASE_DISTRICT_PORTALS_v1/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.18">
<title>TASK_PHASE_DISTRICT_PORTALS_v1 - DAARION Documentation</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.66ac8b77.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#task_phase_district_portals_v1" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="DAARION Documentation" class="md-header__button md-logo" aria-label="DAARION Documentation" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
DAARION Documentation
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
TASK_PHASE_DISTRICT_PORTALS_v1
</span>
</div>
</div>
</div>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="DAARION Documentation" class="md-nav__button md-logo" aria-label="DAARION Documentation" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
DAARION Documentation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../public/" class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../public/getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../public/architecture-overview/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../public/daiS_daos_overview/" class="md-nav__link">
<span class="md-ellipsis">
DAIS & DAOS
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-ellipsis">
Internal
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Internal
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_1" >
<label class="md-nav__link" for="__nav_5_1" id="__nav_5_1_label" tabindex="0">
<span class="md-ellipsis">
Infra
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_1">
<span class="md-nav__icon md-icon"></span>
Infra
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../internal/infra/INFRA_AUTOMATION_PACK_V1/" class="md-nav__link">
<span class="md-ellipsis">
Infra Automation Pack v1
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/infra/monitoring_overview/" class="md-nav__link">
<span class="md-ellipsis">
Monitoring Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/infra/nodes_registry_v0/" class="md-nav__link">
<span class="md-ellipsis">
Nodes Registry v0
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_2" >
<label class="md-nav__link" for="__nav_5_2" id="__nav_5_2_label" tabindex="0">
<span class="md-ellipsis">
Specs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_2">
<span class="md-nav__icon md-icon"></span>
Specs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../internal/specs/matrix_presence_aggregator/" class="md-nav__link">
<span class="md-ellipsis">
Matrix Presence Aggregator
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/specs/city_map_spec/" class="md-nav__link">
<span class="md-ellipsis">
City Map Spec
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/specs/node_join_protocol_draft/" class="md-nav__link">
<span class="md-ellipsis">
Node Join Protocol (Draft)
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="task_phase_district_portals_v1">TASK_PHASE_DISTRICT_PORTALS_v1<a class="headerlink" href="#task_phase_district_portals_v1" title="Permanent link">&para;</a></h1>
<p>Version: 1.0
Status: Ready
Priority: High (City → District → MicroDAO контур)</p>
<hr />
<h1 id="1">1. МЕТА<a class="headerlink" href="#1" title="Permanent link">&para;</a></h1>
<p>Зробити <strong>District-и повноцінними "порталами платформ"</strong> у DAARION.city:</p>
<ul>
<li>окремі сторінки District-ів (SOUL, GREENFOOD, ENERGYUNION),</li>
<li>прив'язка до існуючих District-протоколів,</li>
<li>інтеграція з Rooms, Matrix, Presence, Chat Widget,</li>
<li>відображення MicroDAO всередині District-а.</li>
</ul>
<p>Результат:
користувач, заходячи на DAARION.space, може:</p>
<ul>
<li>потрапити в місто (/city),</li>
<li>з міста — в District-портал (/soul, /greenfood, /energy-union),</li>
<li>з District — у відповідні MicroDAO / кімнати / агентів.</li>
</ul>
<hr />
<h1 id="2">2. ВИХІДНІ ДАНІ<a class="headerlink" href="#2" title="Permanent link">&para;</a></h1>
<p>Уже є:</p>
<ul>
<li>Foundation-документи:</li>
<li><code>GREENFOOD_District_Protocol_v1.md</code></li>
<li><code>ENERGYUNION_District_Protocol_v1.md</code></li>
<li><code>SOUL_District_Protocol_v1.md</code></li>
<li><code>District_Interface_Architecture_v1.md</code></li>
<li>Таблиця <code>microdaos</code> з полем <code>dao_type = 'district'</code> (SOUL, GREENFOOD, ENERGYUNION).</li>
<li>Rooms Layer:</li>
<li>District rooms для:<ul>
<li>SOUL (soul-lobby, soul-events, soul-masters, ...)</li>
<li>GREENFOOD (greenfood-lobby, ... )</li>
<li>ENERGYUNION (energyunion-lobby, energyunion-compute, ...)</li>
</ul>
</li>
<li>Matrix + Chat:</li>
<li><code>rooms.matrix_room_id</code> заповнено,</li>
<li>Chat API працює,</li>
<li>Presence API працює.</li>
<li>Frontend:</li>
<li>City Layer /city, /city/{slug}</li>
<li>Agents, Nodes, MicroDAO базові сторінки</li>
</ul>
<hr />
<h1 id="3-scope">3. SCOPE<a class="headerlink" href="#3-scope" title="Permanent link">&para;</a></h1>
<ol>
<li>Backend District API:</li>
<li><code>GET /api/v1/districts</code></li>
<li><code>GET /api/v1/districts/{slug}</code></li>
<li>Frontend routing:</li>
<li><code>/districts</code> (список всіх District-ів)</li>
<li><code>/districts/[slug]</code> (універсальний портал)</li>
<li>короткі alias-роути:<ul>
<li><code>/soul</code> → SOUL District</li>
<li><code>/greenfood</code> → GREENFOOD District</li>
<li><code>/energy-union</code> → ENERGYUNION District</li>
</ul>
</li>
<li>UI District-порталу:</li>
<li>header (назва, опис, тип, lead agent),</li>
<li>District rooms (список кімнат + переходи),</li>
<li>host agents (lead/core team) + presence,</li>
<li>chat widget (District lobby room),</li>
<li>список MicroDAO всередині District-а.</li>
<li>Інтеграція з City Layer:</li>
<li>посилання з City → District.</li>
</ol>
<hr />
<h1 id="4-1-backend-district-api-city-service">4. МОДУЛЬ 1 — BACKEND: DISTRICT API (CITY-SERVICE)<a class="headerlink" href="#4-1-backend-district-api-city-service" title="Permanent link">&para;</a></h1>
<h2 id="41-get-apiv1districts">4.1. <code>GET /api/v1/districts</code><a class="headerlink" href="#41-get-apiv1districts" title="Permanent link">&para;</a></h2>
<p>Повертає список всіх District-ів.</p>
<p>Приблизний вихід:</p>
<div class="codehilite"><pre><span></span><code><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;uuid&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;soul&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SOUL Retreat District&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Wellness / Retreat / Metahuman&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;dao_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;district&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;lead_agent&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;agent_id_soul&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SOUL&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;rooms&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;uuid&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;soul-lobby&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SOUL Lobby&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;microdaos_count&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;uuid&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;greenfood&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;GREENFOOD District&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;ERP / Supply Chains / Food&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;dao_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;district&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;lead_agent&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;agent_id_greenfood&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;ERP GREENFOOD&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;rooms&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;microdaos_count&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;uuid&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;energy-union&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Energy Union District&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;DePIN / Energy / Compute&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;dao_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;district&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;lead_agent&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;agent_id_helion&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Helion&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;rooms&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;microdaos_count&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">]</span>
</code></pre></div>
<p>Логіка:</p>
<ul>
<li>брати записи з <code>microdaos</code> де <code>dao_type = 'district'</code>;</li>
<li>підвантажити lead-agent (згідно District-протоколів);</li>
<li>підтягнути ключові кімнати (lobby тощо) через <code>rooms</code> та <code>district_id</code> / зв'язки.</li>
</ul>
<h2 id="42-get-apiv1districtsslug">4.2. <code>GET /api/v1/districts/{slug}</code><a class="headerlink" href="#42-get-apiv1districtsslug" title="Permanent link">&para;</a></h2>
<p>Подробиці District-а.</p>
<p>Приблизний вихід:</p>
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;uuid&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;soul&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SOUL Retreat District&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Wellness / Retreat / Metahuman District&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;dao_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;district&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;lead_agent&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;agent_id_soul&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SOUL&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;dais_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;dais_soul&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;core_team&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;agent_spirit&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Spirit&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Guidance&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;agent_logic&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Logic&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Information&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;rooms&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;room_id_lobby&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;soul-lobby&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SOUL Lobby&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;matrix_room_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;!room:matrix...&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;room_id_events&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;soul-events&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Events&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;microdaos&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;microdao_id_1&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;slug&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;soul-hub-1&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Retreat Hub #1&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div>
<p>Якщо District не знайдено → 404.</p>
<hr />
<h1 id="5-2-frontend-api">5. МОДУЛЬ 2 — FRONTEND API КЛІЄНТ<a class="headerlink" href="#5-2-frontend-api" title="Permanent link">&para;</a></h1>
<p>У <code>apps/web/src/lib/api/districts.ts</code>:</p>
<div class="codehilite"><pre><span></span><code><span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">DistrictSummary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">slug</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">description</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">daoType</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;district&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="nx">leadAgent</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="nx">rooms</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">slug</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="p">}[];</span>
<span class="w"> </span><span class="nx">microdaosCount</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">DistrictDetail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">slug</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">description</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">daoType</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;district&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="nx">leadAgent</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">daisId?</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="nx">coreTeam</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">role</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="p">}[];</span>
<span class="w"> </span><span class="nx">rooms</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">slug</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">matrixRoomId?</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="p">}[];</span>
<span class="w"> </span><span class="nx">microdaos</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">slug</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w"> </span><span class="p">}[];</span>
<span class="p">};</span>
<span class="k">export</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">getDistricts</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DistrictSummary</span><span class="p">[]</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">}</span>
<span class="k">export</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">getDistrictBySlug</span><span class="p">(</span><span class="nx">slug</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DistrictDetail</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">}</span>
</code></pre></div>
<hr />
<h1 id="6-3-routing">6. МОДУЛЬ 3 — ROUTING<a class="headerlink" href="#6-3-routing" title="Permanent link">&para;</a></h1>
<h2 id="61-districts">6.1. <code>/districts</code> (список)<a class="headerlink" href="#61-districts" title="Permanent link">&para;</a></h2>
<p>Файл: <code>apps/web/src/app/districts/page.tsx</code></p>
<p>Повинен:</p>
<ul>
<li>завантажити <code>getDistricts()</code>;</li>
<li>показати карточки District-ів:</li>
<li>SOUL</li>
<li>GREENFOOD</li>
<li>ENERGY UNION</li>
<li>кожна картка:</li>
<li>назва</li>
<li>опис</li>
<li>lead agent (ім'я + presence)</li>
<li>кнопка/посилання "Перейти до District".</li>
</ul>
<h2 id="62-districtsslug-district-">6.2. <code>/districts/[slug]</code> (портал District-а)<a class="headerlink" href="#62-districtsslug-district-" title="Permanent link">&para;</a></h2>
<p>Файл: <code>apps/web/src/app/districts/[slug]/page.tsx</code></p>
<p>Логіка:</p>
<ul>
<li>прочитати <code>params.slug</code>;</li>
<li>викликати <code>getDistrictBySlug(slug)</code>;</li>
<li>якщо 404 → <code>notFound()</code>.</li>
</ul>
<hr />
<h1 id="7-4-ui-district-">7. МОДУЛЬ 4 — UI DISTRICT-ПОРТАЛУ<a class="headerlink" href="#7-4-ui-district-" title="Permanent link">&para;</a></h1>
<p>Структура сторінки <code>/districts/[slug]</code>:</p>
<h2 id="71-header">7.1. Header<a class="headerlink" href="#71-header" title="Permanent link">&para;</a></h2>
<ul>
<li>Назва District-а (<code>name</code>)</li>
<li>Опис (<code>description</code>)</li>
<li>Badge: "District"</li>
<li>Breadcrumb:</li>
<li><code>City / Districts / {DistrictName}</code></li>
</ul>
<h2 id="72-lead-agent-core-team">7.2. Lead Agent + Core Team<a class="headerlink" href="#72-lead-agent-core-team" title="Permanent link">&para;</a></h2>
<p>Секція "District Agents":</p>
<ul>
<li>Lead Agent:</li>
<li>аватар,</li>
<li>ім'я (SOUL / GREENFOOD / Helion),</li>
<li>PresenceDot (online/offline/away),</li>
<li>
<p>кнопка "Кабінет агента".</p>
</li>
<li>
<p>Core Team (якщо є):</p>
</li>
<li>список агентів (Spirit, Logic, Energia тощо),</li>
<li>ролі (Guidance, Information, Energy, Scheduler...),</li>
<li>presence.</li>
</ul>
<h2 id="73-rooms">7.3. Rooms<a class="headerlink" href="#73-rooms" title="Permanent link">&para;</a></h2>
<p>Секція "District Rooms":</p>
<ul>
<li>список кімнат District-а:</li>
<li>назва,</li>
<li>опис (якщо є),</li>
<li>scope tag (lobby / events / labs / providers / compute / guidance / etc.),</li>
<li>кнопка "Відкрити кімнату" → <code>/city/{slug}</code> або окремий <code>/rooms/{slug}</code>, залежно від моделі.</li>
<li>Для lobby-кімнати:</li>
<li>окремий акцент: "Головний портал District-а".</li>
</ul>
<p>(Якщо кімнати реалізовані як <code>rooms.scope = 'district'</code>, на UI використовувати їх метадані з БД.)</p>
<h2 id="74-microdao">7.4. MicroDAO<a class="headerlink" href="#74-microdao" title="Permanent link">&para;</a></h2>
<p>Секція "MicroDAO цього District-а":</p>
<ul>
<li>таблиця/карточки:</li>
<li>назва MicroDAO,</li>
<li>тип (якщо є),</li>
<li>кнопка "Відкрити MicroDAO" → <code>/microdao/{slug}</code>.</li>
</ul>
<h2 id="75-chat-district-lobby">7.5. Chat (District Lobby)<a class="headerlink" href="#75-chat-district-lobby" title="Permanent link">&para;</a></h2>
<ul>
<li>Внизу чи праворуч: Chat Widget, прив'язаний до <strong>District Lobby Room</strong>:</li>
<li>отримати lobby room з <code>rooms</code> (наприклад, slug <code>soul-lobby</code>, <code>greenfood-lobby</code>, <code>energyunion-lobby</code>);</li>
<li>чат працює через <code>/api/v1/chat/rooms/{room_id}</code>.</li>
<li>Неавторизованим показувати "Увійти, щоб писати".</li>
</ul>
<hr />
<h1 id="8-5-shortcut-routes">8. МОДУЛЬ 5 — SHORTCUT ROUTES<a class="headerlink" href="#8-5-shortcut-routes" title="Permanent link">&para;</a></h1>
<p>Щоб було зручно заходити на платформи:</p>
<ul>
<li><code>/soul</code> → редірект або пряма сторінка, що використовує <code>getDistrictBySlug("soul")</code>.</li>
<li><code>/greenfood</code><code>getDistrictBySlug("greenfood")</code>.</li>
<li><code>/energy-union</code><code>getDistrictBySlug("energy-union")</code>.</li>
</ul>
<p>Реалізація:</p>
<ul>
<li>створити файли:</li>
<li><code>apps/web/src/app/soul/page.tsx</code></li>
<li><code>apps/web/src/app/greenfood/page.tsx</code></li>
<li><code>apps/web/src/app/energy-union/page.tsx</code></li>
</ul>
<p>Які просто рендерять той самий компонент, що й <code>/districts/[slug]</code>, з фіксованим <code>slug</code>.</p>
<hr />
<h1 id="9-city-layer">9. ІНТЕГРАЦІЯ З CITY LAYER<a class="headerlink" href="#9-city-layer" title="Permanent link">&para;</a></h1>
<p>На сторінці <code>/city</code> або в City Square:</p>
<ul>
<li>для портальних точок (District Portals):</li>
<li>додати кнопки/картки:<ul>
<li>"SOUL Retreat District"</li>
<li>"GREENFOOD District"</li>
<li>"Energy Union District"</li>
</ul>
</li>
<li>клік → переходить на:<ul>
<li><code>/soul</code></li>
<li><code>/greenfood</code></li>
<li><code>/energy-union</code></li>
</ul>
</li>
</ul>
<hr />
<h1 id="10-smoke-">10. SMOKE-ТЕСТИ<a class="headerlink" href="#10-smoke-" title="Permanent link">&para;</a></h1>
<p>Після завершення:</p>
<ol>
<li><code>/districts</code>:</li>
<li>
<p>показує 3 District-и (SOUL, GREENFOOD, ENERGYUNION).</p>
</li>
<li>
<p><code>/districts/soul</code>:</p>
</li>
<li>рендериться без помилок,</li>
<li>видно SOUL як lead agent + presence,</li>
<li>видно Spirit/Logic (як core team, якщо додані),</li>
<li>видно список rooms (soul-lobby, soul-events, soul-guidance...),</li>
<li>
<p>чат-простір для lobby.</p>
</li>
<li>
<p><code>/districts/greenfood</code>:</p>
</li>
<li>рендериться,</li>
<li>видно ERP GREENFOOD agent,</li>
<li>rooms згідно GREENFOOD_District_Protocol,</li>
<li>
<p>microDAO (якщо є) у списку.</p>
</li>
<li>
<p><code>/districts/energy-union</code>:</p>
</li>
<li>рендериться,</li>
<li>видно Helion, Energia,</li>
<li>rooms (lobby, compute, providers, labs...),</li>
<li>
<p>чат-простір.</p>
</li>
<li>
<p><code>/soul</code>, <code>/greenfood</code>, <code>/energy-union</code>:</p>
</li>
<li>
<p>відкривають відповідні портали District-ів.</p>
</li>
<li>
<p>City → District:</p>
</li>
<li>з City UI є лінки, які ведуть на District Portals.</li>
</ol>
<hr />
<h1 id="11">11. ФІНАЛЬНИЙ ЗВІТ<a class="headerlink" href="#11" title="Permanent link">&para;</a></h1>
<p>Після виконання:</p>
<p>Створити файл:</p>
<p><code>docs/debug/district_portals_report_&lt;DATE&gt;.md</code></p>
<p>І включити в нього:</p>
<ul>
<li>список District-ів з <code>/api/v1/districts</code>,</li>
<li>приклади <code>GET /api/v1/districts/{slug}</code>,</li>
<li>скрін/опис <code>/districts</code>, <code>/districts/soul</code>, <code>/districts/greenfood</code>, <code>/districts/energy-union</code>,</li>
<li>підтвердження, що <code>/soul</code>, <code>/greenfood</code>, <code>/energy-union</code> працюють.</li>
</ul>
<hr />
<h1 id="12-prompt-cursor">12. PROMPT ДЛЯ CURSOR<a class="headerlink" href="#12-prompt-cursor" title="Permanent link">&para;</a></h1>
<div class="codehilite"><pre><span></span><code>Виконай TASK_PHASE_DISTRICT_PORTALS_v1.md.
Фокус:
1) Backend: /api/v1/districts, /api/v1/districts/{slug}
2) Frontend: /districts, /districts/[slug], /soul, /greenfood, /energy-union
3) District UI: lead agent, core team, rooms, microDAO list, chat (lobby room)
4) Інтеграція з City Layer (/city → District Portals)
Після завершення створи:
docs/debug/district_portals_report_&lt;DATE&gt;.md
</code></pre></div>
<hr />
<p><strong>Target Date</strong>: Immediate
<strong>Priority</strong>: High
<strong>Dependencies</strong>: City Layer complete, Matrix rooms synced</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": ["navigation.sections", "navigation.instant", "content.code.copy"], "search": "../../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../../assets/javascripts/bundle.3220b9d7.min.js"></script>
</body>
</html>