---
description: Ailoha iOS current main 相对 Release 的前端架构增量、真实 Package owner、隐式依赖与验证前沿
status: active
updated: 2026-08-27
sources:
  - repo://ailoha-agent-iOS@0b90745ed21438b194f8f9401a47d012cdbe66e5
  - repo://ailoha-agent-iOS@6922f359ad08da70242e4ec0c5c4a1486bc2908d
  - https://github.com/Ailoha-ai/ailoha-agent-iOS/compare/0b90745ed21438b194f8f9401a47d012cdbe66e5...6922f359ad08da70242e4ec0c5c4a1486bc2908d
confidence: high
sensitivity: internal
---

# Ailoha iOS main 增量架构：包拆出来以后，谁真正拥有状态？

<!-- brain-capture:ios-frontend-main-delta-architecture -->

## 1. 范围与读者

这不是重新扫描整个 iOS 仓库，也不是用 main 覆盖已有的 `5e6ac6e` 历史地图。它只回答一个更窄、但会改变重构判断的问题：从当前 Release `0b90745` 到 current main `6922f35`，Chat、Home / Onboarding、六个新增 Package 和 Design Token 到底发生了什么；这些变化已经把哪些责任变成了真实边界，哪些还只是可测试的代码 seam。

目标读者是准备设计或评审 Ailoha iOS 重构的人。读完应能说清：

- 页面和 Package 之间真实的调用链；
- 每个 Package 真正持有的状态或副作用；
- 仍由 App target 持有的身份、网络、canonical entity 与恢复责任；
- 下一步该验证边界收益，还是继续搬文件。

## 2. 先看结论

1. **main 已经不是历史地图里的 Chat 双轨。** `Router` 只构造 `TaskChatPageV2`，旧 `TaskChatPage` 和 `ChatPageDebugFlags` 在 main 树中不存在。对 main 继续提出“删除 V1”的任务是重复劳动；应改成验证 V2 长会话、滚动和迁移残留 consumer。
2. **六个新增 Package 都不是空壳。** Task、Import、TwoMeet、Speech、Markdown、Logging 已有 App caller，且分别拥有纯策略、内存协调状态、持久 store、音频设备副作用、进程缓存或日志文件生命周期中的一部分。
3. **Package seam 不等于 feature ownership 已完成。** 用户身份、环境、REST / ARPC、canonical task、页面 projection、上传和登出恢复仍主要留在 App target。不能因为类型进入 Package，就宣称 feature 已解耦。
4. **依赖方向目前仍是隐式的。** `GlobalImports.swift` 用 `@_exported import` 一次性向整个 App 暴露六个新模块；普通 caller 不需要声明自己依赖哪个 Package。编译能过，但 code review、依赖审计和未来 target 拆分缺少局部信号。
5. **颜色 token 已建立生成链，但仍处在双源迁移期。** `colors.tokens.json → build.mjs → AilohaColorTokens.generated.swift` 是真实进展；`ALHColors.swift` 仍手写 adaptive brand colors，所以“已有生成器”不能等于“设计语义已单一来源”。
6. **main 仍没有 App test target。** 本轮三个 Package test suite 全部通过，只能证明包内合同；不能证明账号切换、Root 生命周期、路由、extension、系统权限或跨 Package 组合正确。

## 3. 可探索架构图

- [打开 current main 增量架构图](main-delta-architecture.html)
- [查看冻结的 Archify specification](main-delta-architecture.architecture.json)

推荐先看“main 用户主路径”，再切到“新增 Package seams”和“仍未收口的边界”。图里的实线表达用户主路径或明确调用，虚线表达 App owner 对已抽出 seam 的依赖；边界框不是组织愿景，而是当前 revision 的代码事实。

## 4. Package owner 账本

