Skip to content

Commit ef4a74c

Browse files
anj-sliamhelmer
authored andcommitted
feat (core): Implement tracker related SI changes (google-gemini#19964)
1 parent 073731f commit ef4a74c

File tree

6 files changed

+220
-7
lines changed

6 files changed

+220
-7
lines changed

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

Lines changed: 162 additions & 0 deletions
Large diffs are not rendered by default.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ describe('Core System Prompt (prompts.ts)', () => {
113113
}),
114114
getApprovalMode: vi.fn().mockReturnValue(ApprovalMode.DEFAULT),
115115
getApprovedPlanPath: vi.fn().mockReturnValue(undefined),
116+
isTrackerEnabled: vi.fn().mockReturnValue(false),
116117
} as unknown as Config;
117118
});
118119

@@ -223,6 +224,17 @@ describe('Core System Prompt (prompts.ts)', () => {
223224
expect(prompt).toMatchSnapshot();
224225
});
225226

227+
it('should include the TASK MANAGEMENT PROTOCOL when task tracker is enabled', () => {
228+
vi.mocked(mockConfig.getActiveModel).mockReturnValue(PREVIEW_GEMINI_MODEL);
229+
vi.mocked(mockConfig.isTrackerEnabled).mockReturnValue(true);
230+
const prompt = getCoreSystemPrompt(mockConfig);
231+
expect(prompt).toContain('# TASK MANAGEMENT PROTOCOL');
232+
expect(prompt).toContain(
233+
'**PLAN MODE INTEGRATION**: If an approved plan exists, you MUST use the `tracker_create_task` tool to decompose it into discrete tasks before writing any code',
234+
);
235+
expect(prompt).toMatchSnapshot();
236+
});
237+
226238
it('should use chatty system prompt for preview model', () => {
227239
vi.mocked(mockConfig.getActiveModel).mockReturnValue(PREVIEW_GEMINI_MODEL);
228240
const prompt = getCoreSystemPrompt(mockConfig);
@@ -400,6 +412,7 @@ describe('Core System Prompt (prompts.ts)', () => {
400412
getSkills: vi.fn().mockReturnValue([]),
401413
}),
402414
getApprovedPlanPath: vi.fn().mockReturnValue(undefined),
415+
isTrackerEnabled: vi.fn().mockReturnValue(false),
403416
} as unknown as Config;
404417

405418
const prompt = getCoreSystemPrompt(testConfig);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ describe('PromptProvider', () => {
5656
}),
5757
getApprovedPlanPath: vi.fn().mockReturnValue(undefined),
5858
getApprovalMode: vi.fn(),
59+
isTrackerEnabled: vi.fn().mockReturnValue(false),
5960
} as unknown as Config;
6061
});
6162

