feat(FN-4223): complete Step 4 — disambiguate research copy across surfaces

Fusion-Task-Id: FN-4223
Fusion-Task-Lineage: bc114ff2-ee0f-4e96-b1d2-6ba3112a48e4
This commit is contained in:
Fusion
2026-05-13 05:04:48 -07:00
committed by gsxdsm
parent e01a21889a
commit 789e0d96e4
4 changed files with 18 additions and 18 deletions

View File

@@ -287,16 +287,16 @@ Usage:
Create a GitHub PR for an in-review task
fn task import <owner/repo> [opts] Import GitHub issues as tasks
fn research create --query <text> [--wait] [--max-wait-ms <ms>] [--json]
Create and optionally wait for a research run
Create and optionally wait for a cited-research run (search/fetch/synthesis)
fn research list | ls [--status <status>] [--limit <n>] [--json]
List research runs
fn research show <run-id> [--json] Show research run details
List cited-research runs
fn research show <run-id> [--json] Show cited-research run details
fn research export <run-id> [--format <json|markdown|pdf>] [--output <path>] [--json]
Export research run results
Export cited-research run results
fn research cancel <run-id> [--json]
Cancel an active research run
Cancel an active cited-research run
fn research retry <run-id> [--json]
Retry a failed/cancelled research run
Retry a failed/cancelled cited-research run
fn mission create [title] [desc] Create a new mission
fn mission list | ls List missions
fn mission show | info <id> Show mission details

View File

@@ -127,7 +127,7 @@ export async function runResearchCreate(options: ResearchCreateOptions): Promise
if (options.json) {
jsonOut(run);
} else {
console.log(`Created research run ${runId}.`);
console.log(`Created cited-research run ${runId}.`);
if (run) printRun(run);
}
return;
@@ -179,7 +179,7 @@ export async function runResearchList(options: ResearchListOptions = {}): Promis
}
if (!runs.length) {
console.log("No research runs found.");
console.log("No cited-research runs found.");
return;
}
@@ -195,7 +195,7 @@ export async function runResearchShow(runId: string, options: ResearchCommandOpt
try {
const store = await getStore(options.projectName);
const run = store.getResearchStore().getRun(runId);
if (!run) throw new Error(`Research run not found: ${runId}`);
if (!run) throw new Error(`Cited-research run not found: ${runId}`);
if (options.json) {
jsonOut(run);
@@ -218,7 +218,7 @@ export async function runResearchExport(options: ResearchExportOptions): Promise
try {
const store = await getStore(options.projectName);
const run = store.getResearchStore().getRun(options.runId);
if (!run) throw new Error(`Research run not found: ${options.runId}`);
if (!run) throw new Error(`Cited-research run not found: ${options.runId}`);
const format = (options.format ?? "markdown") as ResearchExportFormat;
if (!RESEARCH_EXPORT_FORMATS.includes(format)) {
@@ -249,7 +249,7 @@ export async function runResearchCancel(runId: string, options: ResearchCommandO
try {
const store = await getStore(options.projectName);
const run = store.getResearchStore().getRun(runId);
if (!run) throw new Error(`Research run not found: ${runId}`);
if (!run) throw new Error(`Cited-research run not found: ${runId}`);
if (!["queued", "running", "cancelling", "retry_waiting"].includes(run.status)) {
throw new Error(`invalid-transition: Run ${runId} cannot be cancelled from status ${run.status}.`);
@@ -274,7 +274,7 @@ export async function runResearchRetry(runId: string, options: ResearchCommandOp
try {
const store = await getStore(options.projectName);
const existing = store.getResearchStore().getRun(runId);
if (!existing) throw new Error(`Research run not found: ${runId}`);
if (!existing) throw new Error(`Cited-research run not found: ${runId}`);
if (existing.status === "retry_exhausted" || existing.lifecycle?.errorCode === "RETRY_EXHAUSTED") {
throw new Error(`retry-exhausted: Run ${runId} has exhausted retry attempts.`);

View File

@@ -1474,7 +1474,7 @@ export default function kbExtension(pi: ExtensionAPI) {
pi.registerTool({
name: "fn_research_run",
label: "fn: Run Research",
description: "Start a bounded research run and optionally wait for findings.",
description: "Cited-research pipeline: create a bounded search/fetch/synthesis run (not an autonomous experiment loop) and optionally wait for completion.",
parameters: Type.Object({
query: Type.String({ description: "Research query or question" }),
wait_for_completion: Type.Optional(Type.Boolean({ description: "Wait for the run to complete before returning (default: false)" })),
@@ -1538,7 +1538,7 @@ export default function kbExtension(pi: ExtensionAPI) {
pi.registerTool({
name: "fn_research_list",
label: "fn: List Research Runs",
description: "List recent research runs.",
description: "Cited-research pipeline: list recent search/fetch/synthesis runs (not experiment-loop sessions)."
parameters: Type.Object({
status: Type.Optional(StringEnum([...RESEARCH_RUN_STATUSES], { description: "Filter by run status" }) as unknown as TSchema),
limit: Type.Optional(Type.Number({ description: "Max runs to return (default: 10)" })),
@@ -1562,7 +1562,7 @@ export default function kbExtension(pi: ExtensionAPI) {
pi.registerTool({
name: "fn_research_get",
label: "fn: Get Research Run",
description: "Get one research run and structured findings.",
description: "Cited-research pipeline: get one run with structured findings and citations (not experiment-loop state)."
parameters: Type.Object({ id: Type.String({ description: "Research run ID" }) }),
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
const store = await getStore(ctx.cwd);
@@ -1604,7 +1604,7 @@ export default function kbExtension(pi: ExtensionAPI) {
pi.registerTool({
name: "fn_research_cancel",
label: "fn: Cancel Research Run",
description: "Cancel an in-flight research run. Terminal runs return INVALID_TRANSITION.",
description: "Cited-research pipeline: cancel an in-flight run; terminal runs return INVALID_TRANSITION (does not control experiment loops)."
parameters: Type.Object({ id: Type.String({ description: "Research run ID" }) }),
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
const store = await getStore(ctx.cwd);
@@ -1666,7 +1666,7 @@ export default function kbExtension(pi: ExtensionAPI) {
pi.registerTool({
name: "fn_research_retry",
label: "fn: Retry Research Run",
description: "Retry a failed research run when lifecycle marks it retryable.",
description: "Cited-research pipeline: retry a failed run when lifecycle marks it retryable (not an autonomous experiment loop retry)."
parameters: Type.Object({ id: Type.String({ description: "Research run ID" }) }),
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
const store = await getStore(ctx.cwd);