Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions src/agents/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import { CUSTOM_MODELS } from '../config/customModels.js';
import { getIterationTrailingMessage } from '../config/hintConfig.js';
import { getRateLimitForModel } from '../config/rateLimits.js';
import { getRetryConfig } from '../config/retryConfig.js';
import { EditFile } from '../gadgets/EditFile.js';
import { FileInsertContent } from '../gadgets/FileInsertContent.js';
import { FileRemoveContent } from '../gadgets/FileRemoveContent.js';
import { FileSearchAndReplace } from '../gadgets/FileSearchAndReplace.js';
import { Finish } from '../gadgets/Finish.js';
import { ListDirectory } from '../gadgets/ListDirectory.js';
import { ReadFile } from '../gadgets/ReadFile.js';
import { Sleep } from '../gadgets/Sleep.js';
import { CreatePR } from '../gadgets/github/index.js';
import { initSessionState } from '../gadgets/sessionState.js';
import { Tmux } from '../gadgets/tmux.js';
import { TodoDelete, TodoUpdateStatus, TodoUpsert } from '../gadgets/todo/index.js';
import {
Expand Down Expand Up @@ -274,6 +277,9 @@ function createAgentBuilderWithGadgets(
llmCallLogger: import('../utils/llmLogging.js').LLMCallLogger,
repoDir: string,
): BuilderType {
// Initialize session state for gadgets (e.g., Finish checks PR requirement for implementation)
initSessionState(agentType);

// Check if AU features should be enabled (repo has .au file at root)
const auEnabled = existsSync(join(repoDir, '.au'));

Expand All @@ -285,7 +291,14 @@ function createAgentBuilderWithGadgets(
// Filesystem gadgets (read-only for planning)
new ListDirectory(),
new ReadFile(),
...(isReadOnlyAgent ? [] : [new EditFile(), new WriteFile()]),
...(isReadOnlyAgent
? []
: [
new FileSearchAndReplace(),
new FileInsertContent(),
new FileRemoveContent(),
new WriteFile(),
]),
// Shell commands via tmux (no timeout issues)
new Tmux(),
new Sleep(),
Expand Down Expand Up @@ -332,7 +345,7 @@ function createAgentBuilderWithGadgets(
.withGadgets(...allGadgets);

// Implementation agent uses sequential execution to ensure file operations
// are properly ordered (e.g., EditFile then ReadFile on same file)
// are properly ordered (e.g., FileSearchAndReplace then ReadFile on same file)
if (agentType === 'implementation') {
return builder.withGadgetExecutionMode('sequential');
}
Expand Down
90 changes: 2 additions & 88 deletions src/agents/prompts/templates/partials/rules-efficiency.eta
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,11 @@

When you encounter multiple errors (type errors, test failures, lint errors):
1. Read and analyze ALL errors before making any fixes
2. Fix ALL errors in a SINGLE response with multiple EditFile calls
2. Fix ALL errors in a SINGLE response with multiple gadget calls (FileSearchAndReplace, FileInsertContent, FileRemoveContent)
3. Run verification ONCE after all fixes
4. Repeat only if new errors appear
4. Repeat only if errors appear again

NEVER fix errors one-by-one. This wastes iterations. Batch all fixes together.

### Debugging Persistent Test Failures (CRITICAL)

If the SAME test fails 2-3 times after your fixes, STOP making more fixes. Instead, investigate:

**When mocks aren't being called (e.g., "Number of calls: 0"):**
1. The problem is NOT your test setup - the code path isn't executing at all
2. Add `console.log` statements to the IMPLEMENTATION code to trace execution:
- At the function entry point
- Before conditional branches
- Inside the block that should call the mocked function
3. Run the test again and read the console output to find where execution stops
4. Fix the actual implementation issue, not the test

**When assertions fail with wrong values:**
1. Add `console.log` to print actual values at key points
2. Check if your changes accidentally broke an existing code path
3. Verify dependencies are wired correctly (DI, imports, function parameters)

**Loop Detection - recognize when you're stuck:**
- If you've edited the same file 3+ times for the same error: STOP
- If you've run `verify-final-vN` where N > 3: STOP
- Step back and ask: "Why isn't the code reaching this point?"
- Read the implementation code, not just the test

**Debug-first approach:**
```
1. Test fails → Add console.log to implementation
2. Run test → Read logs to understand flow
3. Identify root cause → Fix implementation (not test setup)
4. Remove console.log → Verify fix
```

Remember: Tests that "should" call mocks but don't are telling you the implementation path is wrong, not the mock setup.

### Handling Breaking Changes (Critical)

If you modify a function signature, class constructor, or API contract,
do not wait for the compiler/linter to report errors.
Immediately perform a codebase-wide search for all usages of that symbol and update all call sites
in a single batch. Avoid the 'fix-run-repeat' loop for known breaking changes.

### Tooling & Verification

When validating changes, always prioritize auto-fixing commands (e.g., format, lint --fix) before
running read-only checks. If a generated artifact (like a migration or lockfile) looks incorrect,
investigate the environment state rather than manually patching the output.

### Acting on EditFile/WriteFile Results (CRITICAL)

EditFile and WriteFile return structured output. You MUST read and act on it.

**Status Codes:**
- `status=success` - Edit worked, but CHECK THE DIAGNOSTICS SECTION
- `status=failed` - Search content not found, USE THE SUGGESTIONS
- `status=error` - Operation failed (permissions, path), read error message

**On status=failed (search not found):**

The output includes a SUGGESTIONS section with similar content found in the file:
```
SUGGESTIONS (similar content found):
Line 42 (85% similar):
```{what actually exists}```
```

1. READ this section - it shows what the file actually contains
2. Adjust your search pattern to match the actual content
3. Common issues: whitespace differences, indentation, content changed by previous edit
4. NEVER retry the exact same search - that's a loop

**On status=success (check diagnostics):**

Success responses include TypeScript and Biome diagnostics:
```
=== TypeScript Check ===
{any type errors from your edit}

=== Biome Lint ===
{any lint issues from your edit}
```

If diagnostics show issues, FIX THEM IMMEDIATELY before making more edits.
Don't proceed to other files until the current file is clean.

**Recovery Escalation:**
1. First failure: Use SUGGESTIONS to adjust search pattern
2. Second failure: Read entire file with ReadFile, understand actual structure
3. Third failure: Use WriteFile to replace the entire file content
2 changes: 1 addition & 1 deletion src/agents/prompts/templates/planning.eta
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Review the updated description and move to TODO when ready to implement!
- `ReadFile` - Read file contents
- `Tmux` - Run shell commands (for exploration: grep, find, etc.)

⚠️ **You do NOT have access to:** EditFile, WriteFile, CreatePR - these are reserved for the implementation agent.
⚠️ **You do NOT have access to:** FileSearchAndReplace, FileInsertContent, FileRemoveContent, WriteFile, CreatePR - these are reserved for the implementation agent.

## Rules

Expand Down
12 changes: 10 additions & 2 deletions src/agents/respond-to-review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { getCompactionConfig } from '../config/compactionConfig.js';
import { getIterationTrailingMessage } from '../config/hintConfig.js';
import { getRateLimitForModel } from '../config/rateLimits.js';
import { getRetryConfig } from '../config/retryConfig.js';
import { EditFile } from '../gadgets/EditFile.js';
import { FileInsertContent } from '../gadgets/FileInsertContent.js';
import { FileRemoveContent } from '../gadgets/FileRemoveContent.js';
import { FileSearchAndReplace } from '../gadgets/FileSearchAndReplace.js';
import { ListDirectory } from '../gadgets/ListDirectory.js';
import { ReadFile } from '../gadgets/ReadFile.js';
import { Sleep } from '../gadgets/Sleep.js';
Expand All @@ -18,6 +20,7 @@ import {
GetPRDiff,
ReplyToReviewComment,
} from '../gadgets/github/index.js';
import { initSessionState } from '../gadgets/sessionState.js';
import { Tmux } from '../gadgets/tmux.js';
import { githubClient } from '../github/client.js';
import type { AgentInput, AgentResult, CascadeConfig, ProjectConfig } from '../types/index.js';
Expand Down Expand Up @@ -251,6 +254,9 @@ function createRespondToReviewAgentBuilder(
llmCallLogger: import('../utils/llmLogging.js').LLMCallLogger,
repoDir: string,
): BuilderType {
// Initialize session state for gadgets
initSessionState('respond-to-review');

// Check if AU features should be enabled (repo has .au file at root)
const auEnabled = existsSync(join(repoDir, '.au'));

Expand All @@ -259,7 +265,9 @@ function createRespondToReviewAgentBuilder(
// Filesystem gadgets
new ListDirectory(),
new ReadFile(),
new EditFile(),
new FileSearchAndReplace(),
new FileInsertContent(),
new FileRemoveContent(),
new WriteFile(),
// Shell commands via tmux
new Tmux(),
Expand Down
Loading