Introducing Task Demon: Vibe Coding with a Plan

In the last 6 months, the way that leading software engineers build software has undergone a fundamental shift.

The adoption of agentic AI coding assistants has heralded the greatest leap in productivity I have encountered in my 20 year career so far. As I wrote previously, adopting Windsurf doubled my output within a week. Where usually I'd be thrilled to find some way to get 20% more done, and would work hard for that 20%, suddenly I'm getting 100% and it's just... easy.

But if there's a single consistent counter-punch to the Vibe Coding movement, it's the irrefutable fact that no matter how good the agentic AI coding assistant is, it will always do much better work from a detailed prompt that includes a plan, than from your 2 sentence vibe code prompt.

That's what Task Demon does: it takes the 2 sentence vibe prompt and blows it up into a sublimely detailed prompt, usually anywhere between 200 and 1000 lines long, that includes a full implementation plan that will correctly guide the AI to do the right thing, using your project's structure, dependencies and ways of doing things.

A video is worth a million words. This one is 15 minutes but if you use AI to build software, I believe you'll find it worth it:

15 minutes to learn why Task Demon makes Vibe Coding viable for software engineering professionals

How it works

After using Windsurf and later Claude Code for a while, I found that using the following pattern yielded superb results:

  1. Ask the AI to write a plan on how to do a certain Task
  2. Ask it to check that plan as it usually makes mistakes
  3. Ask it to write the code based on that plan

I developed these detailed prompts for each step that I would reuse each time and just swap out the task description. The rest of the prompt text was always stuff about what dependencies to use, how to run tests, and so on. I'd copy the output of each prompt in as the input of the next, until I'd run all 3 prompts and the code had in theory been implemented.

After doing this for a while, it was working very successfully, but I was no longer doing engineering. I was doing manufacturing - copy/pasting text snippets between prompts over and over again in the same way every time, just swapping out a few key sentences and making quite a few mistakes along the way.

Task Demon automates this process. When you create a task with Task Demon, it uses an agentic planning process to generate an extremely detailed prompt that includes detailed background on the project and the task, a full pre-planned implementation plan and any custom instructions you want to add. Just paste the resulting 200-1000 line prompt into Windsurf, Claude Code, or any other agentic AI coding assistant, and let it do the rest.

Planning beats Vibes

Because there are often many ways to do the same thing, the AI will often choose the wrong way to do it for your project. Then you have to prompt it again, pleading with it to do it right this time. Often there are several rounds of this. And to be fair, the AI had no idea that your project already uses Convention X and Library Y - your vibe code prompt definitely didn't tell it.

This is where having a pre-authored plan prompt massively accelerates software development vs Vibe Coding. Task Demon's prompts are incredibly detailed and completely tailored to the specific project that you are working on so when you paste them into Claude Code and press enter, generally speaking you don't have to intervene very much because the prompt already tells Claude Code everything it needs to do the job properly.

Here's an example of a prompt that Task Demon generated:

<purpose>
You are an experienced senior software engineer working on a code repository.
You will be given details about the Project (which represents the repository), including any existing
high-level documentation about the Project.You are being given a detailed plan for some work that needs to be done, including tasks, files, and instructions.
The plan has been prepared for you ahead of time by an LLM Architect, and then checked and improved
by a second Architect. It is likely that the plan is good and you should follow it as closely as possible to completion.Implement the changes described in the plan, following sequentially task by task until the work is complete.
</purpose>

<instructions>
<instruction>Implement all of the tasks in the plan, one by one, in the order specified</instruction>
<instruction>For each task, ensure that the work has been completed according to the instructions in the plan</instruction>
<instruction>Use the tools available to you to examine files in the repository if it helps you make your determination</instruction>
<instruction>Read existing code and comments first, and reuse code where possible</instruction>
<instruction>This is a Next JS application using React and TypeScript. Use those technologies.</instruction>
</instructions>

<data>

Here is an overview of the project you are working on:

<project>
<id>83ad8f85-e269-4fbb-ace5-1d99eb4ca87a</id>
<name>Task Demon</name>
<description>Task Demon is a chatbot-centric SaaS application that acts on behalf of the user to create and maintain tickets (or issues) for work that needs to be done. It also has a number of Agents that can be run on customer devices to automatically use AI to triage, plan and implement work on git repositories.</description>
<status>active</status>
</project>

