fix(skills): honor agent_skill_assignments in runtime skill projection

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.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-17 15:05:20 -04:00
1 parent 14dc9a4897
commit 883fd8e118
1 file changed
+15 -8
+15 -8
View File
@@ -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) {