# APE 真实动作库存与选择机制审计

审计当前HEAD `9a5b577b77a6a87efcd8e6e218693af6faed17ce`。以下路径均相对 `native/src/com/android/commands/monkey/`；[含行号摘录与SHA](evidence/source-excerpts.txt)用于复核，不凭旧论文或最终UTG推导运行机制。

## 实际调用链

`MonkeySourceApe.generateEvents:425–474` 获取 top Activity 与 Accessibility root（源码承认不是原子观察） → `ApeAgent.updateState:278–292` → `StatefulAgent.buildAndValidateNewState:537–543` → `GUITreeBuilder/Naming/State` → `validateAllNewActions:833–837` → `adjustActionsByGUITree:859–860` → `SataAgent.selectNewActionInRound:399–473` → `Graph.markVisited`（输入前） → `ApeAgent.checkInput:175–185` → `MonkeySourceApe.generateEventsForAction:548–565` → 注入回执 → `JevRuntime.inputSummary:764–793` → 下一GUI观察形成 `NATIVE_TRANSITION`。

1. **保留树与理论GUI不同。** `tree/GUITreeBuilder:480–516` 根据 `excludeInvisibleNode/excludeEmptyChild/alwaysIgnoreWebView` 剪枝；`263–285,309–351` 应用XPathlets、父子click补丁、图像文本和WebView策略。`Config:79–104` 给默认值，不代表每个归档覆盖配置均已记录。可见但未暴露交互属性、被剪除或未映射的控件不自动成为动作；图像生成文本会改变原生Naming。
2. **State模型动作。** `model/State:50–65,210–216` 从 StateKey widgets 的 `NamerFactory.decodeActions` 建 `ModelAction[]`，并加无target Back。`naming/ActionPatchNamer:51–77` 对 clickable/checkable 建Click、longClickable建LongClick、scrollType建各方向Scroll；构造动作类型本身不先过滤disabled。`Naming.addNamedNode:212–242` 可过滤空/屏外节点。输入框没有独立的全字符串动作全集。
3. **每动作的控件匹配成员。** `tree/GUITree:198–209` 在当前Naming缓存 `currentNames/currentNodes` 中查Name，得到节点数组；`State.resolveAction:346–358` 从数组随机选**一个**代表。`ModelAction:35–43,208–228` 保存 `resolvedNodes`、`resolvedNode`、`resolvedTree`、timestamp和单个 `GUITreeAction`。所以不是“直到选中才第一次解析”：每个新模型动作会先解析，但也不是“所有Concrete已逐项验证”。
4. **有效性、enabled、优先级。** `StatefulAgent.validateNewAction:813–830` 可能复用同timestamp缓存，否则重解析随机代表；委托 `MonkeySourceApe.validateResolvedAction:338–375` 对该代表检查非空、与root相交（不是完整hit-test或业务成功）；Back有效。`AgentActionScorer:48–94` 依据代表节点设置enabled与priority，结合unvisited、别名数量及图上后继。`Action:59–86` 存enabled/valid，二者不是每个兄弟节点的表。未验证成员应记UNKNOWN，而不是复制代表valid。
5. **选择是一串策略，不是一个Concrete清单。** `SataAgent:399–473` 按buffer、Activity返回、早期/局部greedy、远程greedy、trivial、backward、epsilon、fallback尝试。`ActionFilter` 包含enabled-valid-unvisited/unsaturated集合。`SataAgent.getGreedyActions:599–621` 在useActionDiffer时调用 `model/StateActionDiffer:43–110`，比较相邻State的Name/Type和饱和；否则 `Graph.isActionUnvisitedByName:177–193` 查同Activity+抽象Name+Type历史。后者并非精确Concrete历史。档案未逐轮保存这些完整中间名单/未选原因，不能声称enabled-valid中的每个成员当轮都有被所有策略选择的机会。
6. **输入参数后置。** `ApeAgent.checkInput:175–185` 在模型动作选出后可能随机从 `StringCache` 选择输入文本；XPathlet也可预设（`GUITreeBuilder:129–145`）。`MonkeySourceApe:480–522` 用代表bounds生成click/longclick/scroll/Back；`MonkeySourceApeInput:80–130` 清文本、直接sendText、失败后key fallback。一次控件动作可包含多条低层事件/文本参数，不能按输入事件条数算Concrete执行，不能枚举无限文本组合为完整覆盖分母。