| Package | 已验证的真实 owner | 仍在 App target 的责任 | 这意味着什么 |
|---|---|---|---|
| `AilohaTaskCore` | 本地 operation lease 的内存协调、Task interaction policy、optimistic history matching | canonical task、REST / ARPC、Home / Chat projection、生命周期编排 | 已抽出可测试并发与策略内核，但尚未形成完整 Task repository |
| `AilohaImportCore` | App Group inbox 的 `.writing → ready` 持久协议、文件准入 policy | 登录用户 / 环境绑定、上传、页面流程与错误呈现 | durable store 是真实 owner；跨账号和上传恢复仍需 App 合同 |
| `AilohaTwoMeetCore` | generic SWR entry、in-flight generation / cancellation、聚合 policy | 从 Auth / Config 生成 identity key、服务调用、登出时 `removeAll`、UI | 缓存算法已抽出，但正确隔离依赖 App 提供完整 key 和 reset |
| `AilohaSpeechKit` | `AVAudioEngine`、tap、timer、recording 生命周期 | STT 网络、权限说明、发布状态与 UI | 这是副作用 owner，不只是 helper；应以设备生命周期和中断恢复验收 |
| `AilohaMarkdownKit` | parse、semantic block cache、render view；进程缓存 count limit 为 200 / 100 | Chat row identity、消息流、滚动锚点与页面生命周期 | 渲染成本边界已可独立测；长会话性能仍是 App + Package 的组合问题 |
| `AilohaLoggingKit` | redaction hook、串行文件 IO、rotation、quiesce barrier、zip writer | sink 安装、业务字段选择、上传、登出 / 前后台时序 | 基础设施 owner 已成立；隐私正确性仍取决于 caller 不把 credential 前缀写入 message |

“owner”在这里有严格含义：该模块创建并维护状态，或负责不可随意重复的副作用和恢复，不是“文件放在哪个目录”。

## 5. Home / Onboarding 新运行脊柱

`RootPage` 创建 `MailboxScanStore` 与 `FirstEncounterGuideState`，再把它们注入 Home。Home 直接消费这些对象，因此它们不是 dormant 文件，而是 current main 的首次体验状态链：

`RootPage 创建状态 → Home 读取扫描 / 首遇状态 → 用户进入任务或引导 → App feature owners 执行网络与状态投影`

这条链值得后续单独画用户场景和恢复状态，但本轮不把“类已被构造”推断成“首次体验已验证”。仍未知：冷启动、账号切换、后台恢复和失败重试时，用户是否得到一致且可恢复的状态。

## 6. Design Token：生成链已成立，语义收口未完成

main 的颜色链已经可以复述为：

`design-tokens/tokens/colors.tokens.json → design-tokens/build.mjs → AilohaColorTokens.generated.swift → App / Widget consumers`

这是比散落常量更好的可验证合同：生成结果可以做 determinism check，App 与 Widget 可以共享 revision。但 `ALHColors.swift` 仍保留手写 adaptive 颜色和历史语义，迁移完成至少需要：

1. 列出 legacy token 的真实 consumer 与语义映射；
2. 定义生成 token 和 adaptive token 的唯一职责；
3. 对 App / Widget 做同一 revision 的视觉回归；
4. 在旧 consumer 为零后才删除旧来源。

Talent Signal 可以先验证“语义 token 怎样支撑一套克制、可解释的灵动岛视觉语言”，但不能替 Ailoha 证明 App / Widget 的 token 迁移完成。

## 7. 新发现的 control gap：调用方看不见自己依赖了谁

### 用户 / 团队看到什么

代码已经有更多 Package，但打开一个 App 文件时，往往看不到它使用了哪个 Package；类型像是“天然存在”。重构评审容易把“可编译”误读为“依赖方向已清楚”。

### 代码怎么造成

`Ailoha/GlobalService/GlobalImports.swift` 对六个新模块使用 `@_exported import`。App target 又把这些模块作为 framework products 链接进来，于是任何 App 源文件都可以不写显式 `import` 而直接使用包类型。

### 架构推断（不是原作者意图事实）

从代码效果看，composition convenience 与 feature boundary 被放在了同一个全局入口：六个模块被全 App 暴露，但其中实际包含 Task、Import、TwoMeet、Speech 等 feature-specific owner。源码没有记录原作者为什么这样做；“为了把它们当成全 App 基础能力”只能作为待团队确认的意图假设。

### 怎么改

先选 `AilohaTaskCore` 做一个模块级小实验，而不是把它误写成只影响 Task Chat。当前直接符号 consumer 至少包括：

- `TaskDataModels`、`TaskInteractionService`、`TaskCreationService`、`TaskResponseService`、`TaskHistoryService`；
- `HomeTaskRackItem`、`ChatRowItem` 与 `TaskDebugInfoPanel`。

实验步骤：

