Remove the blanket loop that auto-activated every visible skill whose name/description substring-matched tokens from extraContext and taskPlanContent. This caused 32+ irrelevant skills (xcode-build, ableton-lom, etc.) to load every auto-mode turn. Skill activation now uses only explicit preference sources: always_use_skills, skill_rules, prefer_skills, and skills_used from task plan frontmatter. Closes #2239 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e0c203c3e4
commit
e7e22d5eca
2 changed files with 56 additions and 11 deletions
|
|
@ -420,8 +420,6 @@ export function buildSkillActivationBlock(params: {
|
|||
params.sliceTitle,
|
||||
params.taskId,
|
||||
params.taskTitle,
|
||||
...(params.extraContext ?? []),
|
||||
params.taskPlanContent ?? undefined,
|
||||
);
|
||||
|
||||
const visibleSkills = (typeof getLoadedSkills === 'function' ? getLoadedSkills() : []).filter(skill => !skill.disableModelInvocation);
|
||||
|
|
@ -452,12 +450,6 @@ export function buildSkillActivationBlock(params: {
|
|||
}
|
||||
}
|
||||
|
||||
for (const skill of visibleSkills) {
|
||||
if (skillMatchesContext(skill, contextTokens)) {
|
||||
matched.add(normalizeSkillReference(skill.name));
|
||||
}
|
||||
}
|
||||
|
||||
const ordered = [...matched]
|
||||
.filter(name => installedNames.has(name) && !avoided.has(name))
|
||||
.sort();
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ function buildBlock(
|
|||
});
|
||||
}
|
||||
|
||||
test("buildSkillActivationBlock matches installed skills from task context", () => {
|
||||
test("buildSkillActivationBlock does not auto-activate skills via broad context heuristic", () => {
|
||||
const base = makeTempBase();
|
||||
try {
|
||||
writeSkill(base, "react", "Use for React components, hooks, JSX, and frontend UI work.");
|
||||
|
|
@ -52,7 +52,29 @@ test("buildSkillActivationBlock matches installed skills from task context", ()
|
|||
taskTitle: "Implement React settings panel",
|
||||
});
|
||||
|
||||
assert.match(result, /<skill_activation>/);
|
||||
// Skills should not be activated just because their name appears in task context.
|
||||
// Activation requires explicit preference sources (always_use, skill_rules, prefer_skills, skills_used).
|
||||
assert.equal(result, "");
|
||||
} finally {
|
||||
cleanup(base);
|
||||
}
|
||||
});
|
||||
|
||||
test("buildSkillActivationBlock activates skills via prefer_skills when context matches", () => {
|
||||
const base = makeTempBase();
|
||||
try {
|
||||
writeSkill(base, "react", "Use for React components, hooks, JSX, and frontend UI work.");
|
||||
writeSkill(base, "swiftui", "Use for SwiftUI views, iOS layout, and Apple platform UI work.");
|
||||
loadOnlyTestSkills(base);
|
||||
|
||||
const result = buildBlock(base, {
|
||||
sliceTitle: "Build React dashboard",
|
||||
taskId: "T01",
|
||||
taskTitle: "Implement React settings panel",
|
||||
}, {
|
||||
prefer_skills: ["react"],
|
||||
});
|
||||
|
||||
assert.match(result, /Call Skill\('react'\)/);
|
||||
assert.doesNotMatch(result, /swiftui/);
|
||||
} finally {
|
||||
|
|
@ -105,7 +127,7 @@ test("buildSkillActivationBlock includes skill_rules matches and task-plan skill
|
|||
}
|
||||
});
|
||||
|
||||
test("buildSkillActivationBlock honors avoid_skills", () => {
|
||||
test("buildSkillActivationBlock honors avoid_skills against always_use_skills", () => {
|
||||
const base = makeTempBase();
|
||||
try {
|
||||
writeSkill(base, "react", "Use for React components and frontend UI work.");
|
||||
|
|
@ -114,6 +136,7 @@ test("buildSkillActivationBlock honors avoid_skills", () => {
|
|||
const result = buildBlock(base, {
|
||||
taskTitle: "Implement React settings panel",
|
||||
}, {
|
||||
always_use_skills: ["react"],
|
||||
avoid_skills: ["react"],
|
||||
});
|
||||
|
||||
|
|
@ -138,3 +161,33 @@ test("buildSkillActivationBlock falls back cleanly when nothing matches", () =>
|
|||
cleanup(base);
|
||||
}
|
||||
});
|
||||
|
||||
test("buildSkillActivationBlock does not activate skills from extraContext or taskPlanContent body", () => {
|
||||
const base = makeTempBase();
|
||||
try {
|
||||
writeSkill(base, "xcode-build", "Use for Xcode build workflows and iOS compilation.");
|
||||
writeSkill(base, "ableton-lom", "Use for Ableton Live Object Model scripting.");
|
||||
writeSkill(base, "frontend-design", "Use for frontend design systems and UI components.");
|
||||
loadOnlyTestSkills(base);
|
||||
|
||||
const taskPlan = [
|
||||
"---",
|
||||
"skills_used: []",
|
||||
"---",
|
||||
"# T01: Build the API endpoint",
|
||||
"Use xcode-build patterns and frontend-design tokens.",
|
||||
].join("\n");
|
||||
|
||||
const result = buildBlock(base, {
|
||||
taskTitle: "Build REST API",
|
||||
extraContext: ["Build workflow for iOS and Ableton integration testing"],
|
||||
taskPlanContent: taskPlan,
|
||||
});
|
||||
|
||||
// None of these skills should activate — extraContext and taskPlanContent body
|
||||
// must not be used for heuristic matching.
|
||||
assert.equal(result, "");
|
||||
} finally {
|
||||
cleanup(base);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue