Adopt design comps: dark system, new landing/auth, dashboard shell + canvas

Re-skins the whole app to the dark design comps and wires the new surfaces to
the backend (the /api proxy + auth + schemas are unchanged).

Design system:
- globals.css: remapped @theme tokens to the comp palette (#08080a base, coral
  #ff6f61, status cyan/green/amber/purple/teal); token names preserved
- MeshMark: triangle + 3-node brand glyph; cm-flow/cm-blink/cm-halo keyframes
- marketing flipped light → dark

Backend (migration 0012):
- agents.model_binding (persisted on team deploy) + GET /api/claws/{id}/runtime-config
- routine_runs table + scheduler journaling + GET /api/routines/runs
- GET /api/claws/{id}/compartments (anatomy aggregate)
- GET /api/structure/stats (workspace counts)

Frontend:
- Landing: full dark marketing page (hero constellation, deploy ladder,
  12-topology taxonomy, recursive execution, compare/Pareto, safety, self-host)
- Auth: dark split-panel AuthShell + comp LoginForm + Clerk SignIn themed dark
- Dashboard shell: TopBar (breadcrumb + live stats + deploy + user) + StatusBar
  (runner/sandbox/doors); rail slimmed to 60px + 252px context column
- ConstellationCanvas (radial recursive) replaces the graph view in StructureCanvas;
  selecting a claw opens ComputerPanel (apps/now-running/dock); RoutinesPanel
- Claw anatomy view (/claws/[id]/anatomy) from compartments + runtime-config

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-19 04:12:16 -07:00
co-authored by Claude Opus 4.8
parent 3eca4ed70c
commit 540c74f42e
41 changed files with 2253 additions and 406 deletions
+28
View File
@@ -76,6 +76,34 @@ pub async fn get(pool: &PgPool, agent_id: AgentId) -> Result<Agent, DbError> {
})
}
/// Persist the model a claw was deployed with (e.g. "claude", "gemini",
/// "glm-5.2") — the runtime config is otherwise the only record of it.
pub async fn set_model_binding(
pool: &PgPool,
agent_id: AgentId,
model: &str,
) -> Result<(), DbError> {
sqlx::query!(
"UPDATE agents SET model_binding = $2 WHERE id = $1 AND deleted_at IS NULL",
agent_id.as_uuid(),
model,
)
.execute(pool)
.await?;
Ok(())
}
/// The persisted model binding for a claw, if any (NULL for pre-team claws).
pub async fn model_binding(pool: &PgPool, agent_id: AgentId) -> Result<Option<String>, DbError> {
let row = sqlx::query!(
"SELECT model_binding FROM agents WHERE id = $1 AND deleted_at IS NULL",
agent_id.as_uuid(),
)
.fetch_one(pool)
.await?;
Ok(row.model_binding)
}
/// Patch-style profile update (§7.7 Edit profile): only provided fields
/// change; the system prompt is the Job Description textarea verbatim.
#[allow(clippy::too_many_arguments)]
+1
View File
@@ -7,6 +7,7 @@ pub mod files;
pub mod messages;
pub mod orgs;
pub mod outbox;
pub mod routine_runs;
pub mod routines;
pub mod run_events;
pub mod runs;
+109
View File
@@ -0,0 +1,109 @@
//! Journal of routine firings — one row per execution, powering the dashboard
//! routines panel's run history + live ("now running") loops.
use serde_json::Value;
use sqlx::PgPool;
use time::OffsetDateTime;
use uuid::Uuid;
use crate::DbError;
/// One routine execution.
#[derive(Debug, Clone, serde::Serialize)]
pub struct RoutineRun {
pub id: Uuid,
pub routine_id: Uuid,
pub status: String, // running | ok | error
#[serde(with = "time::serde::rfc3339")]
pub started_at: OffsetDateTime,
#[serde(with = "time::serde::rfc3339::option")]
pub completed_at: Option<OffsetDateTime>,
pub error: Option<String>,
}
/// Record the start of a routine firing; returns the run id to finish later.
pub async fn start(pool: &PgPool, routine_id: Uuid) -> Result<Uuid, DbError> {
let id = Uuid::now_v7();
sqlx::query!(
"INSERT INTO routine_runs (id, routine_id) VALUES ($1, $2)",
id,
routine_id,
)
.execute(pool)
.await?;
Ok(id)
}
/// Mark a routine run terminal (`ok`/`error`).
pub async fn finish(
pool: &PgPool,
id: Uuid,
status: &str,
error: Option<&str>,
) -> Result<(), DbError> {
sqlx::query!(
"UPDATE routine_runs SET status = $2, completed_at = now(), error = $3 WHERE id = $1",
id,
status,
error,
)
.execute(pool)
.await?;
Ok(())
}
/// Recent runs for one routine, newest first.
pub async fn list_by_routine(
pool: &PgPool,
routine_id: Uuid,
limit: i64,
) -> Result<Vec<RoutineRun>, DbError> {
let rows = sqlx::query_as!(
RoutineRun,
r#"SELECT id, routine_id, status, started_at, completed_at, error
FROM routine_runs WHERE routine_id = $1
ORDER BY started_at DESC LIMIT $2"#,
routine_id,
limit,
)
.fetch_all(pool)
.await?;
Ok(rows)
}
/// Recent runs across all of a workspace's routines (the panel's run history).
/// Joined through `routines` → `agents` to scope to the workspace. Each row also
/// carries its routine name for display.
pub async fn recent_for_workspace(
pool: &PgPool,
workspace_id: Uuid,
limit: i64,
) -> Result<Vec<Value>, DbError> {
let rows = sqlx::query!(
r#"SELECT rr.id, rr.routine_id, r.name AS routine_name, rr.status,
rr.started_at, rr.completed_at, rr.error
FROM routine_runs rr
JOIN routines r ON r.id = rr.routine_id
JOIN agents a ON a.id = r.agent_id
WHERE a.workspace_id = $1
ORDER BY rr.started_at DESC LIMIT $2"#,
workspace_id,
limit,
)
.fetch_all(pool)
.await?;
Ok(rows
.into_iter()
.map(|r| {
serde_json::json!({
"id": r.id,
"routine_id": r.routine_id,
"routine_name": r.routine_name,
"status": r.status,
"started_at": r.started_at.format(&time::format_description::well_known::Rfc3339).unwrap_or_default(),
"completed_at": r.completed_at.and_then(|t| t.format(&time::format_description::well_known::Rfc3339).ok()),
"error": r.error,
})
})
.collect())
}
+13
View File
@@ -251,6 +251,19 @@ pub async fn requeue_stale(pool: &PgPool, older_than_secs: f64) -> Result<u64, D
Ok(result.rows_affected())
}
/// How many durable runs are currently `queued` or `running` for a workspace
/// (the dashboard "running now" / status-bar counter).
pub async fn count_active(pool: &PgPool, workspace_id: WorkspaceId) -> Result<i64, DbError> {
let row = sqlx::query!(
"SELECT count(*) AS n FROM topology_runs
WHERE workspace_id = $1 AND status IN ('queued', 'running')",
workspace_id.as_uuid(),
)
.fetch_one(pool)
.await?;
Ok(row.n.unwrap_or(0))
}
/// The most recent runs for a workspace, newest first.
pub async fn list_recent(
pool: &PgPool,