Skip to content

Commit aaab2bf

Browse files
refactor(task): switch to <feedback> wrapper to prevent focus drift after context-management event (condense/truncate) (#9237)
* refactor(task): wrap initial user message in <feedback> instead of <task> to prevent focus drift after context-management Rationale: After a successful context-management event, framing the next user block as feedback reduces model focus drift. Mentions parsing already supports <feedback>, and tool flows (attemptCompletion, responses) are aligned. No change to loop/persistence. * refactor(mentions): drop <task> parsing; standardize on <feedback>; update tests
1 parent ad1e9a8 commit aaab2bf

File tree

4 files changed

+22
-25
lines changed

4 files changed

+22
-25
lines changed

src/core/mentions/__tests__/processUserContentMentions.spec.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe("processUserContentMentions", () => {
3131
const userContent = [
3232
{
3333
type: "text" as const,
34-
text: "<task>Read file with limit</task>",
34+
text: "<feedback>Read file with limit</feedback>",
3535
},
3636
]
3737

@@ -45,7 +45,7 @@ describe("processUserContentMentions", () => {
4545
})
4646

4747
expect(parseMentions).toHaveBeenCalledWith(
48-
"<task>Read file with limit</task>",
48+
"<feedback>Read file with limit</feedback>",
4949
"/test",
5050
mockUrlContentFetcher,
5151
mockFileContextTracker,
@@ -61,7 +61,7 @@ describe("processUserContentMentions", () => {
6161
const userContent = [
6262
{
6363
type: "text" as const,
64-
text: "<task>Read file without limit</task>",
64+
text: "<feedback>Read file without limit</feedback>",
6565
},
6666
]
6767

@@ -74,7 +74,7 @@ describe("processUserContentMentions", () => {
7474
})
7575

7676
expect(parseMentions).toHaveBeenCalledWith(
77-
"<task>Read file without limit</task>",
77+
"<feedback>Read file without limit</feedback>",
7878
"/test",
7979
mockUrlContentFetcher,
8080
mockFileContextTracker,
@@ -90,7 +90,7 @@ describe("processUserContentMentions", () => {
9090
const userContent = [
9191
{
9292
type: "text" as const,
93-
text: "<task>Read unlimited lines</task>",
93+
text: "<feedback>Read unlimited lines</feedback>",
9494
},
9595
]
9696

@@ -104,7 +104,7 @@ describe("processUserContentMentions", () => {
104104
})
105105

106106
expect(parseMentions).toHaveBeenCalledWith(
107-
"<task>Read unlimited lines</task>",
107+
"<feedback>Read unlimited lines</feedback>",
108108
"/test",
109109
mockUrlContentFetcher,
110110
mockFileContextTracker,
@@ -118,11 +118,11 @@ describe("processUserContentMentions", () => {
118118
})
119119

120120
describe("content processing", () => {
121-
it("should process text blocks with <task> tags", async () => {
121+
it("should process text blocks with <feedback> tags", async () => {
122122
const userContent = [
123123
{
124124
type: "text" as const,
125-
text: "<task>Do something</task>",
125+
text: "<feedback>Do something</feedback>",
126126
},
127127
]
128128

@@ -136,7 +136,7 @@ describe("processUserContentMentions", () => {
136136
expect(parseMentions).toHaveBeenCalled()
137137
expect(result[0]).toEqual({
138138
type: "text",
139-
text: "parsed: <task>Do something</task>",
139+
text: "parsed: <feedback>Do something</feedback>",
140140
})
141141
})
142142

@@ -213,7 +213,7 @@ describe("processUserContentMentions", () => {
213213
content: [
214214
{
215215
type: "text" as const,
216-
text: "<task>Array task</task>",
216+
text: "<feedback>Array task</feedback>",
217217
},
218218
{
219219
type: "text" as const,
@@ -237,7 +237,7 @@ describe("processUserContentMentions", () => {
237237
content: [
238238
{
239239
type: "text",
240-
text: "parsed: <task>Array task</task>",
240+
text: "parsed: <feedback>Array task</feedback>",
241241
},
242242
{
243243
type: "text",
@@ -251,7 +251,7 @@ describe("processUserContentMentions", () => {
251251
const userContent = [
252252
{
253253
type: "text" as const,
254-
text: "<task>First task</task>",
254+
text: "<feedback>First task</feedback>",
255255
},
256256
{
257257
type: "image" as const,
@@ -280,7 +280,7 @@ describe("processUserContentMentions", () => {
280280
expect(result).toHaveLength(3)
281281
expect(result[0]).toEqual({
282282
type: "text",
283-
text: "parsed: <task>First task</task>",
283+
text: "parsed: <feedback>First task</feedback>",
284284
})
285285
expect(result[1]).toEqual(userContent[1]) // Image block unchanged
286286
expect(result[2]).toEqual({
@@ -296,7 +296,7 @@ describe("processUserContentMentions", () => {
296296
const userContent = [
297297
{
298298
type: "text" as const,
299-
text: "<task>Test default</task>",
299+
text: "<feedback>Test default</feedback>",
300300
},
301301
]
302302

@@ -308,7 +308,7 @@ describe("processUserContentMentions", () => {
308308
})
309309

310310
expect(parseMentions).toHaveBeenCalledWith(
311-
"<task>Test default</task>",
311+
"<feedback>Test default</feedback>",
312312
"/test",
313313
mockUrlContentFetcher,
314314
mockFileContextTracker,
@@ -324,7 +324,7 @@ describe("processUserContentMentions", () => {
324324
const userContent = [
325325
{
326326
type: "text" as const,
327-
text: "<task>Test explicit false</task>",
327+
text: "<feedback>Test explicit false</feedback>",
328328
},
329329
]
330330

@@ -337,7 +337,7 @@ describe("processUserContentMentions", () => {
337337
})
338338

339339
expect(parseMentions).toHaveBeenCalledWith(
340-
"<task>Test explicit false</task>",
340+
"<feedback>Test explicit false</feedback>",
341341
"/test",
342342
mockUrlContentFetcher,
343343
mockFileContextTracker,

src/core/mentions/processUserContentMentions.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export async function processUserContentMentions({
3030
// Process userContent array, which contains various block types:
3131
// TextBlockParam, ImageBlockParam, ToolUseBlockParam, and ToolResultBlockParam.
3232
// We need to apply parseMentions() to:
33-
// 1. All TextBlockParam's text (first user message with task)
33+
// 1. All TextBlockParam's text (first user message with feedback)
3434
// 2. ToolResultBlockParam's content/context text arrays if it contains
3535
// "<feedback>" (see formatToolDeniedFeedback, attemptCompletion,
3636
// executeCommand, and consecutiveMistakeCount >= 3) or "<answer>"
@@ -40,10 +40,7 @@ export async function processUserContentMentions({
4040
return Promise.all(
4141
userContent.map(async (block) => {
4242
const shouldProcessMentions = (text: string) =>
43-
text.includes("<task>") ||
44-
text.includes("<feedback>") ||
45-
text.includes("<answer>") ||
46-
text.includes("<user_message>")
43+
text.includes("<feedback>") || text.includes("<answer>") || text.includes("<user_message>")
4744

4845
if (block.type === "text") {
4946
if (shouldProcessMentions(block.text)) {

src/core/task/Task.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
12841284
await this.initiateTaskLoop([
12851285
{
12861286
type: "text",
1287-
text: `<task>\n${task}\n</task>`,
1287+
text: `<feedback>\n${task}\n</feedback>`,
12881288
},
12891289
...imageBlocks,
12901290
])

src/core/task/__tests__/Task.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ describe("Cline", () => {
895895
} as const,
896896
{
897897
type: "text",
898-
text: "<task>Text with 'some/path' (see below for file content) in task tags</task>",
898+
text: "<feedback>Text with 'some/path' (see below for file content) in task tags</feedback>",
899899
} as const,
900900
{
901901
type: "tool_result",
@@ -934,7 +934,7 @@ describe("Cline", () => {
934934
// Text within task tags should be processed
935935
expect((processedContent[1] as Anthropic.TextBlockParam).text).toContain("processed:")
936936
expect((processedContent[1] as Anthropic.TextBlockParam).text).toContain(
937-
"<task>Text with 'some/path' (see below for file content) in task tags</task>",
937+
"<feedback>Text with 'some/path' (see below for file content) in task tags</feedback>",
938938
)
939939

940940
// Feedback tag content should be processed

0 commit comments

Comments
 (0)