@calcit/procs 0.13.33 → 0.13.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,110 @@
1
+ # 类型安全的 Option 查询终点 RFC
2
+
3
+ 状态:Implemented(待发布与生态迁移)
4
+ 日期:2026-08-23
5
+
6
+ ## 背景与生态证据
7
+
8
+ `08-05-systematic-nil-reduction-rfc.md` 把公开缺失值统一为 `Option<T>`,边界已经比旧的
9
+ `nil` 契约安全。但迁移后的业务代码出现了新的机械噪音:一次普通查询往往立即接
10
+ `option:unwrap-or`,把“查找”和“缺失时采用业务默认值”拆成两层调用。
11
+
12
+ 对 2026-08-23 同步到各仓库默认分支后的本地 Calcit Snapshot 样本盘点发现:
13
+
14
+ - 约 102 个 Calcit 项目包含 unwrap 相关调用;
15
+ - `unwrap-or` 约 1500 次,直接 `unwrap` 约 300 次;
16
+ - 单行可识别的 `option:unwrap-or (get ...)` 约 985 次;
17
+ - `get-env`、`first`、`last`、`nth` 后立即提供默认值也是重复模式;
18
+ - 典型业务仓库包括 Respo 组件、Lilac、Termina 服务和 Cumulo 应用。
19
+
20
+ 这些调用可分为四类:
21
+
22
+ 1. 查询后立即采用默认值;
23
+ 2. 根据 some/none 分支并绑定 payload;
24
+ 3. 由前置条件证明必然存在的内部不变量;
25
+ 4. Result 的可恢复错误处理。
26
+
27
+ 第一类数量最大,适合由 core API 直接简化。第二类已经由 `if-let`、`when-let` 和
28
+ `match` 覆盖。第三类仍需显式 `.unwrap`,但应保持少量且靠近证明。第四类不能被
29
+ Option 默认值 API 吞掉错误信息。
30
+
31
+ ## 设计原则
32
+
33
+ - 不引入 `Option<T> -> T` 隐式转换;
34
+ - 不让查询函数的原始返回类型随上下文变化;
35
+ - 默认值必须经过现有 `.unwrap-or` 泛型检查;payload 可推断时,类型不兼容继续产生诊断,Dynamic 边界不伪造额外证据;
36
+ - 需要区分“存在”和“缺失”时,继续返回并处理完整 `Option`;
37
+ - 已知 Struct 字段继续使用 `(:field value)`,不允许借查询 helper 绕过字段检查;
38
+ - 名称明确表达这是“以默认值结束查询”,而不是一般的错误恢复。
39
+
40
+ ## API
41
+
42
+ 新增以下 core 宏:
43
+
44
+ | API | 展开语义 | 适用边界 |
45
+ | --- | --- | --- |
46
+ | `get-or base key fallback` | `option:unwrap-or (get base key) fallback` | Map / List / String / Enum 查询 |
47
+ | `get-in-or base path fallback` | `option:unwrap-or (get-in base path) fallback` | 开放动态路径 |
48
+ | `get-env-or name fallback` | `option:unwrap-or (get-env name) fallback` | 环境变量 |
49
+ | `first-or xs fallback` | `option:unwrap-or (first xs) fallback` | 空集合默认值 |
50
+ | `last-or xs fallback` | `option:unwrap-or (last xs) fallback` | 空集合默认值 |
51
+ | `nth-or xs idx fallback` | `option:unwrap-or (nth xs idx) fallback` | 越界默认值 |
52
+
53
+ 使用宏而不是给原查询函数增加多重返回类型:`get x k` 始终保持 `Option<T>`,不会因为
54
+ 第三个参数或期望类型而改变契约。宏展开后仍由已有 Option helper 完成泛型绑定和参数检查;
55
+ 若来源本来就是 `Option<Dynamic>`,结果也不会假装获得具体 payload 类型。
56
+
57
+ ```cirru.no-check
58
+ let
59
+ port $ get-or config :port 6000
60
+ mode $ get-env-or |mode |release
61
+ title $ get-in-or data ([] :page :title) |Untitled
62
+ println port mode title
63
+ ```
64
+
65
+ fallback 沿用普通函数参数的 eager 求值语义。惰性 fallback 暂不开放:验证中发现
66
+ `option:fold` 尚未强制两个回调共享返回类型,已记录为 issue #388。修复并验证该类型缺口后,
67
+ 可以单独评估 `*-or-else`,不能在当前 API 中悄悄改变副作用顺序。
68
+
69
+ ## 分支与不变量
70
+
71
+ 查询值需要分支时不使用 `*-or`:
72
+
73
+ ```cirru.no-check
74
+ if-let
75
+ user $ get users user-id
76
+ render-user user
77
+ render-missing user-id
78
+ ```
79
+
80
+ `if-let` 消费 `Option<T>` 并只在 some 分支绑定 `T`;`when-let` 用于返回
81
+ `Option<R>` 的单分支组合;完整数据流优先使用穷尽 `match`。
82
+
83
+ `.unwrap` 只保留在已有控制流、断言或数据结构不变量确实证明 some 的位置。迁移工具不得把
84
+ `.unwrap` 机械替换为任意空值,也不得用 `unsafe-coerce` 擦除 Option。
85
+
86
+ ## 迁移与验收
87
+
88
+ 首轮生态迁移优先处理机械可验证的形式:
89
+
90
+ ```cirru.no-check
91
+ option:unwrap-or (get config :port) 6000
92
+ ; =>
93
+ get-or config :port 6000
94
+ ```
95
+
96
+ 迁移后必须运行当前项目的 `--check-only`、测试和对应 JS/native 构建。验收至少包括:
97
+
98
+ 1. 六个宏的存在与缺失路径测试;
99
+ 2. fallback 类型不兼容的负向诊断;
100
+ 3. Native 与 JS 的真实项目回归;
101
+ 4. 文档示例检查;
102
+ 5. 发布后在代表性生态仓库中证明辅助调用数量下降。
103
+
104
+ ## 非目标
105
+
106
+ - 不改变 `get`、`get-in`、`first`、`last`、`nth`、`get-env` 的 Option 返回契约;
107
+ - 不为 Result 提供会丢弃错误信息的查询别名;
108
+ - 不删除 `option:unwrap-or` 的内部 lowering 实现;
109
+ - 不保证业务 fallback 是惰性表达式;
110
+ - 不自动修改 Dynamic 或旧 Optional/JsNullish 边界。
package/RFCs/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # RFC 整理索引
2
2
 
