// Package billcost models a province-banded shipping cost table and // provides a single source of truth for two questions: how much does // a parcel cost given the table (CalculateShipCost), and is the // table internally consistent (Reflect). Both routines operate on // the same Band shape so a parser-LLM, a reflector loop, and a // reconciliation pipeline all agree on what a "valid quote" means. // // Why a dedicated package rather than carrying these helpers inside // the bill-recon platform module: the cost-table shape is generic // across logistics carriers (圆通 / 中通 / 韵达 / 京东 / 顺丰), and // the same dry-run validator is the natural fit for any structured // extraction that reduces to "weight bands per partition" -- think // freight, parcel insurance tiers, courier returns, or even non- // logistics tiered pricing. Keeping the algorithm + reflector here // in core/pkg lets every consumer (bill-recon today, future ERP / // CRM extractors) plug into the same contract without copy-paste. // // Schema: a Band names a single (province, weight-segment) row in // the WMS-style cost table. The Reflect function takes a slice of // Bands plus optional strip fees and a return fee, groups by // province, and dry-runs CalculateShipCost over weight points // derived from the bands themselves (not a fixed grid) -- so any // number of bands, any segment lengths, any carrier table layout // works. Violations carry the province / band / weight that // triggered the rule plus a human-readable detail so an LLM // retry loop can correct itself. // // Why dry-run rather than a rule list: a rule list would say // "limit_top > limit_bottom" without verifying the cost function // stays monotonic across segment boundaries. Running the actual // calculation across band-derived sample points exercises the // data structure as a live program would and catches inversions // (e.g. continuation-kg cheaper than first-kg) that a static rule // list would miss without an explicit pricing-model rule. // // billcost 包对省份-重量段的运费表建模, 同一份 Band 数据结构服务两个 // 问题: 给定表算单包裹成本是多少 (CalculateShipCost), 以及这张表内部 // 一致么 (Reflect). 解析 LLM / 反射器循环 / 对账管道全部基于同一 Band // 形状, 不会出现 "什么算合法报价" 的多重定义. // // 为何独立子包而不是放进 bill-recon 平台模块: 运费表形状跨承运商通用 // (圆通/中通/韵达/京东/顺丰), 同一套 dry-run 校验亦适用任何 "按维度分 // 段" 的结构化抽取 -- 货运 / 保险等级 / 退回件 / 甚至非物流的阶梯计价. // 算法 + 反射器留在 core/pkg 让每个消费者 (今天的 bill-recon, 未来的 // ERP / CRM 抽取) 共享同一契约, 免拷贝. // // schema: 一个 Band 命名运费表中一行 (省份 + 重量段). Reflect 接收 // Bands + 可选单带费 + 退回费, 按省份 group 后用 bands 自身派生的重量 // 采样点 (非固定网格) dry-run CalculateShipCost -- 任意段数 / 任意段长 // / 任意承运商布局都能跑. Violations 带触发规则的省份/段/重量 + 人类 // 可读细节, 供 LLM 重试循环自纠. // // 为何 dry-run 而非规则列表: 规则列表会说 "limit_top > limit_bottom" // 但不验证成本函数跨段单调; 在 bands 派生点上实际跑算法把数据结构当 // 真程序执行, 能抓住静态规则列表必须额外加 "定价模型规则" 才能命中的 // 反逻辑 (如续重 kg 比首重 kg 更便宜). package billcost