FN-6140: downgrade missing skill diagnostics to info
Reduce noise from missing requested skill messages in agent logs. - change missing requested skill diagnostics from warning to info in the skill resolver - update engine tests to expect info-level logging for unresolved requested skills - preserve the built-in fusion fallback behavior without emitting not-found diagnostics Files changed: packages/engine/src/__tests__/pi.test.ts | 6 ++-- packages/engine/src/__tests__/skill-resolver.test.ts | 42 +++++++++++----------- packages/engine/src/skill-resolver.ts | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) Fusion-Task-Id: FN-6140 Fusion-Task-Lineage: 3d2efdcd-8c6d-4fda-b5cb-b85421ac755e
This commit is contained in:
@@ -443,7 +443,7 @@ describe("createFnAgent skills parameter", () => {
|
||||
allowedSkillPaths: new Set(),
|
||||
excludedSkillPaths: new Set(),
|
||||
diagnostics: [
|
||||
{ type: "warning" as const, message: 'Requested skill "nonexistent-skill" not found in discovered skills' },
|
||||
{ type: "info" as const, message: 'Requested skill "nonexistent-skill" not found in discovered skills' },
|
||||
],
|
||||
filterActive: true,
|
||||
});
|
||||
@@ -458,8 +458,8 @@ describe("createFnAgent skills parameter", () => {
|
||||
|
||||
// The diagnostics should be logged
|
||||
expect(mockResolveSessionSkills).toHaveBeenCalled();
|
||||
expect(piWarnSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining("warning")
|
||||
expect(piLogSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining("info")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -601,7 +601,7 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
const result = override(base);
|
||||
|
||||
expect(result.diagnostics).toHaveLength(1); // Only CustomSkill not found
|
||||
expect(result.diagnostics[0].type).toBe("warning");
|
||||
expect(result.diagnostics[0].type).toBe("info");
|
||||
expect(result.diagnostics[0].message).toContain("CustomSkill");
|
||||
});
|
||||
|
||||
@@ -676,7 +676,7 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
|
||||
override(base);
|
||||
|
||||
const lastCall = mockPiLog.warn.mock.calls[mockPiLog.warn.mock.calls.length - 1][0] as string;
|
||||
const lastCall = mockPiLog.log.mock.calls[mockPiLog.log.mock.calls.length - 1][0] as string;
|
||||
expect(lastCall).toContain("[reviewer]");
|
||||
expect(lastCall).toContain("missing-skill");
|
||||
});
|
||||
@@ -803,7 +803,7 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
expect(result1.skills.map(s => s.name)).toEqual(["c", "a", "b"]);
|
||||
});
|
||||
|
||||
it("filters discovered Skill[] by requested names and logs warnings for missing skills", () => {
|
||||
it("filters discovered Skill[] by requested names and logs info diagnostics for missing skills", () => {
|
||||
// Create selection with empty allowed paths (only requested names filtering)
|
||||
const selection: SkillSelectionResult = {
|
||||
allowedSkillPaths: new Set<string>(),
|
||||
@@ -831,20 +831,20 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
expect(result.skills).toHaveLength(1);
|
||||
expect(result.skills[0].name).toBe("found-skill");
|
||||
|
||||
// Should produce warning for missing-skill
|
||||
const missingWarning = result.diagnostics.find(d =>
|
||||
d.type === "warning" && d.message.includes("missing-skill") && d.message.includes("not found in discovered skills")
|
||||
// Should produce info diagnostic for missing-skill
|
||||
const missingInfo = result.diagnostics.find(d =>
|
||||
d.type === "info" && d.message.includes("missing-skill") && d.message.includes("not found in discovered skills")
|
||||
);
|
||||
expect(missingWarning).toBeDefined();
|
||||
expect(missingInfo).toBeDefined();
|
||||
|
||||
// Verify structured logger warning output
|
||||
expect(mockPiLog.warn).toHaveBeenCalled();
|
||||
const loggedMessages = mockPiLog.warn.mock.calls.map(c => c[0] as string);
|
||||
// Verify structured logger info output
|
||||
expect(mockPiLog.log).toHaveBeenCalled();
|
||||
const loggedMessages = mockPiLog.log.mock.calls.map(c => c[0] as string);
|
||||
const hasExecutorPrefix = loggedMessages.some(m => m.includes("[executor]") && m.includes("missing-skill"));
|
||||
expect(hasExecutorPrefix).toBe(true);
|
||||
});
|
||||
|
||||
it("does not emit missing-skill warnings for built-in fusion fallback requests", () => {
|
||||
it("does not emit missing-skill info diagnostics for built-in fusion fallback requests", () => {
|
||||
const selection: SkillSelectionResult = {
|
||||
allowedSkillPaths: new Set<string>(),
|
||||
excludedSkillPaths: new Set<string>(),
|
||||
@@ -865,12 +865,12 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
expect(result.skills).toHaveLength(0);
|
||||
expect(
|
||||
result.diagnostics.find((d) =>
|
||||
d.type === "warning"
|
||||
d.type === "info"
|
||||
&& d.message.includes("Requested skill 'fusion' not found in discovered skills"),
|
||||
),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
mockPiLog.warn.mock.calls.some((c) => (c[0] as string).includes("Requested skill 'fusion' not found")),
|
||||
mockPiLog.log.mock.calls.some((c) => (c[0] as string).includes("Requested skill 'fusion' not found")),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
@@ -963,11 +963,11 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
expect(result.skills).toHaveLength(1);
|
||||
expect(result.skills[0].name).toBe("review");
|
||||
|
||||
// No missing-skill warnings since review exists and matches the pattern
|
||||
const missingWarnings = result.diagnostics.filter(d =>
|
||||
d.type === "warning" && d.message.includes("not found")
|
||||
// No missing-skill info diagnostics since review exists and matches the pattern
|
||||
const missingInfoDiagnostics = result.diagnostics.filter(d =>
|
||||
d.type === "info" && d.message.includes("not found")
|
||||
);
|
||||
expect(missingWarnings).toHaveLength(0);
|
||||
expect(missingInfoDiagnostics).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("matches Fusion two-segment patterns against pi-coding-agent bare skill names", () => {
|
||||
@@ -1008,11 +1008,11 @@ describe("createSkillsOverrideFromSelection", () => {
|
||||
expect(result.skills).toHaveLength(1);
|
||||
expect(result.skills[0].name).toBe("web-research");
|
||||
|
||||
// No spurious "not found" warnings
|
||||
const notFoundWarnings = result.diagnostics.filter(d =>
|
||||
d.type === "warning" && d.message.includes("not found")
|
||||
// No spurious "not found" info diagnostics
|
||||
const notFoundInfoDiagnostics = result.diagnostics.filter(d =>
|
||||
d.type === "info" && d.message.includes("not found")
|
||||
);
|
||||
expect(notFoundWarnings).toHaveLength(0);
|
||||
expect(notFoundInfoDiagnostics).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("exclusion patterns with /SKILL.md suffix correctly exclude pi-discovered skills", () => {
|
||||
|
||||
@@ -465,7 +465,7 @@ export function createSkillsOverrideFromSelection(
|
||||
) {
|
||||
const purpose = sessionPurpose ? ` [${sessionPurpose}]` : "";
|
||||
newDiagnostics.push({
|
||||
type: "warning",
|
||||
type: "info" as ResourceDiagnostic["type"],
|
||||
message: `Requested skill '${requestedName}' not found in discovered skills${purpose}`,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user