Here is some background information about this task in the context of the project:

<project-document>
# Task Demon: Add Reset Button to Project Details Page

## Project Overview

**Project Name:** Task Demon
**Project ID:** 2d1b9dd6-a737-4b43-9c2a-6f6323908cb5
**Description:** Task Demon is a chatbot-centric SaaS application designed to automate software development workflows. It acts as an AI-powered task management system that creates and maintains tickets for work that needs to be done. The platform includes specialized AI agents that run on customer devices to automatically triage, plan, and implement work on git repositories. Task Demon integrates deeply with GitHub, providing a seamless experience for managing development tasks.

## Task Details

**Task ID:** eecc9da4-ae5e-4084-84b3-72a6ccbd817f
**Task Name:** Add Reset Button to Project Details Page
**Task Description:** Implement a button on the Project Details page that allows users to reset the project. This button should trigger a new API endpoint that calls a library function to delete all documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions for the project. Additionally, it should set `tasksImported` to false on the project. The reset option should be accessible via a button in the Project Settings page, which opens a confirmation modal to verify the action due to its destructive nature. After the reset is complete, the modal should inform the user of the success and provide a button to 'Go to Project'.

## Relevant Information from Project Documents

### Project Details Page Characterization

- **Core Components:**
- **Server Components:** Located in `app/app/projects/[projectId]`, including:
- `page.tsx`: Main server component that fetches and renders project data.
- `layout.tsx`: Provides ProjectProvider context to child components.
- **Client Components:** Primarily in `components/projects/`, structured as:
- Project header (title, description).
- Settings panel (preferences, GitHub integration).
- Characterization summary section.
- Task list with filtering capabilities.
- Project chat interface.
- Activity feed with real-time updates.
- Documents section organized by type.
- Project agents section.

- **State Management:**
- `ProjectProvider`: Provides project data and UI preferences.
- `use-project-context.tsx`: Context hook managing project state.
- Custom hooks for real-time data synchronization:
- `use-project-events.ts`: Manages project activity with pagination.
- `use-project-events-swr.ts`: Handles real-time updates via Pusher.

- **Data Flow:**
- **Initial Load:** Server fetches project data, tasks, and characterization status.
- **Real-time Updates:** Pusher channels provide WebSocket-based notifications.
- **User Interactions:** Edit project metadata, start/view characterization, filter and view tasks, chat with project AI, monitor activity feed.

### API Documentation

- **Projects API:**
- `/api/projects/:projectId`: Get project details.
- `/api/projects/:projectId/tasks`: List project tasks.
- `/api/projects/:projectId/characterization`: Get project characterization.
- **New Endpoint Required:** A new API endpoint will be needed to handle the reset functionality, which will delete all related data and reset `tasksImported`.

### Security and Compliance

- **Authentication and Access Control:**
- All routes under `/app/*` are protected by middleware.
- Unauthenticated users are redirected to the login page.
- Secure URL handling with proper validation.

- **Data Handling and Storage:**
- User data stored on Vercel's infrastructure.
- All API communication uses HTTPS.
- WebSocket connections secured with WSS.

### UI Technical Documentation

- **Component Architecture:**
- **Base UI Components:** Foundational elements like Button, Input, Badge, Dialog.
- **Composite Components:** Built from UI primitives.
- **Feature Components:** Project components located in `/components/projects/`.

- **Design System:**
- Theme-aware colors adapting to light/dark modes.
- Semantic color naming and CSS variables implemented through Tailwind.

- **UI Patterns and Conventions:**
- TypeScript interfaces for component props.
- Forwarded refs for better composition.
- Consistent variant and size props.

### Pusher Integration

- **Real-time Communication:**
- Pusher channels for project, task, and characterization-specific events.
- WebSockets for streaming AI agent responses.

### Testing and Quality Assurance

- **Testing Frameworks:**
- **Jest:** Primary testing framework for both backend and frontend.
- **@testing-library/react:** Library for testing React components.

- **Testing Methodologies:**
- Unit Testing, Integration Testing, UI Testing, API Testing.

## Implementation Considerations

1. **UI Design:**
- Add a "Reset Project" button to the Project Settings page.
- Implement a confirmation modal to verify the reset action due to its destructive nature.
- After reset, display a success message with a button to 'Go to Project'.

2. **API Development:**
- Develop a new API endpoint to handle the reset functionality.
- Ensure the endpoint deletes all related data (documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions) and sets `tasksImported` to false.

3. **Security:**
- Ensure the reset action is protected by proper authentication and authorization checks.
- Implement secure data handling practices as per the security documentation.

4. **Testing:**
- Write unit and integration tests for the new API endpoint.
- Test the UI components for the reset button and confirmation modal.
- Ensure real-time updates are handled correctly post-reset.

5. **Real-time Updates:**
- Use Pusher to notify the UI of changes post-reset, ensuring the user interface reflects the reset state immediately.

By following these guidelines and utilizing the provided documentation, the task of adding a reset button to the Project Details page can be implemented effectively, ensuring a seamless user experience and maintaining the integrity of the Task Demon platform.
</project-document>

This is the task itself:

<task>
<id>eecc9da4-ae5e-4084-84b3-72a6ccbd817f</id>
<name>Add Reset Button to Project Details Page</name>
<description>Implement a button on the Project Details page that allows users to reset the project. This button should trigger a new API endpoint that calls a library function to delete all documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions for the project. Additionally, it should set `tasksImported` to false on the project. The reset option should be accessible via a button in the Project Settings page, which opens a confirmation modal to verify the action due to its destructive nature. After the reset is complete, the modal should inform the user of the success and provide a button to 'Go to Project'.</description>
<status>closed</status>
</task>

Here is the plan for the work:

