# 5+1 架构追踪视角（System Architecture）

> 独立 subagent 用。fresh context 下，按这 5+1 视角对 system-architecture.md 初稿做强制枚举追踪。
> 卡住的地方 = gap。
>
> 这是移植自 system-design skill 的架构维度视角，聚焦**系统层**的建模合理性，
> 不是 requirements.md 的业务维度。

---

## 根原则：边界 = 捕获不对称

下面的 5+1 视角不是孤立的 checklist，它们共享一个判据——

> **边界存在的唯一理由是捕获一个不对称**（变化率 / 所有权 / 失效域 / 语言的差异）。
> **边界的代价必须与它捕获的不对称相匹配**；没有不对称可捕获的边界 = 零价值（伪 port / 空壳层 / 空壳模块）。

这正是本阶段统摄 metric「**复杂度归位**」的操作化：复杂度该留在内聚单元里，
边界就是内聚单元之间的负空间。划错有两种，都是复杂度没归位——
划多了（同一变化轴劈两半 → 协调成本暴涨） / 划少了（不同变化轴揉一块 → 一处改牵动全场）。

### 三层边界：同一原则，三个代价台阶

模块 / 层 / 系统不是三种边界，是同一条规则在三个代价尺度上的实例。
**唯一区别是"跨越它的代价"**，而代价决定了"配得上这条边界的不对称要多大"：

| 边界 | 跨越代价 | 配得上的不对称 | 判据（怎么知道该划） |
|------|---------|--------------|-------------------|
| **模块** module | import / 函数调用（最廉） | 任何变化轴差异 | "会不会因为不同原因改"→ 2+ 原因=该拆 |
| **层** layer | interface / port（中） | 变化率差异 + 依赖方向 | 依赖指向稳定方；核心层零外部依赖 |
| **系统** system | 进程/网络/契约 + 团队对齐（最贵） | 语言(BC) + 团队 + 部署节奏 + 失效域 | 同一 Ubiquitous Language？同团队？同部署节奏？ |

代价阶梯式上升，**配得上的不对称也要阶梯式上升**。两个最常见的事故：
过早微服务（只够"模块"的不对称上划了"系统"的贵边界）/ 分了层却 god module（层划了、模块没跟上）。

### 边界证伪三连（把"是否合理"变成可操作动作）

对任何一条疑似多余的边界，做三个动作：

- **删（Delete）**：去掉边界，复杂度是塌缩成一块（→ 边界多余，合并）还是仍分散（→ 边界真实）？
- **翻（Invert）**：把依赖方向反过来，行为不变吗？真边界方向被不对称强制（翻不了）；伪边界方向任意（随便指）。
- **挪（Move）**：边界能滑动吗？真边界卡在自然接缝（语言/成本/变化率断裂处）；伪边界可随意平移。

### Port ≠ interface（层边界的双重性）

层边界有个容易被忽略的双重性，是"伪 port"判据的根——

- **结构边界（依赖方向）**：编译期，谁 import 谁；受依赖规则约束，**指向稳定方**。
- **控制边界（调用流）**：运行期，谁 invoke 谁；§9 泳道图展示。

普通 interface 这两者同向。**port 之所以是 port，恰恰是它让两者反向**：
domain 在结构上依赖 port（指向 domain 这个稳定方），运行时却由 domain 通过 port 调用 infra
（控制流向 infra）。**不能反转的 interface = 伪 port**（"只有一个实现"只是它的症状）。

> 下面 5+1 视角，就是上述原则的 6 个检查面：视角1 粒度错配、视角3 空壳层/伪port、
> 视角4 上帝对象、视角5 变化轴堆叠……每一项都是"不对称没捕获好 / 复杂度没归位"。

---

## 追踪规则

1. **并行分组追踪**（不是单 subagent 串行戴 6 副眼镜）— 见下方「并行分组」
2. **卡住的地方 = gap**，标注类型（F/K/D）和具体问题
3. **greenfield 模式**：第 6 视角（Behavior Contract）写降级理由（无现有行为可保持）→ 演进帧组只跑视角 5
4. **交叉验证**：两组独立命中同一 gap → 标 `[CROSS-VALIDATED]`（冗余 = 信号强度）

### 并行分组（3 fresh subagent，各 2 视角，认知帧内聚）

> **为什么拆**：6 视角是 6 副异质认知眼镜。一个 subagent 串行戴 6 副，每换一帧要 re-orient，
> 后半程吃前半程的残留预设（confirmation bias 沿视角链累积）。拆成 3 组并行，每个 subagent
> 只 re-orient 2 次、聚焦一个认知帧，盲区更少。代价：Step2 从 1 个 → 3 个 fresh subagent/轮。
> ②是 D-不可逆密度最高阶段（分层/状态机/领域边界全在这），多 agent ROI 最高。

**何时降级到 2 组 / 1 组（复杂度判据，Step 1 末自评）：**

