Skip to content

Commit ee1b74c

Browse files
anj-skalenkevich
authored andcommitted
fix: update task tracker storage location in system prompt (google-gemini#24034)
1 parent 3a31f9a commit ee1b74c

7 files changed

Lines changed: 77 additions & 17 deletions

File tree

evals/tracker.eval.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,21 @@ describe('tracker_mode', () => {
113113
assertModelHasOutput(result);
114114
},
115115
});
116+
117+
evalTest('USUALLY_PASSES', {
118+
name: 'should correctly identify the task tracker storage location from the system prompt',
119+
params: {
120+
settings: { experimental: { taskTracker: true } },
121+
},
122+
prompt:
123+
'Where is my task tracker storage located? Please provide the absolute path in your response.',
124+
assert: async (rig, result) => {
125+
// The rig sets GEMINI_CLI_HOME to rig.homeDir
126+
const homeDir = rig.homeDir!;
127+
// The response should contain the dynamic path which includes the home directory
128+
// and follows the .gemini/tmp/.../tracker structure.
129+
expect(result).toContain(homeDir);
130+
expect(result).toMatch(/\.gemini\/tmp\/.*\/tracker/);
131+
},
132+
});
116133
});

packages/core/src/core/__snapshots__/prompts.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,7 +2899,7 @@ Use 'read_file' to understand context and validate any assumptions you may have.
28992899
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
29002900