1. 从 global re-export 中移除一个 feature module；
2. 让真实 caller 显式 `import`；
3. 记录出现的编译错误、隐式跨 feature consumer 和循环依赖；
4. 比较增量编译、review 理解时间与改动噪声；
5. 只有收益明确，才扩到其余 feature modules；Foundation / SwiftUI 等广义基础模块另行判断。

### 为什么这样改

显式 import 不会自动得到好架构，但能把依赖变成调用点旁边可见、可搜索、可 lint 的事实。它给未来 target 拆分、依赖图和 review 提供低成本传感器；单模块 pilot 又避免一次性制造全仓 import 噪声。

### 验收

- `AilohaTaskCore` pilot 编译和现有行为不变；
- 找到的跨域 consumer 有明确归属，不用新增全局 escape hatch；
- 没有新循环依赖；
- reviewer 能从 caller 文件判断直接模块依赖；
- 若 import diff 很大但没有暴露结构问题或降低理解成本，则反证这一步值得推广。

## 8. Active、dormant 与 target 不混写

| 判断 | current main 证据 | 当前状态 |
|---|---|---|
| Chat V2 是唯一 route | `Router.swift` 只构造 `TaskChatPageV2`；V1 / debug flag 不在 main 树 | active fact |
| 六个新 Package 有真实 caller | App target product refs + 具体类型使用点 | active fact |
| Home 新 onboarding state 在运行路径 | `RootPage` 创建并注入，Home 消费 | active fact |
| Package 已完成 feature ownership | 身份、网络、canonical state 与恢复仍在 App | false as a completion claim |
| Token 已统一 | generated source 与手写 `ALHColors` 并存 | partial migration |
| hosted App lifecycle tests 已覆盖组合 | Xcode 工程仍无 App unit / UI test product | open gap |
| 显式 import 应全仓推广 | 尚未做 `AilohaTaskCore` 模块级 pilot | hypothesis, not target contract |

## 9. Fact / inference / hypothesis

### Facts

- current main revision 是 `6922f359…`，Release 是 `0b90745e…`；main 比 Release 多 88 个 commits，GitHub compare 返回 300 个文件条目并命中上限。
- Router 只进入 Chat V2。
- 六个新 Package 被 App target 链接、被 `GlobalImports` re-export，并有具体 caller。
- Task / Import / TwoMeet 三个 Package test suite 在 exact clean main 分别为 7/7、2/2、3/3 通过。
- current main 没有 App unit / UI test target。

### Inferences

- 全局 re-export 削弱了 caller-level 依赖可见性，增加后续 target 拆分与架构 review 的认知成本。
- 新 Package 的主要价值是先抽出策略、缓存、持久 store 或设备副作用 owner，而不是已经完成整个 feature 垂直切分。
- main 的重构下一阶段应优先验证组合合同和 owner 边界，不应继续以 Package 数量或文件移动量衡量进展。

### Hypotheses and falsification

- **假设**：`AilohaTaskCore` 显式 import pilot 会暴露当前看不见的跨域依赖，并降低 review 认知成本。**反证**：只产生机械 diff，没有暴露边界问题，reviewer 也没有更快理解依赖。
- **假设**：Package 级性能测试 + App 长会话 trace 能把 Markdown / Task policy 的成本与页面 observation / scroll 成本分开。**反证**：trace 仍无法区分 owner，说明 signpost 和测试夹具不足。
- **假设**：token 单一来源能减少 App / Widget 视觉漂移。**反证**：迁移后仍需大量未声明覆盖或设计语义无法映射，说明 manifest 模型本身不够。

## 10. 性能与成本：本轮能说到哪里

- `AilohaMarkdownKit` 有进程缓存和明确 count limit，能减少重复 parse / semantic split；但没有 memory cost limit、长消息上界与 App 长会话 trace，不能声称滚动性能已经解决。
- `AilohaTaskCore` 把 lease 和 optimistic matching 变成纯边界，便于测竞争与匹配；它不会自动减少 `HomeViewModel` 或 Chat projection 的 observation fan-out。
- `AilohaTwoMeetCore` 统一 in-flight generation 和 SWR，可以减少重复请求；identity key 构造或 logout reset 错误仍会把性能优化变成数据隔离问题。
- 全局 re-export 的主要问题是认知和架构控制，不应无证据包装成运行时性能问题。增量编译是否受益必须实测。

