Wire skills into agent runs: org-scoped, published-only, org-preferred resolution
ISkillCatalog.GetByKeysAsync now takes the org id and resolves each key within that org's namespace only — the org's own published skill, else a shared builtin (null org), never another org's. Org-owned is preferred over the builtin; only Published (golden-tested) skills are injected; the resolved skill@version is recorded in the prompt heading and run trace. AgentRunExecutor threads context.OrganizationId. SeatsPage now loads the org library (builtins + authored + installed), dedupes to one entry per key, and flags drafts (won't run until published). Verified: ArchitectureTests 8/8, IntegrationTests 48/48 (new SkillRunScopingTests: a run assembles the org's own skill over the builtin of the same key, and another org's same-key skill never leaks in), client build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -105,7 +105,12 @@ export function SeatsPage() {
|
||||
if (!organizationId) return
|
||||
void run(async () => {
|
||||
setTeams(await api.get<Team[]>(`/api/orgboard/teams?organizationId=${organizationId}`))
|
||||
setSkills(await api.get<Skill[]>('/api/skills/'))
|
||||
// The org's library = shared builtins + its own authored/installed skills. The API returns
|
||||
// every version (newest first per key); collapse to one selectable entry per key.
|
||||
const lib = await api.get<Skill[]>(`/api/skills/?organizationId=${organizationId}`)
|
||||
const byKey = new Map<string, Skill>()
|
||||
for (const s of lib) if (!byKey.has(s.skillKey)) byKey.set(s.skillKey, s)
|
||||
setSkills([...byKey.values()])
|
||||
await loadConfigs()
|
||||
})
|
||||
}, [organizationId, loadConfigs, run])
|
||||
@@ -359,9 +364,9 @@ export function SeatsPage() {
|
||||
)}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{skills.map((skill) => (
|
||||
<button key={skill.skillKey} onClick={() => toggleSkill(skill.skillKey)}>
|
||||
<button key={skill.skillKey} onClick={() => toggleSkill(skill.skillKey)} title={skill.status !== 'Published' ? 'Draft — add roles + a golden test to publish before an agent can run it' : undefined}>
|
||||
<Badge variant={agent.skillKeys.includes(skill.skillKey) ? 'default' : 'outline'}>
|
||||
{skill.name}
|
||||
{skill.name}{skill.status !== 'Published' ? ' · draft' : ''}
|
||||
</Badge>
|
||||
</button>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user