logs + team parity: pretty step/container renderers; quota + audit on team creation
ci / gates (push) Successful in 6s
ci / frontend (push) Successful in 37s
ci / rust (push) Successful in 2m58s
ci / e2e (push) Skipped
ci / publish (push) Successful in 2m53s

Two bundled changes:

── LiveRunLogs prettification ──────────────────────────────────
The Steps + Container tabs were plain mono lines with a single
color per event. Now they get structured layout:

Steps:
- Color-hashed actor pill (stable palette so [Distiller] and
  [Novelty Analyst] each get their own hue across the session).
- Phase pill (plan=cyan, work=green, synth=amber, aggregate=purple).
- Token count pill formatted 1.2k / 14.3k / etc.
- Gated-action warning pill in amber when > 0.
- Left-border color strip keyed to the actor for at-a-glance
  visual grouping.
- Long outputs collapse to their first 300 chars with a '+ N more'
  toggle to expand the full text.
- 'done' events get a green (or red for error) border strip +
  pill instead of blending into the stream.

Container:
- Splits '[actor] action (outcome) · msg' into colored spans —
  actor pill (deterministic color), action in dim, outcome pill
  green/red/dim by state.
- Non-line events (info/error/done) get their own left-border
  strip so bash echoes and stack traces don't drown in the daemon
  chatter.
- Timestamps switch to HH:MM:SS.mmm — dense but scannable.

Small palette (LOG constants) keeps the color budget bounded — no
new UI vocabulary, just cleaner reads of what was already there.

── Team-wizard governance parity ───────────────────────────────
build_team_with_lifecycle now matches POST /api/claws' governance:
- enforce_new_agent quota check per member (previously bypassed
  workspace agent quotas entirely for team/auto-provision paths).
- audit::append('agent.created', ..., {source: 'team_wizard'}) per
  member so team-created claws appear in the same audit trail as
  individually-created ones. Adding a 'source' key distinguishes
  provenance without changing consumers.

.brain (h5) handling was already consistent between the two paths —
both use the lazy on-first-access load_brain hook seeded from
agents.system_prompt. No change there.
This commit is contained in:
Omar Sobh
2026-07-17 18:20:56 -07:00
parent 956be2cf4f
commit ac8c689f50
2 changed files with 304 additions and 50 deletions
+19
View File
@@ -96,6 +96,11 @@ pub(crate) async fn build_team_with_lifecycle(
let mut claw_ids: Vec<Uuid> = Vec::with_capacity(members.len());
for m in members {
// Parity with the individual `POST /api/claws` handler — each
// claw counts against the workspace's agent quota + emits an
// audit row. Without these the auto-provision + team-wizard
// paths silently bypassed both governance rails.
crate::quota::enforce_new_agent(state, workspace_id).await?;
let agent = Agent {
id: AgentId::new(),
workspace_id,
@@ -109,6 +114,20 @@ pub(crate) async fn build_team_with_lifecycle(
status: AgentStatus::Online,
};
cm_db::repo::agents::insert(&state.pool, &agent, &AccessPolicy::default()).await?;
cm_db::repo::audit::append(
&state.pool,
workspace_id,
cm_db::repo::audit::Actor::User(user_id),
"agent.created",
"agent",
&agent.id.to_string(),
serde_json::json!({
"name": agent.name,
"job_title": agent.job_title,
"source": "team_wizard",
}),
)
.await?;
let claw_id = agent.id.as_uuid();
provisioner
.provision_claw(claw_id, &m.model)