②默认 3 组并行，但 CRUD 单层无状态机这类简单项目跑 3 组是浪费。Step 1 末按以下信号自评分决定组数：

> **与 loop-skeleton 档位的关系：** 下表的 5 信号是架构阶段领域特定的细化，与 loop-skeleton 的「状态复杂度」「跨边界数」信号重叠——「状态复杂度≥中」等价于本表「有显式状态机」，「跨边界数≥中」等价于「Port/seam≥1 个真边界」。L1 档（loop-skeleton）项目本表自评总分通常 ≤1，自动落到 1 组。

| 复杂度信号（每命中 +1 分） | 说明 | 对应 loop-skeleton 信号 |
|---------------------------|------|------------------------|
| 状态复杂度≥中（有显式状态机） | Status/Reason 正交、终态不可逆 | 状态复杂度 |
| Port/seam ≥ 1 个真边界 | 非伪 port（删/翻/挪证伪后仍成立） | 跨边界数 |
| Aggregate / 核心模型 > 2 个 | 有领域建模深度 | （架构专有） |
| 分层 > 2 层 | 非 CRUD 单层 | （架构专有） |
| Refactor 模式 | 视角 6 行为契约启用 | （架构专有） |

| 自评总分 | 组数 | 分组 |
|---------|------|------|
| ≥ 4 | **3 组（默认）** | 建模帧（1+2）/ 结构帧（3+4）/ 演进帧（5，或 5+6） |
| 2-3 | **2 组** | 空间帧（视角 1-4，模型内部+依赖图同属「结构」认知）/ 时间帧（视角 5-6，变更随时间） |
| ≤ 1 | **1 组** | 单 subagent 串行 6 视角（CRUD 单层无状态机、纯技术编排等） |

**阈值偏低（宁可多跑）**：判据偏向跑更多组，防误判降级漏 gap。临界（如总分 3）按 3 组跑。greenfield 时演进帧视角 6 按既有规则降级（只跑视角 5），不影响组数判据。

| 组 | subagent 写入 | 视角 | 认知帧（专找什么）|
|----|--------------|------|------------------|
| **建模帧** | `tracing-round-{N}-modeling.md` | 1 模型完整性 + 2 状态正交性 | 领域模型**内部结构**——装着行为的对象 / 死状态 / status 混进 reason / 粒度错配 |
| **结构帧** | `tracing-round-{N}-structure.md` | 3 分层纪律 + 4 依赖边界 | **依赖图/分层健康**——伪 port / 空壳层 / 循环依赖 / 上帝对象 |
| **演进帧** | `tracing-round-{N}-evolution.md` | 5 变化轴 + 6 行为契约 | **变更随时间的行为**——7 轴堆一文件 / 命名不符责 / 代码有但文档没写的行为 |

**分组依据**：同组两视角共享一个认知帧（看模型的内部结构 / 看依赖图 / 看变化行为），组内重叠是同源强化；组间视角正交，覆盖不重复。

**交叉验证点（组间重叠区——两个组都可能命中的 gap）**：

| 重叠区 | 建模帧 | 结构帧 | 演进帧 | 信号 |
|--------|--------|--------|--------|------|
| **粒度错配** | 视角1「该是 DTO 的建成 aggregate」| | 视角5「拆分粒度过粗/过细」| 两组都报 → 强信号 |
| **伪边界** | | 视角3「伪 port」/ 视角4「interface 过度抽象」| 视角5「一个接口多个变化轴」| 两组都报 → 强信号 |

主 agent 汇总 3 组 gap 时，识别交叉命中（同一边界/模型被两组独立报告），标 `[CROSS-VALIDATED]`——这类 gap 优先级最高（两个独立 context 都盯上了，不是单方盲区）。

**greenfield 处理**：视角 6 行为契约降级 → 演进帧组只跑视角 5（单视角也成立，不强行凑对）。

**收敛判定**（Step 4 复核）：各组（3 组或降级后的 2/1 组）都 CONVERGED（无新 gap）才算整轮收敛。**Step 4 收敛复核只重跑「未 CONVERGED 的组」——已 CONVERGED 的组不必重跑（首轮复核和回流后复核均同此规则）**。任一组有新 gap → 回 Step 3 处理后只重跑该组。

---

## 视角 1: Model Integrity（模型完整性）

追踪核心模型的建模合理性。

### 检查项

- [ ] 每个模型是否明确标注类型（aggregate / 实体 / 值对象 / DTO / 技术封装）？
- [ ] aggregate / 实体是否有不变式守卫（变更通过模型方法收口，不裸赋值）？
- [ ] 值对象是否纯净（无 IO、无状态 mutate、无发事件）？
- [ ] 是否有「装着行为的对象」反模式（模型方法承担了本该在 service 的协调逻辑）？
- [ ] 是否有散落的概念未建模（同一概念在 3+ 文件各写一段）？
- [ ] 是否有空壳模型（无领域行为/状态机/不变量却建为 aggregate）？
- [ ] 建模粒度是否匹配实际（该是 DTO 的被建成 aggregate，或反之）？