3
- 更新时间:2026-08-21
3
+ 更新时间:2026-08-23
4
4
 
5
5
  ## 目录原则
6
6
 
@@ -48,6 +48,7 @@
48
48
  | `08-21-type-quality-ci-adoption-rfc.md` | Draft | 统一使用原生 `analyze quality` 与按 definition baseline,定义生态 CI 层级并禁止各项目重复实现 JS 汇总脚本。 |
49
49
  | `08-21-js-ffi-runtime-contract-validation-rfc.md` | Draft | 在现有 typed JS FFI 声明之上增加 host guard、decoder、runtime contract tests 与 unsafe evidence。 |
50
50
  | `08-21-static-type-system-evolution-roadmap.md` | Draft | 借鉴 Rust/MoonBit 推进 Unknown/Dynamic 分离、穷尽性、局部推断、trait coherence 与框架类型化。 |
51
+ | `08-23-typed-option-query-ergonomics-rfc.md` | Implemented | 保持 Option 边界,新增 `get-or` 等类型安全查询终点,减少业务代码中的机械 unwrap。 |
51
52
 
52
53
  ## 已执行的清理
53
54
 
@@ -0,0 +1,7 @@
1
+ # 类型安全的 Option 查询终点
2
+
3
+ - 盘点本地 Calcit 生态中的 `unwrap` / `unwrap-or` 使用,确认最大重复模式是查询后立即提供默认值。
4
+ - 新增 `get-or`、`get-in-or`、`get-env-or`、`first-or`、`last-or`、`nth-or` 六个 core 宏;宏展开到内部 `option:unwrap-or`,保留 Option 泛型检查和跨后端语义。
5
+ - 保持原查询 API 始终返回 `Option<T>`,分支处理继续使用 `if-let` / `match`,不引入隐式解包或 Dynamic fallback。
6
+ - 增加正常、缺失和 fallback 类型不兼容测试,并更新诊断、升级文档、常见模式与 RFC 索引。
7
+ - 验证中发现 `option:fold` 未强制两个回调共享返回类型,记录为 GitHub issue #388;因此本版不承诺惰性 fallback。
@@ -0,0 +1,6 @@
1
+ # Option 查询终点 review 修正
2
+
3
+ - RFC 的生态统计改为记录样本同步日期与默认分支状态,不包含本机绝对路径。
4
+ - `RuntimeMapMeta`、`RuntimeMapResponse` 的 schema kind 与 `defstruct` 对齐为 `Struct`。
5
+ - Option 迁移诊断只在能识别直接查询来源时推荐对应的 `get-or` 等 helper;普通 Option 值继续给出分支或方法建议。
6
+ - 增加诊断单元测试,覆盖直接查询与无可证明查询来源两条路径。
@@ -0,0 +1,6 @@
1
+ # Definition schema round-trip 修复
2
+
3
+ - 发现连续两次 `calcit edit/tree` 会把 `StructDef` / `EnumDef` schema 误读为匿名 `Enum`。
4
+ - 根因是 Snapshot 的零 payload 类型包装 `:: 'Type` 仅对 `Dynamic` 特判,其他 canonical symbol 落入普通 enum 解析。
5
+ - 统一通过 canonical type symbol parser 读取非 callable 的零 payload schema,并覆盖两次 load/save 的回归测试。
6
+ - 真实复现与影响记录在 calcit-lang/calcit#390。
@@ -0,0 +1,5 @@
1
+ # 发布 0.13.35
2
+
3
+ - 发布 Snapshot schema 往返修复,避免连续编辑把 `StructDef` / `EnumDef` 降级为匿名 `Enum`。
4
+ - 发布前已通过 Rust、Calcit、JS、Agent interface 与 WASM 全量验证。
5
+ - 发布后使用新版本回归并修复受影响的 edn-formatter Snapshot。
@@ -0,0 +1,5 @@
1
+ # 2026-08-23 Release 0.13.34
2
+
3
+ - Add typed `get-or`, `get-in-or`, `get-env-or`, `first-or`, `last-or`, and `nth-or` query defaults.
4
+ - Preserve explicit `Option<T>` contracts while checking fallback payload types when static evidence is available.
5
+ - Improve Option migration diagnostics and document safe branching, defaults, and invariant unwraps.
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.13.33",
3
+ "version": "0.13.35",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.7.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.13.33",
3
+ "version": "0.13.35",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.7.0",