## 必须分开的五层集合

|集合|运行时载体|有无完整性|归档可证范围|
|---|---|---|---|
|GUI理论交互控件|Accessibility tree，经Native预处理后保留GUITree|仅保留树完整，不是全部App交互|2,280抽样树；不认证模型资格|
|State识别的ModelAction|`State.actions[]` + Back|当前State完整模型名单|23,971次有总数；2,131次可从unvisited IDs∪selected ID恢复全部ID，仍缺全属性|
|当前解析Concrete成员|各`ModelAction.resolvedNodes`，tree/timestamp必须一致|已解析成员数组，需标识缓存新鲜度|仅选中node及选中动作成员数量；全数组未记录|
|已验证有效Concrete|每动作的`resolvedNode`与action.valid/enabled|仅随机代表验证，无逐成员有效性全集|已确认选中输入事实，不是其他成员资格|
|策略实际可选动作|各策略局部列表、路径、当前代表绑定|顺序/随机/阶段相关，无统一物化全Concrete集合|仅选中策略/计数，没有每个未选动作的理由|

因此，回答Q1是：**有有限的模型动作与匹配控件缓存；没有一个可直接读出的“全部有效、策略可选、含全部输入实例”的完整Concrete库存。** 对控件层可做更好的被动采集，但仍须分别解释模型成员、缓存代表与策略实际触达。

## 历史与身份

- `GraphElement:25–88` 的visitedAt计数；`Graph.markVisited:508–527` 管理已访问ModelAction集合；`StatefulAgent:562` 在输入前加计数。`Model.appendToActionHistory:135–140` 是生成路径记录，不能仅凭它认证注入成功。
- `ModelAction.resolveAt:220–227`：单节点饱和由ModelAction是否visited决定；多节点为 `min(1, visitedCount/min(nodes.length,saturatedVisitedThreshold))`。这不是逐Concrete覆盖，更不是各参数/结果分支覆盖。
- `JevRuntime.inputSummary:764–793` 只有确认输入才进 `confirmedInputs`；执行成功不证明业务成功。`JevRegistry.confirmedHistory:311–341` 以当前映射的State/ModelAction组织历史，refinement会更改树/动作归属，须核对version与mapping完整性。
- 精确Concrete是 `ConcreteActionIdentity(actionType,JevIdentity.fullName(node))`；`JevIdentity:63–70` 只归一化有来源标记的图像hash文本，保留真实文本、祖先、index及交互patch。动态值会拆分，兄弟行语义又未必入fullName。
- `JevRegistry.hasExactExecution:359–366` 是当前State/action与Concrete；`hasRelatedConcreteExecution:369–386` 为同Activity+精确Concrete存在性，不能认证所有同业务入口或结果。旧的页面history池、related index与原生 `nameToActions` 是不同机制，不能混说为通用语义共享。

## 现有日志为何仍不够

`JevRuntime.stateTelemetry:1022–1062` 记录各类数量、unvisited IDs；`recordSelectionDecision:848–872` 记录选中类型/visit/饱和/fingerprint及resolvedNodeCount。`JevEvidenceAudit:203–239` 只对满足抽样条件的source/target保留树图；`input_event_inventory` 的“inventory”是**单个选中输入的低层事件数组**，不是当前页面动作库存。Pure未运行Region/审核候选机制，其context缺失不能靠决策组日志冒补。

详见 [字段完整性矩阵](analysis/inventory-field-coverage.csv) 和 [Shadow设计](shadow-capture-design.md)。本轮未运行Java重解析旧树，更没有把当前源码运行结果当作历史真实候选。
