This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
frontendcritical PriorityID: angular-19-signal-graph-cycle-quarantine-standard

Angular 19 Signal-Based Reactive Graph Cycle Quarantine Standard

Enforces architectural quarantine mechanisms against reactive graph circularity and microtask starvation in zoneless Angular 19 applications. Eliminates cascading downstream signal writes, misuse of allowSignalWrites in effects, and un-isolated high-frequency event ingestion within the reactive graph. Mandates untracked boundary containment and computed derivation purity to ensure deterministic change detection passes.

Prohibited Anti-Pattern: Cyclic Signal Mutations via Cascading Effects and Unbounded High-Frequency State Writes

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Angular 19 Signal-Based Reactive Graph Cycle Quarantine Standard - Enforces architectural quarantine mechanisms against reactive graph circularity and microtask starvation in zoneless Angular 19 applications. Eliminates cascading downstream signal writes, misuse of allowSignalWrites in effects, and un-isolated high-frequency event ingestion within the reactive graph. Mandates untracked boundary containment and computed derivation purity to ensure deterministic change detection passes.
globs: src/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/angular-19-signal-graph-cycle-quarantine-standard"
---

# Angular 19 Signal-Based Reactive Graph Cycle Quarantine Standard

> **Severity**: CRITICAL | **Category**: frontend
> **Anti-Pattern Warning**: Cyclic Signal Mutations via Cascading Effects and Unbounded High-Frequency State Writes

## System Constraints
You are a Principal Angular Architect enforcing zero-cycle reactive graph standards in zoneless Angular 19 systems. You must reject any reactive derivation implemented via side-effect writes, enforce strict unidirectional state flow with computed primitives, mandate untracked() boundaries for ancillary reads, and ensure high-frequency streams are quarantined before mutating the reactive graph.

## Strict Guidelines
- Engineers MUST NEVER use effect() to synchronize or transform state between signals; all reactive derivations MUST use computed() to guarantee cycle-free unidirectional flow.
- Engineers MUST NOT enable { allowSignalWrites: true } in effect() configurations; this option is an anti-pattern that hides cyclic feedback loops and induces microtask exhaustion.
- Engineers MUST wrap secondary reads inside untracked() when an effect executes an external imperative boundary (e.g., logging, DOM manipulations, analytics) to prevent accidental dependency registration.
- Engineers MUST quarantine high-frequency streaming inputs (e.g., WebSockets, mouse moves, telemetry) using RxJS schedulers, debounce, or audit windows prior to calling signal.set() or signal.update().
- Services MUST encapsulate writable signals as private and expose them strictly as readonly Signal<T> via asReadonly() to prevent external consumers from introducing circular mutation vectors.
- Components NEVER read and mutate the same signal graph node within lifecycle hooks or reactive contexts without an explicit batching or untracked boundary.

## Bad vs Good Implementations
### Anti-Pattern: Inter-Signal Synchronization via Effect with allowSignalWrites

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using effect() with allowSignalWrites: true to project state into another writable signal causes multiple change detection passes, risks infinite loops if downstream signals feed back into multiplier, and violates zoneless change detection scheduling constraints.
```typescript
import { Component, signal, effect, inject } from '@angular/core';
import { MetricsService } from './metrics.service';

@Component({
  selector: 'app-telemetry-monitor',
  standalone: true,
  template: `<div>Rate: {{ normalizedRate() }}</div>`
})
export class TelemetryMonitorComponent {
  private metrics = inject(MetricsService);
  
  rawCounter = signal(0);
  normalizedRate = signal(0);

  constructor() {
    // DANGEROUS: Circular vulnerability & multi-pass dirty checking
    effect(() => {
      const current = this.rawCounter();
      const baseMultiplier = this.metrics.multiplier();
      // Mutating another signal inside effect triggers immediate microtask invalidation
      this.normalizedRate.set(current * baseMultiplier);
    }, { allowSignalWrites: true });
  }
}
```

#### Production Standard (Correct)
> **Standard**: Deriving state via computed() produces an immutable, memoized reactive node evaluated lazily on demand. It guarantees topological evaluation ordering and eliminates runtime cycle hazards without triggering synthetic change detection cycles.
```typescript
import { Component, signal, computed, inject } from '@angular/core';
import { MetricsService } from './metrics.service';

@Component({
  selector: 'app-telemetry-monitor',
  standalone: true,
  template: `<div>Rate: {{ normalizedRate() }}</div>`
})
export class TelemetryMonitorComponent {
  private metrics = inject(MetricsService);
  
  readonly rawCounter = signal(0);
  
  // PURE: Cycle-safe topological dependency derivation
  readonly normalizedRate = computed(() => {
    return this.rawCounter() * this.metrics.multiplier();
  });
}
```

### Anti-Pattern: Implicit Effect Dependency Loop with External Analytics

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The effect implicitly tracks interactionCount(), causing the tracking effect to execute erroneously on button clicks even when filterQuery has not changed, creating unintended reactive coupling.
```typescript
import { Component, signal, effect, inject } from '@angular/core';
import { AnalyticsTracker } from './analytics.tracker';

@Component({
  selector: 'app-filter-view',
  standalone: true,
  template: `<button (click)="increment()">Filter</button>`
})
export class FilterViewComponent {
  private tracker = inject(AnalyticsTracker);
  filterQuery = signal('active');
  interactionCount = signal(0);

  constructor() {
    effect(() => {
      // Intent: send analytics when filterQuery changes
      const query = this.filterQuery();
      // Bug: Reading interactionCount() accidentally registers it as a dependency
      this.tracker.logQuery(query, this.interactionCount());
    });
  }

  increment() {
    this.interactionCount.update(c => c + 1);
  }
}
```

