SC-1 Agent-config schema, migrations, builtin sync #623
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#623
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As a platform engineer, I want the per-kind tables, the shared revision/secret tables, the builtin-sync boot pass, and the resolver landed and unwired from any caller, so that every artifact is queryable from DB but production paths still consume the existing in-process config and we can layer the migration story-by-story behind a feature flag.
Acceptance criteria
Migration
apps/server/src/infrastructure/database/migrations/NNN-agent-config.tscreatesskill,system_prompt,plugin_binding,plugin_marketplace,mcp_server,agent_type_config,config_revision,secret,secret_access_logtables per the spec's schema block.idx_config_revision_lookupon(kind, artifact_id, created_at DESC),idx_secret_access_log_lookupon(secret_id, accessed_at DESC), plus per-tableUNIQUE(name, scope, agent_type, instance_id)covering uniqueness for skills / plugins / MCP / marketplaces / system prompts.agents(id) ON DELETE CASCADEfor everyinstance_idcolumn so dropping an instance reaps its overrides.Builtin sync
apps/server/src/domain/agent-config/builtin-sync.tsexportingsyncBuiltinsFromRepo(). Reads/skills/*.md,config/agents.json,config/mcp-builtin.json,config/marketplaces-builtin.json. Upsertsscope = 'builtin'rows; drift detection via sha256 stored asbuiltin_hash.config/mcp-builtin.jsonandconfig/marketplaces-builtin.jsonare seeded from the current~/.config/claude-hooks/agent-env/*/.claude.jsonandsettings.json. Secret values replaced by${SECRET:<NAME>}placeholders. Document the placeholder convention in the file headers.main.tscallssyncBuiltinsFromRepo()once during startup, after the migration runner.Resolver
apps/server/src/domain/agent-config/resolver.tsexportsresolveSkill,resolveSystemPrompt,resolvePlugins,resolveMarketplaces,resolveMcpServers.pickFromLadderhelper: returns the most-specific row acrossinstance → agent_type → global → builtin. First-match-wins for string-shaped artifacts.plugin_binding,mcp_server,plugin_marketplace): each layer adds rows; an instance-scope row withenabled = falsefor a plugin name shadows a higher layer's enabled row for the same name.Tests
pickFromLadderreturns the most-specific row across all four scope shapes, including null/skip cases.globalrow shadowsbuiltin,agent_typeshadowsglobal,instanceshadowsagent_type).enabled = falseshadows agent-typeenabled = truefor the same plugin name.Out of scope
loadSkill/system_prompt_templateconsumers (SC-3, SC-4).References
specs/agent-config-customization.md§Architecture and §Story SC-1apps/server/src/infrastructure/database/— existing migrations + DAOsapps/server/src/domain/analytics/skill-loader.ts—loadSkillfilesystem reader (consumed by builtin-sync)apps/server/src/shared/config/agents-config-schema.ts—agents.jsonschema (read by builtin-sync)