<plan>
I'll analyze the task of adding a reset button to the Project Details page and create a comprehensive requirements document. Let me start by understanding the task and existing codebase.
# Requirements Document: Add Reset Button to Project Details Page
## Overview of Approach
This task involves adding a reset functionality to the Project Details page, which requires both frontend components and backend services. I'll need to:
1. Create a new API endpoint for resetting a project
2. Implement library functions to handle data deletion operations
3. Add a reset button to the Project Settings component
4. Create a confirmation dialog for the reset action
5. Create a success notification after reset completion
The reset operation is destructive, removing all associated project data (documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions) while maintaining the project itself. Given the severity of this action, proper user confirmation and security checks are essential.
This implementation will follow the existing patterns in the Task Demon application, leveraging the ShadCN UI component library, Next.js App Router, and Drizzle ORM.
## Architectural Overview
### System Components
The reset project functionality will span several architectural layers:
1. **UI Layer**:
- A reset button in the Project Settings panel
- A confirmation dialog using the existing ConfirmationDialog component
- Success notification via the toast system
2. **API Layer**:
- A new REST endpoint at `/api/projects/[projectId]/reset` that handles the project reset request
- Authentication and authorization middleware to ensure only authorized users can reset projects
3. **Data Layer**:
- Library functions to delete associated data across multiple tables
- Database queries using Drizzle ORM to perform the deletions
- Project update to reset the `tasksImported` flag
4. **Notification Layer**:
- Pusher integration to notify UI components of the reset completion
- Real-time updates to reflect the project's new state
### Data Flow
```
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ │ │ │ │ │
│ Project Settings │────►│ Reset API Endpoint│────►│ Reset Functions │
│ + Reset Button │ │ │ │ │
│ │ │ │ │ │
└───────────────────┘ └───────────────────┘ └───────────────────┘
▲ │
│ │
│ ▼
┌───────────────────┐ ┌───────────────────┐
│ │ │ │
│ Success Dialog + │◄─────────────────────────────│ Database │
│ Toast Notification│ │ │
│ │ │ │
└───────────────────┘ └───────────────────┘
```
### Security Considerations
The reset functionality requires special attention to security:
1. **Authentication**: Only authenticated users can access the reset endpoint
2. **Authorization**: Users must have permission to modify the specific project
3. **Confirmation**: A double confirmation pattern prevents accidental resets
4. **Validation**: Server-side validation ensures the projectId is valid
5. **Audit Logging**: The action should be logged for audit purposes
### Error Handling
The implementation includes comprehensive error handling:
1. **UI Error States**: Display appropriate error messages if the reset fails
2. **API Error Responses**: Return structured error responses from the API
3. **Recovery Mechanisms**: Provide guidance for users if errors occur
4. **Validation Errors**: Handle invalid inputs gracefully
## Tasks Breakdown
### Backend Implementation
#### API Endpoint Creation
- [ ] 1. Create a new API route handler file at `app/api/projects/[projectId]/reset/route.ts`
- [ ] 2. Implement the DELETE method handler that validates the request and calls the reset library function
- [ ] 3. Add proper error handling and response formatting
- [ ] 4. Add authentication check using Next Auth
#### Library Functions
- [ ] 5. Create a new library file `lib/db/projects/reset.ts` for project reset functionality
- [ ] 6. Implement function to delete all documents associated with a project
- [ ] 7. Implement function to delete all tasks associated with a project
- [ ] 8. Implement function to delete all characterizations associated with a project
- [ ] 9. Implement function to delete all events associated with a project
- [ ] 10. Implement function to delete all workflows associated with a project
- [ ] 11. Implement function to delete all agents associated with a project
- [ ] 12. Implement function to delete all chats and messages associated with a project
- [ ] 13. Implement function to delete all instructions associated with a project
- [ ] 14. Implement function to set `tasksImported` to false on the project
- [ ] 15. Create a main reset function that orchestrates all the deletion operations in a transaction
### Frontend Implementation
#### UI Components
- [ ] 16. Add a "Reset Project" button to the Project Settings component in `components/projects/project-settings-panel.tsx`
- [ ] 17. Create a confirmation dialog component for the reset action
- [ ] 18. Add success notification using the toast system
- [ ] 19. Implement loading state for the reset button during the operation
#### API Integration
- [ ] 20. Create a reset project API client function in `lib/db/projects/queries.ts`
- [ ] 21. Connect the reset button to the API client function
- [ ] 22. Handle API responses and errors in the UI
### Testing
- [ ] 23. Create API route test file `test/api/projects/reset.test.ts`
- [ ] 24. Write test cases for successful project reset
- [ ] 25. Write test cases for unauthorized access attempts
- [ ] 26. Write test cases for invalid project IDs
- [ ] 27. Create UI test file `test/components/projects/reset-project.test.tsx`
- [ ] 28. Write test for the Reset Project button rendering
- [ ] 29. Write test for confirmation dialog appearance and interaction
- [ ] 30. Write test for success notification
- [ ] 31. Write test for API client function in isolation
### Documentation
- [ ] 32. Update API documentation to include the new reset endpoint
- [ ] 33. Document the reset functionality in the project README or internal documentation
## Detailed Implementation Specifications
### Backend Implementation Details
#### API Endpoint
```typescript
// app/api/projects/[projectId]/reset/route.ts
import { auth } from '@/app/(auth)/auth';
import { resetProject } from '@/lib/db/projects/reset';
import { NextRequest, NextResponse } from 'next/server';
/**
* Handler for resetting a project.
* Deletes all associated data and resets the project state.
*
* @param request The incoming request
* @param params Object containing route parameters
* @returns NextResponse with status and message
*/
export async function DELETE(
request: NextRequest,
{ params }: { params: { projectId: string } }
) {
// Authentication check
const session = await auth();
if (!session || !session.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { projectId } = params;
if (!projectId) {
return NextResponse.json(
{ error: 'Project ID is required' },
{ status: 400 }
);
}
try {
// Call the reset library function
await resetProject(projectId);
return NextResponse.json(
{ message: 'Project reset successfully' },
{ status: 200 }
);
} catch (error) {
console.error('Error resetting project:', error);
return NextResponse.json(
{ error: 'Failed to reset project' },
{ status: 500 }
);
}
}
```
#### Library Functions
```typescript
// lib/db/projects/reset.ts
import { db } from '@/lib/db';
import { and, eq } from 'drizzle-orm';
import { documents, projects, tasks, characterizations, events, workflows, agents, chats, messages, instructions } from '@/lib/db/schema';
/**
* Resets a project by deleting all associated data and setting tasksImported to false.
* This is a destructive operation that cannot be undone.
*
* @param projectId The ID of the project to reset
* @returns Promise that resolves when reset is complete
*/
export async function resetProject(projectId: string): Promise&#x3C;void> {
// Execute all operations in a transaction to ensure consistency
return db.transaction(async (tx) => {
// Delete all documents
await tx.delete(documents).where(eq(documents.projectId, projectId));
// Delete all tasks
await tx.delete(tasks).where(eq(tasks.projectId, projectId));
// Delete all characterizations
await tx.delete(characterizations).where(eq(characterizations.projectId, projectId));
// Delete all events
await tx.delete(events).where(eq(events.projectId, projectId));
// Delete all workflows
await tx.delete(workflows).where(eq(workflows.projectId, projectId));
// Delete all agents
await tx.delete(agents).where(eq(agents.projectId, projectId));
// Delete all chats and messages
// First, get all chat IDs for this project
const projectChats = await tx
.select({ id: chats.id })
.from(chats)
.where(eq(chats.projectId, projectId));
// Delete messages for these chats
for (const chat of projectChats) {
await tx.delete(messages).where(eq(messages.chatId, chat.id));
}
// Delete the chats themselves
await tx.delete(chats).where(eq(chats.projectId, projectId));
// Delete all instructions
await tx.delete(instructions).where(eq(instructions.projectId, projectId));
// Reset the tasksImported flag on the project
await tx
.update(projects)
.set({ tasksImported: false })
.where(eq(projects.id, projectId));
});
}
```
```typescript
// lib/db/projects/queries.ts (addition to existing file)
/**
* Reset a project by deleting all associated data and setting tasksImported to false.
*
* @param projectId - The ID of the project to reset
* @returns Promise that resolves when the project has been reset
*/
export async function resetProjectData(projectId: string): Promise&#x3C;void> {
const response = await fetch(`/api/projects/${projectId}/reset`, {
method: 'DELETE',
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to reset project');
}
}
```
### Frontend Implementation Details
#### Reset Button in Project Settings
```typescript
// components/projects/project-settings-panel.tsx (addition to existing component)
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { Button } from '@/components/ui/button';
import { ConfirmationDialog } from '@/components/ui/confirmation-dialog';
import { useToast } from '@/hooks/use-toast';
import { resetProjectData } from '@/lib/db/projects/queries';
// Add to existing component
const [isResetDialogOpen, setIsResetDialogOpen] = useState(false);
const [isResetting, setIsResetting] = useState(false);
const [resetSuccess, setResetSuccess] = useState(false);
const router = useRouter();
const { toast } = useToast();
const handleResetProject = async () => {
setIsResetting(true);
try {
await resetProjectData(project.id);
setIsResetting(false);
setResetSuccess(true);
toast({
title: 'Project reset successfully',
description: 'All project data has been deleted.',
variant: 'default',
});
} catch (error) {
setIsResetting(false);
toast({
title: 'Failed to reset project',
description: error instanceof Error ? error.message : 'An error occurred',
variant: 'destructive',
});
}
};
// Add this to the JSX in the component's return statement
&#x3C;div className="border-t border-border pt-4 mt-4">
&#x3C;h3 className="text-sm font-medium mb-4">Danger Zone&#x3C;/h3>
&#x3C;div className="rounded border border-destructive p-4">
&#x3C;div className="flex flex-col gap-2">
&#x3C;h4 className="font-medium text-destructive">Reset Project&#x3C;/h4>
&#x3C;p className="text-sm text-muted-foreground">
This will delete all documents, tasks, and other data associated with this project.
This action cannot be undone.
&#x3C;/p>
&#x3C;Button
variant="destructive"
className="mt-2 w-fit"
onClick={() => setIsResetDialogOpen(true)}
>
Reset Project
&#x3C;/Button>
&#x3C;/div>
&#x3C;/div>
&#x3C;/div>
&#x3C;ConfirmationDialog
open={isResetDialogOpen}
onOpenChange={setIsResetDialogOpen}
title="Reset Project"
description="Are you sure you want to reset this project? This will delete all tasks, documents, characterizations, and other data. This action cannot be undone."
confirmText="Reset Project"
cancelText="Cancel"
destructive
onConfirm={handleResetProject}
loading={isResetting}
/>
&#x3C;ConfirmationDialog
open={resetSuccess}
onOpenChange={setResetSuccess}
title="Project Reset Successfully"
description="Your project has been reset. All tasks, documents, and other data have been deleted."
confirmText="Go to Project"
showCancel={false}
onConfirm={() => {
setResetSuccess(false);
router.push(`/app/projects/${project.id}`);
router.refresh();
}}
/>
```
### Test Implementation Details
```typescript
// test/api/projects/reset.test.ts
import { DELETE } from '@/app/api/projects/[projectId]/reset/route';
import { db } from '@/lib/db';
import { projects, documents, tasks, characterizations, events, workflows, agents, chats, messages, instructions } from '@/lib/db/schema';
import { createMocks } from 'node-mocks-http';
import { v4 as uuidv4 } from 'uuid';
import { eq } from 'drizzle-orm';
jest.mock('@/app/(auth)/auth', () => ({
auth: jest.fn(() => Promise.resolve({
user: { id: 'test-user-id', email: 'test@example.com' }
}))
}));
describe('Project Reset API', () => {
let projectId: string;
// Create test data before each test
beforeEach(async () => {
// Create a test project
projectId = uuidv4();
await db.insert(projects).values({
id: projectId,
name: 'Test Project',
description: 'Test Description',
userId: 'test-user-id',
tasksImported: true,
createdAt: new Date(),
updatedAt: new Date(),
});
// Create test documents, tasks, etc. for this project
await db.insert(documents).values({
id: uuidv4(),
projectId: projectId,
title: 'Test Document',
content: 'Test Content',
type: 'note',
createdAt: new Date(),
updatedAt: new Date(),
});
await db.insert(tasks).values({
id: uuidv4(),
projectId: projectId,
title: 'Test Task',
description: 'Test Description',
status: 'open',
createdAt: new Date(),
updatedAt: new Date(),
});
// Add more test data as needed
});
// Clean up after each test
afterEach(async () => {
// Clean up all test data
await db.delete(documents).where(eq(documents.projectId, projectId));
await db.delete(tasks).where(eq(tasks.projectId, projectId));
await db.delete(projects).where(eq(projects.id, projectId));
// Clean up other tables as needed
});
it('should reset a project successfully', async () => {
// Mock the request
const { req, res } = createMocks({
method: 'DELETE',
});
// Call the API route handler
await DELETE(req, { params: { projectId } });
// Check if all associated data was deleted
const projectDocs = await db.select().from(documents).where(eq(documents.projectId, projectId));
expect(projectDocs.length).toBe(0);
const projectTasks = await db.select().from(tasks).where(eq(tasks.projectId, projectId));
expect(projectTasks.length).toBe(0);
// Check if project still exists but tasksImported is set to false
const updatedProject = await db.select().from(projects).where(eq(projects.id, projectId)).limit(1);
expect(updatedProject.length).toBe(1);
expect(updatedProject[0].tasksImported).toBe(false);
});
it('should return 400 for missing project ID', async () => {
// Mock the request
const { req, res } = createMocks({
method: 'DELETE',
});
// Call the API route handler with empty params
const result = await DELETE(req, { params: { projectId: '' } });
const data = await result.json();
expect(result.status).toBe(400);
expect(data.error).toBe('Project ID is required');
});
// More tests for other cases...
});
```
```typescript
// test/components/projects/reset-project.test.tsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ProjectSettingsPanel } from '@/components/projects/project-settings-panel';
import { resetProjectData } from '@/lib/db/projects/queries';
import { useRouter } from 'next/navigation';
// Mock the dependencies
jest.mock('next/navigation', () => ({
useRouter: jest.fn(),
}));
jest.mock('@/hooks/use-toast', () => ({
useToast: () => ({
toast: jest.fn(),
}),
}));
jest.mock('@/lib/db/projects/queries', () => ({
resetProjectData: jest.fn(),
}));
describe('Project Reset Button', () => {
const mockProject = {
id: 'test-project-id',
name: 'Test Project',
description: 'Test Description',
tasksImported: true,
};
const mockRouter = {
push: jest.fn(),
refresh: jest.fn(),
};
beforeEach(() => {
jest.clearAllMocks();
(useRouter as jest.Mock).mockReturnValue(mockRouter);
});
it('should render the reset button in the danger zone', () => {
render(&#x3C;ProjectSettingsPanel project={mockProject} />);
expect(screen.getByText('Reset Project')).toBeInTheDocument();
expect(screen.getByText(/This will delete all documents, tasks, and other data/)).toBeInTheDocument();
});
it('should open confirmation dialog when reset button is clicked', async () => {
render(&#x3C;ProjectSettingsPanel project={mockProject} />);
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
expect(screen.getByText('Are you sure you want to reset this project?')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Reset Project' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
});
it('should call reset API when confirmed', async () => {
(resetProjectData as jest.Mock).mockResolvedValue(undefined);
render(&#x3C;ProjectSettingsPanel project={mockProject} />);
// Click the reset button
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
// Click the confirm button in the dialog
const confirmButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(confirmButton);
// Check if API was called
expect(resetProjectData).toHaveBeenCalledWith(mockProject.id);
});
it('should show success dialog after reset', async () => {
(resetProjectData as jest.Mock).mockResolvedValue(undefined);
render(&#x3C;ProjectSettingsPanel project={mockProject} />);
// Click the reset button
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
// Click the confirm button in the dialog
const confirmButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(confirmButton);
// Wait for the success dialog to appear
await waitFor(() => {
expect(screen.getByText('Project Reset Successfully')).toBeInTheDocument();
});
// Click the "Go to Project" button
const goToProjectButton = screen.getByRole('button', { name: 'Go to Project' });
await userEvent.click(goToProjectButton);
// Verify navigation
expect(mockRouter.push).toHaveBeenCalledWith(`/app/projects/${mockProject.id}`);
expect(mockRouter.refresh).toHaveBeenCalled();
});
it('should handle API errors', async () => {
(resetProjectData as jest.Mock).mockRejectedValue(new Error('API error'));
render(&#x3C;ProjectSettingsPanel project={mockProject} />);
// Click the reset button
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
// Click the confirm button in the dialog
const confirmButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(confirmButton);
// Verify the toast was called (implementation depends on your toast setup)
// You could check for error elements or mock the toast function and verify it's called
});
});
```
## Required Files for Implementation
To implement this feature, the following files will be needed:
1. **New Files:**
- `app/api/projects/[projectId]/reset/route.ts`
- `lib/db/projects/reset.ts`
- `test/api/projects/reset.test.ts`
- `test/components/projects/reset-project.test.tsx`
2. **Files to Modify:**
- `components/projects/project-settings-panel.tsx`
- `lib/db/projects/queries.ts`
3. **Reference Files:**
- `lib/db/schema.ts`
- `components/ui/confirmation-dialog.tsx`
- `components/ui/button.tsx`
- `hooks/use-toast.ts`
- `app/(auth)/auth.ts`
This implementation plan provides a comprehensive guide for adding the reset functionality to the Project Details page, ensuring all required components, API endpoints, and tests are properly specified.

