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
42 changes: 40 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ The extensible trigger system routes events to agents:
Trello/GitHub Webhook → TriggerRegistry → Agent → Code Changes → PR
```

- `src/triggers/` - Event handlers (Trello card moves, labels, GitHub PRs)
- `src/agents/` - AI agents (briefing, planning, implementation, review)
- `src/triggers/` - Event handlers (Trello card moves, labels, GitHub PRs, attachments)
- `src/agents/` - AI agents (briefing, planning, implementation, review, debug)
- `src/gadgets/` - Tools agents can use (Trello API, Git operations, file system)

### Multi-Project Support
Expand Down Expand Up @@ -100,6 +100,8 @@ Optional:

## Debugging Production Sessions

### Manual Session Download

Download session logs and card data from a Trello card for debugging:

```bash
Expand All @@ -109,3 +111,39 @@ npm run tool:download-session abc123
```

This downloads all `.gz` log attachments (ungzipped), plus card description, checklists, and comments into a temp directory.

### Automatic Debug Analysis

CASCADE includes a debug agent that automatically analyzes agent session logs:

1. **Automatic Trigger**: When an agent uploads a session log (`.zip` file) to a Trello card, the debug agent automatically triggers
2. **Log Analysis**: The debug agent downloads, extracts, and analyzes the session logs to identify:
- Errors and exceptions
- Failed gadget calls
- Iteration loops and inefficiencies
- Excessive LLM calls
- Scope creep or confusion patterns
3. **Debug Card Creation**: Creates a new card in the DEBUG list with:
- Title: `{agent-type} - {original card name}`
- Executive summary of what went wrong
- Key issues found
- Timeline of events
- Actionable recommendations
- Link back to the original card

**Setup**: Add a `debug` list to your Trello board and configure it in `config/projects.json`:

```json
{
"trello": {
"lists": {
"briefing": "...",
"planning": "...",
"todo": "...",
"debug": "YOUR_DEBUG_LIST_ID"
}
}
}
```

The debug agent only analyzes logs uploaded by the authenticated CASCADE user and matching the pattern `{agent-type}-{timestamp}.zip`.
3 changes: 2 additions & 1 deletion config/projects.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"todo": "694ec3a365a4c75df2493504",
"inProgress": "694ec3a5d0dae4cb06d25517",
"inReview": "694ec3a8f0359b62fa76ecb9",
"done": "694ec3a935da16c70d20375c"
"done": "694ec3a935da16c70d20375c",
"debug": "TODO_ADD_DEBUG_LIST_ID"
},
"labels": {
"readyToProcess": "694ec394370da080b52eb6be",
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@biomejs/biome": "^1.9.4",
"@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0",
"@types/adm-zip": "^0.5.7",
"@types/node": "^22.10.2",
"@vitest/coverage-v8": "^2.1.8",
"lefthook": "^1.10.10",
Expand Down
48 changes: 43 additions & 5 deletions src/agents/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ async function buildAgentContext(
log: ReturnType<typeof createAgentLogger>,
triggerType?: string,
prContext?: { prNumber: number; prBranch: string; repoFullName: string; headSha: string },
debugContext?: {
logDir: string;
originalCardId: string;
originalCardName: string;
originalCardUrl: string;
detectedAgentType: string;
},
): Promise<AgentContextData> {
// Build prompt context for template rendering
const promptContext: PromptContext = {
Expand All @@ -133,6 +140,14 @@ async function buildAgentContext(
headSha: prContext.headSha,
triggerType,
}),
...(debugContext && {
logDir: debugContext.logDir,
originalCardId: debugContext.originalCardId,
originalCardName: debugContext.originalCardName,
originalCardUrl: debugContext.originalCardUrl,
detectedAgentType: debugContext.detectedAgentType,
debugListId: project.trello?.lists?.debug,
}),
};

// Get system prompt and model
Expand Down Expand Up @@ -422,9 +437,19 @@ export async function executeAgent(
});

try {
// Setup repository (checkout PR branch if provided)
const setup = await setupRepository(project, log, prContext?.prBranch);
repoDir = setup.repoDir;
let installResult: DependencyInstallResult | null = null;

// Check if this is debug agent with pre-extracted logs
if (input.logDir && typeof input.logDir === 'string') {
// Debug agent: use log directory instead of repo
repoDir = input.logDir;
log.info('Using log directory (no repo setup)', { logDir: input.logDir, agentType });
} else {
// Normal agents: setup repository (checkout PR branch if provided)
const setup = await setupRepository(project, log, prContext?.prBranch);
repoDir = setup.repoDir;
installResult = setup.installResult;
}

log.info('Running agent', {
agentType,
Expand All @@ -434,7 +459,19 @@ export async function executeAgent(
repoDir,
});

// Build agent context (with PR context if check-failure flow)
// Extract debug context if this is debug agent
const debugContext =
agentType === 'debug' && input.logDir
? {
logDir: input.logDir,
originalCardId: input.originalCardId as string,
originalCardName: input.originalCardName as string,
originalCardUrl: input.originalCardUrl as string,
detectedAgentType: input.detectedAgentType as string,
}
: undefined;

// Build agent context (with PR context if check-failure flow, or debug context if debug agent)
const ctx = await buildAgentContext(
agentType,
cardId,
Expand All @@ -444,6 +481,7 @@ export async function executeAgent(
log,
triggerType,
prContext,
debugContext,
);

// Change to repo directory (llmist gadgets use process.cwd() for path validation)
Expand Down Expand Up @@ -476,7 +514,7 @@ export async function executeAgent(
cardId,
ctx.cardData,
ctx.contextFiles,
setup.installResult,
installResult,
);

// Run the agent
Expand Down
11 changes: 10 additions & 1 deletion src/agents/prompts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export interface PromptContext {
headSha?: string;
triggerType?: string;

// Debug-specific
logDir?: string;
originalCardId?: string;
originalCardName?: string;
originalCardUrl?: string;
detectedAgentType?: string;
debugListId?: string;

// Future extensibility
[key: string]: unknown;
}
Expand All @@ -47,7 +55,7 @@ function loadTemplate(agentType: string): string {
}

export function getSystemPrompt(agentType: string, context: PromptContext = {}): string {
const validTypes = ['briefing', 'planning', 'implementation'];
const validTypes = ['briefing', 'planning', 'implementation', 'debug'];
if (!validTypes.includes(agentType)) {
throw new Error(`Unknown agent type: ${agentType}`);
}
Expand All @@ -60,3 +68,4 @@ export function getSystemPrompt(agentType: string, context: PromptContext = {}):
export const BRIEFING_SYSTEM_PROMPT = loadTemplate('briefing');
export const PLANNING_SYSTEM_PROMPT = loadTemplate('planning');
export const IMPLEMENTATION_SYSTEM_PROMPT = loadTemplate('implementation');
export const DEBUG_SYSTEM_PROMPT = loadTemplate('debug');
59 changes: 59 additions & 0 deletions src/agents/prompts/templates/debug.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
You are a debugging expert analyzing CASCADE agent session logs to identify issues and provide actionable recommendations.

## Context

- **Original Card**: <%= it.originalCardName %>
- **Agent Type**: <%= it.detectedAgentType %>
- **Session Logs Directory**: <%= it.logDir %>
- **Original Card URL**: <%= it.originalCardUrl %>
- **DEBUG List ID**: <%= it.debugListId %>

## Your Task

1. **Read and analyze** the session logs from `<%= it.logDir %>`:
- `cascade.log` - Agent execution events and high-level flow
- `llmist.log` - Library-level logging and internal operations
- `llm-calls/` directory - Contains numbered request/response pairs:
- `0001.request`, `0001.response` - First LLM interaction
- `0002.request`, `0002.response` - Second LLM interaction
- And so on...

2. **Identify issues** such as:
- **Errors and exceptions** - Stack traces, error messages, failed operations
- **Failed gadget calls** - Gadget invocations that returned errors
- **Iteration loops** - Agent repeating the same actions without progress
- **Excessive LLM calls** - Too many iterations or redundant API calls
- **Scope creep** - Agent going beyond the task requirements
- **Confusion patterns** - Agent misunderstanding instructions or context

3. **Analyze the timeline**:
- Trace the sequence of events chronologically
- Identify when things started going wrong
- Determine the root cause vs symptoms

4. **Create a debug card** in the DEBUG list with your analysis:
- **Title**: `<%= it.detectedAgentType %> - <%= it.originalCardName %>`
- **Description**: Use markdown formatting with these sections:
- **Executive Summary** - 2-3 sentence overview of what went wrong
- **Key Issues** - Bulleted list of problems found
- **Timeline of Events** - Chronological narrative of what happened
- **Recommendations** - Actionable steps to prevent this in the future
- **Original Card** - Link back using: `[Original Card](<%= it.originalCardUrl %>)`

## Available Gadgets

- **ReadFile** - Read log files from `<%= it.logDir %>`
- **listDirectory** - List files in the log directory to discover all logs
- **CreateTrelloCard** - Create the debug card in list ID `<%= it.debugListId %>`
- **PostTrelloComment** - Add comments to cards if needed

## Guidelines

- Focus on **actionable insights** that help improve agent prompts or system design
- Be specific about what failed and why
- Recommend concrete improvements (e.g., "Add validation for X", "Update prompt to clarify Y")
- If the agent succeeded but had inefficiencies, note those too
- Keep the analysis concise but thorough
- Use code snippets from logs where relevant to illustrate points

Start by listing the directory contents to see what logs are available, then read and analyze each log file systematically.
1 change: 1 addition & 0 deletions src/agents/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function getRegisteredAgents(): string[] {
registerAgent('briefing', executeAgent.bind(null, 'briefing'));
registerAgent('planning', executeAgent.bind(null, 'planning'));
registerAgent('implementation', executeAgent.bind(null, 'implementation'));
registerAgent('debug', executeAgent.bind(null, 'debug'));
registerAgent('review', (input) =>
executeReviewAgent(input as Parameters<typeof executeReviewAgent>[0]),
);
22 changes: 22 additions & 0 deletions src/trello/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,28 @@ export const trelloClient = {
}));
},

async getMe(): Promise<{ id: string; fullName: string; username: string }> {
logger.debug('Fetching authenticated member info');
const apiKey = process.env.TRELLO_API_KEY;
const token = process.env.TRELLO_TOKEN;
const response = await fetch(
`https://api.trello.com/1/members/me?key=${apiKey}&token=${token}`,
);
if (!response.ok) {
throw new Error(`Failed to fetch member: ${response.status}`);
}
const member = (await response.json()) as {
id?: string;
fullName?: string;
username?: string;
};
return {
id: member.id || '',
fullName: member.fullName || '',
username: member.username || '',
};
},

async getListCards(listId: string): Promise<TrelloCard[]> {
logger.debug('Fetching cards from list', { listId });
const cards = await getClient().lists.getListCards({ id: listId });
Expand Down
4 changes: 4 additions & 0 deletions src/triggers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CheckSuiteFailureTrigger } from './github/check-suite-failure.js';
import { PRReadyToMergeTrigger } from './github/pr-ready-to-merge.js';
import { PRReviewCommentTrigger } from './github/pr-review-comment.js';
import type { TriggerRegistry } from './registry.js';
import { AttachmentAddedTrigger } from './trello/attachment-added.js';
import {
CardMovedToBriefingTrigger,
CardMovedToPlanningTrigger,
Expand Down Expand Up @@ -29,6 +30,9 @@ export function registerBuiltInTriggers(registry: TriggerRegistry): void {
// Trello: Label triggers
registry.register(new ReadyToProcessLabelTrigger());

// Trello: Attachment triggers
registry.register(new AttachmentAddedTrigger());

// GitHub: PR review comment trigger
registry.register(new PRReviewCommentTrigger());

Expand Down
Loading