# Flutter Controller Pattern

> Use when moving business logic out of Flutter widgets/providers into Riverpod controllers and needing clear boundaries for controller state, use-case orchestration, presentation intents, and controller-focused tests.

- Skill: `tomevault-io/flutter-controller-pattern` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/flutter-controller-pattern`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/flutter-controller-pattern/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/flutter-controller-pattern

---


# Flutter Controller Pattern

## Overview
Use controllers as application orchestrators: widgets dispatch intent, controllers coordinate use cases, and domain logic stays in use cases.

In this repo, `ToolExecutionController` is the reference pattern:
- state holder + query API + intent API in `apps/auravibes_app/lib/providers/tool_execution_controller.dart`
- stream/message manager delegates tool lifecycle to controller in `apps/auravibes_app/lib/providers/messages_manager_provider.dart`
- widgets render state and call intent methods in chat widgets.

## When to Use
- A provider/notifier is mixing state + business rules + side effects.
- Widgets contain permission/execution branching.
- A feature needs reusable intent methods (`run`, `grant`, `skip`, `stop`) across multiple widgets.

## When NOT to Use
- Pure computed read-only value providers.
- One-line UI-only state with no orchestration.

## Controller Responsibilities
- Keep a UI-oriented state model (small immutable entities used for rendering).
- Expose query methods for view logic (for example: `isToolRunning`, `hasRunningToolsForMessage`).
- Expose intent methods for user actions (`runTask`, `grantToolCall`, `skipToolCall`, `stopAllToolCalls`).
- Build/coordinate use cases inside controller methods with injected dependencies.
- Keep cleanup and failure-safe logic in controller (`try/finally`, guard clauses).

## Dependency Boundary Rule
- Default: controllers call use cases, not repositories.
- Allow direct repository calls only for thin reads with no business decisions, no branching by business state, and no cross-repository orchestration.
- If logic includes validation, permission checks, sequencing, metadata updates, retries, or combining dependencies, move it into a use case.
- If a controller method starts looking like domain behavior (not UI orchestration), extract/expand use cases first.

## UI Responsibilities
- Watch controller state and map it to presentation.
- Trigger controller intents from user actions.
- Avoid embedding business flow (permission checks, execution order, metadata updates) in widgets.

## Migration Pattern (old provider -> controller)
1. Extract orchestration logic from old provider into a `@Riverpod(keepAlive: true)` controller.
2. Keep domain rules in use cases and call them from controller methods.
3. Keep only rendering decisions in widgets.
4. Update existing managers/notifiers to delegate specialized flow to controller.

## Testing Guidance
- Controller unit tests:
  - state transitions for running/resolved/cleared flows.
  - guard clause behavior for missing entities/ids.
  - intent method behavior (`runTask`, `grant`, `skip`, `stop`).
  - failure safety (`finally` cleanup always runs).
- Orchestration tests:
  - verifies use cases are called with expected inputs and order.
  - verifies AI continuation only when all tools are resolved/granted.
- Widget tests:
  - verify widgets dispatch the correct controller intents.
  - verify pending/running/resolved UI branches from controller state + metadata.

## Common Mistakes
- Re-adding business rules inside widgets after controller extraction.
- Calling repositories directly from controllers for business actions.
- Storing raw domain-heavy payloads in controller state.
- Skipping query helpers and duplicating filters in UI files.
- Instantiating side-effect services directly in widgets.

## Quick Checklist
- Controller owns orchestration, widgets own presentation.
- Business actions go through use cases (repo access in controller is read-only exception).
- Controller state is minimal and UI-friendly.
- Intent/query APIs are explicit and reusable.
- Use cases remain the business rule boundary.
- Tests cover controller transitions, orchestration, and widget intent dispatch.

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/auravibes-apps) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-11 -->

