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
2 changes: 1 addition & 1 deletion src/backends/progressModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface ProgressContext {
completedTasks?: { subject: string; summary: string; timestamp: number }[];
}

const PROGRESS_SYSTEM_PROMPT = `You are a progress reporter for an AI coding agent called CASCADE. Write a brief, informative progress update based on the agent's current state. Be concise (3-5 sentences max). Focus on what has been accomplished, what's currently in progress, and what remains. Synthesize the agent's own commentary, tool call details (file paths, commands), and completed task summaries into a coherent narrative — do not just list tool names. Use markdown formatting. Write in first person (e.g. "I'm implementing...", "I've completed...", "I'm currently working on..."). Start with a bold header using the exact header provided in the user prompt context (e.g. "**🧑‍💻 Implementation Update** (X min)"). Do not include a progress bar — the system adds that separately.`;
const PROGRESS_SYSTEM_PROMPT = `You are a progress reporter for an AI coding agent called CASCADE. Write a brief, informative progress update based on the agent's current state. Be concise (3-5 sentences max). Focus on what has been accomplished, what's currently in progress, and what remains. Synthesize the agent's own commentary, tool call details (file paths, commands), and completed task summaries into a coherent narrative — do not just list tool names. Use markdown formatting. Write in first person (e.g. "I'm implementing...", "I've completed...", "I'm currently working on..."). Start with a bold header using the exact header provided in the user prompt context (e.g. "**🧑‍💻 Implementation Update** (X min)").`;