## 11. Failure、recovery 与 privacy

- Import store 的 `.writing → ready` 协议为崩溃恢复提供基础；仍需验证旧 session 文件、损坏 entry、磁盘失败和上传后清理。
- SpeechKit 拥有音频硬件生命周期；需覆盖权限拒绝、电话 / route interruption、后台切换和 cancel 后无迟到回调。
- LoggingKit 的 quiesce / rotation / zip 是可靠性基础，但 redactor 无法补救 caller 主动写入 credential 前缀；值最小化必须发生在消息构造前。
- TwoMeet 缓存正确性依赖 user + environment key 与 logout `removeAll`；缓存命中不是隔离证明。
- Package tests 不能替代 Root、Auth、extension、权限和系统副作用的 hosted / simulator / device 验证。

## 12. 推荐阅读顺序

1. 本文“先看结论”和 [main 增量架构图](main-delta-architecture.html)。
2. 图的“main 用户主路径”：确认 App shell、Home、Chat V2 与 feature owners。
3. “新增 Package seams”：逐个对照 owner 账本。
4. “仍未收口的边界”：检查隐式 import、App tests 与 token 双源。
5. 再回到 [完成度与 Revision 审计](completion-and-revision-audit-2026-08-27.md)，区分 Release、main 与本地 Wave 0 候选。
6. 需要设计验证时，再读 [跨 App 重构实验](../ios-cross-app-refactor-experiments-2026-08-27/README.md)；Talent Signal 的验证结果只作为设计证据，不自动升级为 Ailoha 工程结论。

## 13. 仍未解决的问题

- main 的 300-file compare 已命中 API 上限，本轮只沿四个高影响 domain 深挖；没有声称覆盖 88 commits 的全部语义变化。
- 尚无 current main 的真机 / Simulator 行为和 ETTrace / memgraph；性能内容仍是可验证机制，不是生产卡顿结论。
- 尚未证明 GlobalImports pilot 的收益；它是下一验证，不是已经接受的目标架构。
- 冻结图中的 `AilohaLoggingKit` 没有画出 App caller 到 logger 的调用边；文字 owner 账本和 source refs 正确，但视觉上形成孤立节点。按 Archify freeze 合同本轮不改 specification，下次重新交付时补正。
- 尚未确认 token manifest 与 Figma variable / Code Connect 的 revision 合同。
- Talent Signal 灵动岛的业务场景、审美方向与视频脚本仍受 Gate 0 约束：需要用户明确选定验证方向后才能进入第二轮视觉生成与实现。

## 14. Artifact receipt

- Diagram type: `architecture`
- Exact revision: `ailoha-agent-iOS@6922f359ad08da70242e4ec0c5c4a1486bc2908d`
- Frozen spec SHA-256: `f30ab955e31af3565f2b063ecd0df582a0c19c81912374750ff96ee560a67a72`
- Delivered HTML SHA-256: `be78339a84cb6766b692610d6e74024925963bd4b94ad02e3ec5660d4486ab1b`
- Archify showcase validation: 9/9 checks, 0 errors, 0 warnings
- Evidence verification: 24/24 source references resolved in exact main clone
- Package tests: TaskCore 7/7, ImportCore 2/2, TwoMeetCore 3/3
- Visual review: skipped；in-app Browser 拒绝本地 `file://` 页面，按 Archify 规则没有换浏览器或建立绕过。因此只声明结构 / 证据 / showcase 校验通过，不声明视觉复核通过。
- Correction rounds: 2（移除低价值交叉边；校正连接端点）

## 15. 下一步

最小的下一步不是继续拆 Package，而是把“边界是否真的更好”变成三个小实验：

1. `AilohaTaskCore` 模块级显式 import pilot；
2. Markdown 长会话的 Package micro-benchmark + App ETTrace；
3. 一个 hosted App contract test，覆盖 Root / Auth reset 与一个 Package owner 的组合生命周期。

三者都通过后，才有证据决定是推广显式依赖、扩大 Package owner，还是保留当前 seam。Talent Signal 侧则只验证可迁移的交互节奏、信息层级、token 语义和视频可理解性；账号、路由、App Group、音频和日志生命周期仍必须回到 Ailoha 验证。
