AI RULES

Comprehensive guidelines for AI-assisted development within the Editor platform

AI Code Generation Rules - editor2 Platform

Critical Rules for AI Code Generators These rules MUST be followed when generating code for the editor2 platform.

Last Updated: December 27, 2025
Source: Adapted from gograb-modules + editor2 enhancements
Session: 14


Priority Levels

Priority Meaning Action
MUST Mandatory Violation breaks the system
SHOULD Strongly recommended Violation reduces quality
MAY Optional Enhancement when applicable
NEVER Forbidden Causes critical issues

Framework Rules (MUST)

Angular 20 Compliance

MUST_USE:
  - standalone: true                    # All components standalone
  - changeDetection: OnPush             # Always OnPush
  - inject(): true                      # Use inject() function, NOT constructor injection
  - signals: true                       # Prefer Signals over Observables for local state
  - Separate files: true                # .ts, .html, .scss files (best practice)

NEVER_USE:
  - NgModules                           # No module declarations
  - setTimeout                          # Use RxJS timer/delay instead (except tests)
  - Promises                            # Use RxJS Observables
  - any                                 # Use SafeAny if absolutely necessary
  - Constructor injection               # Use inject() function
  - Inline templates                    # Use separate .html files (maintainability)

State Management Hierarchy

ORDER_OF_PREFERENCE:
  1: Signals                            # Local component state, computed values
  2: autoFlashState                     # Persistent state with flash-persistence
  3: RxJS                               # Async operations, HTTP, events
  4: NGXS                               # High-level module state ONLY

SIGNALS_FOR:
  - Component local state
  - Derived/computed values
  - Service-level simple state

AUTO_FLASH_STATE_FOR:
  - User preferences
  - UI state that should persist
  - Module configuration
  - Draft data

RXJS_FOR:
  - HTTP requests
  - Event streams
  - Time-based operations
  - Complex async workflows

NGXS_FOR:
  - Global application state
  - Cross-module state
  - High-level module state

editor2-Specific Rules (MUST)

Intelligence Pyramid Integration

BEFORE_GENERATION:
  - MUST call preflight({ task: "description" })
  - Returns: Past decisions, conventions, warnings, patterns
  - Use returned context to inform generation

DURING_GENERATION:
  - SHOULD call find_similar({ query: "similar task" })
  - Use patterns from successful past generations

AFTER_GENERATION:
  - MUST call log_decision({
      type: "implementation",
      question: "What was decided?",
      chosen: "Selected approach",
      reasoning: "Why this approach",
      confidence: 0.9,
      files: ["affected files"]
    })

Three-Tier AI Architecture

TIER_1_DEVELOPMENT_AI:
  - Location: Cursor IDE with MCP
  - Purpose: Help developers during coding
  - Tools: preflight, log_decision, find_similar
  - Memory: .cursor/ai-memory/

TIER_2_PLATFORM_AI:
  - Location: backend-ai-api (port 3001)
  - Purpose: Generate modules and platforms
  - Services: WorkflowService, AgentProcessService
  - Memory: MongoDB ai-* databases

TIER_3_TENANT_AI:
  - Location: Per-space sandboxed
  - Purpose: Help end-users build spaces
  - Services: SpaceAgentOrchestrator
  - Memory: Per-tenant isolated data

Flash Persistence Integration (MUST)

FOR_PERSISTENT_STATE:
  - MUST use autoFlashState from @storage-system
  - Automatically syncs to IndexedDB
  - Automatically handles tenant context
  - Automatically handles conflicts

EXAMPLE:
  readonly settings = autoFlashState('user-settings', {
    theme: 'dark',
    layout: 'grid'
  });

NEVER:
  - Manual localStorage usage
  - Manual sessionStorage usage
  - Custom persistence logic

Theme System Integration (MUST)

FOR_ALL_STYLING:
  - MUST use CSS variables from theme-system
  - NEVER hardcode colors
  - NEVER hardcode fonts
  - ALWAYS use glassmorphism patterns

CORRECT:
  background: var(--ux-surface);
  color: var(--ux-text-primary);
  backdrop-filter: blur(16px);
  background: rgba(var(--ux-surface-rgb), 0.8);

WRONG:
  background: #ffffff;        # ❌ Hardcoded color
  color: black;               # ❌ Hardcoded color
  font-family: Arial;         # ❌ Not from theme

Library Integration Rules (MUST)

Import Order for editor2

// 1. Angular core
import { Injectable, inject, signal, computed } from '@angular/core';
import { Observable, of } from 'rxjs';

