# 规则分析与批量执行

Mooncakes 0.2.1 的 `kaigeliang/jsonlogic/analysis` 与 `kaigeliang/jsonlogic/batch` 支持 native、JS、Wasm、Wasm GC。native CLI 在 `src/cli/`。

## 全分支静态分析

```moonbit
import { "kaigeliang/jsonlogic/analysis" @analysis }
```

```moonbit
let report = @analysis.check({
  "map": [{ "var": "orders" }, { "var": "price" }],
})
assert_eq(report.root_paths(), ["orders"])
assert_eq(report.scopes.length(), 2)
```

`analyze(rule, max_nodes=100000, max_depth=128)` 返回 scopes、operations、dependencies、diagnostics 和 nodes_used。`check` 在确定的语法问题上抛出 `InvalidRule`，否则返回同一报告。输入无效抛 `InvalidInput(pointer, reason)`，超预算抛 `LimitExceeded(pointer)`；最大深度范围 1–256。

依赖位置是规则中的 JSON Pointer；数据路径保留 JSONLogic 点分隔路径。`StaticPath` 表示可确定路径，`WholeScope` 表示整个当前作用域，`DynamicPath` 表示计算出来的路径。`root_paths()` 去重列出根数据的静态路径，但不包含 WholeScope 和动态依赖；必须同时查看 `dependencies`／`has_dynamic_paths()`。

分析遍历所有可执行分支，不执行规则；短路未选中的分支仍被分析。map／filter／all／some／none 的源表达式使用父作用域，body 使用新的元素作用域；reduce 的 body 使用 current／accumulator 作用域，初始值使用父作用域。多键／空对象按核心语义当作不执行的字面量，集合操作忽略的额外参数不产生假依赖。完整输入仍计入节点／深度检查。

诊断识别未知操作、缺少核心要求的参数和确定无效的 missing_some 结构。它不做完整类型证明，也不保证规则有合适数据、不会除零、不会超预算或一定执行成功。

```sh
moon run src/examples/analysis --target native
```

## 规则集 API

```moonbit
import { "kaigeliang/jsonlogic/batch" @batch }
```

```moonbit
let report = @batch.execute([
  @batch.Rule::{ id: "adult", rule: { ">=": [{ "var": "age" }, 18] } },
], { "age": 22 })
assert_eq(report.successful, 1)
println(report.to_json().stringify())
```

每条规则共享输入 data，按输入顺序保留 id、结果／错误、成功日志和预算信息。规则失败不丢失后续条目。重复／空 id、输入尺寸或预算配置错误在执行前拒绝整个请求，抛出 `BatchError::InvalidRequest(pointer, reason)`。

| 参数 | 默认值 | 含义 |
| --- | --- | --- |
| `max_rules` | 1000 | 最多规则数，允许 1–10000 |
| `max_steps_per_rule` | 100000 | 每条规则最多核心步骤 |
| `max_total_steps` | 1000000 | 整批预算 |
| `max_input_nodes` | 100000 | data 一次加每条 rule 的节点总数 |
| `max_input_string_units` | 2097152 | 所有 id、key、字符串值的 UTF-16 单位总数 |
| `max_depth` | 128 | 输入／执行深度，允许 1–256 |

成功条目收取核心实际 steps_used。核心异常不返回已用步骤，所以失败条目保守收取该条获准的全部预算（单条限制与剩余总预算的较小者）；此时 `steps_used` 为 null，不能表述为实际消耗。总预算耗尽后仍返回剩余所有 id，错误为 BatchLimitExceeded、steps_used 为 0，且不执行这些规则。JSON 大小、解析成本与墙钟时间不是整批步骤预算的替代物。

```sh
moon run src/examples/batch --target native
```

## native CLI

保存 `request.json`：

```json
{"rules":[{"id":"adult","rule":{">=":[{"var":"age"},18]}}],"data":{"age":22},"options":{"max_steps_per_rule":1000,"max_total_steps":10000}}
```

```sh
moon run src/cli --target native -- request.json
```

stdout 是一个 JSON 报告；退出码为 0（所有条目成功）、1（至少一条失败，包括总预算耗尽）、2（使用方法／文件／解析／请求错误）。options 可使用上表全部参数名，未知参数拒绝。文件最多 2097152 字节，要求有效 UTF-8；文件在内存读入后、解码和解析前检查此上限，调用方仍应限制外部上传大小。

```sh
python3 -m unittest discover -s tests -p 'test_batch_cli.py' -v
```

该检查构建并运行实际 CLI，验证退出码、日志、错误后继续、总预算、请求拒绝位置、缺失文件、坏 JSON／UTF-8 和文本上限。
