feat(engine): scope skill loading by session purpose to reduce token overhead

This commit is contained in:
Matthew Greenberg
2026-05-08 20:00:08 -04:00
parent 39e57cbb88
commit 048a03b86b
2 changed files with 82 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
import { describe, it, expect } from "vitest";
import { getSkillPurposeFilter } from "../skill-resolver.js";
describe("getSkillPurposeFilter", () => {
it("returns a pass-all filter for executor sessions", () => {
const filter = getSkillPurposeFilter("executor");
expect(filter("any-skill")).toBe(true);
expect(filter("fusion")).toBe(true);
expect(filter("deployment")).toBe(true);
});
it("filters to review-relevant skills for reviewer sessions", () => {
const filter = getSkillPurposeFilter("reviewer");
expect(filter("code-review")).toBe(true);
expect(filter("security-review")).toBe(true);
expect(filter("review")).toBe(true);
expect(filter("deployment")).toBe(false);
expect(filter("fusion")).toBe(false);
});
it("returns a pass-all filter for unknown session purposes", () => {
const filter = getSkillPurposeFilter("unknown-purpose");
expect(filter("any-skill")).toBe(true);
});
it("filters to minimal skills for heartbeat sessions", () => {
const filter = getSkillPurposeFilter("heartbeat");
expect(filter("monitoring")).toBe(true);
expect(filter("heartbeat")).toBe(true);
expect(filter("fusion")).toBe(false);
expect(filter("code-review")).toBe(false);
});
it("returns a pass-all filter for triage sessions", () => {
const filter = getSkillPurposeFilter("triage");
expect(filter("any-skill")).toBe(true);
expect(filter("fusion")).toBe(true);
});
});

View File

@@ -484,3 +484,46 @@ export function createSkillsOverrideFromSelection(
};
};
}
/**
* Skills that are relevant to each session purpose. Executors get all
* skills (they do the implementation work). Other roles get a scoped
* subset to avoid loading 71KB of reference material for every session.
*
* The filter matches against the skill's directory name (the last path
* segment before SKILL.md).
*/
const REVIEWER_SKILL_ALLOWLIST = new Set([
"code-review",
"security-review",
"review",
]);
const HEARTBEAT_SKILL_ALLOWLIST = new Set([
"monitoring",
"heartbeat",
]);
/**
* Return a filter function that decides whether a skill (by name) should
* be included in a session of the given purpose.
*
* - "executor" and "triage": all skills (pass-through)
* - "reviewer": only review-related skills
* - "heartbeat": only monitoring-related skills
* - unknown: all skills (safe fallback)
*/
export function getSkillPurposeFilter(
sessionPurpose: string,
): (skillName: string) => boolean {
switch (sessionPurpose) {
case "reviewer":
return (name) => REVIEWER_SKILL_ALLOWLIST.has(name);
case "heartbeat":
return (name) => HEARTBEAT_SKILL_ALLOWLIST.has(name);
case "executor":
case "triage":
default:
return () => true;
}
}