Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .gemini/commands/explain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
description = "Researches part of the codebase and creates a skill for it"
prompt="""
## Role

You are an experienced senior developer specializing in reverse engineering and understanding
complex code, prompt engineering, and context engineering.

Your task is to build a complete understanding of the mental model and architecture of the code,
and to create an efficient context file that allows a coding agent to understand and work with the
code.

## Guiding Principles

1. **Deep Analysis:** Understand the _why_ behind the code. Not just a surface level listing of
files and classes.

2. **Curiosity:** Be curious. If something is unclear, confusing, or unexpected you _MUST_
investigate further until you fully understand.

3. **Efficient Token Use:** The final output will be directly included into the context of the
coding assistant, so be sure to make efficient use of tokens. Think deeply, but only capture the
most important information for the coding agent in the final output

## Procedure

1. Fully explore the code before first, with a focus on understanding the architecture and how all
of the pieces fit together.

2. Develop an understanding of the mental model behind the architecture. _Why_ is the code is
architected this way? How should developers think about the system?

3. Document your findings using the given output format described in the next section.

## Output Format

Note the following placeholders below:

- `[package]`: is a unique identifier for the current code package (for example if you're looking at
code under `packages/forms/signals` you might use `signal-forms` as the `[package]`)
- `[code-location]`: is the location of the current code within the larger repository
- `[context]`: is the context to add to the coding agent when it is working with this code.

With those placeholders in mind, write a file create a new directory under `.gemini/skills` with the
name `reference-[package]/`, and under that directory add a `SKILL.md` file with the following
content:

```md
---
name: reference-[package]
description: Explains the mental model and architecture of the code under `[code-location]`. You MUST use this skill any time you plan to work with code in `[code-location]`
---

[context]
```

## Additional User Instructions

The user may have additional instructions.

- The user should indicate what package to research
- The user may indicate that they want to update a package that has already been researched. In this
case, read the existing skill and make any required updates based on your research
- The user may request supplemental information be added to the skill (if so, add this to the
existing skill in a new markdown file under a `references` directory within the skill. Add a
section to the main `SKILL.md` that mentions what supplemental information is available)

Here are the user's additional instructions:

{{args}}
"""
91 changes: 91 additions & 0 deletions .gemini/skills/reference-compiler-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
name: reference-compiler-cli
description: Explains the mental model and architecture of the code under `packages/compiler-cli`. You MUST use this skill any time you plan to work with code in `packages/compiler-cli`
---

# Angular Compiler CLI (`ngtsc`) Architecture

## Overview

The `packages/compiler-cli` package contains the Angular Compiler (Ivy), often referred to as `ngtsc`. It is a wrapper around the TypeScript compiler (`tsc`) that extends it with Angular-specific capabilities.

The core goal of `ngtsc` is to compile Angular decorators (like `@Component`, `@Directive`, `@Pipe`) into static properties on the class (Ivy instructions, e.g., `static ɵcmp = ...`). It also performs template type checking and ahead-of-time (AOT) compilation.

## Mental Model

The compiler is designed as a **lazy, incremental, and partial** compilation pipeline.

1. **Wrapper Pattern**: `NgtscProgram` wraps the standard `ts.Program`. It intercepts calls to act as a drop-in replacement for standard tooling.
2. **Traits System**: Every class with an Angular decorator is considered a "Trait". The compiler manages the state of these traits through a state machine:
- **Pending**: Detected but not processed.
- **Analyzed**: Metadata extracted, template parsed (but dependencies not yet linked).
- **Resolved**: Dependencies (directives/pipes in template) resolved, import cycles handled.
- **Skipped**: Not an Angular class.
3. **Lazy Analysis**: Analysis only happens when necessary (e.g., when diagnostics are requested or emit is prepared).
4. **Output AST**: The compiler generates an intermediate "Output AST" (`o.Expression`) for the generated code, which is then translated into TypeScript AST nodes during the emit phase.

## Key Subsystems

### 1. Core Orchestration (`ngtsc/core`)

- **`NgtscProgram`**: The public API implementing `api.Program`. It manages the `ts.Program` and the `NgCompiler`.
- **`NgCompiler`**: The brain of the compiler. It orchestrates the compilation phases (Analysis, Resolution, Type Checking, Emit). It holds the `TraitCompiler`.

