@calcit/procs 0.12.55 → 0.12.56

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,170 @@
1
+ # RFC: `unsafe-coerce` 驱动的动态边界治理与静态类型强化计划
2
+
3
+ 状态:Draft
4
+ 日期:2026-07-31
5
+ 关联:`07-26-static-semantic-analysis-rfc.md`、`07-08-ffi-features-and-js-object-type-rfc.md`、`06-01-generic-binding-unification-rfc.md`
6
+
7
+ ## 1. 现状与目标
8
+
9
+ 我们将本阶段主目标聚焦在类型边界治理,而不是单纯推进 WASM 后端。
10
+ 针对 FFI(特别是 JS object)和外部大树形结构中大量动态值的问题,`unsafe-coerce` 要成为“静态分析可利用的类型入口点”,降低 `:dynamic` 退化。
11
+
12
+ 目标如下:
13
+
14
+ - 让动态边界明确化:能指出哪些值是故意进入静态盲区,哪些是可治理缺口;
15
+ - 提升静态可用信息:`unsafe-coerce` 后的类型关系要能在后续分析中被持续传播;
16
+ - 降低告警噪音:减少因隐式动态而产生的误报,转而给出可执行的收紧建议。
17
+
18
+ ## 2. 问题定义
19
+
20
+ 当前主要痛点是三类:
21
+
22
+ 1. 外部输入(JS Object、外部树形数据)一旦进入,会被频繁打散成 `:dynamic`;
23
+ 2. `unsafe-coerce` 当前只附加声明类型,不转换值,也不提供运行时校验,静态分析无法区分“推导所得”与“用户信任声明”;
24
+ 3. 未通过显式边界收敛的动态传播,会导致高阶函数、容器、回调、trait 调用处丧失可验证关系。
25
+
26
+ ## 3. 设计思路
27
+
28
+ 我们将类型边界分为五档,贯穿检查与诊断链路:
29
+
30
+ - `sealed-boundary`:明确的外部边界,需经过显式操作收窄;
31
+ - `trusted`:`unsafe-coerce` 给出的用户信任声明,可传播但不视为运行时证明;
32
+ - `validated`:由未来的实际校验操作建立的证据;
33
+ - `unvalidated`:未经过转换但可继续跟踪的弱上下文;
34
+ - `dynamic`:有意接受的动态盲区(可选 opt-in)。
35
+
36
+ `unsafe-coerce` 必须具备两个产出:
37
+
38
+ - 运行时行为:保持原值不变,不承诺验证;
39
+ - 静态元信息:来源类型、声明目标类型、边界位置和 `trusted` 置信等级。
40
+
41
+ 实际完成运行时验证的能力应使用独立操作,并把置信等级提升为 `validated`,不能由 `unsafe-coerce` 冒充。
42
+
43
+ ## 4. 规范草案
44
+
45
+ ### 4.1 `unsafe-coerce` 的静态签名
46
+
47
+ `unsafe-coerce` 调用应显式携带目标类型表达式,并在静态树或旁路分析元数据中记录:
48
+
49
+ - `from-type`:调用点推断来源;
50
+ - `to-type`:目标类型表达式;
51
+ - `confidence`:固定为 `trusted`,不可标为 `validated`;
52
+ - `evidence`:字段集合、泛型约束、变体等。
53
+
54
+ 示例:
55
+
56
+ ```cirru
57
+ unsafe-coerce user-json :js-object
58
+ unsafe-coerce user-json (:: :record User)
59
+ unsafe-coerce tree-data (:: :list (:: :ref TreeNode))
60
+ ```
61
+
62
+ ### 4.2 结构化构造的类型加强策略(enum / struct)
63
+
64
+ 当调用头能够静态确认就是某个 `defstruct` 或 `defenum` 定义时,类型收敛可走“无缝构造”策略,减少 `::` / `%::` / `%{}` 的显式写法。普通 record 实例或 enum tuple 即使携带相同类型信息,也不得被当作构造器:
65
+
66
+ - `enum`:在可推断为 enum 的位置,允许直接写 `Result :ok value`,由类型驱动 rewrite 成 `%:: Result :ok value`;
67
+ - `struct`:在可推断为结构体的上下文,允许按字段对写 `Person :name |Alice :age 20`,并在类型上下文中改写为 `%{} Person :name |Alice :age 20` 的有序结构构造;
68
+ - 规则约束仍保留:
69
+ - `struct` 必须是偶数个参数,按 key/value 成对出现;
70
+ - 字段不能重复;非 `:optional` 字段不能缺失;
71
+ - `enum` 的 tag 与 payload 必须匹配该 enum 的 variant;
72
+ - 任何 key 不在目标 struct 字段中的,回退到原有调用并给出 warning。
73
+
74
+ 示例:
75
+
76
+ ```cirru
77
+ let
78
+ maybe-ok $ Result :ok 1
79
+ person $ Person :name |Alice :age 20
80
+ ...
81
+ ```
82
+
83
+ 负向示例(应保持原样并给 warning):
84
+
85
+ ```cirru
86
+ Person :name |Alice :age
87
+ Result
88
+ Result :bad 1
89
+ Person :email |x
90
+ Result ok 1
91
+ kitty .rename |LagopusB
92
+ ```
93
+
94
+ 说明:
95
+
96
+ - `Person :email |x`:字段不在结构定义中 → 回退并 warning;
97
+ - `Person :name |Alice :age`:奇数参数 → 回退并 warning;
98
+ - `Result ok 1`:enum 首参不是 tag(需 `:ok`)→ 回退并 warning;
99
+ - `kitty .rename |LagopusB`:记录/结构方法调用不能被误判为构造调用。
100
+
101
+ ### 4.3 动态边界的使用规则
102
+
103
+ 1. 来自 FFI/主机接口的值默认进入 `sealed-boundary`;
104
+ 2. 若值要进入“纯 Calcit 计算路径”,必须通过 `unsafe-coerce` 进入可信声明类型,或通过实际校验操作进入已验证类型;
105
+ 3. 对容器与回调关系,`unsafe-coerce` 后应尽量保留内含关系(如 `:: :list T`、`:: :fn` 的参数/返回关联);
106
+ 4. 对于无法构建精确信息的对象(如完全开放结构),允许 `:dynamic`,但必须记录“故意动态”标签与边界位置。
107
+
108
+ ### 4.4 与现有警告体系对齐
109
+
110
+ - 引入/保留告警码:
111
+ - `W_SEALED_BOUNDARY_PASS`
112
+ - `W_MISSING_COERCE`
113
+ - `W_COERCE_COVERAGE_GAP`
114
+ - `W_DYNAMIC_EXIT`
115
+ - `unsafe-coerce` 使用不足的动态传播点应由 `W_MISSING_COERCE` 定位,并给出可替换的目标类型示例;
116
+ - `unsafe-coerce` 后仍不能稳定推断的情况,转为 `W_COERCE_COVERAGE_GAP` 并输出缺失字段/参数位置。
117
+
118
+ ### 4.5 与函数签名协同
119
+
120
+ `unsafe-coerce` 不是为了替代 schema,而是使 schema 可恢复:
121
+
122
+ - 大树节点进入列表/record 时,优先映射为命名结构体或 enum;
123
+ - 回调参数在边界后保持 `:fn` 的关系(arg/return / generics / where);
124
+ - 若同一结构反复出现,鼓励提升为 `defstruct` + `:where` + 类型参数,减少重复 `:dynamic`。
125
+
126
+ ## 5. 实施路线
127
+
128
+ ### Phase 1(1~2 周):把边界变可见
129
+
130
+ - 明确 `unsafe-coerce` 在静态元数据中的记录模型,并保证 local 场景不会擦除边界节点;
131
+ - 增加 `sealed-boundary` / `trusted` / `validated` / `unvalidated` / `dynamic` 标签在诊断中可见;
132
+ - 在 `type-at` 与 `check-types` 输出中显示 `unsafe-coerce` evidence 链路;
133
+ - 增加 `unsafe-coerce` 相关正向用例:JS Object → 记录/列表/enum。
134
+
135
+ ### Phase 2(2~3 周):增强 `unsafe-coerce` 的传播能力
136
+
137
+ - 在 container / fn / struct / enum 场景保留内含关系;
138
+ - 增强跨文件、跨 def 的类型传播,支持大树结构递归字段推断;
139
+ - 给 FFI 边界添加可执行的“首入场 unsafe-coerce 指南”(必须声明哪些层级,以及哪些位置需要真实校验)。
140
+
141
+ ### Phase 3(1~2 周):治理现有动态盲区
142
+
143
+ - 统计 `:dynamic` 产生原因:未转换、边界故意、兼容旧行为;
144
+ - 逐步把“可修复” `:dynamic` 转为结构化 `unsafe-coerce` 或真实校验,保留“故意动态”最小集合;
145
+ - 在 `analyze weak-types` 中增加类型边界报告:按定义、路径、优先级排序。
146
+
147
+ ## 6. 验收指标(建议)
148
+
149
+ 1. 关键 FFI 边界进入非纯路径时,`type-at` 能标出 `sealed-boundary`;
150
+ 2. 对树形/树状 JSON 数据,核心字段至少一层以上可从 `:dynamic` 收窄;
151
+ 3. 同一入口内的未转换动态访问点告警下降且可定位;
152
+ 4. 新增样例在 `check-types` 下可通过,不产生“类型丢失无法解释”的模糊告警。
153
+
154
+ ## 7. 风险与缓解
155
+
156
+ - 风险:`unsafe-coerce` 过度强约束导致现有生态迁移成本上升。
157
+ 缓解:保持 warning-first,逐步收紧。
158
+ - 风险:分析时间上升。
159
+ 缓解:对 `unsafe-coerce` evidence 做缓存并只在必要路径传播。
160
+ - 风险:FFI 数据本身不稳定结构导致验证失败。
161
+ 缓解:支持“部分声明 + `:dynamic` fallback”,让用户明确知道保留了什么边界。
162
+
163
+ ## 8. 依赖关系
164
+
165
+ 优先参考并复用:
166
+
167
+ - `06-01-generic-binding-unification-rfc.md`
168
+ - `07-26-static-semantic-analysis-rfc.md`
169
+ - `07-08-ffi-features-and-js-object-type-rfc.md`
170
+ - 现有类型诊断体系与 `analyze weak-types` 输出规范
@@ -0,0 +1,23 @@
1
+ # Strengthen namespace import diagnostics
2
+
3
+ ## Summary
4
+
5
+ - Replaced namespace/import parser panics and silent fallbacks with contextual errors for malformed namespace forms, short rules, invalid rule kinds, and invalid node shapes.
6
+ - Added one shared import-rule validator for program loading and `cr edit add-import` / `cr edit imports`, so invalid edits are rejected before the snapshot is saved.
7
+ - Detect duplicate local bindings across rules and repeated `:refer` definitions within one rule instead of silently overwriting the earlier import.
8
+ - Preserved legacy `(:ns namespace)` compatibility while validating supported `:require` structures.
9
+ - Clarified that `call-graph --show-unused` reports definitions unreachable from the selected entry, not proven dead code or unused import declarations.
10
+ - Kept unused-definition analysis independent from `--max-depth`, preventing display truncation from producing false dead-code reports.
11
+ - Documented validation behavior, atomic edits, dead-code analysis limits, and the relevant CLI workflow.
12
+
13
+ ## Validation
14
+
15
+ - `cargo fmt`
16
+ - `cargo clippy -- -D warnings`
17
+ - `cargo test`
18
+ - `yarn compile`
19
+ - `yarn check-all`
20
+ - `yarn check-agent-interface` (12/12 scenarios)
21
+ - `cr docs check-md docs/features/imports.md --entry calcit/test.cirru` (4/4 blocks)
22
+ - Isolated CLI regressions confirming malformed and duplicate imports are rejected without changing the snapshot.
23
+ - Compared `call-graph --show-unused` with unlimited depth and `--max-depth 1`; unused-definition results are identical.
@@ -0,0 +1,20 @@
1
+ # Strengthen unsafe-coerce boundaries
2
+
3
+ ## Summary
4
+
5
+ - Kept `unsafe-coerce` visible in preprocessed expressions instead of mutating the source local's type globally, preserving a stable boundary node for later static evidence reporting.
6
+ - Added type-directed shorthand construction for confirmed `defstruct` and `defenum` definitions while preventing record and enum tuple instances from being treated as constructors.
7
+ - Validated shorthand struct fields for pair shape, membership, duplication, required-field coverage, and statically known value type mismatches.
8
+ - Reused typed record and enum constructor nodes so native, JavaScript, and WASM backends receive their existing canonical forms.
9
+ - Documented the boundary model, distinguishing trusted `unsafe-coerce` declarations from future runtime-validated evidence.
10
+ - Added positive and negative preprocessing coverage for constructor rewrites, invalid variants, malformed fields, method syntax, and instance/prototype separation.
11
+
12
+ ## Validation
13
+
14
+ - `cargo fmt`
15
+ - `cargo clippy -- -D warnings`
16
+ - `cargo test`
17
+ - `yarn compile`
18
+ - `yarn check-agent-interface` (12/12 scenarios)
19
+ - `yarn check-all` (native, JavaScript, and WASM checks passed)
20
+ - Current debug `cr --check-only` against `/Users/jon.chen/repo/respo/respo/calcit.cirru`
@@ -0,0 +1,18 @@
1
+ # Warn on duplicate imports
2
+
3
+ - Changed duplicate namespace import bindings from validation errors to recoverable warnings on stderr.
4
+ - Preserved the existing last-rule-wins behavior so duplicate aliases and repeated `:refer` entries do not stop program execution.
5
+ - Kept malformed import structures, invalid rule kinds, and invalid node shapes as errors.
6
+ - Updated CLI editing to save valid duplicate imports after displaying the warning.
7
+ - Added tests for warnings and last-rule-wins resolution, plus an isolated CLI/runtime regression proving execution continues.
8
+ - Updated import documentation to distinguish recoverable duplicate bindings from malformed rules.
9
+
10
+ ## Validation
11
+
12
+ - `cargo fmt`
13
+ - `cargo clippy -- -D warnings`
14
+ - `cargo test`
15
+ - `yarn compile`
16
+ - `yarn check-all`
17
+ - `yarn check-agent-interface` (12/12 scenarios)
18
+ - `cr docs check-md docs/features/imports.md --entry calcit/test.cirru`
@@ -0,0 +1,15 @@
1
+ # Release 0.12.56
2
+
3
+ ## Summary
4
+
5
+ - Bump the Calcit Rust crate and npm package versions from `0.12.55` to `0.12.56`.
6
+ - Refresh the workspace lockfile so package metadata remains consistent.
7
+
8
+ ## Validation
9
+
10
+ - `cargo fmt --check`
11
+ - `cargo clippy -- -D warnings`
12
+ - `yarn compile`
13
+ - `cargo test`
14
+ - `yarn check-all`
15
+ - `yarn check-agent-interface`
@@ -0,0 +1,23 @@
1
+ # Library quality gates and format advisories
2
+
3
+ ## Summary
4
+
5
+ - Add a dedicated Calcit library/module acceptance guide covering Snapshot canonicalization, entries, type slots, weak-type baselines, examples, Markdown checks, entry/backend validation, call-graph limits, consumer regression, and CI evidence.
6
+ - Refresh the project upgrade guide for once-by-default execution, entry modes, unified `:entries`, per-entry type slots, canonical `:dynamic`, and current static-analysis commands.
7
+ - Extend `cr edit format` with recoverable advisories for legacy `:configs`, the `compact.cirru` filename, legacy `:any`, and unresolved dynamic type debt.
8
+ - Keep formatting non-blocking for quality debt and direct users to `check-types` / `weak-types` for semantic paths and recommendations.
9
+
10
+ ## Validation
11
+
12
+ - `cargo fmt`
13
+ - `cargo clippy -- -D warnings`
14
+ - focused `cr` format advisory unit tests
15
+ - `cargo test`
16
+ - `yarn compile`
17
+ - `yarn check-all`
18
+ - `yarn check-agent-interface`
19
+ - `cr docs graph check`
20
+ - `cr docs check-md docs/run/library-quality.md`
21
+ - `cr docs check-md docs/run/upgrade.md`
22
+ - legacy config and filename formatting on temporary Snapshots
23
+ - Respo consumer regression on a temporary Snapshot: format, config show, weak-types summary, and `--check-only`
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.12.55",
3
+ "version": "0.12.56",
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.12.55",
3
+ "version": "0.12.56",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.7.0",