</plan>

Here are some requested instructions from the user. Follow these if possible, but do not do anything contrary to
your main instructions above:

<user-requested-instructions>
The repo consists of a Next JS 15 app in /app and a NPM JS CLI tool in /cli. The Next JS app is the SaaS has an API (see /app/api). The CLI tool integrates closely with the Next JS app (principally via its API), but is a separate codebase, with no code-sharing between the two.
When writing tests, do not import from jest/globals, they are already present for you.
When writing route.test.ts files (to test the API endpoints), do not mock out the database, instead create the data needed for the test via the schema.ts models in a beforeEach or beforeAll function, then surgically delete the data again in an afterAll/afterEach.
We use jest for coding - do not use vitest.
We use the toast hook for UI notifications: `import { useToast } from '@/hooks/use-toast';`
Always specify the use of the App Router pattern, not Page Router in Next JS.
Look at lib/db/schema.ts for the full data model.
We use drizzle for the ORM, make sure you do too and call it correctly.
The Next JS application has the marketing pages for the website (inside the app/(marketing) directory), and the SaaS app pages, which are inside the app/app directory. Most of the time we are working inside app/app
When working on the UI, use the ConfirmationDialog component from confirmation-dialog.tsx in place of document.confirm() when asking for user confirmation.
Use ShadCN components whenever possible.
Run pnpm lint:fix when you are done to make sure you have not introduced any lint errors.
You can run the UI tests using `pnpm test:ui` if you modified any UI or APIs.
When writing tests, do not import from jest/globals, they are already present for you.
When writing route.test.ts files (to test the API endpoints), do not mock out the database, instead create the data needed for the test via the schema.ts models in a beforeEach or beforeAll function, then surgically delete the data again in an afterAll/afterEach.
We use jest for coding - do not use vitest.
We use Next Auth for authentication, imported like this: `import { auth } from '@/app/(auth)/auth';`
We use the toast hook for UI notifications: `import { useToast } from '@/hooks/use-toast';`
</user-requested-instructions>

</data>

Please get started!

This was generated from a 2-sentence description I typed in to one of the Task Demon chatbot UIs. This prompt is 1035 lines long, which is on the longer side of what Task Demon will normally generate, but scrolling through it you can see why any agentic AI coding assistant would have a far better chance implementing the right thing given this, than given a 2 sentence hit-enter-and-hope vibe prompt.

So how does this all work? Characterization, Claude Code and Task Demon itself:

Characterization & Claude Code

Characterization is the way that Task Demon gets to know your project. It is a conversation between 2 agentic AIs - one runs in Task Demon's cloud servers, the other is Claude Code, running in your local environment. Mediating this conversation is a simple NPM module called the Task Demon CLI agent, which just acts as a conduit to allow Task Demon to drive Claude Code.

The Task Demon Characterization Agent starts the process by asking Claude Code for a detailed technical document describing your project at a high level - what languages it uses, whether it appears to be of a well-known framework layout, what dependencies it has, what the database schema looks like, and so on.

When it gets it back (via the Task Demon CLI Agent), the Characterization Agent analyzes this document and will either decide that the project is simple enough to be characterized by this document alone, or it will ask Claude Code for up to half a dozen followup documents on subjects like data schema, API endpoints, business logic, etc.

When the Characterization Agent is satisfied that it has learned enough about your project to be able to make competent plan preparation prompts, it declares the process done and then uses the Characterization as the basis for all of the Task processing it does, from triage to plan generation to task creation to implementation prompt generation.