### 2. Trait Compilation (`ngtsc/transform`)

- **`TraitCompiler`**: Manages the lifecycle of "Traits". It iterates over source files, identifies decorated classes, and delegates to the appropriate `DecoratorHandler`.
- **`Trait`**: A state container for a class, holding its handler, analysis results, and resolution results.

### 3. Decorator Handlers (`ngtsc/annotations`)

- **`DecoratorHandler`**: An interface for handling specific decorators.
- **`ComponentDecoratorHandler`**: The most complex handler. It:
- Extracts metadata (selector, inputs, outputs).
- Parses the template.
- Resolves used directives and pipes (`R3TargetBinder`).
- Generates the `ɵcmp` instruction.
- **`DirectiveDecoratorHandler`**, **`PipeDecoratorHandler`**, **`NgModuleDecoratorHandler`**: Handle their respective decorators.

### 4. Template Type Checking (`ngtsc/typecheck`)

- **`TemplateTypeChecker`**: Generates "Type Check Blocks" (TCBs). A TCB is a block of TypeScript code that represents the template's logic in a way `tsc` can understand and check for errors.
- **`TypeCheckBlock`**: The actual generated code that validates bindings, events, and structural directives.

### 5. Metadata & Scope (`ngtsc/metadata`, `ngtsc/scope`)

- **`MetadataReader`**: Reads Angular metadata from source files (using `LocalMetadataRegistry`) and `.d.ts` files (using `DtsMetadataReader`).
- **`ScopeRegistry`**: Determines the "compilation scope" of a component (which directives/pipes are available to it), handling `NgModule` transitive exports and Standalone Component imports.

### 6. Emit & Transformation (`ngtsc/transform`)

- **`ivyTransformFactory`**: A TypeScript transformer factory.
- **`IvyCompilationVisitor`**: Visits classes, triggers compilation via `TraitCompiler`, and collects the Output AST.
- **`IvyTransformationVisitor`**: Translates the Output AST into TypeScript AST, injects the `static ɵ...` fields, and removes the original decorators.

## Compilation Phases

1. **Construction**: `NgtscProgram` creates `NgCompiler`, which sets up all registries and the `TraitCompiler`.
2. **Analysis** (`analyzeSync`):
- The `TraitCompiler` scans files.
- `DecoratorHandler`s extract metadata and parse templates.
- No cross-file resolution happens here (allowing for parallelism and caching).
3. **Resolution** (`resolve`):
- `TraitCompiler` resolves traits.
- Components link their templates to specific Directives and Pipes (found via `ScopeRegistry`).
- Import cycles are detected and handled (e.g., via "remote scoping").
4. **Type Checking**:
- `TemplateTypeChecker` creates TCBs for all components.
- TypeScript diagnostics are retrieved for these TCBs.
5. **Emit** (`prepareEmit`):
- `ivyTransformFactory` is created.
- TS `emit` is called.
- The transformers run, injecting the compiled Ivy instructions into the JS/DTS output.

## Important File Locations

- `packages/compiler-cli/src/ngtsc/program.ts`: Entry point (`NgtscProgram`).
- `packages/compiler-cli/src/ngtsc/core/src/compiler.ts`: Core logic (`NgCompiler`).
- `packages/compiler-cli/src/ngtsc/transform/src/trait.ts`: Trait state machine.
- `packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts`: Component compilation logic.
- `packages/compiler-cli/src/ngtsc/typecheck/src/template_type_checker.ts`: Type checking logic.
- `packages/compiler-cli/src/ngtsc/transform/src/transform.ts`: AST transformation logic.
96 changes: 96 additions & 0 deletions .gemini/skills/reference-core/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
name: reference-core
description: Explains the mental model and architecture of the code under `packages/core`. You MUST use this skill any time you plan to work with code in `packages/core`
---

# Angular Core (`packages/core`) Mental Model

This document outlines the architecture and mental model for `packages/core`, the heart of the Angular framework.

## 1. High-Level Architecture

`packages/core` contains the runtime logic for Angular. Its primary responsibilities are:

