# Phase 3: ANCL Framework — Full Fidelity Lovable Clone

## Goal

Close every remaining gap between ANCL-generated output and the reference `sample_apps/lovable_clone` app. The framework already lowers a meaningful widget surface and infers dependencies. Phase 3 is about **runtime depth, visual polish, and semantic correctness** so the generated app is indistinguishable from the handwritten one.

---

## Phase 3 Completion Criteria

- [ ] `lovable_clone.ancl` parses without error  
- [ ] The compiler generates every screen, bloc, service, and widget  
- [ ] The generated app boots and navigates between Home → Chat → Preview  
- [ ] Attachment pick/display/remove works in the generated app  
- [ ] Chat thread renders user/assistant bubbles, markdown, and thinking indicator  
- [ ] Preview screen shows generated HTML via iframe/blob URL  
- [ ] Design tokens (fonts, colors, radii, shadows) match the reference exactly  
- [ ] Persistence (Isar) saves and restores projects and files  

---

## Remaining Phase 2 Blocker (must land first)

### Fix `p:14x0` Style Scalar Parsing in Grammar

> [!IMPORTANT]
> The ANCL V2 grammar `styleValue` accepts `number` before `styleValueText`, so `14x0` is parsed as `14` and the trailing `x0` causes `end of input expected`.

**Fix**: Update `styleValueText` regex in `ancl_grammar.dart` to explicitly accept the `NxM` scalar format (number × number), or re-order `styleValue` so `styleValueText` is tried first for non-pure-number tokens.

#### [MODIFY] [ancl_grammar.dart](file:///c:/Users/affan/Affan%20Projects/samaa/connectit/quickapp/lib/src/compiler/parser_v2/ancl_grammar.dart)
- In `styleValue()`, promote `styleValueText` above `number` **or** add a dedicated `dimensionScalar` rule that matches `\d+x\d+` before falling through to `number`.  
- Verify `p:14x0`, `m:8x0`, `m:12x8x12x16`, and `h:42` all parse.

---

## Phase 3 Tracks

---

### Track 1 · Grammar & Parser Hardening

**Why**: Several ANCL style and dimension patterns used in `lovable_clone.ancl` don't parse today.

#### [MODIFY] [ancl_grammar.dart](file:///c:/Users/affan/Affan%20Projects/samaa/connectit/quickapp/lib/src/compiler/parser_v2/ancl_grammar.dart)

- Add `dimensionScalar` rule → `\d+(x\d+){1,3}` (e.g. `14x0`, `12x8x12x16`)
- Add `percentDimension` rule → `\d+(\.\d+)?[hw]` (e.g. `0.8w`, `0.7h`)
- Re-order `styleValue` to match: `hexColor | dimensionScalar | percentDimension | number | quotedString | styleValueText`
- Add `conditionalExpr` rule to `expression()` for ternary syntax: `cond ? val : val`
- Ensure `actionRef` allows inline string literals like `ChangeView("home")`

---

### Track 2 · Screen-Local Stateful Generation (Priority 1)

**Why**: Both `home_view.dart` and `chat_view.dart` require `StatefulWidget` with local fields, controllers, `initState`, and `dispose`. ANCL screen state blocks already have syntax (`S(View){ field:Type, init(){}, dispose(){} }`) but the **compiler doesn't generate** the stateful code.

#### [MODIFY] [ast_to_ir.dart](file:///c:/Users/affan/Affan%20Projects/samaa/connectit/quickapp/lib/src/compiler/ir/ast_to_ir.dart)
- Detect whether a screen `S(...)` has state members or lifecycle declarations.
- Set an `hasLocalState: true` flag on `IRScreenNode`.
- Lower state members into `IRLocalField` entries in the screen IR.
- Lower `init()` and `dispose()` into `IRLifecycleBlock` entries.

#### [MODIFY] Screen code-generator (in `pipeline/`)
- When `hasLocalState` is true, emit a `StatefulWidget` + `State<>` class pair.
- Emit `late` fields for `TextEditingController` and `ScrollController`.
- Emit `initState()` and `dispose()` with proper controller lifecycle calls.
- Emit `setState((){})` when a local variable mutates (e.g. `_activeTab = t`).

---

### Track 3 · Attachment Runtime (Priority 2)

**Why**: `AddAttachment` / `RemoveAttachment` in the bloc are wired to `AttachmentService.pickFile()`, which does OS file picking, MIME detection, and base64 encoding. The compiler currently stubs this.

#### [NEW] Generated `lib/services/attachment_service.dart`
Generated by the pipeline when `@attachment` or `FilePick` token is detected. Template matches the reference `attachment_service.dart` exactly:
- `pickFile()` static method via `file_picker`
- MIME detection map
- Image → base64 data URI path
- Text → UTF-8 decode path
- `buildTextContext()` for prompt enrichment

#### [MODIFY] Pipeline dependency inference
- Auto-add `file_picker: ^8.0.0` and `mime: ^2.0.0` to `pubspec.yaml` when attachment service is generated.