// 2. editor2 core libraries (in this order)
import { BrowserModuleContract, ModuleManifest, ModuleDecorator } from '@libs-core/module-base';
import { LoggerService } from '@libs-core/log-system';
import { EventBusService, DomainEvent } from '@libs-core/event-system';
import { authGuard, permissionGuard, roleGuard, ContextService } from '@libs-core/security';
import { BaseEntity, AuditFields, ApiResponse, Permission, SystemRoles } from '@libs-core/shared-models';
import { PublicAction, ExecutableAction, ActionContext, ActionParams } from '@libs-core/action-registry';
import { BaseRepository } from '@libs-core/data-access';

// 3. editor2 foundational libraries
import { autoFlashState, GgStorage } from '@storage-system';

// 4. Module local imports
import { moduleRoutes } from './module.routes';
import { EntityRepository } from './data/repositories';

Library Usage Patterns

@libs-core/module-base:
  - MUST implement BrowserModuleContract
  - MUST use @ModuleDecorator
  - MUST define ModuleManifest

@libs-core/log-system:
  - MUST use LoggerService.child() for scoped logging
  - Logger is tenant-aware automatically

@libs-core/security:
  - MUST protect all routes with authGuard
  - MUST use permissionGuard for resource access

@libs-core/shared-models:
  - MUST use BaseEntity for all entities
  - MUST check shared-models BEFORE creating local types

@libs-core/action-registry:
  - MUST use @PublicAction decorator
  - MUST implement ExecutableAction<T> interface

@libs-core/data-access:
  - MUST extend BaseRepository<T>
  - MUST use findAll(), findById(), create(), update(), delete()

@storage-system:
  - MUST use autoFlashState for persistent state
  - NEVER use localStorage directly

@theme-system:
  - MUST use CSS variables (var(--ux-*))
  - MUST use glassmorphism patterns
  - NEVER hardcode colors

Naming Conventions (MUST)

File Naming

Pattern: kebab-case
Examples:
  - user-management.module.ts
  - product-catalog.routes.ts
  - navigate-to-user.action.ts
  - user.repository.ts
  - user-list.component.ts
  - user-list.component.html      # Separate HTML file
  - user-list.component.scss      # Separate SCSS file

Class Naming

Pattern: PascalCase
Examples:
  Module:     UserManagementModule
  Action:     NavigateToUserAction
  Repository: UserRepository
  Component:  UserListComponent
  Service:    UserManagementService
  Event:      UserCreatedEvent

Permission Naming

Pattern: <resource>:<action>
Examples:
  - users:read
  - users:create
  - users:update
  - users:delete
  - users:manage

Action ID Naming

Pattern: <resource>:<action-verb>
Examples:
  - users:navigate-to-user
  - users:create-user
  - users:update-user
  - users:delete-user
  - products:navigate-to-product

Component Rules (MUST)

File Structure (CRITICAL - Best Practice)

MUST_USE_SEPARATE_FILES:
  reason: "Best practice for maintainability, team collaboration, editor support"
  structure: |
    component-name/
      ├── component-name.component.ts     # Logic
      ├── component-name.component.html   # Template
      └── component-name.component.scss   # Styles

CORRECT:
  templateUrl: './component-name.component.html'   # ✅ Separate file
  styleUrl: './component-name.component.scss'      # ✅ Separate file

WRONG:
  template: `...`                                  # ❌ Inline template
  styles: [`...`]                                  # ❌ Inline styles

Component Template (.ts file)

// component-name/component-name.component.ts

import { Component, inject, signal, computed, input, output, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LoggerService } from '@libs-core/log-system';

@Component({
  selector: 'lib-component-name',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './component-name.component.html',  // MUST use separate file
  styleUrl: './component-name.component.scss',     // MUST use separate file
  changeDetection: ChangeDetectionStrategy.OnPush, // MUST be OnPush
})
export class ComponentNameComponent implements OnInit {
  // MUST use inject() for dependencies
  private readonly logger = inject(LoggerService).child({ source: 'ComponentNameComponent' });

  // MUST use signals for local state
  readonly loading = signal(false);
  readonly data = signal<Data[]>([]);
  readonly error = signal<string | null>(null);

  // MUST use computed for derived values
  readonly isEmpty = computed(() => this.data().length === 0);
  readonly hasError = computed(() => this.error() !== null);

  // MUST use input() for inputs (Angular 20 style)
  readonly limit = input<number>(10);
  readonly showHeader = input<boolean>(true);

  // MUST use output() for outputs
  readonly itemSelected = output<Item>();

  ngOnInit(): void {
    this.loadData();
  }

  private loadData(): void {
    this.loading.set(true);
    // Implementation
  }
}

Component HTML Template

<!-- component-name/component-name.component.html -->

