feat(FN-3706): gate research tools behind experimental feature

The merge introduces a research tool surface gating mechanism: shared availability helpers in core and engine, applied to the executor and triage agent so research prompts and tool exposure are gated behind experimental-feature flags, with tests covering the new logic.

Fusion-Task-Id: FN-3706
This commit is contained in:
Fusion
2026-05-07 15:50:20 -07:00
committed by gsxdsm
parent e3daa7b3b9
commit aaaebdcb0d
11 changed files with 231 additions and 24 deletions

View File

@@ -8,7 +8,6 @@ import type {
} from "@fusion/core";
import {
buildTriageMemoryInstructions,
isResearchExperimentalEnabled,
resolveAgentPrompt,
sortTasksByPriorityThenAgeAndId,
} from "@fusion/core";
@@ -56,6 +55,10 @@ import {
createTaskDocumentReadTool,
createTaskDocumentWriteTool,
} from "./agent-tools.js";
import {
getResearchGuidanceForSurface,
isResearchToolSurfaceEnabled,
} from "./tool-availability.js";
export const TRIAGE_SYSTEM_PROMPT = `You are a task specification agent for "fn", an AI-orchestrated task board.
@@ -244,10 +247,6 @@ When the planning conversation produces a structured plan, save it as a document
- Testing & Verification must run before Documentation & Delivery
- Avoid giant catch-all steps; split outcomes so execution can be verified incrementally
## Research tools
When spec work needs missing domain context, you may use research tools (\`fn_research_run\`, \`fn_research_list\`, \`fn_research_get\`, \`fn_research_cancel\`). Keep research bounded to the task at hand, prefer concise queries, and write durable findings into task documents when useful.
If research is unavailable or unconfigured, continue planning with repository context and clearly note assumptions.
## Guidelines
- Read the project structure and relevant source files to understand context BEFORE writing
- Check package.json/scripts and explicit project commands to align real lint/test/build/typecheck commands
@@ -951,7 +950,7 @@ export class TriageProcessor {
}),
createTaskDocumentWriteTool(this.store, task.id),
createTaskDocumentReadTool(this.store, task.id),
...(isResearchExperimentalEnabled(settings)
...(isResearchToolSurfaceEnabled(settings)
? createResearchTools({
store: this.store,
rootDir: this.rootDir,
@@ -1016,7 +1015,13 @@ export class TriageProcessor {
const triageSystemPrompt = buildSystemPromptWithInstructions(
resolveAgentPrompt("triage", settings.agentPrompts)
|| (isFast ? FAST_TRIAGE_SYSTEM_PROMPT : TRIAGE_SYSTEM_PROMPT),
[triageIdentitySection, triageInstructions].filter((section) => section.trim()).join("\n\n"),
[
triageIdentitySection,
triageInstructions,
isResearchToolSurfaceEnabled(settings)
? getResearchGuidanceForSurface("triage")
: "",
].filter((section) => section.trim()).join("\n\n"),
);
const triageContributions = this.options.pluginRunner
?.getPromptContributionsForSurface("triage")