feat(FN-1511): apply skill selection to reviewer, merger, and heartbeat sessions
This commit is contained in:
@@ -905,6 +905,7 @@ export class HeartbeatMonitor {
|
||||
|
||||
// Lazy-load createKbAgent and promptWithFallback
|
||||
const { createKbAgent, promptWithFallback } = await import("./pi.js");
|
||||
const { buildSessionSkillContextSync } = await import("./session-skill-context.js");
|
||||
|
||||
// Build tools with task creation tracking and run context for mutation correlation
|
||||
const heartbeatTools = this.createHeartbeatTools(agentId, taskStore, taskId, runContext, audit);
|
||||
@@ -916,6 +917,9 @@ export class HeartbeatMonitor {
|
||||
agent: agent.role as AgentRole,
|
||||
});
|
||||
|
||||
// Build skill selection context for heartbeat session (uses waking agent's skills, no role fallback)
|
||||
const skillContext = buildSessionSkillContextSync(agent, "heartbeat", rootDir);
|
||||
|
||||
// Create agent session
|
||||
const { session } = await createKbAgent({
|
||||
cwd: rootDir,
|
||||
@@ -939,6 +943,8 @@ export class HeartbeatMonitor {
|
||||
toolCallCount++;
|
||||
agentLogger?.onToolEnd(name, isError, result);
|
||||
},
|
||||
// Skill selection: use waking agent's skills (heartbeat has no role fallback)
|
||||
...(skillContext.skillSelectionContext ? { skillSelection: skillContext.skillSelectionContext } : {}),
|
||||
});
|
||||
|
||||
// Track for monitoring
|
||||
|
||||
@@ -2339,6 +2339,7 @@ export class TaskExecutor {
|
||||
validatorFallbackModelId: settings.validatorFallbackModelId,
|
||||
store,
|
||||
taskId,
|
||||
task: detail,
|
||||
agentPrompts: settings.agentPrompts,
|
||||
agentStore: this.options.agentStore,
|
||||
rootDir: this.rootDir,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { join } from "node:path";
|
||||
import { getTaskMergeBlocker, type TaskStore, type MergeResult, type MergeDetails, type WorkflowStep, type WorkflowStepResult, type Settings, type AgentPromptsConfig } from "@fusion/core";
|
||||
import { resolveAgentPrompt } from "@fusion/core";
|
||||
import { createKbAgent, describeModel, promptWithFallback, compactSessionContext } from "./pi.js";
|
||||
import { buildSessionSkillContext } from "./session-skill-context.js";
|
||||
import type { WorktreePool } from "./worktree-pool.js";
|
||||
import { AgentLogger } from "./agent-logger.js";
|
||||
import { mergerLog } from "./logger.js";
|
||||
@@ -2018,6 +2019,22 @@ async function runAiAgentForCommit(params: AiAgentParams): Promise<{ success: bo
|
||||
mergerInstructions,
|
||||
);
|
||||
|
||||
// Build skill selection context (assigned agent skills take precedence over role fallback)
|
||||
let skillContext = undefined;
|
||||
if (options.agentStore) {
|
||||
try {
|
||||
const task = await store.getTask(taskId);
|
||||
skillContext = await buildSessionSkillContext({
|
||||
agentStore: options.agentStore,
|
||||
task,
|
||||
sessionPurpose: "merger",
|
||||
projectRootDir: rootDir,
|
||||
});
|
||||
} catch {
|
||||
// Graceful fallback - no skill selection
|
||||
}
|
||||
}
|
||||
|
||||
const { session } = await createKbAgent({
|
||||
cwd: rootDir,
|
||||
systemPrompt: mergerSystemPrompt,
|
||||
@@ -2030,6 +2047,8 @@ async function runAiAgentForCommit(params: AiAgentParams): Promise<{ success: bo
|
||||
defaultProvider: settings.defaultProvider,
|
||||
defaultModelId: settings.defaultModelId,
|
||||
defaultThinkingLevel: settings.defaultThinkingLevel,
|
||||
// Skill selection: use assigned agent skills if available, otherwise role fallback
|
||||
...(skillContext?.skillSelectionContext ? { skillSelection: skillContext.skillSelectionContext } : {}),
|
||||
});
|
||||
|
||||
options.onSession?.(session);
|
||||
@@ -2472,6 +2491,22 @@ If issues are found that need attention, describe them clearly.`;
|
||||
}
|
||||
const postMergeSystemPrompt = buildSystemPromptWithInstructions(systemPrompt, postMergeInstructions);
|
||||
|
||||
// Build skill selection context for post-merge session
|
||||
let postMergeSkillContext = undefined;
|
||||
if (mergeOptions.agentStore) {
|
||||
try {
|
||||
const task = await store.getTask(taskId);
|
||||
postMergeSkillContext = await buildSessionSkillContext({
|
||||
agentStore: mergeOptions.agentStore,
|
||||
task,
|
||||
sessionPurpose: "merger",
|
||||
projectRootDir: rootDir,
|
||||
});
|
||||
} catch {
|
||||
// Graceful fallback - no skill selection
|
||||
}
|
||||
}
|
||||
|
||||
const { session } = await createKbAgent({
|
||||
cwd: rootDir,
|
||||
systemPrompt: postMergeSystemPrompt,
|
||||
@@ -2481,6 +2516,8 @@ If issues are found that need attention, describe them clearly.`;
|
||||
fallbackProvider: settings.fallbackProvider,
|
||||
fallbackModelId: settings.fallbackModelId,
|
||||
defaultThinkingLevel: settings.defaultThinkingLevel,
|
||||
// Skill selection: use assigned agent skills if available, otherwise role fallback
|
||||
...(postMergeSkillContext?.skillSelectionContext ? { skillSelection: postMergeSkillContext.skillSelectionContext } : {}),
|
||||
});
|
||||
|
||||
mergerLog.log(`${taskId}: [post-merge] workflow step '${workflowStep.name}' using model ${describeModel(session)}${useOverride ? " (workflow step override)" : ""}`);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import type { TaskStore, TaskComment, AgentPromptsConfig } from "@fusion/core";
|
||||
import { resolveAgentPrompt } from "@fusion/core";
|
||||
import { createKbAgent, describeModel, promptWithFallback } from "./pi.js";
|
||||
import { buildSessionSkillContext } from "./session-skill-context.js";
|
||||
import { AgentLogger } from "./agent-logger.js";
|
||||
import { reviewerLog } from "./logger.js";
|
||||
import { checkSessionError } from "./usage-limit-detector.js";
|
||||
@@ -208,6 +209,8 @@ export interface ReviewOptions {
|
||||
store?: TaskStore;
|
||||
/** Task ID for agent log persistence. Required alongside `store`. */
|
||||
taskId?: string;
|
||||
/** Task with optional assignedAgentId for skill selection. */
|
||||
task?: { assignedAgentId?: string | null };
|
||||
/** User comments on the task (author === "user"). For spec reviews, the reviewer explicitly checks that every comment is addressed. */
|
||||
userComments?: TaskComment[];
|
||||
/** Agent prompt configuration for resolving custom reviewer prompts. */
|
||||
@@ -283,6 +286,21 @@ export async function reviewStep(
|
||||
reviewerInstructions,
|
||||
);
|
||||
|
||||
// Build skill selection context (assigned agent skills take precedence over role fallback)
|
||||
let skillContext = undefined;
|
||||
if (options.agentStore && options.rootDir) {
|
||||
try {
|
||||
skillContext = await buildSessionSkillContext({
|
||||
agentStore: options.agentStore,
|
||||
task: options.task ?? {},
|
||||
sessionPurpose: "reviewer",
|
||||
projectRootDir: options.rootDir,
|
||||
});
|
||||
} catch {
|
||||
// Graceful fallback - no skill selection
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn a reviewer agent with read-only tools
|
||||
const { session } = await createKbAgent({
|
||||
cwd,
|
||||
@@ -297,6 +315,8 @@ export async function reviewStep(
|
||||
fallbackProvider: validatorFallbackProvider,
|
||||
fallbackModelId: validatorFallbackModelId,
|
||||
defaultThinkingLevel: options.defaultThinkingLevel,
|
||||
// Skill selection: use assigned agent skills if available, otherwise role fallback
|
||||
...(skillContext?.skillSelectionContext ? { skillSelection: skillContext.skillSelectionContext } : {}),
|
||||
});
|
||||
|
||||
reviewerLog.log(`${taskId}: reviewer using model ${describeModel(session)}`);
|
||||
|
||||
@@ -1203,6 +1203,7 @@ export class TriageProcessor {
|
||||
defaultThinkingLevel: currentSettings.defaultThinkingLevel,
|
||||
store,
|
||||
taskId,
|
||||
task: currentDetail,
|
||||
userComments: currentUserComments.length > 0 ? currentUserComments : undefined,
|
||||
agentStore: this.options.agentStore,
|
||||
rootDir,
|
||||
|
||||
Reference in New Issue
Block a user