<div class="component-container">
  <header class="component-header" *ngIf="showHeader()">
    <h2>{{ title }}</h2>
  </header>

  @if (loading()) {
    <div class="loading-state">
      <p>Loading...</p>
    </div>
  } @else if (hasError()) {
    <div class="error-state">
      <p>{{ error() }}</p>
    </div>
  } @else {
    @if (isEmpty()) {
      <div class="empty-state">
        <p>No items found</p>
      </div>
    } @else {
      <div class="data-grid">
        @for (item of data(); track item.id) {
          <div class="data-item" (click)="onItemClick(item)">
            <h3>{{ item.name }}</h3>
            <p>{{ item.description }}</p>
          </div>
        }
      </div>
    }
  }
</div>

Component SCSS Styles

// component-name/component-name.component.scss

.component-container {
  padding: var(--spacing-4);
  backdrop-filter: blur(16px);
  background: rgba(var(--ux-surface-rgb), 0.8);
  border-radius: var(--radius-lg);
}

.component-header {
  margin-bottom: var(--spacing-4);
  
  h2 {
    color: var(--ux-text-primary);
    font-size: var(--font-size-xl);
    font-weight: 600;
  }
}

.loading-state,
.error-state,
.empty-state {
  padding: var(--spacing-8);
  text-align: center;
  color: var(--ux-text-secondary);
}

.error-state {
  color: var(--ux-error);
}

.data-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--spacing-4);
}

.data-item {
  padding: var(--spacing-4);
  backdrop-filter: blur(8px);
  background: rgba(var(--ux-surface-rgb), 0.6);
  border: 1px solid var(--ux-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    border-color: var(--ux-primary);
  }

  h3 {
    margin: 0 0 var(--spacing-2) 0;
    color: var(--ux-text-primary);
    font-size: var(--font-size-lg);
  }

  p {
    margin: 0;
    color: var(--ux-text-secondary);
    font-size: var(--font-size-sm);
  }
}

Repository Rules (MUST)

BaseRepository Methods (CRITICAL)

INHERITED_METHODS_FROM_BASE_REPOSITORY:
  findById(id: string): Observable<T | null>     # Get single entity by ID
  findAll(): Observable<T[]>                      # Get all entities
  create(entity: Partial<T>): Observable<T>       # Create new entity
  update(id: string, entity: Partial<T>): Observable<T>  # Update entity
  delete(id: string): Observable<boolean>         # Delete entity

CORRECT_USAGE:
  repository.findAll()                  # ✅ Correct
  repository.findById(id)               # ✅ Correct
  repository.create(data)               # ✅ Correct

WRONG_USAGE:
  repository.getAll()                   # ❌ WRONG - method does NOT exist
  repository.get(id)                    # ❌ WRONG - use findById()
  repository.save(data)                 # ❌ WRONG - use create() or update()

Repository Template

// data/repositories/entity.repository.ts

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { BaseRepository } from '@libs-core/data-access';
import { LoggerService } from '@libs-core/log-system';
import { Entity } from '../models/entity.model';

@Injectable({ providedIn: 'root' })
export class EntityRepository extends BaseRepository<Entity> {
  private readonly http = inject(HttpClient);
  private readonly logger = inject(LoggerService).child({ source: 'EntityRepository' });

  // MUST define static ENTITY_NAME
  static readonly ENTITY_NAME = 'entity';

  // MUST define protected properties
  protected entityName = 'entity';
  protected baseUrl = '/api/entities';

  // Inherited methods from BaseRepository:
  // - findAll(): Observable<Entity[]>
  // - findById(id: string): Observable<Entity | null>
  // - create(entity: Partial<Entity>): Observable<Entity>
  // - update(id: string, entity: Partial<Entity>): Observable<Entity>
  // - delete(id: string): Observable<boolean>

  // Add custom methods if needed:
  findByStatus(status: string): Observable<Entity[]> {
    this.logger.debug('Finding entities by status', { status });
    return this.http.get<Entity[]>(`${this.baseUrl}/by-status/${status}`);
  }
}

Route Rules (MUST)

Route Protection

// Every route MUST have guards:
canActivate: [authGuard, permissionGuard('resource:action')]

// Admin routes MUST include roleGuard:
canActivate: [authGuard, roleGuard(SystemRoles.ADMIN), permissionGuard('resource:manage')]

Route Data

// Every route MUST include data:
data: {
  title: 'Page Title',
  breadcrumb: 'Breadcrumb Text',
  permissions: ['resource:action'],
  animation: 'fade',           // Use flash-animations
  animationSpeed: 'fast'
}

Lazy Loading

// MUST use loadComponent for lazy loading:
{
  path: 'users',
  loadComponent: () => import('./components/user-list/user-list.component')
    .then(m => m.UserListComponent),
  data: { title: 'Users', permissions: ['users:read'] }
}

Module Structure (MUST)

Directory Structure

