AI 编程的工程化实践:Flutter AI Harness 的设计与落地

Flutter AI Harness:从代码生成到可验证的工程协作

面向生产级的AI Harness开源模板,并基于此讨论项目契约、任务闭环、架构边界与多工具适配。

项目地址:github.com/bladeofgod/...

摘要

AI 编程工具已经可以承担页面实现、错误修复、测试补充和代码审查等工作。真正影响长期效率的,不再只是单次生成质量,而是 AI 能否持续理解同一套工程规则,能否在明确边界内修改代码,以及交付结果能否被稳定验证。

Flutter AI Harness 是一套面向 Flutter 与 Android、iOS 混合工程的仓库模板。它没有把 AI 封装成应用运行时能力,而是把项目契约、Command、Agent、Skill、任务卡、Review、质量门禁和工具适配放进代码仓库,让 AI 与开发者共享同一组工程事实。

这套模板同时提供一个本地电商 Demo,但 Demo 只是参考实现。更重要的使用方式,是让 AI 读取 Harness 的设计,结合既有工程的技术栈和约束进行裁剪与改造。


一、代码生成不是完整的工程能力

在一个短任务中,AI 很容易表现出较高效率:根据截图搭页面、补一个接口、修复一处异常,往往都能快速得到可运行结果。但当修改跨越多个模块,或者代码需要持续迭代时,问题会从"能否生成"转向"如何约束"。

一个工程至少要回答以下问题:

  • 技术栈和架构不变量由谁定义;
  • 包与 Feature 之间允许怎样依赖;
  • 需求如何拆成可独立验收的任务;
  • 哪些文件可以编辑,哪些文件只能由生成器维护;
  • 静态检查、单元测试、平台构建和运行验证分别在何时触发;
  • Review 发现的问题如何进入修复和复审,而不是停留在一份报告中。

如果这些信息只存在于聊天记录或个人经验里,每次对话都要重新解释,规则也很容易在多轮修改后失效。AI 的执行速度越快,结构漂移反而可能越早出现。

Harness 解决的正是这一层问题:它不替代编码工具,而是为编码工具提供可读取的工程上下文、可执行的流程和可验证的反馈。

二、Harness 的四层结构

Flutter AI Harness 将工程控制面分成四层:

  1. 项目契约:定义技术栈、目录职责、依赖方向、数据边界和生成文件规则。
  2. 工作流资产:用 Command 描述流程,用 Agent 描述角色,用 Skill 提供按需知识,用 Memory 保存低频且长期有效的经验。
  3. 执行与装配:任务卡进入实现,代码通过聚焦测试和平台运行得到验证。
  4. 验证与反馈:静态门禁、只读 Review、UI Spec、证据归档和 CI 构成交付反馈。

图 1:规则、流程、执行和验证共同构成 Harness。单独增加提示词,并不能替代这个闭环。

这四层并不是为了增加流程数量,而是为了明确不同信息的生命周期。稳定不变量应进入项目契约;特定技术知识应按任务加载;一次性实现要求应留在任务卡;只有能够跨任务复用的经验才进入 Memory。

这种区分可以减少上下文浪费。AI 不需要在每次任务中加载所有平台规范、全部历史 Review 和所有业务模块,只需读取项目契约,再按当前任务补充相关 Command、Agent 或 Skill。

三、仓库中的事实源如何组织

当前仓库的核心结构如下:

text 复制代码
flutter-ai-harness/
├── CLAUDE.md        权威项目契约
├── AGENTS.md        Codex 入口
├── .claude/         Command、Agent、Skill 与 Memory 事实源
├── .agents/         生成的 Codex Skill 适配
├── .codex/          生成的 Codex Agent 适配
├── docs/            架构、任务、Review 与设计输入
├── scripts/         Git Hooks 与可执行质量门禁
└── app/             Flutter Workspace 与参考 Demo

其中,CLAUDE.md 负责定义仓库级不变量,.claude/ 是 AI 工程资产的唯一事实源。Codex 所需的 AGENTS.md、Skill 和 Agent 配置由仓库工具确定性生成,而不是另外维护一套内容相近的文档。

这一设计解决了多工具协作中常见的配置漂移:Claude 与 Codex 可以保留各自的发现和调用机制,但它们读取的工程规则来自同一个源头。修改 Command、Agent 或 Skill 后,生成检查会阻止过期适配层进入提交。

docs/ 也不是一个不加区分的文档集合。当前约定中:

位置 保存内容 不保存什么
docs/tasks/ 尚未完成的任务卡 虚构计划和固定 Sprint 层级
docs/tasks/done/ 已完成任务与验收信息 可复用项目知识
docs/reviews/ Review 报告与测试证据 无法复现的口头结论
docs/app-operator/ 人工安排的 UI Spec、Audit、Run 普通任务的默认门禁
.claude/memories/ 低频、长期有效的工程经验 任务流水账和重复规范

任务产物与长期知识分开,既方便追溯,也避免 Memory 随项目推进不断膨胀。

四、Flutter Workspace 的边界设计

