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:
gsxdsm
2026-06-09 15:50:53 -07:00
parent b7a56cc399
commit a57167e96a
3 changed files with 25 additions and 25 deletions

View File

@@ -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")
);
});
});

View File

@@ -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", () => {

View File

@@ -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}`,
});
}