function formatProgressUserPrompt(context: ProgressContext): string {
const {
Expand Down
13 changes: 2 additions & 11 deletions src/backends/progressMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,7 @@ export class ProgressMonitor implements ProgressReporter {
captureException(err instanceof Error ? err : new Error(String(err)), {
tags: { source: 'progress_model', agentType: this.config.agentType },
});
summary = formatStatusMessage(
progressContext.iteration,
progressContext.maxIterations,
this.config.agentType,
);
summary = formatStatusMessage(this.config.agentType);
}

// Post to PM provider (Trello/JIRA)
Expand All @@ -217,12 +213,7 @@ export class ProgressMonitor implements ProgressReporter {
// Post to GitHub
if (this.githubPoster) {
try {
await this.githubPoster.update(
summary,
progressContext.iteration,
progressContext.maxIterations,
this.config.agentType,
);
await this.githubPoster.update(summary, this.config.agentType);
} catch (err) {
this.config.logWriter('WARN', 'Failed to update GitHub PR comment', {
error: String(err),
Expand Down
14 changes: 2 additions & 12 deletions src/backends/progressState/githubPoster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,11 @@ export interface GitHubProgressPosterConfig {
export class GitHubProgressPoster {
constructor(private readonly config: GitHubProgressPosterConfig) {}

async update(
summary: string,
iteration: number,
maxIterations: number,
agentType: string,
): Promise<void> {
async update(summary: string, agentType: string): Promise<void> {
const { initialCommentId } = getSessionState();
if (!initialCommentId) return;

const body = formatGitHubProgressComment(
this.config.headerMessage,
iteration,
maxIterations,
agentType,
);
const body = formatGitHubProgressComment(this.config.headerMessage, agentType);
// Replace the todo section with the AI-generated summary
const bodyWithSummary = body.replace(/\n\n📋[\s\S]*?\n\n/, `\n\n${summary}\n\n`);
await githubClient.updatePRComment(
Expand Down
52 changes: 5 additions & 47 deletions src/config/statusUpdateConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,10 @@ export function getStatusUpdateConfig(agentType: string): StatusUpdateConfig {
/**
* Format a status update message for posting to Trello.
*
* @param iteration - Current iteration number
* @param maxIterations - Maximum allowed iterations
* @param agentType - Type of agent posting the update
* @returns Formatted markdown message
*/
export function formatStatusMessage(
iteration: number,
maxIterations: number,
agentType: string,
): string {
const progress = Math.round((iteration / maxIterations) * 100);
const progressBar = createProgressBar(progress);

export function formatStatusMessage(agentType: string): string {
// Get current todo status
const todos = loadTodos();
const inProgressTodo = todos.find((t) => t.status === 'in_progress');
Expand All @@ -73,11 +64,7 @@ export function formatStatusMessage(

const { emoji, label } = getAgentLabel(agentType);

const lines = [
`**${emoji} ${label}** (${agentType})`,
'',
`${progressBar} ${progress}% (iteration ${iteration}/${maxIterations})`,
];
const lines = [`**${emoji} ${label}** (${agentType})`];

if (totalCount > 0) {
lines.push('', `**Tasks:** ${doneCount}/${totalCount} complete`);
Expand All @@ -92,46 +79,17 @@ export function formatStatusMessage(
/**
* Format a GitHub progress comment that updates the initial PR comment.
*
* Renders a progress bar, todo list, and metadata footer.
* Renders a todo list and metadata footer.
*
* @param headerMessage - Original comment text preserved as header (e.g., "🔍 Reviewing PR...")
* @param iteration - Current iteration number
* @param maxIterations - Maximum allowed iterations
* @param agentType - Type of agent posting the update
* @returns Formatted markdown comment body
*/
export function formatGitHubProgressComment(
headerMessage: string,
iteration: number,
maxIterations: number,
agentType: string,
): string {
const progress = Math.round((iteration / maxIterations) * 100);
const progressBar = createProgressBar(progress);

export function formatGitHubProgressComment(headerMessage: string, agentType: string): string {
const todos = loadTodos();
const todoSection = formatTodoList(todos);

const lines = [
headerMessage,
'',
'---',
'',
`**Progress:** ${progressBar} ${progress}% (iteration ${iteration}/${maxIterations})`,
'',
todoSection,
'',
`<sub>Last updated: iteration ${iteration} · ${agentType}</sub>`,
];
const lines = [headerMessage, '', '---', '', todoSection, '', `<sub>${agentType}</sub>`];

return lines.join('\n');
}

/**
* Create a text-based progress bar.
*/
function createProgressBar(percent: number): string {
const filled = Math.round(percent / 10);
const empty = 10 - filled;
return `[${'█'.repeat(filled)}${'░'.repeat(empty)}]`;
}
10 changes: 4 additions & 6 deletions tests/unit/backends/githubPoster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('GitHubProgressPoster — update()', () => {
});

const poster = makePoster();
await poster.update('summary', 3, 20, 'implementation');
await poster.update('summary', 'implementation');

expect(mockGithubClient.updatePRComment).not.toHaveBeenCalled();
});
Expand All @@ -62,12 +62,10 @@ describe('GitHubProgressPoster — update()', () => {
mockGithubClient.updatePRComment.mockResolvedValue(undefined as never);

const poster = makePoster();
await poster.update('AI-generated summary', 5, 20, 'implementation');
await poster.update('AI-generated summary', 'implementation');

expect(mockFormatGitHubProgressComment).toHaveBeenCalledWith(
'**🧑‍💻 Implementation Update**',
5,
20,
'implementation',
);
expect(mockGithubClient.updatePRComment).toHaveBeenCalledWith(
Expand All @@ -94,7 +92,7 @@ describe('GitHubProgressPoster — update()', () => {
mockGithubClient.updatePRComment.mockResolvedValue(undefined as never);

const poster = makePoster();
await poster.update('My AI summary', 2, 10, 'review');
await poster.update('My AI summary', 'review');

const callArg = mockGithubClient.updatePRComment.mock.calls[0][3];
expect(callArg).toContain('My AI summary');
Expand All @@ -120,7 +118,7 @@ describe('GitHubProgressPoster — update()', () => {
headerMessage: 'Header',
logWriter,
});
await poster.update('summary', 1, 5, 'review');
await poster.update('summary', 'review');

expect(logWriter).toHaveBeenCalledWith(
'INFO',
Expand Down
Loading