from pathlib import Path
import json,csv,numpy as np
ROOT=Path(__file__).resolve().parents[1]
def read(n):return json.loads((ROOT/'analysis'/n).read_text())
def write(n,s):(ROOT/n).write_text(s.strip()+'\n')
def table(rows,keys):
 return '| '+' | '.join(keys)+' |\n|'+ '|'.join('---' for _ in keys)+'|\n'+'\n'.join('| '+' | '.join(str(r.get(k,'NA')).replace('|','/') for k in keys)+' |' for r in rows)+'\n'
summ=read('run-summary.json');rs={p.stem:json.loads(p.read_text()) for p in (ROOT/'analysis/runs').glob('*.json')};sens=read('sensitivity.json');prefix=read('prefix-summary.json');comp=read('focus-comparison.json');ranks=read('automatic-top3.json');cases=read('cases.json')
def region(rid,id):return next(x for x in rs[rid]['regions'] if x['id']==id)
def link(rid,id,order=0):return f'[播放 {rid} / {id}](visuals/index.html#run={rid}&region={id}&order={order})'
common='所有角色/功能标签继承既有离线审阅，未经人工金标确认；本轮没有调用新语义模型。计数为真实确认执行，不把拓扑边计作频次。'
write('README.md',f'''# Region 探索流量与时间序列离线验证

完成范围：五 App、十条有效 Pure、**23,279 次确认执行**；Native 最终结构基线514个非Singleton，默认Infomap443个社区（349个非Singleton、94个Singleton），122个同源Activity作用域的入口组。没有启动设备、GPU、Provider或新实验，没有修改正式实现。

**主要结果：Infomap能定位实际预算流转区域；不能把这些社区直接当完整业务功能或充分探索证明。PPR分数能关联入口，但本批sweep常扩张到公共导航，暂不宜作为主边界。**

## 从这里审阅

- [交互查看器：状态图、真实GUI、时间波段、三算法、前缀留出](visuals/index.html)
- [六个研究问题与建议](conclusion.md)
- [真实加权图构造与数据缺口](graph-construction.md)
- [Dominator基线](dominator-baseline.md) / [Infomap](infomap-analysis.md) / [PPR](ppr-analysis.md)
- [时间与共现](temporal-analysis.md) / [统一比较与前缀](algorithm-comparison.md)
- [五App真实案例与失败案例](representative-cases.md)
- [十run基础表](analysis/run-summary.csv)、[所有Region指标](analysis/region-metrics.csv)、[参数敏感性](analysis/sensitivity.csv)、[前缀检验](analysis/prefix-summary.csv)、[自动Top3](analysis/automatic-top3.json)

## 数据与复算

只读复用此前六轮目录，原始归档严格来自第六轮 `evidence/archive-manifest.json` 的十条COMPLETED_VALID白名单。每条确认Native事件逐行核对原始jev-events；输入、receipt和GUI资产复用既有证据。原件SHA、源码摘录和保护清单在 [evidence/](evidence/read-provenance.json)。不存在State ID跨Rep直接相等的匹配。

在当前仓库运行（不改工程依赖，现有成熟库已安装）：

```bash
PYTHONDONTWRITEBYTECODE=1 OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 python reports/region-flow-community-study-20261108/analysis/analyze.py
PYTHONDONTWRITEBYTECODE=1 python reports/region-flow-community-study-20261108/analysis/summarize.py
PYTHONDONTWRITEBYTECODE=1 python reports/region-flow-community-study-20261108/analysis/ppr_checks.py
PYTHONDONTWRITEBYTECODE=1 OPENBLAS_NUM_THREADS=1 python reports/region-flow-community-study-20261108/analysis/build_viewer.py
PYTHONDONTWRITEBYTECODE=1 python reports/region-flow-community-study-20261108/analysis/write_reports.py
PYTHONDONTWRITEBYTECODE=1 python reports/region-flow-community-study-20261108/analysis/verify_viewer.py
```

依赖版本和全部参数见 [parameters.json](analysis/parameters.json)。Python3.13.11，Infomap2.15.1、NetworkX3.2.1、NumPy2.0.2、SciPy1.17.0；ARI使用已安装scikit-learn，版本见code-provenance。脚本只写本研究目录；复算需要本地原始十归档和前六轮，不是脱敏网站中路径即可重跑。

## 离线查看

复制整个 `visuals/` 目录，在浏览器用file://打开index.html。按run延迟载入本地JS；无需服务器、网络或CDN。选择算法、Back处理、区域、25/50/75%前缀，播放或拖动时间轴。Source/Target切换真实图；点击State查看历史代表图。局部显示只是视野，不删除算法图边。PPR多区域重叠以外环显示，时间轴保留多条重叠lane。全程节点布局仅是可视坐标，不是GUI空间或业务真值。

历史截图可能晚于游标，仅供审阅，**未参与历史前缀计算**；未认证同GUI时明确标记，控件框使用虚线投影。完整Concrete库存和剩余机会仍NA；本轮没有重新计算Concrete覆盖。

## 可视证据可用性

[每run GUI可用性表](analysis/gui-availability.csv)区分同GUI证据、历史代表图和MISSING。特别是Wiki Rep1/2分别987/814个Source执行缺图，不能假装全轨迹都有精确截图；图缺失不影响已确认转换顺序，但限制语义审阅。完整Concrete库存仍为NA。

## 边界

{common} 前缀区域来自物理截断的当时图，已知标签作为研究条件，不证明在线当时已经自动发现入口；Dominator历史根快照不可完整恢复，A-flow是明确标注的观测段首根代理。全部断点不冒认重启，左右删失不计完整停留。验证PASS是数据/网页验收，不是独立科学审查。''')
rows=[]
for r in summ:rows.append(dict(Run=r['run'],确认执行=r['executions'],历史State=r['states'],State对=r['state_pairs'],Back=r['back_executions'],SelfLoop=r['self_loops'],连续段=r['segments'],未确认Native=r['unconfirmed_native']))
write('graph-construction.md',f'''# 真实执行流量图：原始转换与时间连续性分开

{common}

## 构造与守恒

第六轮events.jsonl只保留已确认input链；本轮再次逐条比对白名单原始Native事件（原文件行号），共23,279条。每条保留Source、ModelAction、Concrete digest/fullName、实际Target、Native时间/step/事件序号、input/receipt路径与GUI标识。`analysis/traces/<run>.jsonl`是全部动作级序列；`analysis/action-edges/`按Source/ModelAction/Target/type聚合；`analysis/edges/`按State对计真实次数。每run边权和等于确认执行数；没有用UTG边的final visits累加替代执行。

{table(rows,['Run','确认执行','历史State','State对','Back','SelfLoop','连续段','未确认Native'])}

V使用原生裸State ID（包含已退役的历史ID），不是收尾State过滤后子集。Graph.java:199–200只更新新分配ID的版本前缀；getOrCreateState:247–269复用现存对象，State counter不因版本变化重置。因此版本是元数据，不把同一现存State在每个版本复制。另运行version-scoped敏感性，完整partition在run-summary/version_sensitivity；两种口径不强行alias。新ID/新转换不一定代表新业务行为，可能受APE抽象变化影响。

## Back、Self-loop和重启

- G1：每个确认GUI转换权重1，保留MODEL_BACK和Self-loop。
- G2：仅明确MODEL_BACK乘0.25，其余1；不是证明0.25最佳，仅固定敏感性。
- G3：仅去明确MODEL_BACK；用于反证，不作为默认清洗。
- 点击Navigate up、工具栏返回、未知图标没有统一可靠返回分类，保留原Action/type并标导航语义UNKNOWN。没有把同Activity转换都判内部或所有Back都判退出。
- 真实执行中没有可单独认证的restart转换链；重启次数NA，不能宣称0。断点可能来自未记录操作、重启、GUI更替或抽象变化，不一律叫Reset。

相邻执行须同时满足：Native order连续、时间递增、前Target=后Source、GUI ID与GUI timestamp连续、前观察版本=后input版本。失败即分段；**分段不造一条target→nextsource边**，但保留各自已认证转换。总段数见上表。NativeTransition中的refinement=false不代表抽象版本从未变化。

## 时间、新发现与删失

预算分母是确认GUI执行条数，不是全部Monkey输入数或墙钟总耗时。source∈R的动作计预算；Source在外、Target在内的确认边计进入。离开后同一认证段再进才计保守重入；段首内部为左删失，段末未见退出为右删失。完整停留为有确认入/出边的Source动作数，含离开动作。另保留所有观测片段长度与删失数量，不能用完整样本均值替代全部停留。

Native `new_state`原样保留。首次Transition用按时间首次 `(raw Source, ModelAction, raw Target)`，另报State对首次，不能当独立业务分支数。新ModelAction为原生事件标志；饱和/未访问来自输入前同State、同版本Selection快照，不从收尾图回填。

**新增State同时报告来源归集与目标是否仍在R。** 从R中的动作到区域外新State仍是留出新增事实；不把它追认成旧区域成员，也不丢弃以制造零收益。完整库存/Concrete覆盖NA。

## 来源与审计

[白名单与读取SHA](evidence/read-provenance.json) · [代码版本](evidence/code-provenance.json) · [源码摘录](evidence/source-excerpts.txt) · [数值验收](evidence/numerical-validation.json)。GUI像素衍生图、原件SHA与对齐限制见 [image-index](evidence/image-index.json)。''')
rows=[dict(Run=r['run'],原生最终非Singleton=r['A_final_non_singleton'],流量根代理非Singleton=r['A_flow_non_singleton'],原生最终State=r['final_states'],历史State=r['states'],同Activity入口组=r['entry_groups']) for r in summ]
write('dominator-baseline.md',f'''# Dominator：结构基线保留两种输入口径

## 定义没有变化

JevRegion.Calculator.prepare/structure（JevRegion.java:71–116）先从多root求可达，再以前驱支配集合交集收敛，建立idom和children；每个非Root Header的子树含Header本身。本轮只保留size≥2，不套成熟门限或nested selection。原生最终图基线复用第一轮经独立NetworkX及删点等价核验的514个非Singleton；没有修改Native定义。

{table(rows,['Run','原生最终非Singleton','流量根代理非Singleton','原生最终State','历史State','同Activity入口组'])}

## A-final与A-flow不能混称

**A-final** 是归档收尾拓扑与原生roots的精确结构。将真实执行的裸ID投影到这些成员，未出现/退役ID不补alias。它用于描述现有最终结构；**不能出现在早期前缀结果中**。

**A-flow** 把同一支配定义放在本轮确认流量图上，以截至当时已出现的连续段首Source作为保守多root代理。StatefulAgent.updateGraph:667–676仅在appActivityJustStarted时加entry tree；Graph:391–405再更新entryStates，现有日志不提供每个历史时刻完整root集合。段首还可能是取证缺口，故A-flow不是精确重演在线root。A-flow有530个非Singleton，前缀同样仅用当时段首，所有结果明确标proxy。

该缺口限制了三算法完全公平的历史根对照。不能利用更保守代理导致的小Region，宣称Infomap全面优于Native。A-final仍是核心结构基线；统一图A-flow作为补充控制。

## 结构优势与局限的具体差异

ODK Rep2 `g11s38→{{g11s38,g11s41}}`原生Region只有2 State、125来源执行、内部10、Pstay8%。实际Download入口109次中只有2次Target在它内。默认Infomap四State社区包含全部109目标；这说明它更贴近这一段实际流量，不证明业务流程完整恢复。

ActivityDiary Rep1 Header `g21s63`子树5 State、253来源执行；MainActivity来源Add的53次中24个Target在内，编辑与颜色/字段还有其他共享后继。Dominator仍准确描述支配关系，**不保证入口条件化功能范围**。同功能不同分支在汇合点之前通常互不支配，汇合后若所有root路径经过该点，仍可形成后部子树。

Omni Snooze的组合操作能形成局部子树/社区，但这不能将日期、重复规则操作改判为Ⅰ类。Scarlet高频新建的入口Target可能Singleton，非Singleton结构发现不是功能价值过滤器。

完整Header、成员、进入/离开、真实流量见 [region-metrics](analysis/region-metrics.csv)、[各run结构JSON](analysis/runs/odkcollect-Rep2.json)，可切换 [查看器](visuals/index.html)。''')
# Sensitivity main table.
srows=[]
for r in summ:
 ss=[s for s in sens if s['run']==r['run'] and s['method']=='Infomap'];default=[s for s in ss if s['seed']==11 and s['markov_time']==1]
 srows.append(dict(Run=r['run'],G1=r['infomap_modules']['G1'],G2=r['infomap_modules']['G2'],G3=r['infomap_modules']['G3'],G2_ARI=round(next(s['ARI_vs_G1_default'] for s in default if s['graph']=='G2'),3),G3_ARI=round(next(s['ARI_vs_G1_default'] for s in default if s['graph']=='G3'),3),随机种子最小ARI=round(min(s['ARI_vs_G1_default'] for s in ss if s['graph']=='G1' and s['markov_time']==1),3)))
