# 核心设计与边界

## 执行路径

CSV/JSONL → MoonBit 表格解析 → 样例约束 → 原子表达式枚举 → 输出引导的有界程序搜索 → 候选在真实输入行上分组 → 人工补充样例或明确选择 → JSON 配方 → 按列名绑定并批量解释执行。

`model.mbt` 是纯解释器；`calendar.mbt` 负责公历日期；`table.mbt` 负责 CSV/JSONL；`synthesis.mbt` 生成候选；`disagreement.mbt` 选择分歧行；`recipe.mbt` 负责版本化 AST 与批处理；`protocol.mbt` 提供统一 JSON 边界。`api/` 仅导出函数。浏览器 Worker 和 Node CLI 共用编译后的 MoonBit 核心。JavaScript 只负责 UI、文件 I/O、调用和下载。

## 有界搜索，不是固定场景匹配

1. 输入样例按输入和输出排序、去重；从全部样例建立观察语法：输入列、去空白、标点/显式分隔词、ASCII 数字/字母连续段、两端锚定的字符区间、大小写转换和显式日期格式。连续分隔词/字符段的可用索引以所有样例的最小段数界定。
2. 一个原子必须在所有样例上可执行，其结果必须是对应目标的子串，且至少在一个样例上非空。不同程序即使在训练样例上同值也保留，因此 `end-4` 与分隔符提取可以产生不同预测。
3. 搜索状态为每个目标输出已消费的位置向量和程序片段。原子只有匹配所有输出的当前位置才产生转移；各目标剩余串的公共前缀可产生常量片段。不枚举相邻常量的等价拆分。相同位置向量共享原子/常量转移缓存（最多 1024 个状态），不同程序前缀仍保留；这不是完整 VSA 实现。
4. 最小堆按成本和稳定序号扩展路径；完成所有输出时得到 `Concat` 程序。最多保留一定数量候选，限制路径片段数、原子尝试数、搜索步骤和队列长度。触及资源限制返回 `truncated=true`。配置里的片段数定义本次语法边界。
5. 排名是偏好简单结构的启发式：字段成本 2，trim 基础 3，分隔词 5，连续段 6，位置截取 12，常量 40+长度；转换再加成本。**成本不是准确率，也不是完备或最优性证明。**队列容量不足会舍弃转移并明确报告。

该实现是独立编写的有界枚举/搜索器，不调用 LLM、PROSE 或其他项目。程序合成、候选排名、交互消歧本身是已有技术。上述为平直字符串搜索；v0.3 增加下述条件和结构搜索，但仍未实现完整 Flash Fill/VSA、循环或任意谓词学习。

trim/case 变体检查全部样例，并包含 trim 后 ASCII 大小写转换。分隔符来自每列全部样例的标点单字符与连续标点片段（≤16 字符）；每列最多 64 个，超过时报告截断。调用方可再提供最多 16 个文字分隔符。Token 后允许一次固定前/后缀截取，仍不搜索任意深度组合。日期候选只来自观察到的有效显式格式。语法限制仍可能漏掉可执行规则，增加预算不能消除。

步骤计数在 v0.2 改为路径弹出及未缓存的原子尝试；`cached_states` / `cache_hits` 说明复用情况。因此 v0.1 与 v0.2 的步数不能直接作为加速倍数。样例顺序及重复样例不改变最终候选顺序；新增不同样例可能改变观察语法。

## 分歧选择

对每个未标注输入，计算保留候选的输出（包括失败），按相同结果分组。分数为 `n² - Σ group_size²`，平衡分割的行优先，同分按原始行号。分数仅表示当前候选分歧，无分歧不证明规则正确。界面/CLI 最多检查前 5000 行，界面默认显示前 200 行以及额外标注行。

## 数据语义

- 所有单元格都是文本。CSV 不推断数字；JSONL 只接受同构 string/null 对象，null 转为空文本，数字、嵌套结构、重复键和不一致字段集合拒绝。
- 字符区间按 Unicode scalar value 计数，不按 UTF-16 code unit，也不按用户感知字素；组合附加符与 emoji ZWJ 序列可能由多个字符构成。ASCII 大小写与连续段不声称完整 Unicode 分词/大小写支持。
- `Token` 保留连续分隔符产生的空字段，索引从 0 开始，负索引从末尾计算。越界、缺列、空分隔符不会静默降级。`Run` 为 ASCII 字母或数字最大连续段。
- 支持 `YYYY-MM-DD`、`YYYY/MM/DD`、`YYYYMMDD`、`DD/MM/YYYY`、`MM/DD/YYYY`。年份 0001–9999；不猜月日顺序，不支持时区，严格检查闰年和每月天数。
- 配方 version=1，按保存的列名在下一批数据中重绑定。结果包含每行成功值或错误；任一行失败时不生成部分 CSV。结果 JSON 保留输入行顺序。
- 面向电子表格的 CSV 默认为可能被解释为公式的值添加单引号；精确机器往返可通过 API `spreadsheet_safe:false` 关闭。此机制不是通用安全审计产品，也不保证所有表格软件行为完全相同。

