Angular patterns — standalone components, signals, inject(), reactive forms, HTTP interceptors, and new control flow
95
94%
Does it follow best practices?
Impact
99%
2.75xAverage score across 4 eval scenarios
Passed
No known issues
{
"context": "Tests whether the agent proactively applies Angular best practices when building a polling notification component. The task describes only business requirements -- it says nothing about takeUntilDestroyed, signals, inject(), standalone, or OnPush. The agent should apply these patterns on its own.",
"type": "weighted_checklist",
"checklist": [
{
"name": "takeUntilDestroyed for polling cleanup",
"description": "The polling interval subscription uses takeUntilDestroyed() from @angular/core/rxjs-interop to automatically unsubscribe on component destroy, NOT manual unsubscribe in ngOnDestroy.",
"max_score": 14
},
{
"name": "toSignal or signal for reactive state",
"description": "The unread count and/or notification list are stored as signals (via toSignal() or signal()), NOT as plain class properties assigned in subscribe callbacks.",
"max_score": 12
},
{
"name": "inject() for dependency injection",
"description": "Services and DestroyRef are injected using the inject() function, NOT constructor parameter injection.",
"max_score": 12
},
{
"name": "Service uses catchError with fallback",
"description": "Both service methods pipe through catchError and return sensible fallback values rather than letting errors propagate unhandled.",
"max_score": 12
},
{
"name": "Service uses map() to unwrap response",
"description": "The service uses map() to extract the nested data from the API response wrapper objects.",
"max_score": 8
},
{
"name": "Standalone component",
"description": "The notification bell component uses standalone: true. No NgModule is created.",
"max_score": 10
},
{
"name": "OnPush change detection",
"description": "The component uses changeDetection: ChangeDetectionStrategy.OnPush.",
"max_score": 8
},
{
"name": "New control flow syntax",
"description": "Templates use @if and @for (with track) instead of *ngIf and *ngFor structural directives.",
"max_score": 10
},
{
"name": "providedIn root on service",
"description": "The notification service uses @Injectable({ providedIn: 'root' }).",
"max_score": 6
},
{
"name": "Functional interceptor or error handling pattern",
"description": "Error handling in the service distinguishes error types or provides meaningful console error logging before returning the fallback, not silently swallowing errors.",
"max_score": 8
}
]
}