slice 3.5d: agent_template_link + brain seed helper + skills merge
ci / gates (push) Successful in 4s
ci / frontend (push) Successful in 38s
ci / rust (push) Failing after 3m1s
ci / e2e (push) Skipped
ci / publish (push) Skipped

Ships the lineage layer that ties agents back to their team template
and wires the MCP skills server to actually merge template default
skills with per-agent overrides.

Migration 0050 adds `agent_template_link` (agent_id PK, template_id,
template_version, role_slot, seeded_at, created_at + indexes for
template/role lookups). Populated at agent-materialization time by
Slice 4's mission-launch orchestrator; read here by the skills MCP
server and by future level-up (Slice 8.5).

New Rust surface:
  - cm_db::repo::agent_template_link  (upsert / get / mark_seeded /
    agents_for_template — the last is what level-up's "prompt upgrade
    on template N+1" query needs)
  - cm_api::brain_seed::ingest(claw_id, seed_md, identity_prompt)
    opens cm_brain::ClawBrain on spawn_blocking, sets system_prompt
    on first touch, writes seed as agent_md, commits. Idempotent —
    skips when agent_md already populated.
  - cm_api::mcp_skills::mcp_skills tools/call now resolves the caller
    agent's template + role via agent_template_link and merges
    template default skills with per-agent overrides (was overrides-
    only in Slice 3.5b).
  - cm_api::team_template_loader now binds template_role_skills after
    upserting each template — looks up each declared skill by name,
    attaches with pin_in_context=true for foundation skills and the
    first two role skills. Missing skills log + skip.
  - Boot ordering: skills load BEFORE team templates so the binding
    lookup resolves.

Follow-up (Slice 4): mission-launch orchestrator calls brain_seed::ingest
+ agent_template_link::upsert when minting a team from a template.
Until that lands, the link is populated only by manual writes; the
MCP merge is silent-no-op for agents without a link (falls through
to overrides-only), which matches the pre-3.5d behavior.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-19 14:16:16 -07:00
co-authored by Claude Opus 4.7
parent 520a717dec
commit 85a97dffca
8 changed files with 290 additions and 20 deletions
+8 -14
View File
@@ -271,23 +271,17 @@ async fn run() -> Result<(), String> {
runtime.clone(),
std::time::Duration::from_secs(3),
);
// Load builtin team templates from disk into team_templates +
// template_roles. Idempotent per boot; edits to templates/teams/*.toml
// go live on the next deploy.
// Boot-time content loaders — skills first, then team templates
// (Slice 3.5d): the team_template_loader binds template_role_skills
// by looking up skills by name, so the skills catalog must be
// populated first. Both are idempotent per boot.
{
let pool = pool.clone();
tokio::spawn(async move {
let n = cm_api::team_template_loader::load_builtins(&pool).await;
eprintln!("team_template_loader: loaded {n} builtin team template(s)");
});
}
// Load builtin skills from skills/**/*.md into the skills catalog
// (Slice 3.5c). Same idempotent-per-boot semantics.
{
let pool = pool.clone();
tokio::spawn(async move {
let n = cm_api::skills_loader::load_builtins(&pool).await;
eprintln!("skills_loader: loaded {n} builtin skill(s)");
let n_skills = cm_api::skills_loader::load_builtins(&pool).await;
eprintln!("skills_loader: loaded {n_skills} builtin skill(s)");
let n_tpl = cm_api::team_template_loader::load_builtins(&pool).await;
eprintln!("team_template_loader: loaded {n_tpl} builtin team template(s)");
});
}
// Outbound-email delivery: drains the §15-gated `outbox` over SMTP. Inert