feat(mvp): DAGI Integration Fix - gov_level, DAIS, nodes table

TASK_PHASE_MVP_DAGI_INTEGRATION_FIX_20251201

A) Agents Layer:
- A1: Added gov_level to API and UI (list + profile)
- A2: Added dais_identity_id to API and UI
- A3: Added home_microdao_id/name/slug for ownership display

B) MicroDAO Layer:
- B1/B2: Already implemented (agents, rooms, citizens, district badge)

C) Nodes Layer:
- C1: Node Dashboard already implemented
- C2: Created nodes table migration with owner_microdao_id
- C3: INSERT NODE1/NODE2 with dao_daarion ownership

D) Backend Fixes:
- D1: Extended /api/agents/* with DAIS/governance fields
- D2/D3: Already implemented

Files changed:
- services/city-service/repo_city.py
- services/city-service/models_city.py
- services/city-service/routes_city.py
- services/city-service/migrations.py
- apps/web/src/lib/types/agents.ts
- apps/web/src/lib/agent-dashboard.ts
- apps/web/src/app/agents/page.tsx
- apps/web/src/components/agent-dashboard/AgentSummaryCard.tsx

Reports:
- docs/debug/mvp_dagi_integration_fix_report_20251201.md
- docs/tasks/TASK_PHASE_MVP_DAGI_INTEGRATION_FIX_20251201.md
This commit is contained in:
Apple
2025-11-30 08:45:07 -08:00
parent a23deae3c4
commit 644edd3f30
22 changed files with 1227 additions and 82 deletions

View File

@@ -41,6 +41,46 @@ async def run_migrations():
""")
logger.info("Migration: Added room_role, is_public, sort_order to city_rooms table.")
# TASK C2: Create nodes table with owner_microdao (replaces node_cache for ontology)
await conn.execute("""
CREATE TABLE IF NOT EXISTS nodes (
id TEXT PRIMARY KEY,
display_name TEXT NOT NULL,
hostname TEXT,
owner_microdao_id TEXT REFERENCES microdaos(id),
node_type TEXT,
environment TEXT DEFAULT 'unknown',
cpu_cores INTEGER,
ram_gb INTEGER,
gpu_count INTEGER DEFAULT 0,
disk_gb INTEGER,
status TEXT DEFAULT 'unknown',
guardian_agent_id TEXT,
steward_agent_id TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
""")
logger.info("Migration: Created nodes table with owner_microdao.")
# TASK C3: Insert NODE1 and NODE2 if not exist
await conn.execute("""
INSERT INTO nodes (id, display_name, hostname, owner_microdao_id, node_type, environment, status, guardian_agent_id, steward_agent_id)
VALUES
('node-1-hetzner-gex44', 'Hetzner GEX44 Production', '144.76.224.179', 'dao_daarion', 'compute', 'production', 'online', 'monitor-node1', 'node-steward-node1'),
('node-2-macbook-m4max', 'MacBook Pro M4 Max', '192.168.1.33', 'dao_daarion', 'hybrid', 'development', 'online', 'monitor-node2', 'node-steward-node2')
ON CONFLICT (id) DO UPDATE SET
display_name = EXCLUDED.display_name,
hostname = EXCLUDED.hostname,
owner_microdao_id = EXCLUDED.owner_microdao_id,
node_type = EXCLUDED.node_type,
environment = EXCLUDED.environment,
guardian_agent_id = EXCLUDED.guardian_agent_id,
steward_agent_id = EXCLUDED.steward_agent_id,
updated_at = NOW();
""")
logger.info("Migration: Inserted/updated NODE1 and NODE2 in nodes table.")
except Exception as e:
logger.error(f"Error running migrations: {e}")
raise

View File

@@ -306,6 +306,10 @@ class AgentSummary(BaseModel):
node_label: Optional[str] = None # "НОДА1" / "НОДА2"
home_node: Optional[HomeNodeView] = None
# Governance & DAIS (A1, A2)
gov_level: Optional[str] = None # personal, core_team, orchestrator, district_lead, city_governance
dais_identity_id: Optional[str] = None # DAIS identity reference
# Visibility & roles
visibility_scope: str = "city" # global, microdao, private
is_listed_in_directory: bool = True
@@ -313,10 +317,13 @@ class AgentSummary(BaseModel):
is_public: bool = False
is_orchestrator: bool = False # Can create/manage microDAOs
# MicroDAO
# MicroDAO (A3)
primary_microdao_id: Optional[str] = None
primary_microdao_name: Optional[str] = None
primary_microdao_slug: Optional[str] = None
home_microdao_id: Optional[str] = None # Owner microDAO
home_microdao_name: Optional[str] = None
home_microdao_slug: Optional[str] = None
district: Optional[str] = None
microdaos: List[MicrodaoBadge] = []
microdao_memberships: List[Dict[str, Any]] = [] # backward compatibility

View File

@@ -386,10 +386,17 @@ async def list_agent_summaries(
pm.district AS district,
COALESCE(a.public_skills, ARRAY[]::text[]) AS public_skills,
a.crew_team_key,
-- DAIS & Governance fields (A1, A2)
a.gov_level,
a.dais_identity_id,
a.home_microdao_id,
hm.name AS home_microdao_name,
hm.slug AS home_microdao_slug,
COUNT(*) OVER() AS total_count
FROM agents a
LEFT JOIN node_cache nc ON a.node_id = nc.node_id
LEFT JOIN microdaos pm ON a.primary_microdao_id = pm.id
LEFT JOIN microdaos hm ON a.home_microdao_id = hm.id
WHERE {where_sql}
ORDER BY a.display_name
LIMIT ${len(params) + 1} OFFSET ${len(params) + 2}

View File

@@ -184,14 +184,21 @@ async def list_agents(
node_id=agent.get("node_id"),
node_label=agent.get("node_label"),
home_node=home_node,
# Governance & DAIS (A1, A2)
gov_level=agent.get("gov_level"),
dais_identity_id=agent.get("dais_identity_id"),
visibility_scope=agent.get("visibility_scope", "city"),
is_listed_in_directory=agent.get("is_listed_in_directory", True),
is_system=agent.get("is_system", False),
is_public=agent.get("is_public", False),
is_orchestrator=agent.get("is_orchestrator", False),
# MicroDAO (A3)
primary_microdao_id=agent.get("primary_microdao_id"),
primary_microdao_name=agent.get("primary_microdao_name"),
primary_microdao_slug=agent.get("primary_microdao_slug"),
home_microdao_id=agent.get("home_microdao_id"),
home_microdao_name=agent.get("home_microdao_name"),
home_microdao_slug=agent.get("home_microdao_slug"),
district=agent.get("district"),
microdaos=microdaos,
microdao_memberships=agent.get("microdao_memberships", []),