packages/core/src/prompts/promptProvider.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ export class PromptProvider {
159159
approvedPlan: approvedPlanPath
160160
? { path: approvedPlanPath }
161161
: undefined,
162+
taskTracker: config.isTrackerEnabled(),
162163
}),
163164
!isPlanMode,
164165
),
@@ -168,9 +169,11 @@ export class PromptProvider {
168169
planModeToolsList,
169170
plansDir: config.storage.getPlansDir(),
170171
approvedPlanPath: config.getApprovedPlanPath(),
172+
taskTracker: config.isTrackerEnabled(),
171173
}),
172174
isPlanMode,
173175
),
176+
taskTracker: config.isTrackerEnabled(),
174177
operationalGuidelines: this.withSection(
175178
'operationalGuidelines',
176179
() => ({

packages/core/src/prompts/snippets.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import {
2727
READ_FILE_PARAM_END_LINE,
2828
SHELL_PARAM_IS_BACKGROUND,
2929
EDIT_PARAM_OLD_STRING,
30+
TRACKER_CREATE_TASK_TOOL_NAME,
31+
TRACKER_LIST_TASKS_TOOL_NAME,
32+
TRACKER_UPDATE_TASK_TOOL_NAME,
3033
} from '../tools/tool-names.js';
3134
import type { HierarchicalMemory } from '../config/memory.js';
3235
import { DEFAULT_CONTEXT_FILENAME } from '../tools/memoryTool.js';
@@ -41,6 +44,7 @@ export interface SystemPromptOptions {
4144
hookContext?: boolean;
4245
primaryWorkflows?: PrimaryWorkflowsOptions;
4346
planningWorkflow?: PlanningWorkflowOptions;
47+
taskTracker?: boolean;
4448
operationalGuidelines?: OperationalGuidelinesOptions;
4549
sandbox?: SandboxMode;
4650
interactiveYoloMode?: boolean;
@@ -66,6 +70,7 @@ export interface PrimaryWorkflowsOptions {
6670
enableGrep: boolean;
6771
enableGlob: boolean;
6872
approvedPlan?: { path: string };
73+
taskTracker?: boolean;
6974
}
7075

7176
export interface OperationalGuidelinesOptions {
@@ -83,6 +88,7 @@ export interface PlanningWorkflowOptions {
8388
planModeToolsList: string;
8489
plansDir: string;
8590
approvedPlanPath?: string;
91+
taskTracker?: boolean;
8692
}
8793

8894
export interface AgentSkillOptions {
@@ -120,6 +126,8 @@ ${
120126
: renderPrimaryWorkflows(options.primaryWorkflows)
121127
}
122128
129+
${options.taskTracker ? renderTaskTracker() : ''}
130+
123131
${renderOperationalGuidelines(options.operationalGuidelines)}
124132
125133
${renderInteractiveYoloMode(options.interactiveYoloMode)}
@@ -464,6 +472,24 @@ ${trimmed}
464472
return `\n---\n\n<loaded_context>\n${sections.join('\n')}\n</loaded_context>`;
465473
}
466474

475+
export function renderTaskTracker(): string {
476+
const trackerCreate = formatToolName(TRACKER_CREATE_TASK_TOOL_NAME);
477+
const trackerList = formatToolName(TRACKER_LIST_TASKS_TOOL_NAME);
478+
const trackerUpdate = formatToolName(TRACKER_UPDATE_TASK_TOOL_NAME);
479+
480+
return `
481+
# TASK MANAGEMENT PROTOCOL
482+
You are operating with a persistent file-based task tracking system located at \`.tracker/tasks/\`. You must adhere to the following rules:
483+
484+
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.
485+
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}.
486+
3. **IGNORE FORMATTING BIAS**: Trigger the protocol based on the **objective complexity** of the goal, regardless of whether the user provided a structured list or a single block of text/paragraph. "Paragraph-style" goals that imply multiple actions are multi-step projects and MUST be tracked.
487+
4. **PLAN MODE INTEGRATION**: If an approved plan exists, you MUST use the ${trackerCreate} tool to decompose it into discrete tasks before writing any code. Maintain a bidirectional understanding between the plan document and the task graph.
488+
5. **VERIFICATION**: Before marking a task as complete, verify the work is actually done (e.g., run the test, check the file existence).
489+
6. **STATE OVER CHAT**: If the user says "I think we finished that," but the tool says it is 'pending', trust the tool--or verify explicitly before updating.
490+
7. **DEPENDENCY MANAGEMENT**: Respect task topology. Never attempt to execute a task if its dependencies are not marked as 'closed'. If you are blocked, focus only on the leaf nodes of the task graph.`.trim();
491+
}
492+
467493
export function renderPlanningWorkflow(
468494
options?: PlanningWorkflowOptions,
469495
): string {
@@ -583,6 +609,9 @@ function workflowStepStrategy(options: PrimaryWorkflowsOptions): string {
583609
if (options.approvedPlan) {
584610
return `2. **Strategy:** An approved plan is available for this task. Treat this file as your single source of truth. You MUST read this file before proceeding. If you discover new requirements or need to change the approach, confirm with the user and update this plan file to reflect the updated design decisions or discovered requirements. Once all implementation and verification steps are finished, provide a **final summary** of the work completed against the plan and offer clear **next steps** to the user (e.g., 'Open a pull request').`;
585611
}
612+
if (options.approvedPlan && options.taskTracker) {
613+
return `2. **Strategy:** An approved plan is available for this task. Treat this file as your single source of truth and invoke the task tracker tool to create tasks for this plan. You MUST read this file before proceeding. If you discover new requirements or need to change the approach, confirm with the user and update this plan file to reflect the updated design decisions or discovered requirements. Make sure to update the tracker task list based on this updated plan. Once all implementation and verification steps are finished, provide a **final summary** of the work completed against the plan and offer clear **next steps** to the user (e.g., 'Open a pull request').`;
614+
}
586615

587616
if (options.enableWriteTodosTool) {
588617
return `2. **Strategy:** Formulate a grounded plan based on your research.${

packages/core/src/tools/tool-names.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,18 @@ export const LS_TOOL_NAME_LEGACY = 'list_directory'; // Just to be safe if anyth
154154

155155
export const EDIT_TOOL_NAMES = new Set([EDIT_TOOL_NAME, WRITE_FILE_TOOL_NAME]);
156156

157-
export const TRACKER_CREATE_TASK_TOOL_NAME = 'tracker_create_task';
158-
export const TRACKER_UPDATE_TASK_TOOL_NAME = 'tracker_update_task';
159-
export const TRACKER_GET_TASK_TOOL_NAME = 'tracker_get_task';
160-
export const TRACKER_LIST_TASKS_TOOL_NAME = 'tracker_list_tasks';
161-
export const TRACKER_ADD_DEPENDENCY_TOOL_NAME = 'tracker_add_dependency';
162-
export const TRACKER_VISUALIZE_TOOL_NAME = 'tracker_visualize';
163-
164157
// Tool Display Names
165158
export const WRITE_FILE_DISPLAY_NAME = 'WriteFile';
166159
export const EDIT_DISPLAY_NAME = 'Edit';
167160
export const ASK_USER_DISPLAY_NAME = 'Ask User';
168161
export const READ_FILE_DISPLAY_NAME = 'ReadFile';
169162
export const GLOB_DISPLAY_NAME = 'FindFiles';
163+
export const TRACKER_CREATE_TASK_TOOL_NAME = 'tracker_create_task';
164+
export const TRACKER_UPDATE_TASK_TOOL_NAME = 'tracker_update_task';
165+
export const TRACKER_GET_TASK_TOOL_NAME = 'tracker_get_task';
166+
export const TRACKER_LIST_TASKS_TOOL_NAME = 'tracker_list_tasks';
167+
export const TRACKER_ADD_DEPENDENCY_TOOL_NAME = 'tracker_add_dependency';
168+
export const TRACKER_VISUALIZE_TOOL_NAME = 'tracker_visualize';
170169

171170
/**
172171
* Mapping of legacy tool names to their current names.
@@ -229,6 +228,12 @@ export const ALL_BUILTIN_TOOL_NAMES = [
229228
GET_INTERNAL_DOCS_TOOL_NAME,
230229
ENTER_PLAN_MODE_TOOL_NAME,
231230
EXIT_PLAN_MODE_TOOL_NAME,
231+
TRACKER_CREATE_TASK_TOOL_NAME,
232+
TRACKER_UPDATE_TASK_TOOL_NAME,
233+
TRACKER_GET_TASK_TOOL_NAME,
234+
TRACKER_LIST_TASKS_TOOL_NAME,
235+
TRACKER_ADD_DEPENDENCY_TOOL_NAME,
236+
TRACKER_VISUALIZE_TOOL_NAME,
232237
] as const;
233238

234239
/**

0 commit comments

Comments
 (0)