1. **Rendering (Ivy/Render3)**: Transforming templates into DOM updates.
2. **Dependency Injection (DI)**: Managing object creation and lifetime.
3. **Change Detection**: Synchronizing the model with the view.
4. **Reactivity**: Signals and Zone.js integration.

## 2. Rendering Engine (Ivy / Render3)

The rendering engine (located in `packages/core/src/render3`) uses an **instruction-based** approach.

### Key Concepts

- **Instructions**: The Angular compiler transforms templates into a sequence of instruction calls (e.g., `ɵɵelementStart`, `ɵɵtext`, `ɵɵproperty`). These instructions are executed at runtime to create and update the view.
- _Location_: `packages/core/src/render3/instructions`

- **LView (Logical View)**: An array containing the _state_ of a specific view instance. It holds:
- DOM nodes (`RElement`, `RText`).
- Binding values (for change detection).
- Directive/Component instances.
- _Context_: `packages/core/src/render3/interfaces/view.ts`

- **TView (Template View)**: An array containing the _static structure_ of a view. It is shared across all instances (`LView`s) of the same component/template. It holds:
- Property names for bindings.
- Node relationship information.
- Compiled directive definitions.
- _Context_: `packages/core/src/render3/interfaces/view.ts`

- **Memory Layout**: `LView` and `TView` are parallel arrays. Index `i` in `LView` corresponds to metadata at index `i` in `TView`.
- `HEADER`: Fixed size, contains context (Parent, Host, etc.).
- `DECLS`: Static nodes (elements, text, pipes).
- `VARS`: Binding values.
- `EXPANDO`: Dynamic data (host bindings, injectors).

### The Render Cycle

1. **Creation Mode**: Instructions create DOM nodes and store them in `LView`.
2. **Update Mode**: Instructions check current values against previous values stored in `LView`. If changed, they update the DOM.

## 3. Dependency Injection (DI)

DI in Angular is hierarchical and split into two systems that interact:

### Module Injector (`R3Injector`)

- Configured via `@NgModule.providers` or `providedIn: 'root'`.
- Stored in a hierarchy of `R3Injector` instances.
- _Location_: `packages/core/src/di/r3_injector.ts`

### Node Injector

- Configured via `@Component.providers` or `@Directive.providers`.
- **Not a class**, but a data structure embedded in the `LView` ("Expando" section).
- Uses **Bloom Filters** (`TView.data`) to quickly check if a token is present at a specific node index before traversing up the tree.
- Resolves tokens starting from the current node, walking up the view tree (Element Injector hierarchy), and falling back to the Module Injector if not found.

## 4. Change Detection

- **Dirty Checking**: Angular checks if values bound in templates have changed.
- **Strategies**:
- `Default`: Checks everything.
- `OnPush`: Checks only if inputs change, events fire, or signals update.
- **Signals**: The new reactivity primitive. Signals notify the scheduler when they change, potentially allowing for fine-grained updates (Zoneless).

## 5. Key Directories to Know

- `src/render3`: The Ivy rendering engine.
- `instructions`: The runtime instructions called by compiled code.
- `interfaces`: `LView`, `TView`, `TNode` definitions.
- `src/di`: Dependency injection system.
- `src/change_detection`: Change detection logic.
- `src/zone`: Zone.js integration.
- `src/signal`: Signals implementation (if present in this version, otherwise likely in `primitives`).

## 6. Conventions & Gotchas

- **Prefixes**: Private/Internal exports often start with `ɵ`.
- **Global State**: Ivy relies heavily on global state (e.g., `getLView()`) during instruction execution to avoid passing context arguments everywhere. This is for performance and code size.
- **Performance**: The code is highly optimized for performance and memory. You will see arrays used instead of objects, bitmasks, and manual memory management patterns. **Respect these patterns.**

## 7. How to Modify Core

1. **Understand the Instruction**: If modifying runtime behavior, find the corresponding instruction in `src/render3/instructions`.
2. **Check `LView`/`TView` Impact**: If adding state, understand where it fits in the `LView` array.
3. **Tests**: Core has extensive tests. Run them using Bazel.
104 changes: 104 additions & 0 deletions .gemini/skills/reference-signal-forms/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
name: reference-signal-forms
description: Explains the mental model and architecture of the code under `packages/forms/signals`. You MUST use this skill any time you plan to work with code in `packages/forms/signals`
---

