teams: zeroclaw container coords + coding_readwrite risk profile
ci / gates (push) Successful in 5s
ci / frontend (push) Successful in 37s
ci / rust (push) Successful in 2m58s
ci / e2e (push) Skipped
ci / publish (push) Successful in 2m46s

Slice 3a of the per-loop-team arc — prerequisites for the runtime
spawn hookup that lands in 3b:

0046 migration
- ALTER TABLE teams ADD zeroclaw_container TEXT
- ALTER TABLE teams ADD zeroclaw_gateway_url TEXT
Both NULL until the runtime's spawn_team fn (3b) provisions the
container and persists its coordinates. Mirrors the shape already on
research_topics (0038) so the resolver code path can generalize.

cm-db
- team_container_coords / set_team_container_coords: dynamic
  sqlx::query() readers/writers for the new columns.

Runtime template (gw-04, out-of-band edit on
/var/lib/clawmates-runtime-template/config.toml + shared runtime
/root/clawmates-runtime/data/.zeroclaw/config.toml)
- New [risk_profiles.coding_readwrite]: adds file_write + shell on
  top of the research_readonly baseline. Still excludes http_request /
  browser / composio (egress stays behind the MCP door).

Slice 3b will add spawn_team (bind-mounts paired-topic repo, uses
team-scoped state dir, injects team.risk_profile into the config
template) and rewire topology_worker to resolve gateway URL through
team_id when the loop has one.
This commit is contained in:
Omar Sobh
2026-07-16 22:02:58 -07:00
parent 0b7f247b0e
commit d687a00524
2 changed files with 65 additions and 0 deletions
+53
View File
@@ -372,3 +372,56 @@ pub async fn set_team_for_research_topic(
.await?;
Ok(())
}
/// 0046: read the team's per-container coordinates. Both fields NULL
/// means the team has never spawned; the runtime provisions on first
/// iteration.
pub async fn team_container_coords(
pool: &PgPool,
id: Uuid,
workspace_id: WorkspaceId,
) -> Result<Option<(Option<String>, Option<String>)>, DbError> {
use sqlx::Row;
let row: Option<sqlx::postgres::PgRow> = sqlx::query(
"SELECT zeroclaw_container, zeroclaw_gateway_url FROM teams
WHERE id = $1 AND workspace_id = $2",
)
.bind(id)
.bind(workspace_id.as_uuid())
.fetch_optional(pool)
.await?;
Ok(row.map(|r| {
(
r.try_get::<Option<String>, _>("zeroclaw_container")
.ok()
.flatten(),
r.try_get::<Option<String>, _>("zeroclaw_gateway_url")
.ok()
.flatten(),
)
}))
}
/// 0046: set (or clear) the team's per-container coordinates once
/// spawn_team lands them.
pub async fn set_team_container_coords(
pool: &PgPool,
id: Uuid,
workspace_id: WorkspaceId,
container: Option<&str>,
gateway_url: Option<&str>,
) -> Result<(), DbError> {
sqlx::query(
"UPDATE teams
SET zeroclaw_container = $3,
zeroclaw_gateway_url = $4
WHERE id = $1 AND workspace_id = $2",
)
.bind(id)
.bind(workspace_id.as_uuid())
.bind(container)
.bind(gateway_url)
.execute(pool)
.await?;
Ok(())
}