write('infomap-analysis.md',f'''# Infomap：确认流量确实形成社区，但不是业务金标分区

## 可复算配置

成熟Infomap2.15.1 Python库，有向、加权、two_level=True、num_trials=5、num_threads=1、默认seed11、Markov time1、teleport0.15、unrecorded teleportation、Self-loop保留。对三种Back图各运行seed11/23/47 × Markov time0.5/1/2，十run共270次完整图划分；另外90次前缀图。保存版本、codelength、社区成员和参数；没有自己实现Infomap优化器。

{table(srows,['Run','G1','G2','G3','G2_ARI','G3_ARI','随机种子最小ARI'])}

默认G1共443个社区，其中349个非Singleton；不是443个已经确认的独立功能。降权/删除Back会改变分区，ODK两Rep去Back的ARI降至0.339/0.448，不能据此把Back清掉后最漂亮结果当主结论。固定Markov1时随机seed也会影响AD/Wiki等结果，完整敏感性见 [sensitivity.csv](analysis/sensitivity.csv)。Markov尺度全范围最低ARI约0.106，社区尺度不稳定必须保留。

## 正例：ODK Download Rep2

`Infomap-G1-004 = {{g11s37,g11s38,g11s41,g20s82}}`：345来源执行（15.9%确认预算）、230内部、115确认进入、10次同连续段确认重入、完整停留P90=3、最长11步。全部109个冻结Download入口Target都在内；直接结构Region `g11s38`仅覆盖2个。不是靠把首页吞入获得高覆盖；首页`g1s1`在另一个社区。

事件#1899–1902：Download→同页Back→Cancel→Back到主菜单；同样三步后部片段反复出现，完整路径最高84次。对齐缺口使全轨迹被分段，重入10是保守段内计数，不是把115全部称重复进入。

## 反例与有用的不同粒度

- ODK Rep1最大社区14 State，含首页、列表和Download，消费1797/2074步、内部1746；这是跨功能导航循环，**不能命名为纯Download Region**。它仍是实际预算聚集单元，跨Rep业务边界不稳定。
- Omni Rep2 `g8s37` PasswordActivity单节点117来源执行、117自环；Infomap输出Singleton。它表明等待/无效输入也能占预算，不证明识别了功能状态群。Singleton单列，未混进非Singleton主比较。
- Omni Snooze Rep1一个真实连续流程被拆到 `Infomap-G1-030/007/004`（日期时间、重复规则、其他选择）；全局划分不能保证同一业务所有分支相邻为一个社区。
- ActivityDiary共享编辑页面被全局单一模块分配，不能同时表达Add/Edit两个功能归属；业务多归属仍需入口和轨迹证据。
- Wikipedia不同搜索/文章/语言/媒体轨迹形成多个模块，不可把一个模块直接叫全站Search。

高内部流量部分是算法优化目标内生性，以上结论另经真实停留、重入、时间共现和留出检验。没有功能金标precision/recall，不提供“更准”的虚假百分比。''')
pprrows=[]
for r in summ:pprrows.append(dict(Run=r['run'],同源Activity入口组=r['entry_groups'],默认局部解=r['ppr_local_solutions'],无局部解=r['entry_groups']-r['ppr_local_solutions']))
write('ppr-analysis.md',f'''# 入口条件化PPR：分数有关联性，sweep边界容易泛化

## 种子和Activity约束

继承第六轮116个功能×run候选，按**Source Activity**拆为122组；UNKNOWN Activity按Source State再拆，不跨Activity候选匹配。保留不同ModelAction、Concrete、Source State和多个实际Target。Add56/63、Edit81/101，ODK Download121/109，WikiⅠSearch29/55；不把Ⅲ输入/提交当Ⅰseed。ODK第二轮旧104与当前109之差为此前已确认5个get_forms父卡片，并非本轮新增入口。

Snooze局部日期操作和Scarlet CreateList未确认Ⅰ入口仅作流量上下文，不伪造PPR种子。跨Rep以相同功能候选、Source Activity、真实控件/GUI和结果审查，见 [cross-rep-evidence](analysis/cross-rep-evidence.csv)，不比较State ID相等。

{table(pprrows,['Run','同源Activity入口组','默认局部解','无局部解'])}

## 有向局部划分而非随意分数阈值

NetworkX PageRank；alpha=0.75/0.85/0.95，频次种子与每Target均匀种子；G1/G2/G3均运行。默认alpha0.85、按真实目标次数加权。完整State分数、排名和**每一步sweep**在 `analysis/ppr/<run>.json`。

为使有向切割有稳定体积，先由真实加权转移P构造Q=0.85P+0.15均匀teleport（dangling均匀），pi为其平稳分布。F(i,j)=pi(i)Q(i,j)，Phi(R)=F(R,¬R)/min(pi(R),1−pi(R))。以ppr/pi降序sweep，要求覆盖所有已观察seed且pi(R)≤0.5，取最小Phi；无可行非平凡集记NO_LOCAL_SOLUTION。全部未受半体积限制的最小集也保留，避免隐藏公共导航扩张。这里是明确实现的**正则化有向流cut实验**，不声称等同所有PPR局部算法或某论文完整算法。

另比较主Target单种子与多Target，并对28个重点组独立重算sweep三点cut及平稳流守恒，通过 [ppr-cut-validation](evidence/ppr-cut-validation.json)。库PageRank解与本研究cut选择分别负责，不自造优化器。

## 算法依据与实现边界

采用成熟库而非自行编写Infomap优化器。主要依据是Infomap官方产品与代码说明、Rosvall/Bergstrom原始map-equation论文、NetworkX PageRank API；下载状态及SHA见 [算法文献索引](evidence/algorithm-references.json)。若特定旧API链接404或论文证书失败，失败原样保留，不冒称已读；已经成功获取官方Infomap页面、原始论文摘要及PageRank文档。本研究正则化有向cut的精确定义与数值验收优先于笼统套用某论文保证。

## 结果：本批尚不能把PPR作为主定位边界

- ODK Rep2 Download：alpha0.75/0.85/0.95均18 State，默认1902来源步骤、1877内部、包含MainMenu `g1s1`、表单列表等，占确认预算87.8%。相比Infomap四State，100% seed覆盖是约束内生，不是功能更完整证明。
- ActivityDiary Rep1 MainActivity Add：alpha变化得到40/38/35 State；Main Edit46/45/无局部解；默认Add/Edit有大量重叠。共同编辑页可重叠是优点，首页/其他页面也被包含是边界风险；不能因含共同页就认为所有Save结果等价。
- Wiki Rep2 Search（Main来源）181/178/157 State，Page来源195/190/174 State，明显大于局部搜索模块，阅读、语言及导航被共同包含。源Activity仅限制入口成员，不保证游走永远不跨Activity；这是有意保留的真实流。
- 默认122组有121个局部解；“有解”并不代表有业务意义。较大alpha有更多无解，不用降低任意阈值隐藏失败。

PPR区域大小、公共hub、重叠Jaccard和主Target敏感性分别见 [sensitivity](analysis/sensitivity.csv)、[counterexamples](analysis/counterexamples.json)、[ppr-overlap](analysis/ppr-overlap.csv)、[multi-target](analysis/ppr-multi-target-sensitivity.csv)。这只否定本批配置直接作为功能边界的可靠性，不否定PPR分数作为入口邻域关联线索的价值。''')
# Automatic ranking table.
rankingtext=[]
for kind,rr in ranks.items():
 rows=[]
 for r in rr:rows.append(dict(Run=r['run'],Region=r['region'],Size=r['size'],内部=r['internal_flow'],完整最长=r['dwell_max'],P90=r['dwell_p90'],确认重入=r['confirmed_reentries_within_segment'],晚期步=r['late']['steps'],晚期新S=r['late']['new_state'],晚期新T=r['late']['new_transition']))
 rankingtext.append('### '+kind+'\n\n'+table(rows,['Run','Region','Size','内部','完整最长','P90','确认重入','晚期步','晚期新S','晚期新T']))