29012901
# TASK MANAGEMENT PROTOCOL
2902-
You are operating with a persistent file-based task tracking system located at \`.tracker/tasks/\`. You must adhere to the following rules:
2902+
You are operating with a persistent file-based task tracking system located at \`/mock/.gemini/tmp/session/tracker\`. You must adhere to the following rules:
29032903

29042904
1. **NO IN-MEMORY LISTS**: Do not maintain a mental list of tasks or write markdown checkboxes in the chat. Use the provided tools (\`tracker_create_task\`, \`tracker_list_tasks\`, \`tracker_update_task\`) for all state management.
29052905
2. **IMMEDIATE DECOMPOSITION**: Upon receiving a task, evaluate its functional complexity and scope. If the request involves more than a single atomic modification, or necessitates research before execution, you MUST immediately decompose it into discrete entries using \`tracker_create_task\`.
@@ -3079,7 +3079,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
30793079
5. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback on the prototype.
30803080

30813081
# TASK MANAGEMENT PROTOCOL
3082-
You are operating with a persistent file-based task tracking system located at \`.tracker/tasks/\`. You must adhere to the following rules:
3082+
You are operating with a persistent file-based task tracking system located at \`/mock/.gemini/tmp/session/tracker\`. You must adhere to the following rules:
30833083

30843084
1. **NO IN-MEMORY LISTS**: Do not maintain a mental list of tasks or write markdown checkboxes in the chat. Use the provided tools (\`tracker_create_task\`, \`tracker_list_tasks\`, \`tracker_update_task\`) for all state management.
30853085
2. **IMMEDIATE DECOMPOSITION**: Upon receiving a task, evaluate its functional complexity and scope. If the request involves more than a single atomic modification, or necessitates research before execution, you MUST immediately decompose it into discrete entries using \`tracker_create_task\`.

packages/core/src/core/prompts.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ describe('Core System Prompt (prompts.ts)', () => {
9393
storage: {
9494
getProjectTempDir: vi.fn().mockReturnValue('/tmp/project-temp'),
9595
getPlansDir: vi.fn().mockReturnValue('/tmp/project-temp/plans'),
96+
getProjectTempTrackerDir: vi
97+
.fn()
98+
.mockReturnValue('/mock/.gemini/tmp/session/tracker'),
9699
},
97100
isInteractive: vi.fn().mockReturnValue(true),
98101
isInteractiveShellEnabled: vi.fn().mockReturnValue(true),

packages/core/src/prompts/promptProvider.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ describe('PromptProvider', () => {
6464
storage: {
6565
getProjectTempDir: vi.fn().mockReturnValue('/tmp/project-temp'),
6666
getPlansDir: vi.fn().mockReturnValue('/tmp/project-temp/plans'),
67+
getProjectTempTrackerDir: vi
68+
.fn()
69+
.mockReturnValue('/tmp/project-temp/tracker'),
6770
},
6871
isInteractive: vi.fn().mockReturnValue(true),
6972
isInteractiveShellEnabled: vi.fn().mockReturnValue(true),
@@ -104,6 +107,36 @@ describe('PromptProvider', () => {
104107
);
105108
});
106109

110+
it('should include the task tracker storage location in the system prompt', () => {
111+
vi.mocked(mockConfig.isTrackerEnabled).mockReturnValue(true);
112+
const mockTrackerDir = '/mock/tracker/path';
113+
vi.mocked(mockConfig.storage.getProjectTempTrackerDir).mockReturnValue(
114+
mockTrackerDir,
115+
);
116+
117+
const provider = new PromptProvider();
118+
const prompt = provider.getCoreSystemPrompt(mockConfig);
119+
120+
expect(prompt).toContain('# TASK MANAGEMENT PROTOCOL');
121+
expect(prompt).toContain(`located at \`${mockTrackerDir}\``);
122+
});
123+
124+
it('should sanitize the task tracker storage location in the system prompt', () => {
125+
vi.mocked(mockConfig.isTrackerEnabled).mockReturnValue(true);
126+
const mockTrackerDir = '/mock/tracker/path\nwith-newline]and-bracket';
127+
vi.mocked(mockConfig.storage.getProjectTempTrackerDir).mockReturnValue(
128+
mockTrackerDir,
129+
);
130+
131+
const provider = new PromptProvider();
132+
const prompt = provider.getCoreSystemPrompt(mockConfig);
133+
134+
expect(prompt).toContain('# TASK MANAGEMENT PROTOCOL');
135+
expect(prompt).toContain(
136+
'located at `/mock/tracker/path with-newlineand-bracket`',
137+
);
138+
});
139+
107140
it('should handle multiple context filenames in user memory section', () => {
108141
vi.mocked(getAllGeminiMdFilenames).mockReturnValue([
109142
DEFAULT_CONTEXT_FILENAME,

packages/core/src/prompts/promptProvider.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ export class PromptProvider {
7272
const activeSnippets = isModernModel ? snippets : legacySnippets;
7373
const contextFilenames = getAllGeminiMdFilenames();
7474

75+
let trackerDir = context.config.isTrackerEnabled()
76+
? context.config.storage.getProjectTempTrackerDir()
77+
: undefined;
78+
79+
if (trackerDir) {
80+
// Sanitize path to prevent prompt injection
81+
trackerDir = trackerDir.replace(/\n/g, ' ').replace(/\]/g, '');
82+
}
83+
84+
// --- Context Gathering ---
7585
let planModeToolsList = '';
7686
if (isPlanMode) {
7787
const allTools = context.toolRegistry.getAllTools();
@@ -149,7 +159,7 @@ export class PromptProvider {
149159
})),
150160
skills.length > 0,
151161
),
152-
taskTracker: context.config.isTrackerEnabled(),
162+
taskTracker: trackerDir,
153163
hookContext: isSectionEnabled('hookContext') || undefined,
154164
primaryWorkflows: this.withSection(
155165
'primaryWorkflows',
@@ -167,7 +177,7 @@ export class PromptProvider {
167177
approvedPlan: approvedPlanPath
168178
? { path: approvedPlanPath }
169179
: undefined,
170-
taskTracker: context.config.isTrackerEnabled(),
180+
taskTracker: trackerDir,
171181
topicUpdateNarration:
172182
context.config.isTopicUpdateNarrationEnabled(),
173183
}),
@@ -180,7 +190,6 @@ export class PromptProvider {
180190
planModeToolsList,
181191
plansDir: context.config.storage.getPlansDir(),
182192
approvedPlanPath: context.config.getApprovedPlanPath(),
183-
taskTracker: context.config.isTrackerEnabled(),
184193
}),
185194
isPlanMode,
186195
),