模板中的 Demo 使用 Flutter Pub Workspace 和 Melos 管理多个 Package。当前依赖方向为:

text 复制代码
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

这里的箭头表示左侧 Package 可以依赖右侧 Package。apps/demo 位于最上层,负责全局服务、路由和依赖装配;app_coreapp_ui 位于基础层,不能反向引用业务实现。

各 Package 的职责并不复杂:

  • app_core 提供 ApiClientApiTransport、存储抽象、日志和平台无关基础设施;
  • app_data 提供 Domain Entity、Fixture、LocalDataSource、Mapper 以及未来的协议或持久化适配;
  • app_ui 保存设计 Token 和不包含业务规则的通用 UI;
  • app_im 保存消息基础设施,不承载 Feature 页面;
  • app_features 保存业务 API 抽象、Controller、Page、Route 与 Feature 实现;
  • apps/demo 只做装配,不直接依赖 Feature 内部实现类。

数据类型边界

跨层传递的数据统一使用 Domain Entity 或明确的 Value Object。Proto Message、数据库 Row 和原始 Fixture Payload 必须在数据适配层完成转换:

text 复制代码
Fixture Payload ─┐
Wire / Proto ────┼─> Mapper -> Domain Entity -> API -> Controller -> UI
Database Row ────┘

这条约束的价值在于隔离变化。当前 Demo 没有真实远程 API,使用确定性 Fixture 和本地 Mock 链路;未来引入真实 Endpoint 时,可以替换 Transport、DataSource 和 Mapper,而不需要让页面或业务 API 感知底层协议变化。

模板没有提前引入 Dio、Proto 或 Drift 来填充技术清单。只有出现真实消费者、远程协议或跨重启持久化需求时,相关依赖才进入对应 Package。对模板工程而言,控制无效抽象的数量,与建立分层本身同样重要。

五、任务卡驱动的交付闭环

普通开发任务遵循一条相对短的闭环:

图 2:任务卡负责收敛范围,Review 与证据负责把结果反馈给后续任务。

1. 产品输入

输入可以是需求说明、Figma 节点、原型或技术问题。涉及 Figma 时,Agent 通过本地 MCP 读取真实节点,不依靠截图猜测布局。

2. 任务卡

任务卡不绑定固定生产者。开发者、Agent、Command 或外部工具都可以创建,只要名称清晰且唯一,并包含足够的事实来源、范围、依赖、限制和验收方式。

3. 实现与聚焦验证

执行阶段只加载当前任务需要的 Skill,完成代码后优先运行受影响范围内的格式检查、静态分析和测试。共享契约或基础 Package 发生变化时,再扩大验证范围。

4. 只读 Review 与显式修复

Review 默认只报告问题,不在审查过程中顺手修改代码。修复需要明确进入下一阶段,完成后重新审查。这样能够区分"发现了什么"和"实际改了什么",也便于控制跨任务改动。

5. 证据归档

归档内容包括运行过的命令、结果、环境限制和仍未覆盖的平台。原始日志中的本机路径、设备标识和凭据需要脱敏,不能为了保留证据引入新的信息泄露风险。

六、UI 自动化为什么独立于普通任务

模板提供 UI 行为 Spec、静态 Audit 和运行 Run 三类结构化产物:

text 复制代码
.spec.yaml   产品要求 App 应该如何表现
.audit.yaml  代码静态上是否实现了这些行为
.run.yaml    行为是否在指定平台真实运行通过

三者分别回答产品契约、代码实现和运行结果,不应混为一份报告。

UI 自动化由人独立安排。只有在明确选择 Spec 和平台后,App Operator 才通过 Marionette 连接运行中的 Debug App,执行检查并生成对应平台的 Run。普通任务执行不会自动启动 App Operator,也不会因为缺少 Run 文件而无法归档。

这种设计有两点考虑:

第一,真实设备和本地 MCP 连接依赖外部环境,不适合作为每个小任务的强制前置;第二,静态审计没有通过时,继续运行设备测试没有实际价值。把两者分开,可以在保持反馈完整的同时,避免给日常开发增加不必要的等待和人工确认。

Marionette 操作的是 Flutter Widget Tree,并不覆盖 Android、iOS 的原生系统界面。涉及相册权限、系统弹窗或原生页面时,仍需使用相应平台工具或人工验证。

七、质量门禁如何落到可执行规则

模板中的质量规则不是一份建议清单,而是由脚本、Git Hook 和 CI 共同执行。

仓库级检查包括:

  • Dart 格式与静态分析;
  • 单元测试、Widget 测试和按需 Integration Test;
  • Feature 之间的内部引用检查;
  • Controller 的 API 注入方式检查;
  • 壳工程越界引用检查;
  • Workspace Package 依赖矩阵检查;
  • Claude 与 Codex 适配层同步检查;
  • 文档链接、配置文件、任务卡 Schema 和敏感信息检查;
  • Android Debug 与 iOS no-codesign Debug 构建。