## 限制与资源预算

| 边界 | 默认/上限 |
| --- | --- |
| 学习样例 | 1–32 个；输入 1–16 列；每个输入/目标 ≤128 Unicode 字符 |
| 候选 | 默认 64，最多 256 |
| 搜索片段 | 默认 6，最多 8 |
| 原子尝试 | 默认 30000，最多 100000（每次最多检查全部样例） |
| 搜索步骤 | 默认 200000，最多 1000000；到达限额停止并报告 |
| 前沿队列 | 默认 2048，最多 8192 |
| 表格 | 最多 20000 行、64 列；单元格 ≤65536 UTF-16 units |
| 文本/协议 | CSV/JSONL 输入 ≤2000000 UTF-16 units；JSON 请求 ≤4000000 |
| 配方 | 最大表达式深度 16、节点数 256、单次拼接 ≤32 段 |
| 批量输出 | 全批单元格总长度 ≤2000000 UTF-16 units |

JSON API 已有输入字节/结构边界；库调用方直接传入的数组仍应在业务入口控制大小。无外部网络和动态代码执行。工作台 Worker 支持取消；CSV/JSONL 当前为内存模式，不是流式大数据处理器。

## 后续可验证工作

已补充三套公开记录、SQLite 接入验证及上游 Foofah 全部 250 个外部任务，尚缺真实用户反馈和从未参与开发的盲测任务集。后续优先减少搜索截断与过拟合、保持候选多样性、研究程序集压缩和更强 Unicode 处理。每项扩展都要同步语义、来源、对照测试和预算。

## v0.3 条件与正则

`branch_search.mbt` 在平直搜索无候选后，尝试空值、正则提示和低基数字段相等谓词。先排序/去重训练样例，再对每个不同划分分别学习两侧，组合为短路 `If`。两侧各至少 2 个不同观测，避免把单条答案包装成规则；最多 3 层，默认 2 层，总计最多 64 次子学习。原子/步骤预算由全部子学习共享，统计相加；非单样例调用先给平直搜索一半预算，因此 v0.2/0.3 计数不直接作速度对比。找到平直解时优先返回平直候选，不穷举更多条件方案。

`predicates.mbt` 调用工具链自带 `core/string.Regex`，不调用 JS Regex 实现业务逻辑。支持官方正则方言的量词、捕获、交替、字符类、锚点、Unicode 和不区分 ASCII 大小写修饰。整串匹配锚定整个非捕获分组，避免把 `^a|b$` 当作整串匹配。空匹配使用 core 的 Unicode 字符推进。模式最多 256 UTF-16 单位，整串模式最多 248；缓存最多 64 模式；捕获组 0–32、匹配数最多 4096；替换支持 `$0..$9`、`$$`，未参与/不存在的替换组为空串，提取未参与组则报错。

额外限制数字重复界乘积 ≤4096，且乘积 × 模式长度 ≤16384，防止嵌套有界重复在 core 构造 NFA 时扩张。该检查保守地计入所有数字重复，即使它们出现在不相交分支；有些 core 能接受的模式会因项目资源预算被拒绝。不是无限制 PCRE 兼容实现。

自动搜索只枚举用户提供的模式、组 0–4、出现位置 0/1/-1，将其捕获作为可 trim/case/拼接的原子；不学习任意正则字符串或替换模板。Not/All/Any 可保存执行，但条件学习当前只枚举原子谓词。

## v0.3 结构程序

`transforms.mbt` 实现 17 类操作，`pipeline.mbt` 负责 v2 格式与命名列重绑定，`table_search.mbt` 负责有界宽度优先搜索。每个状态记录所有训练表的结果，观察等价状态只扩展一次；期望输出仅来自用户训练表。优先尝试投影见证，再尝试逐列行学习及结构算子；目标比较包含列名、单元格、空串和行序，不是只比较维度。首候选按搜索发现顺序选择，不看测试表答案。

默认 4 步、128 个保留状态、2000 次结构尝试、8 候选；可配置到 6 步/2048 状态/100000 次/32 候选。最多 8 对训练表，每表输入 128 行/16 列、输出 512 行/32 列。最多尝试 16 次行映射；每次每输出字段单独限 800 原子、6000 步、4 片段、256 前沿，最多 16 输出字段、32 行，且关闭条件回退。`row_searches` 是行映射尝试次数；结构 evaluations 不包含这些内部步骤。全部状态另限累计 100 万单元格和 800 万序列化 UTF-16 单位，触限报告 `truncated`。

这些算子都能显式编排，但自动参数空间较窄：Unpivot/Fold/Melt/GroupRows 主要尝试前缀键和后缀值列，PackRows 只枚举 2–8 行块，筛选只尝试空值或观察值。解释器支持的全部合法参数不一定在学习器搜索中。MapRows 是逐列学习，不是自动探索整个条件/表格联合语言。

