FN-6107: always summarize untitled agent-created tasks

Ensure agent-created untitled tasks still request AI-generated titles even when project auto-summarization is disabled.

- force summarize=true for agent-created tasks that do not provide an explicit title
- add engine tests covering untitled, titled, and title-generation behavior with autoSummarizeTitles disabled
- document the agent-task summarization behavior in settings docs
- add a patch changeset for the published CLI package

Files changed:
 .changeset/agent-task-title-summaries.md          |  5 ++
 docs/settings-reference.md                        |  2 +-
 packages/engine/src/__tests__/agent-tools.test.ts | 63 +++++++++++++++++++++++
 packages/engine/src/agent-tools.ts                |  1 +
 4 files changed, 70 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-6107

Fusion-Task-Lineage: d0c25981-a5cb-48ca-b835-9267817b4edd
This commit is contained in:
gsxdsm
2026-06-09 11:40:54 -07:00
parent 94b7cf01bd
commit 934071cc3c
4 changed files with 70 additions and 1 deletions

View File

@@ -144,6 +144,7 @@ describe("createTaskCreateTool", () => {
dependencies: ["PROJ-001"],
column: "triage",
priority: undefined,
summarize: true,
source: undefined,
}, {
settings: { autoSummarizeTitles: false },
@@ -167,6 +168,7 @@ describe("createTaskCreateTool", () => {
expect(store.createTask).toHaveBeenCalledWith(expect.objectContaining({
priority: "high",
summarize: true,
}), expect.objectContaining({ settings: { autoSummarizeTitles: false } }));
});
@@ -220,6 +222,7 @@ describe("createTaskCreateTool", () => {
await tool.execute("call-1", { description: "Test" } as any, undefined, undefined, {} as any);
expect(store.createTask).toHaveBeenCalledWith(expect.objectContaining({
summarize: true,
source: {
sourceType: "agent_heartbeat",
sourceAgentId: "agent-123",
@@ -245,6 +248,7 @@ describe("createTaskCreateTool", () => {
await tool.execute("call-1", { description: "spawn follow-up" } as any, undefined, undefined, {} as any);
expect(store.createTask).toHaveBeenCalledWith(expect.objectContaining({
summarize: true,
source: {
sourceType: "agent_heartbeat",
sourceAgentId: "agent-123",
@@ -297,6 +301,65 @@ describe("createTaskCreateTool", () => {
expect(second.wasDuplicate).toBe(true);
expect(store.createTask).toHaveBeenCalledTimes(1);
});
it("passes summarize: true when no title provided", async () => {
const created = { id: "FN-201", description: "untitled follow-up", dependencies: [], column: "triage" };
const store = {
getSettings: vi.fn().mockResolvedValue({ autoSummarizeTitles: false }),
createTask: vi.fn().mockResolvedValue(created),
};
await createAgentTask(store as any, { description: "untitled follow-up" } as any);
expect(store.createTask).toHaveBeenCalledWith(expect.objectContaining({
description: "untitled follow-up",
summarize: true,
}), expect.objectContaining({ settings: { autoSummarizeTitles: false } }));
});
it("does not set summarize when title is provided", async () => {
const created = { id: "FN-202", title: "Explicit title", description: "titled follow-up", dependencies: [], column: "triage" };
const store = {
getSettings: vi.fn().mockResolvedValue({ autoSummarizeTitles: false }),
createTask: vi.fn().mockResolvedValue(created),
};
await createAgentTask(store as any, { title: "Explicit title", description: "titled follow-up" } as any);
expect(store.createTask).toHaveBeenCalledWith(expect.objectContaining({
title: "Explicit title",
summarize: undefined,
}), expect.objectContaining({ settings: { autoSummarizeTitles: false } }));
});
it("summarize triggers title generation even when autoSummarizeTitles is false", async () => {
const summarizeSpy = vi.spyOn(core, "summarizeTitle").mockResolvedValue("Generated title");
const created = { id: "FN-203", description: "untitled follow-up", dependencies: [], column: "triage" };
const store = {
getSettings: vi.fn().mockResolvedValue({
autoSummarizeTitles: false,
titleSummarizerProvider: "openai",
titleSummarizerModelId: "gpt-4o-mini",
}),
createTask: vi.fn().mockResolvedValue(created),
};
await createAgentTask(store as any, { description: "untitled follow-up" } as any, { rootDir: "/repo" });
const createInput = vi.mocked(store.createTask).mock.calls[0]?.[0];
const createOptions = vi.mocked(store.createTask).mock.calls[0]?.[1] as { onSummarize?: (description: string) => Promise<string | null> };
expect(createInput).toEqual(expect.objectContaining({
description: "untitled follow-up",
summarize: true,
}));
expect(createOptions).toEqual(expect.objectContaining({
settings: { autoSummarizeTitles: false },
}));
expect(createOptions.onSummarize).toBeTypeOf("function");
await expect(createOptions.onSummarize?.("Long agent-created task description")).resolves.toBe("Generated title");
expect(summarizeSpy).toHaveBeenCalledWith("Long agent-created task description", "/repo", "openai", "gpt-4o-mini");
summarizeSpy.mockRestore();
});
});
describe("createDelegateTaskTool", () => {

View File

@@ -779,6 +779,7 @@ export async function createAgentTask(
input.githubTracking?.enabled !== false && resolvedTracking.enabled;
const createInput: TaskCreateInput = {
...input,
summarize: !input.title?.trim() ? true : undefined,
source: nextSource,
githubTracking: shouldPrefillGithubTrackingEnabled
? {