///|
fn empty_graph() -> GraphInfo {
{
analyzed: false,
components: 0,
cyclic_components: 0,
cyclic_transactions: 0,
bfs_roots: 0,
edge_budget_exceeded: false,
}
}
///|
fn coverage_indexed(
h : History,
writes : Map[String, Map[String, WriteRef]],
) -> Array[KeyCoverage] {
let reads : Map[String, Int] = Map([])
let unresolved : Map[String, Int] = Map([])
for tx in h.transactions {
if tx.status != Committed {
continue
}
for op in tx.ops {
if op.kind != Read {
continue
}
reads[op.key] = reads.get_or_default(op.key, 0) + 1
if h.initial.get(op.key) != Some(op.version) {
let source = writes.get_or_default(op.key, Map([])).get(op.version)
if source is None ||
(source is Some(w) && h.transactions[w.tx].status == Unknown) {
unresolved[op.key] = unresolved.get_or_default(op.key, 0) + 1
}
}
}
}
let result : Array[KeyCoverage] = []
let keys = h.initial.keys().collect()
keys.sort()
for key in keys {
let mut count = 0
match writes.get(key) {
Some(versions) =>
for _, w in versions {
if w.is_final && h.transactions[w.tx].status == Committed {
count += 1
}
}
None => ()
}
result.push({
key,
committed_reads: reads.get_or_default(key, 0),
committed_final_writes: count,
unresolved_reads: unresolved.get_or_default(key, 0),
})
}
result
}
///|
fn order_source_cn(source : String, writes : Int) -> String {
match source {
"asserted" => "采集声明的版本链"
"searched" => "搜索得到的可行补全(非观测事实)"
"single-writer" =>
if writes == 0 {
"仅初始版本"
} else {
"单写者推断"
}
_ => "版本顺序缺失"
}
}
///|
fn finding_cn(f : Finding) -> String {
match f.code {
"dependency_cycle" =>
"这些事务的必要先后关系形成闭环,无法同时满足。"
"no_serial_execution" =>
"已穷尽预算范围内全部可行串行前缀,没有执行能重现所有读取和声明的版本顺序。"
"aborted_read" =>
"已提交事务读到了已回滚事务写入的版本。"
"intermediate_read" =>
"读到了其他事务在提交前已被自身后续写入覆盖的中间版本。"
"future_read" => "事务读到了自己尚未执行的未来写入版本。"
"read_your_writes" =>
"事务没有读到自己最近一次写入的版本。"
"non_repeatable_read" =>
"没有自身写入介入,同一事务对同键读到了不同版本。"
"missing_version_order" =>
"多个已提交写者的版本先后未被采集,当前不能给出完整判断。"
"missing_interval" =>
"严格模型缺少共同观察时钟下的完整开始和结束时间。"
"unknown_commit" =>
"事务的提交结果未知,不能将它当作已提交事务。"
"unknown_writer" =>
"读取来源存在记录,但写者的提交结果未知。"
"unobserved_version" =>
"读取版本没有记录中的写者,可能缺少采集窗口或来源记录。"
"edge_limit" =>
"依赖数超出预算,图已截断,不能据此认定符合模型。"
"search_limit" =>
"精确补全未完成;查看 search 中的规模或计算预算原因。"
_ => f.message
}
}
///|
fn dependency_cn(d : Dependency) -> String {
match d {
WR =>
"目标事务读到了来源事务的最终写入,来源事务必须先执行。"
WW => "提供的同键版本链要求来源写入先于目标写入。"
RW =>
"来源事务读到了较早版本,必须先于写入较晚版本的目标事务。"
RT =>
"在共同观察时钟下,来源事务完成时间早于目标事务开始时间。"
}
}
///|
fn next_steps(r : Report) -> Array[String] {
let result : Array[String] = []
for f in r.findings {
let advice = match f.code {
"missing_version_order" | "search_limit" =>
"补采同键已提交最终写入的版本链,或提取预算内的小型复现窗口。"
"missing_interval" =>
"使用同一单调观察时钟记录已提交事务的开始和结束。"
"unknown_commit" | "unknown_writer" =>
"核对事务最终提交结果,保留未知状态直到有实际证据。"
"unobserved_version" =>
"扩大采集窗口并寻找读取版本的写入来源。"
"edge_limit" =>
"缩小原始采集窗口后重新分析;截断图不能提供完整的符合模型结论。"
"dependency_cycle" | "no_serial_execution" =>
"保留原始日志,使用 shrink 缩减反例,并用 capsule 保存可复现证据。"
"duplicate_write_version" | "initial_version_reused" =>
"重新采集,为每次同键写入分配唯一版本标记。"
_ =>
if f.severity == "error" {
"按输入格式核对初始状态、事务标识、版本顺序和时间字段。"
} else {
"核对对应事务的操作下标和版本来源,保留原始采集记录。"
}
}
if !result.contains(advice) && result.length() < 32 {
result.push(advice)
}
}
result
}