Flutter AI Harness: A Repo Template That Gives AI Coding Tools a Readable Engineering Contract
Flutter AI Harness: From Code Generation to Verifiable Engineering Collaboration
A production-oriented AI Harness open-source template, and a discussion on project contracts, task closed loops, architectural boundaries, and multi-tool adaptation.
Project address: https://github.com/bladeofgod/flutter-ai-harness
Abstract
AI programming tools can already handle page implementation, bug fixes, test supplementation, and code reviews. What truly affects long-term efficiency is no longer just the quality of a single generation, but whether AI can consistently understand the same set of engineering rules, modify code within clear boundaries, and deliver results that can be stably verified.
Flutter AI Harness is a repository template for Flutter and Android/iOS hybrid projects. It does not encapsulate AI as an application runtime capability. Instead, it places the project contract, Commands, Agents, Skills, task cards, Reviews, quality gates, and tool adaptations into the code repository, allowing AI and developers to share the same set of engineering facts.
This template also provides a local e-commerce Demo, but the Demo is only a reference implementation. The more important usage is to let AI read the Harness design and tailor and modify it according to the existing project's tech stack and constraints.
1. Code Generation Is Not a Complete Engineering Capability
In a short task, AI can easily demonstrate high efficiency: building a page from a screenshot, supplementing an interface, or fixing an exception often yields runnable results quickly. But when modifications span multiple modules, or code needs continuous iteration, the problem shifts from "can it generate" to "how to constrain it."
An engineering project must at least answer the following questions:
- Who defines the tech stack and architectural invariants;
- What dependencies are allowed between packages and Features;
- How requirements are broken down into independently verifiable tasks;
- Which files can be edited, and which files can only be maintained by generators;
- When static checks, unit tests, platform builds, and runtime verifications are triggered;
- How issues found in Review enter the fix and re-review cycle, rather than staying in a report.
If this information only exists in chat logs or personal experience, it must be re-explained in every conversation, and rules can easily become invalid after multiple rounds of modification. The faster AI executes, the sooner structural drift may appear.
Harness solves exactly this layer of problems: it does not replace coding tools but provides them with readable engineering context, executable processes, and verifiable feedback.
2. The Four-Layer Structure of Harness
Flutter AI Harness divides the engineering control plane into four layers:
- Project Contract: Defines the tech stack, directory responsibilities, dependency direction, data boundaries, and generated file rules.
- Workflow Assets: Uses Commands to describe processes, Agents to describe roles, Skills to provide on-demand knowledge, and Memory to store low-frequency, long-term effective experience.
- Execution and Assembly: Task cards enter implementation, and code is verified through focused tests and platform runs.
- Verification and Feedback: Static gates, read-only Reviews, UI Specs, evidence archiving, and CI constitute the delivery feedback.
Figure 1: Rules, processes, execution, and verification together constitute the Harness. Simply adding prompts cannot replace this closed loop.
These four layers are not meant to increase the number of processes but to clarify the lifecycle of different information. Stable invariants should enter the project contract; specific technical knowledge should be loaded per task; one-time implementation requirements should stay in the task card; only experience reusable across tasks should enter Memory.
This distinction reduces context waste. AI does not need to load all platform specifications, all historical Reviews, and all business modules for every task. It only needs to read the project contract and then supplement relevant Commands, Agents, or Skills based on the current task.
3. How the Source of Truth in the Repository Is Organized
The core structure of the current repository is as follows:
flutter-ai-harness/
├── CLAUDE.md Authoritative project contract
├── AGENTS.md Codex entry point
├── .claude/ Command, Agent, Skill, and Memory source of truth
├── .agents/ Generated Codex Skill adaptation
├── .codex/ Generated Codex Agent adaptation
├── docs/ Architecture, tasks, Reviews, and design inputs
├── scripts/ Git Hooks and executable quality gates
└── app/ Flutter Workspace and reference Demo
Here, CLAUDE.md is responsible for defining repository-level invariants, and .claude/ is the single source of truth for AI engineering assets. The AGENTS.md, Skill, and Agent configurations required by Codex are deterministically generated by repository tools, rather than maintaining another set of documents with similar content.
This design solves the common configuration drift in multi-tool collaboration: Claude and Codex can retain their own discovery and invocation mechanisms, but the engineering rules they read come from the same source. After modifying Commands, Agents, or Skills, generation checks prevent outdated adaptation layers from entering commits.
docs/ is also not an undifferentiated document collection. The current conventions are:
| Location | Content Saved | What Not to Save |
|---|---|---|
docs/tasks/ |
Incomplete task cards | Fictional plans and fixed Sprint hierarchies |
docs/tasks/done/ |
Completed tasks and acceptance info | Reusable project knowledge |
docs/reviews/ |
Review reports and test evidence | Unreproducible verbal conclusions |
docs/app-operator/ |
Manually scheduled UI Spec, Audit, Run | Default gates for ordinary tasks |
.claude/memories/ |
Low-frequency, long-term effective engineering experience | Task logs and repeated specifications |
Separating task artifacts from long-term knowledge facilitates traceability and prevents Memory from continuously expanding as the project progresses.
4. Boundary Design of the Flutter Workspace
The Demo in the template uses Flutter Pub Workspace and Melos to manage multiple Packages. The current dependency direction is:
apps/demo -> app_features, app_data, app_im, app_core, app_ui
app_features -> app_data, app_im, app_core, app_ui
app_data / app_im -> app_core
app_core / app_ui -> no other workspace packages
The arrow here indicates that the left Package can depend on the right Package. apps/demo is at the top layer, responsible for global services, routing, and dependency assembly; app_core and app_ui are at the base layer and cannot reference business implementations in reverse.
The responsibilities of each Package are not complex:
app_coreprovidesApiClient,ApiTransport, storage abstractions, logging, and platform-independent infrastructure;app_dataprovides Domain Entities, Fixtures, LocalDataSources, Mappers, and future protocol or persistence adapters;app_uistores design Tokens and general UI without business rules;app_imstores messaging infrastructure, not Feature pages;app_featuresstores business API abstractions, Controllers, Pages, Routes, and Feature implementations;apps/demoonly does assembly and does not directly depend on Feature internal implementation classes.
Data Type Boundaries
Data passed across layers uniformly uses Domain Entities or explicit Value Objects. Proto Messages, database Rows, and raw Fixture Payloads must be converted in the data adaptation layer:
Fixture Payload ─┐
Wire / Proto ────┼─> Mapper -> Domain Entity -> API -> Controller -> UI
Database Row ────┘
The value of this constraint lies in isolating changes. The current Demo has no real remote API and uses deterministic Fixtures and local Mock chains; when real Endpoints are introduced in the future, Transport, DataSource, and Mapper can be replaced without making pages or business APIs aware of underlying protocol changes.
The template does not pre-introduce Dio, Proto, or Drift to fill a technology checklist. Only when there are real consumers, remote protocols, or cross-restart persistence requirements do the relevant dependencies enter the corresponding Package. For a template project, controlling the number of invalid abstractions is as important as establishing the layering itself.
5. Task Card-Driven Delivery Closed Loop
Ordinary development tasks follow a relatively short closed loop:
Figure 2: Task cards are responsible for converging scope, while Reviews and evidence are responsible for feeding results back to subsequent tasks.
1. Product Input
Input can be requirement descriptions, Figma nodes, prototypes, or technical issues. When Figma is involved, the Agent reads real nodes through a local MCP, not by guessing layouts from screenshots.
2. Task Card
Task cards are not bound to a fixed producer. Developers, Agents, Commands, or external tools can all create them, as long as the name is clear and unique, and contains sufficient fact sources, scope, dependencies, constraints, and acceptance methods.
3. Implementation and Focused Verification
The execution phase only loads the Skills needed for the current task. After completing the code, format checks, static analysis, and tests within the affected scope are run first. When shared contracts or base Packages change, the verification scope is expanded.
4. Read-Only Review and Explicit Fixes
Reviews report issues by default and do not casually modify code during the review process. Fixes must explicitly enter the next phase and be re-reviewed after completion. This distinguishes "what was found" from "what was actually changed" and facilitates controlling cross-task changes.
5. Evidence Archiving
Archived content includes executed commands, results, environmental limitations, and platforms not yet covered. Local paths, device identifiers, and credentials in raw logs need to be sanitized; evidence preservation must not introduce new information leakage risks.
6. Why UI Automation Is Independent of Ordinary Tasks
The template provides three types of structured artifacts: UI behavior Specs, static Audits, and runtime Runs:
.spec.yaml How the product requires the App to behave
.audit.yaml Whether these behaviors are implemented statically in code
.run.yaml Whether the behaviors actually pass on the specified platform
The three answer the product contract, code implementation, and runtime results respectively and should not be mixed into a single report.
UI automation is scheduled independently by humans. Only after explicitly selecting a Spec and platform does the App Operator connect to the running Debug App via Marionette, execute checks, and generate the Run for the corresponding platform. Ordinary task execution does not automatically start the App Operator, nor will it fail to archive due to a missing Run file.
This design has two considerations:
First, real devices and local MCP connections depend on external environments and are unsuitable as mandatory prerequisites for every small task; second, if the static audit has not passed, continuing to run device tests has no practical value. Separating the two can maintain complete feedback while avoiding unnecessary waiting and manual confirmation for daily development.
Marionette operates on the Flutter Widget Tree and does not cover native Android or iOS system interfaces. When dealing with album permissions, system dialogs, or native pages, corresponding platform tools or manual verification are still required.
7. How Quality Gates Become Executable Rules
The quality rules in the template are not a list of suggestions but are enforced by scripts, Git Hooks, and CI together.
Repository-level checks include:
- Dart formatting and static analysis;
- Unit tests, Widget tests, and on-demand Integration Tests;
- Internal reference checks between Features;
- Controller API injection method checks;
- Shell project cross-boundary reference checks;
- Workspace Package dependency matrix checks;
- Claude and Codex adaptation layer synchronization checks;
- Document links, configuration files, task card Schema, and sensitive information checks;
- Android Debug and iOS no-codesign Debug builds.
These checks are triggered based on impact scope, rather than requiring developers to manually execute all commands after every modification. The implementation phase runs focused checks, the commit and push phases execute lightweight gates via Hooks, and CI provides unified remote results. Steps requiring devices, MCP authorization, or Apple toolchains accurately record environmental limitations.
Gates themselves also need cost control. A rule is only worth long-term maintenance when it corresponds to a real risk, has clear failure information, and has positive and negative Fixtures. Otherwise, the quality system can easily become another process burden to bypass.
8. Two Adoption Methods for the Template
Figure 3: The two paths share the same set of engineering principles but differ in the degree to which directories and business code are retained.
Method 1: Run the Reference Demo Directly
The repository includes a Shoppe-style local e-commerce Demo covering flows like Welcome, Auth, Shop, Categories, Wishlist, Cart, Profile, Settings, Orders, Search, Promotions, Rewards, Support, and Product Detail.
The Demo uses deterministic local Fixtures and Mock APIs, without depending on a remote backend. Its main purpose is to demonstrate how the project contract, task cards, Figma inputs, code implementation, Reviews, and quality gates collaborate within a single repository.
This path is suitable for evaluating the complete form of the Harness and for verifying the local environment and Android/iOS build chains.
Method 2: Adapt to an Existing Project
For existing projects, a more reasonable approach is not to copy the entire directory but to first let AI complete an adaptation analysis:
- Read the Harness's project contract, architecture documents, and
.claude/source of truth; - Inventory the target project's tech stack, Package boundaries, native platforms, CI, and team processes;
- Categorize assets into "directly reusable," "needs adjustment," and "for reference only";
- First form an adaptation plan and task cards, then start migration;
- Update the target project's own source of truth and regenerate adaptation layers for tools like Codex;
- Validate the new process with the first real business task, then decide whether to continue expanding.
On this path, directory names, state management, routing solutions, platform integrations, and commands can all be adjusted. What needs to be preserved are the engineering principles and the feedback closed loop, not the repository's appearance.
9. Applicable Boundaries and Trade-offs
Flutter AI Harness is more suitable for the following scenarios:
- Flutter Monorepos or hybrid projects with long-term maintenance of Android and iOS native hosts;
- Multiple AI tools participating in development, requiring a unified source of truth;
- Teams wanting to turn architectural constraints into CI-executable rules;
- Requirements that will iterate continuously, requiring the preservation of tasks, Reviews, and verification evidence;
- Hoping AI can read Figma and operate Debug Apps, but not wanting these tools to intrude on ordinary task flows.
It cannot replace the following work:
- Product scope, business rules, and interaction trade-offs;
- Design draft authorization, material licensing, and real data strategies;
- Native system UI, signing, permissions, and device compatibility verification;
- The team's final decisions on high-risk modifications, release scope, and external system access.
Additionally, the Harness should not grow indefinitely. More Agents and Skills are not always better, and Memory should not become a second project document. For every asset added, it should be clear what repetitive problem it solves and why existing contracts, task cards, or scripts cannot assume that responsibility.
Conclusion
The change brought by AI programming is not just an increase in code generation speed; it also changes how projects preserve and execute engineering knowledge. Rules that previously relied on developers' long-term memory need to gradually become readable, executable, and reviewable assets within the repository.
Flutter AI Harness provides a concrete implementation: the project contract is responsible for stable boundaries; Commands, Agents, and Skills are responsible for on-demand execution; task cards and Reviews are responsible for controlling change scope; Git Hooks and CI are responsible for providing deterministic feedback; and the Demo is used to verify that these designs can work in a real Flutter project.
It is not a plugin that must be installed as-is. You can run the Demo directly, or let AI re-abstract based on the target project. For most existing projects, the latter is often more valuable: tools and directories can change, but a clear source of truth, unidirectional architectural boundaries, independent verification phases, and traceable delivery results should be preserved.