#### [NEW] Generated `AttachmentTray` widget
- `AttachmentTray` ANCL token → generates a `Row` of dismissible chips (already has a reference in `lib/presentation/widgets/attachment_chips.dart`).
- Chips show file name + remove button wired to bloc `RemoveAttachmentEvent`.
- Image attachments show a thumbnail.

---

### Track 4 · Benchmark Chat Primitives (Priority 3)

**Why**: The chat screen is the most visible screen. It needs first-class primitives, not generic lists.

#### [NEW] Generated `lib/presentation/widgets/chat_thread.dart`
- `ChatThread` ANCL token → generates a `BlocBuilder`-wired `ListView` with auto-scroll.
- Role-aware bubble render: `user` → right-aligned dark chip; `assistant` → left-aligned card with `MarkdownBody`.
- Thinking indicator when `state.simulationStep == 1`.
- Copy affordance with `Clipboard.setData`.

#### [NEW] Generated `lib/presentation/widgets/composer.dart`
- `Composer` ANCL token → generates the sticky bottom row (text field + attachment button + send button).
- Wired to `SendMessageEvent` and `AddAttachmentEvent`.

#### [MODIFY] [ast_to_ir.dart](file:///c:/Users/affan/Affan%20Projects/samaa/connectit/quickapp/lib/src/compiler/ir/ast_to_ir.dart)
- Register `ChatThread`, `Composer`, `AttachmentTray` as first-class IR widget types with their codegen paths.

---

### Track 5 · Design System & Visual Fidelity (Priority 4)

**Why**: Generated output looks generic without branded tokens. The reference app uses Inter font, custom dark palette, `lucide_icons`, and nuanced spacing/radii.

#### [MODIFY] Generated `lib/theme/app_theme.dart`
- Generate a `ThemeData` with:
  - `colorScheme.background = #09090B`
  - `colorScheme.surface = #1C1C1E`
  - `GoogleFonts.inter()` as the base text theme
  - Custom `ButtonStyle` defaults (rounded, dark surfaced)
  - `CardTheme` with the reference dark card style

#### [MODIFY] Pipeline `main.dart` generation
- Set `debugShowCheckedModeBanner: false`
- Wire `AppTheme.dark()` into `MaterialApp`
- Add `ConstrainedBox(maxWidth: 448)` centering shell around the scaffold

#### [MODIFY] Icon lowering in code-generator
- When `Icon(LucideIcons.*)` is present in the IR, emit `LucideIcons.<name>` from the `lucide_icons` package.
- Auto-add `lucide_icons: ^1.1.0` to `pubspec.yaml`.

---

### Track 6 · Exact Preview Mode (Priority 5)

**Why**: The reference uses `dart:ui_web`, `dart:html`, and iframe/blob URLs for web-native HTML preview.

#### [NEW] Generated `lib/presentation/widgets/generated_html_preview.dart` (web path)
- On web: use `dart:ui_web` to register a platform view; inject an `<iframe>` with a `blob:` URL containing the generated HTML.
- On mobile: use `webview_flutter` with `loadHtmlString`.
- Expose a unified `GeneratedHtmlPreview(content: String)` widget for both platforms.

---

### Track 7 · Isar Persistence (Priority 6)

**Why**: Projects and files are persisted and restored across sessions via Isar.

#### [MODIFY] Pipeline schema generation
- `@schema:{ Project{...}, ProjectFile{...} }` → generate `lib/data/local/isar_schemas.dart` with `@collection` annotations.
- Generate `LocalStorage` singleton that opens Isar and exposes typed collections.

#### [MODIFY] Generated `main.dart`
- Await `LocalStorage.init()` before `runApp(...)`.
- Inject the `Isar` instance into the `LovableBloc` constructor.

---

## Verification Plan

### Automated
```
dart bin/quickapp.dart build sample_apps/lovable_clone/lovable_clone.ancl
cd output/lovable_clone && flutter pub get && flutter build web
```

### Manual
1. Run `flutter run -d chrome` on the generated app.
2. Verify Home screen renders with gradient background, badge, hero text, and composer.
3. Type a prompt → verify transition to Chat view.
4. Attach a file → verify chip appears and can be removed.
5. Wait for AI response → verify markdown bubble renders.
6. Click Preview → verify generated HTML renders in iframe.
7. Kill and reopen the app → verify project is restored from Isar.

---

## Implementation Order

| Step | Track | Effort | Impact |
|------|-------|--------|--------|
| 1 | Phase 2 blocker — style scalar grammar fix | S | Unblocks everything |
| 2 | Track 2 — stateful screen generation | M | Home + Chat fidelity |
| 3 | Track 5 — design system tokens | M | Visual polish |
| 4 | Track 3 — attachment runtime | M | Core feature |
| 5 | Track 4 — chat primitives | M | Core feature |
| 6 | Track 6 — exact preview | S | Preview fidelity |
| 7 | Track 7 — Isar persistence | M | Full runtime parity |