### 常见 gap

- **F**：代码里 X 概念散落在 3 个文件，但文档没建模
- **K**：模型 Y 的不变式是什么？文档没说
- **D**：概念 Z 该建 aggregate 还是 DTO？选择理由不清晰

---

## 视角 2: State Orthogonality（状态正交性）

追踪状态机设计的合理性。

### 检查项

- [ ] Status 枚举是否只描述「现在处于哪个阶段」（不含终止原因）？
- [ ] 终止原因是否独立为 Reason 字段（不混进 status）？
- [ ] 终态集合是否明确标注且不可逆？
- [ ] 合法转换是否画成图（或表），能跑一遍可达性？
- [ ] 是否所有终态都能到达？是否有死状态？
- [ ] 资源转换是否由状态推导（而非 boolean flag 控制清理行为）？
- [ ] 转换严格度是否匹配实际需要（有无过度收紧或过度宽松）？

### 常见 gap

- **F**：状态机有 8 态但其中 3 态其实是「终止原因」，应抽到 Reason 字段
- **K**：状态 X 到状态 Y 的转换是否合法？文档没说
- **D**：状态机该收紧（显式转换表）还是保持宽松（只守终态）？

---

## 视角 3: Layering Discipline（分层纪律）

追踪系统分层的合理性。

### 检查项

- [ ] 是否明确回答了「核心计算是什么」（决定分层深度的根因）？
- [ ] 分层深度是否匹配系统性质（有业务规则 vs 纯技术编排）？
- [ ] 依赖方向是否严格向下（上层依赖下层，不反向）？
- [ ] 核心层（domain/engine）是否零外部 SDK 依赖（边界由 port 或 lint 固化）？
- [ ] 是否有空壳层（只有 DTO 没有行为的层）？
- [ ] 是否有伪 port（只有一个实现的 interface，无边界价值）？
- [ ] Port 的价值定位是否明确（「可替换性」vs「边界载体」）？

### 常见 gap

- **F**：engine 层 import 了外部 SDK，破坏零依赖边界
- **K**：这个系统有业务领域规则吗？该套 DDD 四层还是三层？
- **D**：PersistencePort 只有一个实现，该保留为 port 还是降为具体类？

---

## 视角 4: Dependency Boundary（依赖边界）

追踪模块间的依赖健康度。

### 检查项

- [ ] 依赖图是否有环（循环依赖）？
- [ ] 是否有上帝对象（单文件 > 400 行 / 函数 > 80 行）？
- [ ] 是否有扁平 struct 打包不同生命周期的字段？
- [ ] 是否有 boolean flag 控制资源清理行为？
- [ ] interface 是否过度抽象（参数列表 > 5 个 / 方法 > 10 个）？
- [ ] **deletion test**：删掉疑似 shallow 的模块，复杂度是否集中？

### 常见 gap

- **F**：模块 A 和模块 B 互相 import，形成循环依赖
- **K**：struct X 的 6 个字段生命周期不同，该不该拆？
- **D**：上帝对象 Y 该按什么轴拆？

---

## 视角 5: Change Axis（变化轴）

追踪模块拆分是否按变化轴。

### 检查项

- [ ] 每个文件是否只承担一个变化轴（只有一个改动原因）？
- [ ] 拆分粒度是否合理（不过粗也不过细）？
- [ ] 是否有「7 个变化轴堆在一个文件」的反模式？
- [ ] 命名是否反映承担的变化轴（看名知责）？
- [ ] 相同变化轴的代码是否内聚（不散落在多文件）？

### 常见 gap

- **F**：某文件 261 行堆了 7 个变化轴
- **K**：模块 X 的变化轴是什么？为什么和模块 Y 合在一个文件？
- **D**：该按变化轴拆成 3 个文件，还是保持 1 个用注释分区？

---

## 视角 6: Behavior Contract（行为契约，refactor 专用）

> greenfield 模式：写降级理由「无现有行为可保持」，跳过本视角。

追踪重构是否保持现有行为。

### 检查项

- [ ] 「代码有但 requirements 没写」的行为是否逐条列出（落在 deliverable §12 行为契约清单）？
- [ ] 每条行为是否标注源码位置（file:line）？
- [ ] 每条行为是否标注「保持 / 变更 / 删除」（变更/删除须拆为独立 ticket，不裹进架构 PR）？
- [ ] 冲突行为（`[CONFLICT]`）是否已由用户决策？
- [ ] 行为变更是否与架构变更分离（架构保持行为等价，行为变更独立）？

### 常见 gap

- **F**：代码里某操作后有精确副作用（如触发 AI），但文档没提
- **K**：某边界行为要保持吗？
- **D**：某行为的处理该作为架构 PR 的一部分还是独立 ticket？

---

gap 分流（F/K/D）与收敛判定详见 `../../full-shared/references/loop-skeleton.md` 的 Step 3-4。
