SC-3 Skill resolver swap (skillForEvent reads from DB) #625

Closed
opened 2026-05-01 10:33:24 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As a platform engineer, I want skillForEvent to route through the new resolver so dispatch picks up DB-stored skill overrides immediately, while /skills/*.md stays as the factory image and the existing delta-skill resume rule keeps working unchanged.

Acceptance criteria

Loader swap

  • apps/server/src/domain/analytics/skill-loader.ts::skillForEvent becomes:
    if (STATELESS_SKILLS.has(base)) return resolveSkill(base, agent);
    const stored = await getSession(...);
    if (!stored) return resolveSkill(base, agent);
    try { return await resolveSkill(`${base}-delta`, agent); }
    catch { return resolveSkill(base, agent); }
    
  • loadSkill(name) filesystem reader stays as the factory-image loader called by builtin-sync.ts only.
  • Verify dispatch entry points (agent-runner.ts, dispatch/*) consume skillForEvent and not loadSkill directly. Migrate any stragglers.

Legacy skill_overrides migration

  • agents.json::types[].skill_overrides becomes a no-op at runtime. builtin-sync reads the field, converts each entry into an agent_type-scope skill row whose body equals the contents of the named file in /skills/, then ignores the field on subsequent boots.
  • Migration logs a one-line warning per converted entry.
  • docs/agents-architecture.md documents the field as deprecated and points operators at the dashboard.

Tests

  • Existing apps/server/src/domain/analytics/skill-loader.test.ts cases re-pass against the resolver-backed implementation.
  • New unit: an agent_type-scope skill row shadows the builtin for the matching agent.
  • New unit: an instance-scope skill row shadows the agent-type one.
  • Migration test: agents.json::types[].skill_overrides = { review: "design-review" } produces an agent_type-scope skill row named review whose body is the contents of /skills/design-review.md.

Out of scope

  • Per-instance editing surface (SC-7+).
  • System-prompt template swap (SC-4).
  • Plugin / MCP swap (SC-5).

References

  • specs/agent-config-customization.md §Story SC-3
  • apps/server/src/domain/analytics/skill-loader.ts — primary swap site
  • apps/server/src/http/webhook-routing.ts::skillForAgent and the legacy skill_overrides resolution map
  • apps/server/src/shared/config/agents-config-schema.tsskill_overrides: z.record(z.string(), z.string()).optional()
  • Depends on SC-1.
## User story As a platform engineer, I want `skillForEvent` to route through the new resolver so dispatch picks up DB-stored skill overrides immediately, while `/skills/*.md` stays as the factory image and the existing delta-skill resume rule keeps working unchanged. ## Acceptance criteria ### Loader swap - [ ] `apps/server/src/domain/analytics/skill-loader.ts::skillForEvent` becomes: ```ts if (STATELESS_SKILLS.has(base)) return resolveSkill(base, agent); const stored = await getSession(...); if (!stored) return resolveSkill(base, agent); try { return await resolveSkill(`${base}-delta`, agent); } catch { return resolveSkill(base, agent); } ``` - [ ] `loadSkill(name)` filesystem reader stays as the factory-image loader called by `builtin-sync.ts` only. - [ ] Verify dispatch entry points (`agent-runner.ts`, `dispatch/*`) consume `skillForEvent` and not `loadSkill` directly. Migrate any stragglers. ### Legacy `skill_overrides` migration - [ ] `agents.json::types[].skill_overrides` becomes a no-op at runtime. `builtin-sync` reads the field, converts each entry into an `agent_type`-scope `skill` row whose body equals the contents of the named file in `/skills/`, then ignores the field on subsequent boots. - [ ] Migration logs a one-line warning per converted entry. - [ ] `docs/agents-architecture.md` documents the field as deprecated and points operators at the dashboard. ### Tests - [ ] Existing `apps/server/src/domain/analytics/skill-loader.test.ts` cases re-pass against the resolver-backed implementation. - [ ] New unit: an `agent_type`-scope skill row shadows the builtin for the matching agent. - [ ] New unit: an `instance`-scope skill row shadows the agent-type one. - [ ] Migration test: `agents.json::types[].skill_overrides = { review: "design-review" }` produces an `agent_type`-scope `skill` row named `review` whose body is the contents of `/skills/design-review.md`. ## Out of scope - Per-instance editing surface (SC-7+). - System-prompt template swap (SC-4). - Plugin / MCP swap (SC-5). ## References - `specs/agent-config-customization.md` §Story SC-3 - `apps/server/src/domain/analytics/skill-loader.ts` — primary swap site - `apps/server/src/http/webhook-routing.ts::skillForAgent` and the legacy `skill_overrides` resolution map - `apps/server/src/shared/config/agents-config-schema.ts` — `skill_overrides: z.record(z.string(), z.string()).optional()` - Depends on **SC-1**.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#625
No description provided.