Task Demon

Task Demon is an agentic AI SaaS application that upgrades your simple ticket descriptions into highly effective LLM prompts that help you Vibe Code like a grownup. Using Task Demon to drive Claude Code has more than doubled my output; often it seems more like a 10x increase.

Screenshot of 10+ tasks completed in a day with Task Demon
Knocking out large numbers of tickets is a lot easier with Task Demon

Claude Code by itself is already an immensely powerful tool for software engineering, but it's also a bottleneck in that it can only really do one thing at a time. With an excellent prompt containing a detailed plan, Claude Code can usually complete the task much faster than with a vibe prompt, and usually with minimal human intervention.

This stuff hasn't suddenly become magic - the reason Task Demon gives you a "Copy Prompt" button is that it's still expecting you to keep an eye on Claude Code (or whichever agent you use) as it does its thing. Task Demon does have a "YOLO Mode", but that's a topic for another day... for now Task Demon gets you much closer to a one-shot prompt for most tasks, but you are still going to want to refine or tweak things pretty often during its implementation.

Individual Mode Available Now; Team Plans Coming Soon

Today's release of Task Demon makes the Individual mode available to everyone, and I'm working on the Team mode now - expect it to be available in the next few weeks.

In the meantime I'm generally releasing updates multiple times per day, which you can see (as well as come get support) in the Task Demon Discord Server.

I write Task Demon by myself, and there's zero dollars of Venture Capital or other funding behind me. It's a paid product aimed at professionals who write code or otherwise contribute to software getting written. It has more than doubled my output, and its ROI measured against its cost is in the tens of thousands of percent. If you can't get at least a 10% productivity boost while using it, email me at support@taskdemon.ai and I'll a) try to make it work better for you and b) refund your money, no questions asked.

Try it out!

You can try out Task Demon for free at https://www.taskdemon.ai/trial - there's a limit of 100 free trials per month, but they reset every month.

Share Post:

What to Read Next

After exploring how Task Demon enhances productivity with agentic AI coding assistants, you might find How I built bragdoc.ai in 3 weeks intriguing as it shares insights into rapidly developing AI-driven projects. Additionally, Teams using Next.js and Vercel have an advantage discusses how these tools can offer a competitive edge, which complements the use of AI in software development.