fix(workforce): a crew should not read as an alphabetical run

Seeding the name pick with the role index (0..n) started every crew at the top
of the pool and took the next free names, so the first mission after the switch
to per-mission crews hired Aarav, Abebe, Adaora, Adrian, Agnieszka. Unique and
correct, and transparently generated.

Seed from the claw's own uuid instead. UUIDv7 puts its random bytes LAST — the
leading bytes are a timestamp, which would cluster the same way — so the tail
is what spreads five picks across the whole pool.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-10 15:57:54 -07:00
co-authored by Claude Opus 5
parent 98037f9b3e
commit d3a398716b
2 changed files with 56 additions and 2 deletions
+19 -2
View File
@@ -495,8 +495,25 @@ async fn mint_team_from_template(
// choice that has now flipped twice, and the query is the hard part.
let reused: Option<uuid::Uuid> = None;
// Seed the name choice from the claw's OWN id, not its position in the
// team.
//
// Seeding with the role index (0..n) started every crew near the top of
// the pool and took the next free names, so the first mission hired
// Aarav, Abebe, Adaora, Adrian, Agnieszka — correct, unique, and
// transparently alphabetical. A crew should look like a team, not like
// a listing. UUIDv7 puts its random bytes LAST (the leading bytes are a
// timestamp, which would cluster again), so the tail is what spreads
// the five picks across the whole pool.
let agent_id = cm_domain::AgentId::new();
let name_seed = {
let uuid = agent_id.as_uuid();
let b = uuid.as_bytes();
u64::from_le_bytes([b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]])
};
let agent = Agent {
id: cm_domain::AgentId::new(),
id: agent_id,
workspace_id,
// A PERSON's name, with the role in `job_title`.
//
@@ -513,7 +530,7 @@ async fn mint_team_from_template(
// node carry the slot, so nothing downstream keys off the display
// name. Only the reused branch below ignores this, deliberately: a
// claw you already hired keeps the name it already had.
name: crate::agent_names::pick(&taken_names, idx as u64),
name: crate::agent_names::pick(&taken_names, name_seed),
job_title: role.slot.clone(),
// This is the ONLY consumer of the templates' `system_prompt` prose,
// and it feeds the *chat* path, not missions: it lands in