执行限制：最多 16 步，2 万行/64 列/20 万单元格，列名最多 256 UTF-16 单位，单元格上限沿用普通表。所有操作复制结构数组，不修改输入。SplitColumn 每行必须分成约定列数；Explode 保留空片段；Unpivot/Fold 保留空值；Melt 明确选择是否跳过空串，零值保留；PackRows 不补不完整尾块；GroupRows 保留重复项并用空串补齐短组；Pivot 保持首见键序、缺失格为空串，重复格和未知类别报错，不隐式聚合。空表转置因无法形成至少一列而报错。

管道按保存的输入列名重绑定，新表可重排或增加列，多余列忽略，缺少保存列报错。格式校验同时拒绝静态非法参数；是否存在列、实际拆分数和透视冲突需要运行数据才能验证。结构管道出现错误时整表失败，不返回假装完整的部分结果。


## v0.4 搜索、泛化与资源控制

结构算子增加 PivotGrid、CombineColumns、SegmentRows、CarryContext，共 21 类。PivotGrid 把标签作为数据保存在首行，输出 c0…内列名，支持每批出现新类别；依然拒绝重复键/类别单元格。CombineColumns 按显式给定顺序连接字段，并放在最早源列的位置。SegmentRows 支持“分隔行不进入记录”或“标记行开始记录并保留标记”；连续空分隔不产生空记录，短记录用空字符串补齐；首标记前的内容会报错。CarryContext 将最近表头的指定字段加到后续明细，列名为 context_ 原名；明细先于表头时报错。

搜索仍遵守原来的 max_depth、max_states、max_evaluations、max_candidates。保留状态的总数仍限 128（默认），不是偷偷改成仅限前沿大小。优先级由输出形状差距、非空单元格多重集差距和程序成本组成，和最终的逐格相等验收分开；它不是可采纳启发式或最优性证明。每次扩展只保留最多 8 个非等价、优先级较好的后继，并及时释放其余结果；触及该裁剪同样标记 truncated。

最终候选按公开的 pipeline_cost 排名，不再按发现先后直接选第一条。成本对常量、位置截取、显式值筛选和依赖整表维度的转置给出不同偏好，属于可检查的归纳先验，不代表概率或正确性。找到 max_candidates 个解后仍在原预算内搜索，可用更低成本程序替换已保留项；最多记录 512 个目标程序键。

结构组合见证包含相关列投影→分组、键向下填充→动态透视、值列 Fold→拆列→动态透视。参数只来自训练输入/输出及观察到的分隔符，没有任务名特例。每个计划按原始算子数扣深度和 evaluations；即使计划中途失败，也保守扣除计划长度。所有训练表都必须精确通过。rejected 是被拒绝的计划数，不能冒充底层运行步骤数。

行映射可从超过 32 行的训练表取 32 条确定性代表样本，但候选还必须通过所有训练行才能入选。每字段仍限 800 原子尝试/6000 搜索步，最多 16 次行映射尝试；字段结果缓存最多 64 项，单键 ≤16384 UTF-16 单位，避免重复构造巨大缓存。

多对训练输入仍要求相同输入列名，输出维度可以不同。固定列投影和逐行映射只对一致的中间/目标模式尝试，避免跨模式索引越界。直接转置和动态透视可由不同维度的训练对共同约束；两个测试分别证明增加样例可以区分“整表转置”和“每三行一条记录”。这不等于凭单个样例即可知道用户意图。

正则学习新增有限上下文见证：输出必须属于 ASCII 数字/字母/字母数字类，共享最多 16 个字符的前/后字面上下文；解释器仍使用 core 正则。另枚举空格、下划线、连字符、斜杠、点的有限替换。它们与用户提供的最多 16 个模式提示并存，不声称任意正则/替换模板合成。

## v0.5 表格与文本搜索的组合

表格状态达到目标行数时，先找能直接复制的列，再学习其余列。平直表达式无解时，可以按空值、枚举值、模式提示或带分隔符的字母/数字形状分支。两个子树共享总预算，先为右子树预留搜索空间。最多 32 行用于生成行映射候选，选中前在所有训练行复算。

替换模板推断同时维护每条训练输出的字符位置。每一步可以消费一个在所有例子上都匹配的变化捕获组，或一个共同的字面字符。重复状态由位置向量和已用引用数识别，每个模式最多访问 256 个状态。自动推断的形状至多含八个字母或数字段，显式提示最多引用组 1–9。最长模式、模板输出和重复次数仍由解释器限制。

分组算子按完整键元组的首次出现顺序建立行到组的映射。对每个可能的计量列，在全部训练批次比较候选计数、求和和极值列，再组合为多指标程序。每组键最多保留八种组合，被剪枝时标记搜索截断。结构搜索复用目标表的单元格频数和已有状态键，减少重复扫描和序列化。