packages/core/src/prompts/snippets.legacy.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export interface SystemPromptOptions {
3737
hookContext?: boolean;
3838
primaryWorkflows?: PrimaryWorkflowsOptions;
3939
planningWorkflow?: PlanningWorkflowOptions;
40-
taskTracker?: boolean;
40+
taskTracker?: string;
4141
operationalGuidelines?: OperationalGuidelinesOptions;
4242
sandbox?: SandboxOptions;
4343
interactiveYoloMode?: boolean;
@@ -63,7 +63,7 @@ export interface PrimaryWorkflowsOptions {
6363
enableWriteTodosTool: boolean;
6464
enableEnterPlanModeTool: boolean;
6565
approvedPlan?: { path: string };
66-
taskTracker?: boolean;
66+
taskTracker?: string;
6767
topicUpdateNarration?: boolean;
6868
}
6969

@@ -95,7 +95,6 @@ export interface PlanningWorkflowOptions {
9595
planModeToolsList: string;
9696
plansDir: string;
9797
approvedPlanPath?: string;
98-
taskTracker?: boolean;
9998
}
10099

101100
export interface AgentSkillOptions {
@@ -132,7 +131,7 @@ ${
132131
: renderPrimaryWorkflows(options.primaryWorkflows)
133132
}
134133
135-
${options.taskTracker ? renderTaskTracker() : ''}
134+
${options.taskTracker ? renderTaskTracker(options.taskTracker) : ''}
136135
137136
${renderOperationalGuidelines(options.operationalGuidelines)}
138137
@@ -491,10 +490,10 @@ An approved plan is available for this task.
491490
`;
492491
}
493492

494-
export function renderTaskTracker(): string {
493+
export function renderTaskTracker(trackerDir: string): string {
495494
return `
496495
# TASK MANAGEMENT PROTOCOL
497-
You are operating with a persistent file-based task tracking system located at \`.tracker/tasks/\`. You must adhere to the following rules:
496+
You are operating with a persistent file-based task tracking system located at \`${trackerDir}\`. You must adhere to the following rules:
498497
499498
1. **NO IN-MEMORY LISTS**: Do not maintain a mental list of tasks or write markdown checkboxes in the chat. Use the provided tools (\`${TRACKER_CREATE_TASK_TOOL_NAME}\`, \`${TRACKER_LIST_TASKS_TOOL_NAME}\`, \`${TRACKER_UPDATE_TASK_TOOL_NAME}\`) for all state management.
500499
2. **IMMEDIATE DECOMPOSITION**: Upon receiving a task, evaluate its functional complexity and scope. If the request involves more than a single atomic modification, or necessitates research before execution, you MUST immediately decompose it into discrete entries using \`${TRACKER_CREATE_TASK_TOOL_NAME}\`.

packages/core/src/prompts/snippets.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export interface SystemPromptOptions {
4747
hookContext?: boolean;
4848
primaryWorkflows?: PrimaryWorkflowsOptions;
4949
planningWorkflow?: PlanningWorkflowOptions;
50-
taskTracker?: boolean;
50+
taskTracker?: string;
5151
operationalGuidelines?: OperationalGuidelinesOptions;
5252
sandbox?: SandboxOptions;
5353
interactiveYoloMode?: boolean;
@@ -74,7 +74,7 @@ export interface PrimaryWorkflowsOptions {
7474
enableGrep: boolean;
7575
enableGlob: boolean;
7676
approvedPlan?: { path: string };
77-
taskTracker?: boolean;
77+
taskTracker?: string;
7878
topicUpdateNarration: boolean;
7979
}
8080

@@ -101,7 +101,6 @@ export interface PlanningWorkflowOptions {
101101
planModeToolsList: string;
102102
plansDir: string;
103103
approvedPlanPath?: string;
104-
taskTracker?: boolean;
105104
}
106105

107106
export interface AgentSkillOptions {
@@ -139,7 +138,7 @@ ${
139138
: renderPrimaryWorkflows(options.primaryWorkflows)
140139
}
141140
142-
${options.taskTracker ? renderTaskTracker() : ''}
141+
${options.taskTracker ? renderTaskTracker(options.taskTracker) : ''}
143142
144143
${renderOperationalGuidelines(options.operationalGuidelines)}
145144
@@ -537,14 +536,14 @@ ${trimmed}
537536
return `\n---\n\n<loaded_context>\n${sections.join('\n')}\n</loaded_context>`;
538537
}
539538

540-
export function renderTaskTracker(): string {
539+
export function renderTaskTracker(trackerDir: string): string {
541540
const trackerCreate = formatToolName(TRACKER_CREATE_TASK_TOOL_NAME);
542541
const trackerList = formatToolName(TRACKER_LIST_TASKS_TOOL_NAME);
543542
const trackerUpdate = formatToolName(TRACKER_UPDATE_TASK_TOOL_NAME);
544543

545544
return `
546545
# TASK MANAGEMENT PROTOCOL
547-
You are operating with a persistent file-based task tracking system located at \`.tracker/tasks/\`. You must adhere to the following rules:
546+
You are operating with a persistent file-based task tracking system located at \`${trackerDir}\`. You must adhere to the following rules:
548547
549548
1. **NO IN-MEMORY LISTS**: Do not maintain a mental list of tasks or write markdown checkboxes in the chat. Use the provided tools (${trackerCreate}, ${trackerList}, ${trackerUpdate}) for all state management.
550549
2. **IMMEDIATE DECOMPOSITION**: Upon receiving a task, evaluate its functional complexity and scope. If the request involves more than a single atomic modification, or necessitates research before execution, you MUST immediately decompose it into discrete entries using ${trackerCreate}.

0 commit comments

Comments
 (0)