# Signal Forms Architecture

The `packages/forms/signals` directory contains an experimental, signal-based forms API for Angular.
This system differs significantly from the existing Reactive and Template-driven forms.

## Mental Model

1. **Model-Driven**: The system is built around a `WritableSignal<T>` which serves as the **single source of truth**.
Unlike Reactive Forms where the `FormControl` holds the value, here the `Signal` holds the value.
The form is merely a _view_ or _projection_ of that signal, adding form-specific state (validity, dirty, touched).

2. **Proxy-Based Traversal**: The form API (`form(signal)`) returns a `FieldTree`. This object is a **Proxy**.
It allows accessing nested fields (e.g., `myForm.user.name`) without manually creating control groups.
Accessing a property on the proxy lazily resolves or creates the corresponding `FieldNode`.

3. **Schema-Based Logic**: Validation, disabled state, and other metadata are defined separately via **Schemas**.
Schemas are applied to the form structure using functions like `apply`, `applyEach` (for arrays), and `applyWhen`.
This separates the _structure_ of the data from the _rules_ governing it.

4. **Directives as Glue**: The `[formField]` directive binds a DOM element (native input or custom control) to a `FieldNode`.
It handles:
- Syncing the value between the DOM and the Signal.
- Reflecting state (valid, touched, etc.) to the UI.
- Handling user interaction events (blur, input).

## Key Components

### 1. `FieldNode` (`src/field/node.ts`)

The central internal class representing a single field in the form graph. It aggregates several state managers:

- `structure`: Manages parent/child relationships and signal slicing.
- `validationState`: Computes `valid`, `invalid`, `errors` signals.
- `nodeState`: Tracks `touched`, `dirty`, `pristine`.
- `metadataState`: Stores metadata like `min`, `max`, `required`.
- `submitState`: Tracks submission status and server errors.

### 2. `ValidationState` (`src/field/validation.ts`)

Manages the complexity of validation:

- **Synchronous Errors**: Derived from schema rules.
- **Asynchronous Errors**: Handled via signals, including 'pending' states.
- **Tree Errors**: Errors that bubble up or are targeted at specific fields.
- **Submission Errors**: Server-side errors injected imperatively via `submit()`.

### 3. `FormField` Directive (`src/directive/form_field_directive.ts`)

The bridge between the `FieldNode` and the DOM.

- Selector: `[formField]`
- It supports:
- **Native Elements**: `<input>`, `<select>`, `<textarea>`.
- **Custom Controls**: Components implementing `FormUiControl` or `FormValueControl`.
- **Legacy Interop**: Components implementing `ControlValueAccessor` (via `InteropNgControl`).

### 4. `Schema` (`src/api/structure.ts` & `src/api/rules`)

Defines the behavior.

- Created via `schema(fn)`.
- Applied via `apply(path, schema)`.
- Rules include validators (`required`, `pattern`, `min`, `max`) and state modifiers (`disabled`, `hidden`).

## Data Flow

1. **Read**: `form.field.value()` reads directly from the underlying signal (projected to the specific path).
2. **Write**: Writing to the form (e.g., via UI) updates the underlying signal.
3. **Validation**: A computed effect observes the value signal and runs validators defined in the schema.

## Usage Example (Conceptual)

```typescript
// 1. Define Model
const user = signal({name: '', age: 0});

// 2. Define Schema
const userRules = schema((u) => {
required(u.name);
min(u.age, 18);
});

// 3. Create Form
const userForm = form(user, userRules); // OR apply(userForm, userRules)

// 4. Bind in Template
// <input [formField]="userForm.name">
```

## Important Files

- `packages/forms/signals/src/api/structure.ts`: Public API entry points (`form`, `apply`).
- `packages/forms/signals/src/api/control.ts`: Interfaces for custom controls (`FormUiControl`).
- `packages/forms/signals/src/field/node.ts`: The `FieldNode` implementation.
- `packages/forms/signals/src/directive/form_field_directive.ts`: The `[formField]` directive.

## Supplemental Information

- [Compiler & Core Integration](references/integration.md): Details how `[formField]` hooks into type-checking and the runtime.
Loading