#### Production Standard (Correct)
> **Standard**: Wrapping secondary reads in untracked() quarantines the dependency graph. The effect only fires when filterQuery emits, preventing spurious side-effect cascades and maintaining stable execution frequency.
```typescript
import { Component, signal, effect, untracked, inject } from '@angular/core';
import { AnalyticsTracker } from './analytics.tracker';

@Component({
  selector: 'app-filter-view',
  standalone: true,
  template: `<button (click)="increment()">Filter</button>`
})
export class FilterViewComponent {
  private tracker = inject(AnalyticsTracker);
  readonly filterQuery = signal('active');
  readonly interactionCount = signal(0);

  constructor() {
    effect(() => {
      const query = this.filterQuery();
      // Quarantine secondary dependencies to isolate graph updates
      const count = untracked(() => this.interactionCount());
      this.tracker.logQuery(query, count);
    });
  }

  increment() {
    this.interactionCount.update(c => c + 1);
  }
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Angular 19 Signal-Based Reactive Graph Cycle Quarantine Standard

Angular 19 Signal-Based Reactive Graph Cycle Quarantine Standard defines an industrial-grade behavioral standard for frontend engineering. Enforces architectural quarantine mechanisms against reactive graph circularity and microtask starvation in zoneless Angular 19 applications. Eliminates cascading downstream signal writes, misuse of allowSignalWrites in effects, and un-isolated high-frequency event ingestion within the reactive graph. Mandates untracked boundary containment and computed derivation purity to ensure deterministic change detection passes. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Cyclic Signal Mutations via Cascading Effects and Unbounded High-Frequency State Writes Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftCyclic Signal Mutations via Cascading Effects and Unbounded High-Frequency State WritesCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST NEVER use effect() to synchronize or transform state between signals

Engineers MUST NEVER use effect() to synchronize or transform state between signals; all reactive derivations MUST use computed() to guarantee cycle-free unidirectional flow.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT enable { allowSignalWrites

Engineers MUST NOT enable { allowSignalWrites: true } in effect() configurations; this option is an anti-pattern that hides cyclic feedback loops and induces microtask exhaustion.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST wrap secondary reads inside untracked() when an effect executes an external imperative boundary (e.g., logging, DOM manipulations, analytics) to prevent accidental dependency registration.

Engineers MUST wrap secondary reads inside untracked() when an effect executes an external imperative boundary (e.g., logging, DOM manipulations, analytics) to prevent accidental dependency registration.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST quarantine high-frequency streaming inputs (e.g., WebSockets, mouse moves, telemetry) using RxJS schedulers, debounce, or audit windows prior to calling signal.set() or signal.update().

Engineers MUST quarantine high-frequency streaming inputs (e.g., WebSockets, mouse moves, telemetry) using RxJS schedulers, debounce, or audit windows prior to calling signal.set() or signal.update().

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST encapsulate writable signals as private and expose them strictly as readonly Signal<T> via asReadonly() to prevent external consumers from introducing circular mutation vectors.

Services MUST encapsulate writable signals as private and expose them strictly as readonly Signal<T> via asReadonly() to prevent external consumers from introducing circular mutation vectors.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Components NEVER read and mutate the same signal graph node within lifecycle hooks or reactive contexts without an explicit batching or untracked boundary.

Components NEVER read and mutate the same signal graph node within lifecycle hooks or reactive contexts without an explicit batching or untracked boundary.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Angular 19 Signal-Based Reactive Graph Cycle Quarantine Standard critical for AI coding assistants?

Enforces architectural quarantine mechanisms against reactive graph circularity and microtask starvation in zoneless Angular 19 applications. Eliminates cascading downstream signal writes, misuse of allowSignalWrites in effects, and un-isolated high-frequency event ingestion within the reactive graph. Mandates untracked boundary containment and computed derivation purity to ensure deterministic change detection passes. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Cyclic Signal Mutations via Cascading Effects and Unbounded High-Frequency State Writes) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related FRONTEND Rules

View all rules →
frontend
119

SolidStart 1.0 Server Functions & Async Boundaries Production Standard

SolidStart 1.0 relies on the Vinxi bundler to split `server$` closures into independent HTTP POST RPC endpoints. Direct lexical closure over client signals within `server$` scopes or failure to demarcate async boundaries with `<Suspense>` causes silent serialization failures, client-bundle secret leaks, and SSR hydration mismatches. Enforcing strict parameter passing, runtime input validation, and Solid async primitives maintains security and fine-grained reactivity across network boundaries.

frontend
119

Astro 5 Actions & Content Layer Production Standard

Enforces strict type safety and architectural correctness for Astro 5 Server Actions and the zero-waterfall Content Layer API. Prevents runtime contract mismatches, hydration mismatches, and unhandled mutation exceptions across dynamic and prerendered boundaries. Failure to follow these patterns leads to silent data fetching waterfalls, build-time cache corruptions, and unhandled server action exceptions.

frontend
51

Nuxt 4 Nitro Server Engine & Shared Directory Production Standard

Nuxt 4 enforces strict boundary segregation between client UI in the app/ directory, backend endpoints in server/, and universal contracts in shared/. Violating cross-boundary isolation or maintaining module-scoped state in Nitro server handlers causes catastrophic cross-request data corruption and hydration mismatches under concurrent production traffic. Architects must enforce request-isolated H3 event contexts, universal serialization schemas, and strict path-alias boundaries.

1 Rule in Stack

Angular