write('temporal-analysis.md',f'''# 时间序列验证：聚集、滞留、重入、收益分别测量

## 指标口径

内部流量Pstay按确认实际次数；预算是Source在Region内的确认GUI步骤比。真实外→内边计进入；同一认证连续段内离开后重入才计重复。完整停留只用已确认入口和出口，不跨断点拼长段；均值、中位、P90、最长、所有片段与左右删失数独立保存。详细分布在每run/region metrics.episodes；原始顺序、时间和Action完整保留。

Region切换表按Infomap全局分区统计，每条真实边保留Back标签，见 [inter-region-transitions](analysis/inter-region-transitions.csv)。重启未独立认证，断点不计普通跨社区边。Dominator/PPR有重叠，不强制唯一标签，不将不同Region预算相加。

## 能看到“一波一波”，但不能宣称严格周期性

ODK Rep2四State Download社区连续活动 `#173–184`（11来源动作）、`#226–232`（6步），晚期 `#2104–2107`、`#2136–2139` 等三步反复片段；中间回首页/列表社区。`#1899 Download→#1900 Back(仍同下载页)→#1901 Cancel→#1902 Back到主菜单`可逐步播放。

Scarlet Rep2九State社区1372步（56.2%预算）、内部1239、确认进入130、段内重入106；晚期489步仍占用预算但0新State、2首次转换。它与大尺度PPR吞并44节点不同，时间轴显示高频首页/编辑往返；不是业务新建覆盖充分的证明。

反例：Wikipedia Rep2 Search关联16节点社区，最后20%来源36步产生5新State（4个在成员内、1个跨出）、31首次转换；ActivityDiary Rep1最大流量社区晚期95步有4新State（2内2外）、56首次转换。高流量和重入本身不能判低收益。

## 滑窗共现及其样本缺口

只在认证连续段中用每个起点的完整20/50/100步滑窗，记录“至少共同出现一次”的State集合；内部与跨界平均Jaccard独立报告，并以相同边际出现次数下独立期望作有限控制（不是完整置换显著性检验）。同规模分层另见method-summary；没有用社区内流量高作唯一评价。

ODK Rep2 Download在20步326个完整窗口：内部平均0.469、跨界0.081、边际独立期望0.115；50步111窗口内部1.0，但只覆盖长连续片段、样本成员也可能变少，不能拿它当全程效果。**100步没有完整连续窗口，NA而非0。** Omni Rep1两State长驻留社区029，20步内部0.566/跨界0.010，100步1.0/0.093；Scarlet Rep2在100步内部0.351、跨界0.319、独立期望0.348，区分度弱，不能只挑小窗口的好结果。

## 自动Top3与去重

全部从默认G1的非Singleton社区自动排序，不手动挑漂亮图。晚期高流量榜的展示条件为全程内部≥100次，仅用于案例短名单，不是定位或饱和阈值；其余榜不加流量阈值。最长与P90两榜都保留，避免少样本P90代替真正最长。

{chr(10).join(rankingtext)}

榜单允许同社区重复，完整JSON以 `(run,region)` 去重即可。不是五类独立样本，也不是独立重复试验。所有失败和样本缺口保留。''')
# Prefix aggregation.
prows=[]
for method in ['A-flow','Infomap-G1','PPR-G1']:
 for f in [.25,.5,.75]:
  zz=[r for r in prefix if r['method']==method and r['prefix']==f and r['size']>=2]
  prows.append(dict(Method=method,前缀=f,非Singleton=len(zz),留出仍活动=sum(r['holdout_steps']>0 for r in zz),留出有重入=sum(r['holdout_reentries']>0 for r in zz),留出新State=sum(r['holdout_new_state']>0 for r in zz),留出新Transition=sum(r['holdout_new_transition']>0 for r in zz),对最终最佳Jaccard中位=round(float(np.median([r['final_best_jaccard'] for r in zz])),3)))
