From 883fd8e1180a43f89dacb6bb8ff38030d78f5954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 15:05:20 -0400 Subject: [PATCH] fix(skills): honor agent_skill_assignments in runtime skill projection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After Wave D1 switched to pi-coding-agent's loadSkills, the runtime ignored the per-agent assignment table entirely — every agent saw the full company catalog. The UI (SkillAgentToggles) still let users curate which skills each agent should see, so user decisions silently did nothing. Pi's progressive-disclosure model accepts a skillPaths list at load time. Use that to pass only assigned skills, preserving the user's curation while keeping the description-only prompt footprint. - listRuntimeSkillEntries reads db.listAgentSkillAssignments(agentId), filters company skills to the assigned set, passes only those paths to loadSkills. - Empty assignment set short-circuits (no SKILL.md scan, no prompt section). - connectorId parameter stays for signature compatibility; no current connector-specific policy applies. UI contract unchanged. Runtime now obeys it. --- src/main/skills/runtime.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/skills/runtime.ts b/src/main/skills/runtime.ts index 85d665d6..5406c100 100644 --- a/src/main/skills/runtime.ts +++ b/src/main/skills/runtime.ts @@ -19,21 +19,28 @@ interface RuntimeDeps { export function createSkillRuntime({ db, logger, skillsRoot, skillFilesDir, importFromLocal }: RuntimeDeps) { /** - * Project all company skills through pi-coding-agent's progressive-disclosure - * loader. Every agent in the company sees the full catalog — descriptions - * only, full SKILL.md loaded on-demand by the agent via the `read` tool. + * Project the agent's assigned skills through pi-coding-agent's + * progressive-disclosure loader. Users curate skill visibility per agent + * via `agent_skill_assignments`; runtime honors that selection by only + * passing assigned SKILL.md directories to `loadSkills`. Pi returns + * descriptions for the system prompt; the agent loads full SKILL.md + * on demand via the `read` tool. * - * The agentId / connectorId parameters are retained for signature - * compatibility with the orchestrator but are intentionally unused: pi's - * model has no per-agent filtering and no per-connector token budget. + * connectorId is retained for signature compatibility and reserved for + * future connector-specific policy (no current use). */ function listRuntimeSkillEntries( companyId: string, - _agentId: string, + agentId: string, _connectorId: string, ): ProjectedSkill[] { + const assignedIds = new Set(db.listAgentSkillAssignments(agentId)); + if (assignedIds.size === 0) return []; const companySkills = db.listCompanySkills(companyId); - const skillPaths = companySkills.map((s) => skillFilesDir(companyId, s.slug)); + const skillPaths = companySkills + .filter((s) => assignedIds.has(s.id)) + .map((s) => skillFilesDir(companyId, s.slug)); + if (skillPaths.length === 0) return []; const { skills, diagnostics } = loadSkills({ skillPaths, includeDefaults: false }); for (const diag of diagnostics) {