libs/libs-modules/<module-name>/
├── src/
│   ├── lib/
│   │   ├── actions/                    # Public actions
│   │   │   ├── index.ts
│   │   │   ├── navigate-to-entity.action.ts
│   │   │   ├── create-entity.action.ts
│   │   │   ├── update-entity.action.ts
│   │   │   └── delete-entity.action.ts
│   │   ├── components/                 # UI Components (separate files!)
│   │   │   ├── index.ts
│   │   │   ├── entity-list/
│   │   │   │   ├── entity-list.component.ts
│   │   │   │   ├── entity-list.component.html
│   │   │   │   └── entity-list.component.scss
│   │   │   ├── entity-detail/
│   │   │   │   ├── entity-detail.component.ts
│   │   │   │   ├── entity-detail.component.html
│   │   │   │   └── entity-detail.component.scss
│   │   │   └── entity-form/
│   │   │       ├── entity-form.component.ts
│   │   │       ├── entity-form.component.html
│   │   │       └── entity-form.component.scss
│   │   ├── data/                       # Data access
│   │   │   ├── repositories/
│   │   │   │   ├── index.ts
│   │   │   │   └── entity.repository.ts
│   │   │   └── index.ts
│   │   ├── embeddables/                # Widget components
│   │   │   ├── index.ts
│   │   │   └── entity-widget/
│   │   │       ├── entity-widget.component.ts
│   │   │       ├── entity-widget.component.html
│   │   │       └── entity-widget.component.scss
│   │   ├── events/                     # Domain events
│   │   │   ├── index.ts
│   │   │   └── entity.events.ts
│   │   ├── models/                     # Interfaces
│   │   │   ├── index.ts
│   │   │   ├── entity.model.ts
│   │   │   └── entity-filters.model.ts
│   │   ├── services/                   # Module services
│   │   │   ├── index.ts
│   │   │   └── entity-api.service.ts
│   │   ├── <module-name>.module.ts     # Main module class
│   │   └── <module-name>.routes.ts     # Angular routes
│   └── index.ts                        # Barrel exports
├── project.json
├── tsconfig.json
├── tsconfig.lib.json
└── README.md

Barrel Exports (MUST)

// src/index.ts
export * from './lib/<module-name>.module';
export * from './lib/<module-name>.routes';
export * from './lib/models';
export * from './lib/services';
export * from './lib/data';
export * from './lib/components';
export * from './lib/embeddables';
export * from './lib/actions';
export * from './lib/events';

Generation Workflow Integration (MUST)

Entry Points (MUST Know)

FOR_COMPLETE_PLATFORMS:
  - Route: /modularity/ai-platform
  - Service: WorkflowService (backend-ai-api)
  - Method: 5-phase workflow with SSE streaming
  - Output: Complete universe with multiple modules

FOR_SINGLE_MODULES:
  - Route: /modularity/workbench
  - Service: AgentProcessService (backend-ai-api)
  - Method: 6-step guided creation or 8-phase agent
  - Output: Single Nx library module

FOR_QUICK_MODULES:
  - Route: /modularity/ai-builder
  - Service: AIModuleGeneratorService
  - Method: Direct generation
  - Output: Module definition (can export to Nx library)

FOR_VISUAL_UNIVERSE_BUILDING:
  - Route: /modular-universe
  - Service: AI Panel + UniverseModuleService
  - Method: Drag-drop AI-generated modules
  - Output: Visual universe structure

Validation Requirements (MUST)

AFTER_GENERATION:
  - MUST validate file structure
  - MUST validate theme-system usage
  - MUST validate flash-persistence usage
  - MUST validate BrowserModuleContract implementation
  - MUST validate import order
  - MUST validate naming conventions
  - MUST provide auto-fix suggestions

VALIDATION_TOOLS:
  - MCP: validate_module tool
  - Service: ValidationService
  - Display: Real-time in UI with auto-fix buttons

Anti-Patterns (NEVER)

Code Anti-Patterns

NEVER:
  - NgModules (use standalone: true)
  - Constructor injection (use inject())
  - setTimeout in production (use RxJS timer/delay)
  - Promises (use RxJS Observables)
  - any type (use SafeAny if needed)
  - Inline templates (use separate .html files)
  - Inline styles (use separate .scss files)
  - Hardcoded colors (use CSS variables)
  - Direct localStorage (use autoFlashState)
  - Duplicate auth logic (use @libs-api/auth-core)
  - Hardcode database names (use constants)

Architecture Anti-Patterns

NEVER:
  - Create new storage systems (use @storage-system)
  - Create new theme systems (use @theme-system)
  - Bypass guards on routes
  - Skip Intelligence Pyramid (preflight, log_decision)
  - Generate code without validation
  - Deploy without testing

Quality Checklist

Before marking generation complete:

Code Quality

Integration Quality

Documentation Quality

Intelligence Pyramid


Reference Implementation

User Management Module: libs/core/user-management/

Use this as the gold standard for:


Related Documentation


Version: 1.0.0
Last Updated: December 27, 2025
Maintained By: editor2 development team