write('algorithm-comparison.md',f'''# 三算法比较：不能以内部流量自证优越

## 同图与规模控制

A-final保留现有Native精确收尾结构；A-flow将相同支配定义放到确认图/历史段首根代理。Infomap与PPR共享G1/G2/G3确认加权图。为防大Region自然获得高流量，保存每个Region的size、budget、Pstay、完整停留、重入、晚期S/T、原生ModelAction提示，并分别统计2–5、6–15、≥16规模层；见 [method-summary](analysis/method-summary.csv)。不能把不同size分布的总均值当公平优越性检验。

| 维度 | Dominator | Infomap | PPR sweep |
|---|---|---|---|
| 核心定义 | 严格结构支配 | 实际随机游走流社区 | 入口条件随机游走+有向cut |
| 预算流转 | 常碎片化，但局部结构清楚 | 本批能显示反复流转单元 | 常大到公共导航/近全run |
| 入口关联 | 非直接一一对应 | 需另接入口实际目标/轨迹 | 显式seed，但目标覆盖内生 |
| 分叉汇合 | 汇合前支配不成立常碎片 | 可合并频繁往返，也可切开同功能 | 可跨分支，但可吞掉其他功能 |
| 共享State | 子树可nested，不等于功能多归属 | 全局单分区，不能直接表达多功能 | 允许重叠，但共享不证明模式/结果等价 |
| 时间证据 | 完整段/重入可独立检验 | 此项增加实际研究价值 | 大区域容易天然长驻留 |
| 跨Rep | 局部结构与抽象有关 | ODK Rep1/2社区业务粒度不同 | seed差异与公共hub导致大小差异 |

## 真时间前缀

25/50/75%按确认事件数物理截断再构图、Infomap、PPR与A-flow。只有当时已执行的冻结Ⅰ标签成员及实际Target作seed，不从最终State集合补边/补root/补目标。全部候选（含单点/无解）和G1/G2/G3共保存在prefix-validation；G1精简表2542行。**标签本身是事后可审核研究条件，不代表在线当时已经自动识别功能。**

{table(prows,['Method','前缀','非Singleton','留出仍活动','留出有重入','留出新State','留出新Transition','对最终最佳Jaccard中位'])}

这里每列数的是“有该现象的区域数”，不是收益总量或预测准确率；Region重叠与多个前缀高度相关。Jaccard只衡量结构成员延续，不证明功能身份，A-flow的1.0常来自小子树，不能拿来直接判赢家。

## 两个相反的留出案例

- **ODK Rep2 75%**：当时Infomap三State `g11s37/g11s38/g11s41`，训练246来源步；冻结成员在后续98步、34确认进入中0新State/0新ModelAction三元转换。确实验证这组已知状态后部高度重复；但随后其他来源Sent控件到新 `g20s82`（#1762），不能因不属旧成员而声称整个Download相关页面永无新发现。
- **Wiki Rep2 75%**：当时六State组含 `g19s94/g39s173/g78s364/g86s410/g86s411/g86s413`，后续24来源步、17确认进入，2新State/21首次转换。新增节点仍未追认旧成员；是旧区域动作的跨边界发现事实。入口ⅠSearch→Ⅲ查询/清除/语言选择仍有新分支。

## 结论强度

支持下一阶段以Infomap流量社区作为**预算活动候选**，接已有Ⅰ入口和短实际轨迹，保留Dominator作局部结构核对。暂不支持把PPR最小cut直接当Region边界，也不支持替换Native后立即禁用。当前只有2 Rep/App、无业务功能金标、动作库存缺失、抽象可能变化，无法给出正式泛化性能排名或安全SUPPRESS结论。''')
# Cases per run largest-flow plus focus.
sections=[]
for c in cases:
 rid=c['run'];r=rs[rid];es=[json.loads(l) for l in (ROOT/f'analysis/traces/{rid}.jsonl').open()];e=next(e for e in es if e['transition_id']==c['focus_event']);z=region(rid,c['region']);m=z['metrics'];lo=max(0,e['order']-1);seq=[v for v in es[lo:lo+6] if v['segment']==e['segment']]
 seqrows=[dict(序号=v['order']+1,事件=v['transition_id'],Source=v['state'],Action=v['content_desc'] or v['text'] or v['resource_id'] or v['action_type'],Target=v['target_state'],新State=v['new_state'],首次转换=v['first_model_transition_flow']) for v in seq]
 sections.append(f'''## {rid}：{c['title']}

{link(rid,c['region'],e['order'])}。焦点事件 `{e['transition_id']}`，Native step {e['step']}、原jev-events行{e['event_line']}；Source Activity `{e['source_activity']}`，实际Target `{e['target_state']}`。控件 `{e['resource_id']}`，ModelAction `{e['model_action']}`；Concrete digest `{e['identity_digest']}`。

默认相关模块 `{z['id']}`，{m['size']} State、{m['source_steps']}来源步、内部{m['internal_flow']}、确认进入{m['confirmed_entries']}、保守重入{m['confirmed_reentries_within_segment']}、完整停留P90 {m['dwell_p90']}、最长{m['dwell_max']}。这是焦点目标所在模块，不是人工确认业务边界。真实图片见查看器Source/Target与对应 [浏览器截图](evidence/viewer-{rid}.png)（Rep1/Rep2未各截图的情况通过查看器切换）。

{table(seqrows,['序号','事件','Source','Action','Target','新State','首次转换'])}''')
# Only reference captured existing screenshot paths.
sections=[s.replace(f'[浏览器截图](evidence/viewer-{rid}.png)',f'[五App浏览器验收](evidence/browser-validation.json)') if not (ROOT/f'evidence/viewer-{rid}.png').exists() else s for s,rid in zip(sections,[c['run'] for c in cases])]
write('representative-cases.md',f'''# 五App真实案例、反例与可审核证据

{common} 每个run全量确认动作都能播放，局部State图与三方法成员同时保留。Screenshot来自归档真实像素；同State代表图不保证当次GUI对齐。控件虚线框仅bounds投影，不能据此认证当前可执行库存。

## 先看这些反例

1. **ODK Rep1大流量社区误作纯Download**：14 State含首页/列表/Download，内部1746。Rep2 Download可分成四节点，跨Rep不能按相同State ID或社区序号匹配。
2. **ODK Rep2低收益也非永久零收益**：Download模块晚期80来源步0新State但1首次转换，即 `#1763 g20s82→OK→g11s38`；前一步 `#1762 Sent→g20s82` 的文字/目标Activity冲突保留，不强行改标Download。全功能充分性仍UNKNOWN。
3. **AD同编辑页不同结果**：`g28e189:231 Edit→g21s63; g28e190:232 Save→g28s87` 与 `g28e233:275 Add→g21s63; g28e234:276 Save→g28s90`。共享编辑State不代表Save业务结果可合并。两组Ⅰ入口仍按相同source Activity关联；不同Activity不直接拼组。
4. **Omni Snooze切分**：#1004–1022真实连续路径，Main→Snooze日期→时间/年→重复规则，多模块轮换。日期字段是组合操作，不用同名/同目标升级Ⅰ入口；Snooze没有伪造PPR seed。
5. **Scarlet CreateList**：Rep1 `g44s187`单State126步、110自环，Activity为CreateListNote；Ⅰ入口仍待确认，PPR记未提供种子而不是零功能价值。CreateNote Rep2高重复，Rep1晚期仍出现新转换；动态数据实例不是独立新功能数。
6. **Wiki SearchⅠ/Ⅲ明确分开**：#1872具名Search入口从Page到Search；#1873 Back仍在Search且新State；#1874 Clear query、#1875 Clear history、#1876语言选择。Back不能全部删除，Ⅲ输入/提交不能混作Ⅰseed。文章/语言/媒体结果仍在完整流量中，不手工清边。
7. **无意义或有限意义社区**：Omni Rep2 Password单点117次自环；它是预算问题证据，不是多State功能Region成功。长驻留也可能一次性活动：最长87/66步榜不必反复重入，必须同时看次数。

{chr(10).join(sections)}

## 分叉/汇合不是逆向杜撰路径

[counterexamples.json](analysis/counterexamples.json)保存来自同一模块内不同Source进入共同Target的两条真实短历史，每条都保留自己的事件顺序和segment；不是将UTG前驱任意拼成一条历史。AD明确Add/Edit进入 `g21s63` / `g27s96` 的入口与PPR共享成员也在该表；PPR覆盖共同State是关联证据，不保证其余成员均同功能。

所有case标题仅为先前研究线索。相关目标Activity来自既有证据，缺失保留UNKNOWN；图片资产哈希、原件路径、原生事件与input/receipt定位完整保留。''')
write('conclusion.md',f'''# 结论：流量社区有实际价值，入口PPR边界尚不可靠

本轮只读十条完成Pure：23,279确认执行、514个原生非Singleton基线；有向加权Infomap、入口PPR、G1/G2/G3、三个真实历史前缀全部跑完。所有图和GUI可在 [交互查看器](visuals/index.html) 审查；没有在线改动或新实验。功能角色不是人工金标。

## Q1. Infomap能否识别反复流转社区？

**能，识别的是实际预算活动单元。** 默认443社区/349非Singleton。ODK Rep2四State `g11s37/g11s38/g11s41/g20s82` 有345来源步、230内部、115确认进入、10次段内重入、完整最长11步、P90=3。全部109个冻结Download入口目标命中，原生g11s38两State子树仅2/109。Scarlet Rep2九State社区1372步、内部1239、106次重入，也明显补充结构Region碎片化遗漏的流量图景。

但ODK Rep1最大14节点社区合并首页/列表/Download；Omni密码单点自环、Snooze被多模块切分。不能把所有模块称独立功能Region。

## Q2. PPR是否比Dominator更具代表性？

**分数和重叠有入口关联价值，但本批sweep边界没有足够可靠性。** ODK Rep2 Download从Dominator局部碎片扩为18State、1902步，包含首页和其他功能；alpha0.75/0.85/0.95均18，并非某个幸运阈值。AD Main来源Add默认38State、Edit45State，含共同编辑页但也含公共导航；Wiki Search Main/Page来源178/190State。seed覆盖率受算法约束，不能自证业务更准。PPR目前不宜做主边界。

## Q3. 时间轴是否呈集中活动、跳出、再进？

**存在阶段性波段，未证明严格周期规律。** ODK Download #173–184、#226–232与晚期多次三步片段重复；#1899–1902 Download→Back同页→Cancel→Back主菜单可逐步审查。共现20步内部0.469、跨界0.081；100步因断点无完整窗口，NA。Omni、AD、Scarlet、Wiki各有真实波段和不同长短停留；完整分布、删失和例外都保留。

## Q4. 哪些区域明显重复消耗预算？

ODK Rep2 Download最后20%来源80步0新State/1首次转换；75%前缀的三State版本在后续98来源步、34确认进入中S/T双零。Scarlet Rep2九State晚期489来源步0新State、2首次转换。Omni Rep1最大流量五State模块晚期240步0新State、2首次转换。它们值得Shadow预算研究，**不代表剩余动作机会清零**。ODK Rep1晚期#1978 Download→#1979首次Checkbox/新转换继续反驳State零增量等于无价值。

## Q5. 哪些高流量区域仍有收益？

AD Rep1最大社区晚期95来源步4新State（2内2外）、56首次转换；Wiki Rep2搜索关联16节点社区晚期36步5新State（4内1外）、31首次转换。Wiki75%前缀六节点组留出24步仍2新State/21转换。Scarlet Rep1高流量18节点社区晚期也有新State/44首次转换。计数可能受抽象变化或数据实例影响，不能直接当业务成功数，但足以否定“高流量即可禁用”。

## Q6. 下一代定位优先什么？

**优先验证Infomap流量社区＋既有Ⅰ入口/真实轨迹关联；保留Dominator作为局部结构核对。** 它最直接对应这轮“预算在哪些状态群消耗”的问题，时间验证有具体增益；不是要求一个业务功能等于一个全局社区。PPR分数可保留为辅助关联/重叠视角，暂不把最小cut强制设为边界。结论不是Infomap在所有功能上更准：规模、算法内生目标、历史root缺口、Back和Markov敏感性、动态State拆分、两Rep样本与缺金标都限制外推。

## 下一阶段最小在线验证方案（只提案，未实施）

被动复用确认Transition频次与时间段、原生ModelAction饱和/未访提示；在预算不变且不改变选择的Shadow中，低频生成小型流量社区快照，将已知Ⅰ入口的实际目标和短连续轨迹挂接。保留Back与自环，显式重启/缺口分段；同时记录公共导航占比、成员漂移、跨社区新发现和仍有未访模型提示。

用过去窗口计算候选，前瞻比较后续重入/停留、新State、首次转换及原生动作进展；对公共hub合并、动态对象与不同Save结果单独审核。先验证可稳定追踪预算活动且不掩盖未来发现，再讨论任何充分性/预算决策。此轮没有实现Shadow、Locator、Concrete覆盖、阈值或SUPPRESS。''')
print('REPORTS',len(list(ROOT.glob('*.md'))))