这些检查按影响范围触发,而不是要求开发者在每次修改后手工执行所有命令。实现阶段运行聚焦检查,提交和推送阶段由 Hook 执行轻量门禁,CI 再提供统一的远端结果。需要设备、MCP 授权或 Apple 工具链的步骤,则准确记录环境限制。

门禁本身也需要控制成本。一个规则只有在对应真实风险、具备清晰失败信息并有正反 Fixture 时,才值得长期维护。否则,质量系统很容易变成另一套需要绕开的流程负担。

八、模板的两种采用方式

图 3:两条路径共享同一套工程原则,但对目录和业务代码的保留程度不同。

方式一:直接运行参考 Demo

仓库包含一套 Shoppe 风格的本地电商 Demo,覆盖 Welcome、Auth、Shop、Categories、Wishlist、Cart、Profile、Settings、Orders、Search、Promotions、Rewards、Support 和 Product Detail 等流程。

Demo 使用确定性本地 Fixture 和 Mock API,不依赖远程后端。它的主要作用是展示项目契约、任务卡、Figma 输入、代码实现、Review 和质量门禁如何在同一个仓库中协作。

这条路径适合评估 Harness 的完整形态,也适合验证本机环境和 Android、iOS 构建链路。

方式二:改造到现有工程

对于已经存在的工程,更合理的做法不是复制整个目录,而是先让 AI 完成适配分析:

  1. 阅读 Harness 的项目契约、架构文档和 .claude/ 事实源;
  2. 盘点目标工程的技术栈、Package 边界、原生平台、CI 和团队流程;
  3. 将资产分成"可直接复用""需要调整""只作为参考"三类;
  4. 先形成适配方案和任务卡,再开始迁移;
  5. 更新目标工程自己的事实源,并重新生成 Codex 等工具的适配层;
  6. 用第一张真实业务任务验证新流程,再决定是否继续扩展。

在这条路径中,目录名称、状态管理、路由方案、平台集成和命令都可以调整。需要保留的是工程原则和反馈闭环,而不是仓库外观。

九、适用边界与取舍

Flutter AI Harness 更适合以下场景:

  • Flutter Monorepo 或长期维护 Android、iOS 原生宿主的混合项目;
  • 多个 AI 工具共同参与开发,需要统一事实源;
  • 团队希望把架构约束变成 CI 可执行规则;
  • 需求会持续迭代,需要保留任务、Review 和验证证据;
  • 希望 AI 能读取 Figma、操作 Debug App,但不希望这些工具侵入普通任务流程。

它不能替代以下工作:

  • 产品范围、业务规则和交互取舍;
  • 设计稿授权、素材许可和真实数据策略;
  • 原生系统 UI、签名、权限和设备兼容性验证;
  • 团队对高风险修改、发布范围和外部系统访问的最终决定。

另外,Harness 不应无限增长。Agent 和 Skill 不是越多越好,Memory 也不应该成为第二份项目文档。每增加一项资产,都应明确它解决了什么重复问题,以及为什么现有契约、任务卡或脚本不能承担这个职责。

结语

AI 编程带来的变化,不只是代码生成速度提高,也改变了项目如何保存和执行工程知识。过去依赖开发者长期记忆的规则,需要逐步变成仓库内可读取、可执行和可审查的资产。

Flutter AI Harness 给出了一种具体实现:项目契约负责稳定边界,Command、Agent 和 Skill 负责按需执行,任务卡与 Review 负责控制变更范围,Git Hook 与 CI 负责提供确定性反馈,Demo 则用于验证这些设计能够在真实 Flutter 工程中工作。

它不是必须原样安装的插件。可以直接运行 Demo,也可以让 AI 基于目标工程重新抽象。对多数已有项目而言,后者往往更有价值:工具和目录可以变化,但清晰的事实源、单向的架构边界、独立的验证阶段和可追溯的交付结果,应当保留下来。

相关推荐
廋到被风吹走1 小时前
【AI】从“卖能力“到“卖信任“,合规与安全成为新战场
人工智能·安全
蓝速科技1 小时前
蓝速科技 3D 全息舱展览馆落地实测:降噪算力与成像质量深度评测
人工智能·科技·3d
jieyucx1 小时前
Nuxt4阶段六:工程化与进阶 —— 模块、中间件、插件、TS 与测试
中间件·vue·web·nuxt·全栈·ssr
小小测试开发2 小时前
PromptFoo 源码分析与工程实战:LLM 测试框架的架构与最佳实践
人工智能·架构
IT_陈寒2 小时前
React的useEffect依赖项把我坑惨了
前端·人工智能·后端
dozenyaoyida2 小时前
AI与大模型新闻日报 | 2026-07-22
人工智能·搜索引擎·新闻·gpt-5.6·claude fable5
GeekArch2 小时前
第28讲:避坑——AI堆栈分配错误、栈溢出BUG
c语言·人工智能·stm32·mcu·学习·bug
凌虚2 小时前
基于 PostgreSQL WAL 构建 CDC 系统:原理与工程实现
数据库·后端·postgresql
ShallWeL2 小时前
【机器学习】(23)—— 神经网络入门
人工智能·神经网络·机器学习