Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Le Mie Competenze
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automazione Processi
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sistemi Custom
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
🚀
Democratizzare la Tecnologia
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
💡
Unire Informatica ed Economia
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
🎯
Creare Soluzioni su Misura
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Trasforma la Tua Attività con la Tecnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Nuovo
Visualizza
Reinvention With Agentic AI Learning Program
Anthropic
Dicembre 2024
Nuovo
Visualizza
Agentic AI Fluency
Anthropic
Dicembre 2024
Nuovo
Visualizza
AI Fluency for Students
Anthropic
Dicembre 2024
Nuovo
Visualizza
AI Fluency: Framework and Foundations
Anthropic
Dicembre 2024
Nuovo
Visualizza
Claude with the Anthropic API
Anthropic
Dicembre 2024
Visualizza
Master SQL
RoadMap.sh
Novembre 2024
Visualizza
Oracle Certified Foundations Associate
Oracle
Ottobre 2024
Visualizza
People Leadership Credential
Connect
Settembre 2024
💻 Linguaggi & Tecnologie
☕Java
🐍Python
📜JavaScript
🅰️Angular
⚛️React
🔷TypeScript
🗄️SQL
🐘PHP
🎨CSS/SCSS
🔧Node.js
🐳Docker
🌿Git
💼
12/2024 - Presente
Custom Software Engineering Analyst
Accenture
Bari, Puglia, Italia · Ibrida
Analisi e sviluppo di sistemi informatici attraverso l'utilizzo di Java e Quarkus in Health and Public Sector. Formazione continua su tecnologie moderne per la creazione di soluzioni software personalizzate ed efficienti e sugli agenti.
💼
06/2022 - 12/2024
Analista software e Back End Developer Associate Consultant
Links Management and Technology SpA
Esperienza nell'analisi di sistemi software as-is e flussi ETL utilizzando PowerCenter. Formazione completata su Spring Boot per lo sviluppo di applicazioni backend moderne e scalabili. Sviluppatore Backend specializzato in Spring Boot, con esperienza in progettazione di database, analisi, sviluppo e testing dei task assegnati.
💼
02/2021 - 10/2021
Programmatore software
Adesso.it (prima era WebScience srl)
Esperienza nell'analisi AS-IS e TO-BE, evoluzioni SEO ed evoluzioni website per migliorare le performance e l'engagement degli utenti.
🎓
2018 - 2025
Laurea in Informatica
Università degli Studi di Bari Aldo Moro
Bachelor's degree in Computer Science, focusing on software engineering, algorithms, and modern development practices.
📚
2013 - 2018
Diploma - Sistemi Informativi Aziendali
Istituto Tecnico Commerciale di Maglie
Technical diploma specializing in Business Information Systems, combining IT knowledge with business management.
Contattami
Hai un progetto in mente? Parliamone! Compila il form qui sotto e ti risponderò al più presto.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
07 - Debugging with Cursor AI: Find and Fix Bugs 3x Faster
Debugging is one of the most time-consuming activities in a developer's daily work. Studies from
Microsoft and Google consistently show that senior developers spend between 30 and 40 percent of
their productive time finding and fixing bugs. With AI-native IDEs, that figure is dropping fast.
Developers using Cursor with an optimized debugging workflow report up to 65 percent reduction in
time spent debugging - not because AI is infallible, but because it transforms a solitary,
often frustrating process into a structured, systematic collaboration.
This article goes beyond "ask AI to fix your bug." We explore Cursor's specific debugging
features: the Debug Mode introduced in Cursor 2.2, the Bugbot
system for proactive PR review, and advanced strategies for memory leaks, race conditions,
and flaky tests in TypeScript and Angular. By the end, you will have a repeatable debugging
workflow that transforms bug hunting from a dark art into a verifiable engineering process.
What You Will Learn in This Article
How Cursor 2.2 Debug Mode works and its runtime-log-based agent loop
Bugbot: proactive bug detection on pull requests with automatic autofix
Cmd+K and inline chat workflow for instant stack trace analysis
Setting up the TypeScript/Angular debugger with source maps in Cursor
AI strategies for memory leaks, race conditions, and flaky tests
Integration with Chrome DevTools and the native VS Code debugger
Anyone who has spent three hours staring at a stack trace only to discover the problem was
an undefined on a nullable field knows exactly what we are talking about.
Traditional debugging carries an enormous cognitive load: you must hold the entire program
state in your head, formulate hypotheses, add logs, reproduce the bug, interpret results,
and iterate. Each interruption - a new log statement to add, a breakpoint to reposition -
breaks concentration and forces a mental context switch.
Developers using Cursor for debugging do not eliminate this process - they accelerate it
radically. The key insight is that AI can simultaneously hold the entire codebase context
in "memory" while you focus on the high-level logic. Cursor 2.2 formalized this approach
with Debug Mode, a completely redesigned agent loop built around runtime
information and human verification.
Traditional Debugging vs AI-Assisted: The Numbers
Activity
Traditional
With Cursor AI
Saving
Stack trace analysis
15-30 min
2-5 min
~80%
Root cause identification
1-4 hours
20-45 min
~70%
Fix and verification
30-90 min
10-25 min
~65%
Memory leak investigation
2-6 hours
45-90 min
~70%
Race condition detection
4-12 hours
1-3 hours
~75%
Flaky test stabilization
2-8 hours
30-60 min
~80%
Debug Mode: Cursor 2.2's Agent Loop
On December 10, 2025, Cursor released version 2.2 introducing Debug Mode,
one of the most significant features in the IDE's history. This is not a simple integration
of the VS Code debugger with AI - it is a completely redesigned agent loop built around
runtime information and human collaboration.
How the Debug Loop Works
The fundamental difference from generic AI-assisted debugging is that Debug Mode does not
immediately try to generate a fix. Instead, it follows a five-phase process:
The Debug Mode Cycle
Hypothesis Generation: Cursor reads the codebase and generates multiple
hypotheses about what might be wrong, without assuming it knows the cause
Instrumentation: The agent adds targeted runtime logs at the points
identified as likely sources of the problem
Guided Reproduction: Cursor asks the user to reproduce the bug with
instrumentation in place and collects runtime data
Targeted Fix: Based on real data, proposes a minimal, precise fix
rather than a speculative rewrite
Verification and Cleanup: After verification, removes all instrumentation
leaving a clean diff ready to commit
To activate Debug Mode, open the Composer panel, click the dropdown next to the send button,
and select "Debug Mode". From that point, the agent will operate in this loop instead of
proceeding directly with code changes.
// Example: how Cursor instruments code during Debug Mode
// File: src/app/services/payment.service.ts
// BEFORE instrumentation
async processPayment(order: Order): Promise<PaymentResult> {
const cart = await this.cartService.getCart(order.userId);
const total = this.calculateTotal(cart);
return this.paymentGateway.charge(order.paymentMethod, total);
}
// AFTER instrumentation added by Cursor Debug Mode
async processPayment(order: Order): Promise<PaymentResult> {
console.log('[DEBUG:cursor] processPayment called', {
orderId: order.id,
userId: order.userId,
paymentMethod: order.paymentMethod
});
const cart = await this.cartService.getCart(order.userId);
console.log('[DEBUG:cursor] cart retrieved', {
cartId: cart?.id,
itemCount: cart?.items?.length,
cartIsNull: cart === null
});
const total = this.calculateTotal(cart);
console.log('[DEBUG:cursor] total calculated', { total, cartTotal: cart?.total });
const result = await this.paymentGateway.charge(order.paymentMethod, total);
console.log('[DEBUG:cursor] payment result', { success: result.success, error: result.error });
return result;
}
// After reproduction, Cursor sees in the logs:
// [DEBUG:cursor] cart retrieved { cartId: undefined, itemCount: undefined, cartIsNull: false }
// This reveals that cart exists but items is undefined - bug found!
The targeted instrumentation approach is powerful because it eliminates guesswork. Instead
of rewriting code based on hypotheses, Cursor gathers concrete evidence before acting.
The final result is always a minimal diff: only the necessary fix, without unsolicited
refactoring or unrequested feature additions.
When Debug Mode is Most Effective
Intermittent bugs that do not always reproduce (race conditions, timing issues)
Problems in legacy code you do not know well
Bugs that only appear in production with real data
Errors with deep stack traces crossing multiple libraries
Unexpected behaviors without explicit errors (silent failures)
Debug Mode is less useful for compilation errors or obvious TypeScript errors,
where Cmd+K inline is much faster.
Bugbot: Proactive Bug Detection on PRs
While Debug Mode resolves bugs after they manifest, Bugbot attempts to
intercept them before they reach production. Released as version 1 in July 2025 and
significantly enhanced with Bugbot v11 in January 2026, it integrates into the code
review process by automatically analyzing every pull request.
How Bugbot Works
Bugbot analyzes the PR diff using multiple parallel passes, each with a different ordering
of the changes to stimulate different reasoning patterns in the model. Results are combined
with majority voting to reduce false positives. This approach, similar to an ensemble of
human reviewers, has demonstrated the ability to catch real bugs that pass unnoticed
in traditional code reviews.
// Example Bugbot rules configuration in .cursor/bugbot.rules
// These rules customize what Bugbot considers a bug in your project
# Rules for Angular/TypeScript project
## Dangerous Patterns
- Flag any use of 'any' in public service functions
- Report non-null assertion operators '!' on Angular input properties
- Highlight subscribe() without corresponding unsubscribe() or takeUntilDestroyed()
- Warn when a SQL migration has no corresponding rollback
## Project Invariants
- Components must not access HttpClient directly, only through services
- All forms must have both client-side AND server-side validation
- Do not use localStorage directly, use StorageService
## False Positives to Ignore
- *.spec.ts files may use 'any' for mocks
- Configuration files may have non-null assertions
Bugbot Autofix: Automatic Resolution
The most powerful feature of Bugbot v11 is Autofix: when Bugbot identifies
a bug in a PR, it can automatically spawn a Cloud Agent to implement the fix. The agent
proposes changes as a PR comment or additional commit, allowing the reviewer to accept or
reject the fix with a single click.
// Bug found by Bugbot on PR #142:
// File: src/app/components/user-profile/user-profile.component.ts
// PROBLEM: Memory leak - Observable not unsubscribed
@Component({
selector: 'app-user-profile',
template: `<div>{{ user?.name }}</div>`
})
export class UserProfileComponent implements OnInit {
user: User | null = null;
constructor(private userService: UserService) {}
ngOnInit() {
// BUGBOT: Observable subscription without unsubscribe
// Causes memory leak when component is destroyed
this.userService.getCurrentUser().subscribe(user => {
this.user = user;
});
}
}
// FIX PROPOSED BY BUGBOT AUTOFIX:
@Component({
selector: 'app-user-profile',
template: `<div>{{ user?.name }}</div>`
})
export class UserProfileComponent {
private destroyRef = inject(DestroyRef);
user: User | null = null;
constructor(private userService: UserService) {
this.userService.getCurrentUser()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(user => {
this.user = user;
});
}
}
Fast Debugging with Cmd+K and Inline Chat
For most everyday bugs, Debug Mode and Bugbot are powerful but sometimes oversized tools.
The fastest way to resolve obvious bugs in Cursor is through Cmd+K (inline edit)
and the Chat panel.
Instant Stack Trace Analysis
When an exception appears in the console or terminal, the most effective workflow is:
Select the entire stack trace in the console
Press Cmd+Shift+L to add the selection to the chat context
Write: "Analyze this stack trace and identify the root cause. Show where in the code the problem is located and propose a minimal fix."
Cursor does not just read the first line of the error. It follows the file paths in the stack,
retrieves the relevant code from your project, and mentally reconstructs the call chain
that caused the exception.
// Real stack trace from an Angular NgRx app
ERROR TypeError: Cannot read properties of undefined (reading 'items')
at CartComponent.getItemCount (cart.component.ts:47:35)
at CartComponent_Template (cart.component.html:12:18)
at executeTemplate (core.mjs:11223)
at refreshView (core.mjs:11094)
at refreshComponent (core.mjs:12147)
at refreshChildComponents (core.mjs:11060)
// What you ask Cursor:
// "This stack trace comes from an Angular NgRx app.
// CartComponent.getItemCount accesses 'items' on a property
// that turns out to be undefined. Analyze cart.component.ts and
// the corresponding store to find where the data is not initialized."
// Cursor responds by analyzing:
// 1. cart.component.ts - how the store is accessed
// 2. cart.reducer.ts - the reducer's initial state
// 3. cart.selectors.ts - the selectors used in the component
// And identifies:
// PROBLEM in cart.reducer.ts:
const initialState: CartState = {
// 'items' is missing! The initial state lacks the property
loading: false,
error: null
// items: [] <-- this line is missing
};
// FIX:
const initialState: CartState = {
items: [], // added
loading: false,
error: null
};
Cmd+K for Contextual Inline Fixes
When you have already identified the problematic line, Cmd+K is the fastest
way to apply a fix. Select the problematic code, press Cmd+K, and describe the problem in
natural language. Cursor modifies only the selected code without touching the rest of the file.
// Select this code in an Angular service and press Cmd+K:
getUserData(id: string) {
return this.http.get(`/api/users/
#123;id}`);
}
// Type: "add error handling, strong typing with User interface,
// and a 5-second timeout"
// Cursor generates:
getUserData(id: string): Observable<User> {
return this.http.get<User>(`/api/users/#123;id}`).pipe(
timeout(5000),
catchError((error: HttpErrorResponse) => {
if (error.status === 404) {
return throwError(() => new Error(`User #123;id} not found`));
}
if (error.name === 'TimeoutError') {
return throwError(() => new Error('Request timed out'));
}
return throwError(() => new Error('Failed to load user data'));
})
);
}
Setting Up the TypeScript/Angular Debugger in Cursor
Cursor uses the same debugging engine as VS Code, which means all launch.json
configurations you know work identically. The difference is that Cursor adds an AI layer
around the process to help you interpret what is happening and fix issues faster.
Source Maps Setup for TypeScript
The fundamental requirement for effective TypeScript debugging is correct source map
configuration. Without source maps, the debugger points to compiled JavaScript files
instead of the original TypeScript sources, making it impossible to read the code
during debugging.
// tsconfig.json - base configuration for debugging
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"sourceMap": true, // REQUIRED for TS debugging
"inlineSources": true, // Include source in source maps
"inlineSourceMap": false, // Use separate .map files
"outDir": "./dist",
"strict": true,
"moduleResolution": "node"
}
}
Memory Leaks, Race Conditions, and Flaky Tests with AI
These three categories of bugs are historically the hardest to debug because they are
non-deterministic. They manifest intermittently, often only in production or under load,
and attempts to isolate them frequently make them disappear. Cursor's AI brings a significant
advantage precisely here: it can statically analyze code to identify patterns that
lead to these bugs, even before they manifest at runtime.
Memory Leaks in Angular: Diagnosis and Fix
The most common memory leak in Angular is an unmanaged RxJS subscription. But many other
problematic patterns exist that Cursor learns to recognize in your specific project.
Race conditions in Angular often emerge when multiple asynchronous HTTP requests complete
in unpredictable order, or when component state gets updated after the component has been
destroyed. The classic example is a search box where the user types quickly.
// Classic Angular race condition: concurrent HTTP requests
// User types quickly in a search box - each keystroke launches
// a new request, but they may not arrive in order
// PROBLEM:
@Component({
selector: 'app-search',
template: `
<input (input)="onSearch($event)">
<div *ngFor="let result of results">{{ result.title }}</div>
`
})
export class SearchComponent {
results: SearchResult[] = [];
constructor(private searchService: SearchService) {}
onSearch(event: Event) {
const query = (event.target as HTMLInputElement).value;
// RACE CONDITION: if user types "an" then "ang", the response
// for "an" might arrive AFTER "ang", showing wrong results
this.searchService.search(query).subscribe(results => {
this.results = results;
});
}
}
// SOLUTION with switchMap (generated by Cursor):
@Component({
selector: 'app-search',
template: `
<input [formControl]="searchControl">
<div *ngFor="let result of results$ | async">{{ result.title }}</div>
`
})
export class SearchComponent {
searchControl = new FormControl('');
private destroyRef = inject(DestroyRef);
results$ = this.searchControl.valueChanges.pipe(
debounceTime(300), // Wait 300ms after last keystroke
distinctUntilChanged(), // Ignore if value hasn't changed
filter(query => (query?.length ?? 0) >= 2), // Min 2 characters
switchMap(query => // Cancel previous request
this.searchService.search(query ?? '').pipe(
catchError(() => of([])) // Handle errors without breaking the stream
)
),
takeUntilDestroyed(this.destroyRef)
);
constructor(private searchService: SearchService) {}
}
Flaky Tests: Stabilization Strategies
Flaky tests - tests that pass and fail intermittently - are one of the most frustrating
problems in modern development. Cursor is particularly effective at identifying causes
because it can simultaneously analyze the test, the tested code, and timing patterns.
// Flaky test in Angular: async/await and timing problems
// This test fails about 30% of the time
// FLAKY TEST:
it('should update user when form is submitted', fakeAsync(() => {
const fixture = TestBed.createComponent(UserFormComponent);
const component = fixture.componentInstance;
fixture.detectChanges();
component.nameControl.setValue('John Doe');
component.onSubmit();
// Problem: the test doesn't wait for Observable completion
expect(component.successMessage).toBe('User updated successfully');
}));
// What you ask Cursor:
// "This test is flaky - it fails intermittently. Analyze
// UserFormComponent and identify why the test is non-deterministic.
// Propose a stable version of the test."
// STABLE TEST (generated by Cursor):
it('should update user when form is submitted', fakeAsync(() => {
const userServiceSpy = jasmine.createSpyObj('UserService', ['updateUser']);
userServiceSpy.updateUser.and.returnValue(of({ success: true }).pipe(delay(100)));
TestBed.configureTestingModule({
declarations: [UserFormComponent],
providers: [
{ provide: UserService, useValue: userServiceSpy }
]
});
const fixture = TestBed.createComponent(UserFormComponent);
const component = fixture.componentInstance;
fixture.detectChanges();
component.nameControl.setValue('John Doe');
component.onSubmit();
// Advance virtual time by 100ms to complete the delay
tick(100);
fixture.detectChanges();
expect(component.successMessage).toBe('User updated successfully');
expect(userServiceSpy.updateUser).toHaveBeenCalledOnceWith({
name: 'John Doe'
});
}));
AI-Assisted Performance Profiling
Performance debugging is a discipline in itself: it is not about finding errors but about
understanding why something is slow. Cursor does not replace dedicated profilers like
Chrome DevTools or Angular DevTools, but dramatically accelerates the process of
interpreting profiling data and implementing optimizations.
// Example workflow: optimizing a slow Angular component
// Angular DevTools identified that this component
// causes 850ms of change detection on every input
// Problematic component (data from profiler):
@Component({
selector: 'app-large-table',
template: `
<table>
<tr *ngFor="let item of processedItems">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ formatDate(item.createdAt) }}</td>
<td>{{ calculateTotal(item) }}</td>
</tr>
</table>
`
})
export class LargeTableComponent {
@Input() items: RawItem[] = [];
// PROBLEM 1: getter recalculated on every change detection cycle
get processedItems() {
return this.items.map(item => this.processItem(item));
}
// PROBLEM 2: function called in template - recreated every time
formatDate(date: Date): string {
return new Intl.DateTimeFormat('en-US').format(date);
}
// PROBLEM 3: expensive computation in template
calculateTotal(item: RawItem): number {
return item.prices.reduce((acc, price) => acc + price.amount, 0);
}
private processItem(item: RawItem): ProcessedItem { /* ... */ }
}
// OPTIMIZED VERSION (generated by Cursor with explanation):
@Component({
selector: 'app-large-table',
template: `
<table>
<tr *ngFor="let item of processedItems; trackBy: trackById">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.formattedDate }}</td>
<td>{{ item.total }}</td>
</tr>
</table>
`,
changeDetection: ChangeDetectionStrategy.OnPush // FIX 3: OnPush CD
})
export class LargeTableComponent {
private _items: RawItem[] = [];
processedItems: ProcessedItem[] = [];
@Input() set items(value: RawItem[]) {
this._items = value;
// FIX 1: compute only when input changes, not on every CD cycle
this.processedItems = value.map(item => this.processItem(item));
}
// FIX 2: trackBy to prevent unnecessary DOM recreation
trackById(index: number, item: ProcessedItem): string {
return item.id;
}
private dateFormatter = new Intl.DateTimeFormat('en-US');
private processItem(item: RawItem): ProcessedItem {
return {
...item,
// Pre-compute everything during transformation
formattedDate: this.dateFormatter.format(item.createdAt),
total: item.prices.reduce((acc, price) => acc + price.amount, 0)
};
}
}
The Complete Debugging Workflow: Reproduce, Isolate, Fix, Test
Having individual powerful features is not enough. The real competitive advantage comes from
integrating these tools into a repeatable, systematic workflow. Here is the workflow that
the most productive Cursor users have standardized.
Phase 1: Reproduce with Maximum Context
Before touching the code, gather all available information about the bug. With Cursor,
this means providing the AI with the richest possible context.
// Template for the first debugging message in Cursor Chat:
/*
BUG REPORT:
- Expected behavior: [description]
- Observed behavior: [description]
- Frequency: [always / intermittent at X%]
- Environment: [dev / staging / prod]
- Last related change: [commit hash or feature name]
ERROR OUTPUT:
[paste the complete stack trace here]
STEPS TO REPRODUCE:
1. [step 1]
2. [step 2]
FILES LIKELY INVOLVED:
- src/app/services/order.service.ts
- src/app/components/checkout/checkout.component.ts
@codebase analyze the relevant files and propose the top 3
hypotheses for the root cause, ordered by probability.
*/
Phase 2: Isolate with a Minimal Test
After identifying the most probable hypothesis, ask Cursor to create a test that reproduces
the bug in isolation. This has two benefits: it verifies the hypothesis and provides an
automatic regression test.
// Prompt to create an isolation test:
// "Based on the analysis, the bug appears to be in
// OrderService.calculateDiscount() when items has elements
// with quantity: 0. Create a Jest unit test that reproduces
// exactly this scenario and verifies the correct behavior."
// Cursor generates:
describe('OrderService.calculateDiscount', () => {
let service: OrderService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(OrderService);
});
// Test that reproduces the bug
it('should handle items with zero quantity without throwing', () => {
const orderWithZeroQty = {
items: [
{ id: '1', price: 100, quantity: 2 },
{ id: '2', price: 50, quantity: 0 }, // problematic case
{ id: '3', price: 75, quantity: 1 }
],
discountCode: 'SAVE10'
};
// BUG: this throws instead of returning 0
expect(() => service.calculateDiscount(orderWithZeroQty)).not.toThrow();
expect(service.calculateDiscount(orderWithZeroQty)).toBe(17.5);
});
});
Phase 3: Fix with Incremental Verification
// Prompt for the fix:
// "The isolation test confirms the bug. The problem is in calculateDiscount
// where quantity === 0 causes a division by zero in the average unit price
// calculation. Fix calculateDiscount to handle the quantity === 0 case
// and ensure all existing tests continue to pass."
// Cursor analyzes and generates the fix:
calculateDiscount(order: Order): number {
const validItems = order.items.filter(item => item.quantity > 0); // FIX
if (validItems.length === 0) {
return 0;
}
const subtotal = validItems.reduce(
(sum, item) => sum + (item.price * item.quantity),
0
);
const discount = this.discountService.getDiscount(order.discountCode);
return subtotal * (discount / 100);
}
Best Practices for AI-Assisted Debugging
1. Always Provide Precise Context
AI-assisted debugging is only as effective as the context you provide. The difference between
a vague prompt and a precise one can be the difference between 10 minutes and 2 hours of work.
Principles for Effective Debugging Prompts
Complete stack trace: always 5-10 lines, not just the first
Expected vs observed behavior: be explicit about both
File context: use @filename.ts to include relevant files
Last change: mention the commit or feature if the bug is recent
Environment: dev/staging/prod often changes behavior
Frequency: always/intermittent/only under load
2. Never Blindly Trust AI Fixes
AI can generate fixes that resolve the symptom but not the cause. The correct workflow is
always: understand the proposed fix, verify with tests, and consciously approve.
Anti-Pattern: Accepting Fixes Without Understanding Them
The "vibe debugging" pattern - asking AI to fix a bug, accepting the first proposal
without understanding it, pushing to production - is the fastest way to accumulate
technical debt. Every fix must be:
Understood at the logic level
Verified with at least one test
Reviewed for unintended side effects
3. Use Cursor Rules for Debugging Standards
You can configure specific Cursor Rules for debugging that instruct the AI about your
project's patterns, preventing fixes that violate your conventions.
// .cursor/rules/debugging.mdc
---
name: Debugging Standards
globs: ["src/**/*.ts", "src/**/*.spec.ts"]
---
# Debugging Standards for This Project
## When proposing a fix for a bug:
1. Explain the root cause in at most 3 sentences
2. Show the PROBLEMATIC code first with comment // PROBLEM:
3. Show the CORRECTED version with comment // FIX:
4. Add a regression test for the problematic case
## Patterns to avoid in fixes:
- Do not use 'any' as a temporary fix for TypeScript errors
- Do not add try/catch without specific error handling
- Do not use '!' (non-null assertion) to silence nullable errors
- Do not modify tests to make them pass instead of fixing the code
## Preferred patterns:
- Use Optional Chaining (?.) for nullable accesses
- Use Nullish Coalescing (??) for default values
- Use type guards for narrowing
- Use catchError with specific error types in RxJS
Traditional vs AI-Assisted Debugging: When to Use Each
AI does not replace all debugging approaches. There are scenarios where manual traditional
debugging is still superior or complementary.
Guide: Which Approach to Use
Scenario
Recommended Approach
Tool
TypeScript / compilation error
Cmd+K inline
Cursor inline edit
Stack trace with runtime error
Chat with file context
Cursor Chat + @file
Intermittent bug / race condition
Debug Mode
Cursor Debug Mode (2.2)
Progressive memory leak
Profiler + AI analysis
Chrome DevTools + Cursor Chat
Performance regression
Profiler + AI optimization
Angular DevTools + Cursor
Bug in unknown legacy code
Debug Mode + @codebase
Cursor Debug Mode + context
Hardware / low-level debugging
Native debugger
gdb/lldb, manual breakpoints
Security vulnerability
Manual code review
Cursor + expert human review
Conclusions: Building an AI-Assisted Debugging Culture
Debugging with Cursor AI is not simply a matter of tools - it is a mindset shift. The most
productive developers do not "ask AI to fix bugs" - they build a structured dialogue with
the AI, providing precise context, verifying hypotheses with tests, and using the right
tool for each type of problem.
Cursor 2.2's Debug Mode represents a qualitative leap: it is no longer necessary to be
an expert in the codebase to debug effectively. The hypothesis-driven approach with
runtime instrumentation drastically reduces time spent guessing. Bugbot shifts part of
the bug detection burden to the code review moment, reducing the number of bugs
that reach production.
For Angular teams, the gain is particularly significant in historically challenging areas:
subscription leaks, race conditions in Observables, async flaky tests, and change detection
performance. Cursor knows these patterns and recognizes them quickly, where a less
experienced developer might spend hours.
Checklist to Start AI-Assisted Debugging
Configure launch.json with source maps enabled
Enable sourceMap: true in tsconfig.json
Create Cursor Rules for your project's debugging standards
Practice the "BUG REPORT" template in debugging prompts
Experiment with Debug Mode on a real bug in your codebase
Configure Bugbot if you use pull requests (GitHub/GitLab)
Integrate the workflow: reproduce - test - fix - verify with Cursor
Continue the Cursor IDE Series
You have completed the debugging article. Continue with the other articles in the series: