@calcit/procs 0.13.26 → 0.13.28

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.
Files changed (92) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/README.md +34 -34
  3. package/RFCs/02-04-runtime-traits-plan.md +1 -1
  4. package/RFCs/02-17-register-platform-api-rfc.md +1 -1
  5. package/RFCs/02-18-language-theory-evolution-plan.md +3 -3
  6. package/RFCs/03-05-function-schema-dual-track-rfc.md +3 -3
  7. package/RFCs/03-18-query-def-tree-show-chunked-display-plan.md +11 -11
  8. package/RFCs/04-13-type-slot-mechanism-rfc.md +10 -10
  9. package/RFCs/05-12-program-diff-rfc.md +7 -7
  10. package/RFCs/06-15-effects-graph-rfc.md +16 -16
  11. package/RFCs/07-06-semantic-tree-navigation-rfc.md +33 -33
  12. package/RFCs/07-19-doc-knowledge-index-rfc.md +15 -15
  13. package/RFCs/07-19-type-introspection-consistency-rfc.md +3 -3
  14. package/RFCs/07-26-agent-docs-and-evaluation-rfc.md +1 -1
  15. package/RFCs/07-26-agent-machine-protocol-rfc.md +5 -5
  16. package/RFCs/07-26-safe-structured-editing-rfc.md +4 -4
  17. package/RFCs/07-26-static-semantic-analysis-rfc.md +9 -9
  18. package/RFCs/07-28-git-module-store-rfc.md +4 -4
  19. package/RFCs/07-28-persistent-tree-cursor-rfc.md +54 -54
  20. package/RFCs/08-08-cross-backend-host-ffi-contracts-rfc.md +4 -4
  21. package/RFCs/08-14-architecture-scaffold-rfc.md +7 -7
  22. package/RFCs/08-14-todo-placeholder-rfc.md +2 -2
  23. package/RFCs/08-18-calcit-typed-js-ffi-boundary-rfc.md +2 -2
  24. package/RFCs/08-21-js-ffi-runtime-contract-validation-rfc.md +295 -0
  25. package/RFCs/08-21-setup-calcit-version-and-toolchain-contract-rfc.md +241 -0
  26. package/RFCs/08-21-static-type-system-evolution-roadmap.md +315 -0
  27. package/RFCs/08-21-type-quality-ci-adoption-rfc.md +272 -0
  28. package/RFCs/README.md +7 -5
  29. package/editing-history/20260820-1704-repository-maintenance-review.md +20 -0
  30. package/editing-history/20260821-1512-type-system-ecosystem-rfcs.md +25 -0
  31. package/editing-history/20260821-1648-type-quality-and-ffi-doc-hints.md +12 -0
  32. package/editing-history/202608211958-calcit-command-alias.md +6 -0
  33. package/editing-history/202608212018-cli-review-followups.md +4 -0
  34. package/editing-history/ARCHIVE.md +45 -4
  35. package/editing-history/README.md +3 -1
  36. package/history/202608191628-revert-transparent-union-types.md +5 -0
  37. package/history/202608191741-release-01327.md +4 -0
  38. package/history/202608212020-release-01328.md +5 -0
  39. package/lib/package.json +11 -11
  40. package/package.json +11 -11
  41. package/profiling/README.md +3 -3
  42. package/profiling/profile-once.sh +1 -1
  43. package/profiling/samply-once.sh +4 -4
  44. package/profiling/samply-summary.py +1 -1
  45. package/RFCs/08-19-transparent-union-types-rfc.md +0 -522
  46. package/editing-history/2026-07-28-1346-edit-transaction.md +0 -27
  47. package/editing-history/2026-07-28-1454-persistent-tree-cursor.md +0 -30
  48. package/editing-history/2026-07-28-1651-cursor-focus-stack-clipboard.md +0 -30
  49. package/editing-history/2026-07-28-1719-cursor-navigation-search-selection.md +0 -21
  50. package/editing-history/2026-07-28-1958-agent-rfc-split.md +0 -14
  51. package/editing-history/2026-07-28-2004-cursor-editing-docs.md +0 -14
  52. package/editing-history/2026-07-28-2132-cursor-recoverable-clipboard.md +0 -18
  53. package/editing-history/2026-07-28-2151-cursor-native-structural-editing.md +0 -20
  54. package/editing-history/2026-07-28-2158-document-cursor-native-workflows.md +0 -13
  55. package/editing-history/2026-07-29-0022-add-cursor-cli-options.md +0 -7
  56. package/editing-history/2026-07-29-0022-audit-cursor-development-scenarios.md +0 -6
  57. package/editing-history/2026-07-29-0022-complete-cursor-structural-edits.md +0 -8
  58. package/editing-history/2026-07-29-0022-document-cursor-edit-recipes.md +0 -8
  59. package/editing-history/2026-07-29-0022-edit-target-cursor-alias.md +0 -6
  60. package/editing-history/2026-07-29-0022-guide-agents-through-cursor-workflows.md +0 -7
  61. package/editing-history/2026-07-29-0022-query-from-active-cursor.md +0 -8
  62. package/editing-history/2026-07-29-0022-tree-target-cursor-alias.md +0 -5
  63. package/editing-history/202608021730-release-0.12.58.md +0 -5
  64. package/editing-history/202608021928-release-0.12.59.md +0 -5
  65. package/editing-history/202608082312-release-0.13.5.md +0 -10
  66. package/editing-history/202608090107-release-0.13.6.md +0 -10
  67. package/editing-history/202608091812-release-0.13.7.md +0 -8
  68. package/editing-history/202608101042-release-0.13.8.md +0 -6
  69. package/editing-history/202608101101-release-pr-workflow.md +0 -8
  70. package/editing-history/202608101102-release-doc-tracked-path.md +0 -5
  71. package/editing-history/202608110140-release-0.13.9.md +0 -4
  72. package/editing-history/202608111349-release-0.13.10.md +0 -13
  73. package/editing-history/202608111650-release-0.13.11.md +0 -5
  74. package/editing-history/202608121900-release-0.13.12.md +0 -5
  75. package/editing-history/202608130003-release-0.13.13.md +0 -9
  76. package/editing-history/202608131650-release-0.13.15.md +0 -10
  77. package/editing-history/20260816-0254-release-0.13.17.md +0 -5
  78. package/editing-history/20260817-0006-release-0-13-18.md +0 -6
  79. package/editing-history/202608171118-project-module-runtime-resolution.md +0 -6
  80. package/editing-history/202608171133-visible-module-versions-and-cleanup.md +0 -6
  81. package/editing-history/202608171140-module-caches-root.md +0 -5
  82. package/editing-history/202608171200-module-cache-review-follow-up.md +0 -5
  83. package/editing-history/202608171205-release-0-13-19.md +0 -4
  84. package/editing-history/202608171215-module-path-resolution-docs.md +0 -4
  85. package/editing-history/202608171409-module-cache-review-followup.md +0 -5
  86. package/editing-history/202608171427-module-cache-review-followup-locking.md +0 -5
  87. package/editing-history/202608171438-module-docs-home-lock.md +0 -4
  88. package/editing-history/202608171611-dependency-audit-review.md +0 -4
  89. package/editing-history/202608181000-release-0-13-20.md +0 -5
  90. package/editing-history/202608181930-release-0-13-21.md +0 -5
  91. package/history/202608191418-rfc-defenum-syntax.md +0 -4
  92. package/history/202608191430-transparent-union-review.md +0 -5
@@ -1,522 +0,0 @@
1
- # RFC: `deftype` 具名透明联合类型与控制流收窄
2
-
3
- 状态:Partial(MVP 第 1 轮已实现)
4
- 日期:2026-08-19
5
- 关联:`02-04-runtime-traits-plan.md`、`04-15-match-syntax-rfc.md`、`05-31-generic-where-bounds-mfs.md`、`06-01-generic-binding-unification-rfc.md`、`07-26-static-semantic-analysis-rfc.md`、`08-18-calcit-typed-js-ffi-boundary-rfc.md`
6
-
7
- ## 1. 摘要
8
-
9
- 本 RFC 提议新增 `deftype`,用于声明**具名、透明、无运行时包装**的联合类型,并补齐围绕联合类型的控制流收窄能力。
10
-
11
- 首要用例是 Respo 虚拟 DOM:`Component` 与 `Element` 是两个不同的 Struct,但 `tree`、`children`、diff 与 effect 遍历都需要把它们当作同一类节点传递。当前只能把这些位置声明成 `Dynamic`,或使用 `defenum` 再包一层 constructor。前者失去字段安全,后者改变数据表示并给 DSL 增加构造、解包噪音。
12
-
13
- 目标写法:
14
-
15
- ```cirru.no-check
16
- deftype RespoNode
17
- or 'Component 'Element
18
- ```
19
-
20
- `Component` 和 `Element` 的值可以直接进入 `RespoNode` 位置,运行时仍保持原有 Struct 表示。代码通过 `struct-match`、`type-match?` 或带 `:narrows` 契约的 predicate 恢复具体成员类型。
21
-
22
- ### 当前实施范围(2026-08-19)
23
-
24
- 已落地第一轮 MVP:`deftype Name (or ...)` 是编译期透明声明,并在声明点拒绝无效成员;裸 `TypeRef` 在赋值检查和 Struct 字段运行时验证处展开为成员集合;现有 `&struct:matches?` 的 true branch 和 `struct-match` binder 会获得匹配 Struct 的具体类型。`struct-match` 对 transparent union 检查非成员/重复分支与覆盖完整性。运行时没有 union wrapper,也没有新的 JS ABI。
25
-
26
- 尚未实现的部分保持为本 RFC 的后续阶段:`_` branch 的剩余 union、公共 `type-match?`、用户 `:narrows` guard、参数化 `deftype`,以及 data-shape/严格 EDN decode 对 union 的支持。
27
-
28
- ## 2. 设计判断
29
-
30
- ### 2.1 `deftype` 与 `defenum` 分工
31
-
32
- `defenum` 继续表示需要运行时 tag、payload arity 和构造器身份的代数数据类型:
33
-
34
- ```cirru.no-check
35
- defenum RequestState
36
- :idle
37
- :loading
38
- :failed 'String
39
- ```
40
-
41
- `deftype` 表示已有类型之间的静态集合,不产生新的值构造器:
42
-
43
- ```cirru.no-check
44
- deftype RespoNode
45
- or 'Component 'Element
46
- ```
47
-
48
- 两者分别对应两种不同需求:
49
-
50
- - `defenum`:值本身需要携带“属于哪个 variant”的新表示;
51
- - `deftype`:值已经有可靠的运行时身份,只需要描述“这个位置允许哪些类型”。
52
-
53
- ### 2.2 `deftype` 与 trait 分工
54
-
55
- Trait 描述开放的能力集合,适合算法只依赖共同方法的场景;联合类型描述封闭的数据备选,适合分支后读取各自字段的场景。
56
-
57
- Respo renderer 需要区分 `Component` 与 `Element`,并读取完全不同的字段,因此核心节点应使用联合类型。DOM FFI 只关心对象支持哪些字段和方法,应继续使用 `:kind :external-object` trait。
58
-
59
- 若联合类型的所有成员都实现同一个 trait,联合值可以满足该 trait bound;这不把 union 自动转换成新的 runtime trait object。
60
-
61
- ### 2.3 与 Rust、MoonBit 经验的关系
62
-
63
- 本设计沿用 Rust/MoonBit 的两条经验:
64
-
65
- 1. 封闭的数据分支应由编译器进行穷尽性与分支类型检查;
66
- 2. 开放扩展和行为分派交给 trait/interface,不用一套机制同时承担两种职责。
67
-
68
- Calcit 的差异是保留动态语言的数据表示:`deftype` 不要求像 Rust/MoonBit enum 一样重新包装已有值。它更接近一个具名的静态 sum,但每个成员仍使用自身的 nominal runtime identity。
69
-
70
- ## 3. 语法
71
-
72
- ### 3.1 基本形式
73
-
74
- `deftype` 接收名称和一个类型表达式。MVP 只开放 `or` 类型表达式:
75
-
76
- ```cirru.no-check
77
- deftype RespoNode
78
- or 'Component 'Element
79
-
80
- deftype AttrValue
81
- or 'String 'Number 'Bool 'EventHandler
82
- ```
83
-
84
- 这里采用普通前缀语法,没有引入 `A | B` 之类的中缀 token。对应 AST 形状稳定为:
85
-
86
- ```json
87
- ["deftype", "RespoNode", ["or", "'Component", "'Element"]]
88
- ```
89
-
90
- 较长的声明可以使用 Cirru 的 `,` splice 保持同一个 `or` 表达式:
91
-
92
- ```cirru.no-check
93
- deftype DomPropValue $ or
94
- , 'String
95
- , 'Number
96
- , 'Bool
97
- , 'EventHandler
98
- ```
99
-
100
- 推荐短 union 保持单行 RHS;只有成员较多时使用上面的展开写法。
101
-
102
- ### 3.2 类型引用
103
-
104
- 其他 schema 使用普通 nominal 引用,不展开成员:
105
-
106
- ```cirru.no-check
107
- defstruct Component (:name 'Tag)
108
- :tree $ :: 'Optional 'RespoNode
109
-
110
- defn render-node (node)
111
- struct-match node
112
- Component component
113
- :tree component
114
- Element element
115
- :children element
116
-
117
- :: 'Fn $ {}
118
- :args $ [] 'RespoNode
119
- :return 'Unit
120
- ```
121
-
122
- `RespoNode` 在 public schema、诊断和类型自省中保留名字;只有匹配和归一化时才读取成员集合。
123
-
124
- ### 3.3 泛型边界
125
-
126
- MVP 不开放参数化 `deftype`,避免同时引入 alias 参数替换、递归 kind 检查和高阶类型问题。以下能力留作独立扩展:
127
-
128
- ```cirru.no-check
129
- ; Future, not part of MVP.
130
- deftype ScalarOr (T)
131
- or 'T 'String 'Number
132
- ```
133
-
134
- 现有参数化 `defenum`、Struct 和容器类型不受影响。
135
-
136
- ## 4. 静态语义
137
-
138
- ### 4.1 名义名称,透明成员
139
-
140
- `RespoNode` 是具名定义,工具和 schema 不应在输出中随意展开为匿名集合。但赋值关系按照成员透明计算:
141
-
142
- - `Component` 可以赋给 `RespoNode`;
143
- - `Element` 可以赋给 `RespoNode`;
144
- - `RespoNode` 不能在未收窄时赋给 `Component`;
145
- - union `A` 可以赋给 union `B`,当且仅当 `A` 的每个成员都能赋给 `B`;
146
- - union 与成员的匹配必须保持方向性,不能因为其中一侧是宽类型而双向通过。
147
-
148
- 这与集合包含关系一致:实际值的可能集合必须是目标类型允许集合的子集。
149
-
150
- ### 4.2 归一化
151
-
152
- 解析 `or` 时执行:
153
-
154
- 1. 解析 namespace-qualified TypeRef;
155
- 2. 展平嵌套 union;
156
- 3. 按 nominal identity 去重;
157
- 4. 拒绝零成员和单成员 union,单类型别名不属于 MVP;
158
- 5. 拒绝直接或间接只由 alias 构成的循环;
159
- 6. 允许通过 Struct/Enum 字段形成递归数据图;
160
- 7. union 出现 `Dynamic` 时给出错误,因为 `or Dynamic T` 等价于丢失整个约束。
161
-
162
- 例如 `Component.tree -> Optional<RespoNode>` 与 `RespoNode -> Component | Element` 是合法递归;`deftype A (or 'B)`、`deftype B (or 'A)` 不是。
163
-
164
- ### 4.3 构造与返回
165
-
166
- `deftype` 不生成 constructor,也不改变 `%{}`、`%::` 或字面量:
167
-
168
- ```cirru.no-check
169
- let
170
- component $ %{} Component (:name :root)
171
- element $ %{} Element (:name :div)
172
- nodes $ [] component element
173
- render-all nodes
174
- ```
175
-
176
- 当 `render-all` 的参数声明为 `List<RespoNode>` 时,list literal 与 `conj`/`append` 的泛型统一应允许成员提升到 union。
177
-
178
- MVP 不从任意不同分支自动合成匿名 union。只有存在以下证据时才提升到具名 union:
179
-
180
- - 函数参数或返回 schema;
181
- - 容器的期望元素类型;
182
- - `assert-type`;
183
- - 已有 local 类型;
184
- - 明确的 `deftype` 定义引用。
185
-
186
- 这样避免一次普通 `if` 把整个程序推断成不断增长的匿名类型集合。
187
-
188
- ### 4.4 未收窄操作
189
-
190
- union 值未收窄前只能执行所有成员都安全支持的操作:
191
-
192
- - 可以传给接受该 union 或更宽 union 的函数;
193
- - 可以执行所有成员共同满足的 trait bound/method;
194
- - 不允许直接读取某个成员独有的 Struct 字段;
195
- - 不因为多个 Struct 恰好有同名字段就默认进行 structural field merge。
196
-
197
- 最后一条是有意限制。共同字段合并会引入字段 variance、optional 与写操作规则,MVP 先要求显式收窄。
198
-
199
- ## 5. 控制流收窄
200
-
201
- 仅有 union 声明不足以替代 `Dynamic`。必须让运行时判定产生静态证据,而且证据要能通过 `if`、`cond`、`and` 和 pattern matching 传播。
202
-
203
- ### 5.1 `struct-match`
204
-
205
- Phase 1 直接增强现有 `struct-match`,不新增 Respo 专用 accessor:
206
-
207
- ```cirru.no-check
208
- defn node-name (node)
209
- struct-match node
210
- Component component
211
- :name component
212
- Element element
213
- :name element
214
- ```
215
-
216
- 若 scrutinee 是 `RespoNode`:
217
-
218
- - `Component` 分支 binder 类型为 `Component`;
219
- - `Element` 分支 binder 类型为 `Element`;
220
- - pattern 必须是 union 的 Struct 成员;
221
- - 所有成员已覆盖时不要求 `_`;
222
- - 缺少成员且没有 `_` 时给出穷尽性诊断;
223
- - `_` binder 保留尚未覆盖成员组成的剩余 union,而不是退化成 `Dynamic`。
224
-
225
- 这项能力应修复当前 `struct-match` runtime 能匹配、但分支 binder 仍缺少具体静态类型的问题。
226
-
227
- ### 5.2 `type-match?`
228
-
229
- 新增公共 predicate `type-match?`,参数顺序保持 value-first:
230
-
231
- ```cirru.no-check
232
- if
233
- type-match? node Component
234
- :tree node
235
- nil
236
- ```
237
-
238
- 它同时承担运行时判定与编译器可识别的 narrowing primitive:
239
-
240
- - true branch:`node` 收窄到 `Component`;
241
- - false branch:从原 union 排除 `Component`;
242
- - 第二个参数必须是静态可解析的具体类型定义;
243
- - external-object trait 只有静态证据,没有可靠 runtime identity,不允许用于该 predicate;
244
- - 参数化容器只检查外层 runtime kind,不声称验证内部元素类型。
245
-
246
- 底层可复用现有 `&struct:matches?`、Enum definition identity 和 builtin kind 判定,但业务代码不应直接依赖这些 primitive 的组合。
247
-
248
- ### 5.3 用户定义 type guard
249
-
250
- 为了保留 `component?`、`element?` 这类领域名称,函数 schema 新增 `:narrows`:
251
-
252
- ```cirru.no-check
253
- defn component? (value)
254
- type-match? value Component
255
-
256
- :: 'Fn $ {}
257
- :args $ [] 'RespoNode
258
- :return 'Bool
259
- :narrows $ {}
260
- 0 'Component
261
- ```
262
-
263
- key 是从零开始的参数位置,value 是 true 分支证明的目标类型。规则如下:
264
-
265
- - 被标记函数必须返回 `Bool`;
266
- - 目标类型必须是对应参数声明类型的成员或子类型;
267
- - 编译器必须验证函数体是可证明等价的 guard;MVP 不提供绕过验证的 trusted 标记;
268
- - 普通函数不能仅靠 schema 谎称 narrowing;
269
- - false 分支从原 union 排除目标类型。
270
-
271
- MVP 只接受函数体直接调用 `type-match?` 的可验证 guard。组合 guard 和用户自定义验证器留到后续,避免把 `:narrows` 变成另一种 `unsafe-coerce`。
272
-
273
- ### 5.4 逻辑表达式传播
274
-
275
- `and` 必须按从左到右的短路语义传播 true evidence:
276
-
277
- ```cirru.no-check
278
- if
279
- and
280
- component? old-tree
281
- component? new-tree
282
- compare-components old-tree new-tree
283
- nil
284
- ```
285
-
286
- 调用 `compare-components` 时,两个 local 都是 `Component`。`or` 的 true 分支通常只得到多个可能性的 union,false 分支则累积排除证据。
287
-
288
- `cond` 每个后续分支继承前面 predicate 为 false 的排除结果:
289
-
290
- ```cirru.no-check
291
- cond
292
- component? node
293
- render-component node
294
- (element? node)
295
- render-element node
296
- ```
297
-
298
- 当 `node` 是 `Component | Element` 时,第二个 condition 进入前已经排除了 `Component`;`element?` 再确认具体类型。实现应保存每个 local 的 positive/negative type set,而不是只记录单个覆盖类型。
299
-
300
- ## 6. 通用类型匹配
301
-
302
- `struct-match` 足以覆盖 Respo 的第一阶段。为了让 union 能包含 Struct、Enum 和 builtin 类型,后续增加原生 `match-type`:
303
-
304
- ```cirru.no-check
305
- match-type value
306
- Component component
307
- :tree component
308
- Element element
309
- :children element
310
- String text
311
- count text
312
- ```
313
-
314
- 每个 arm 是 `Type binder body...`,符合 Cirru 现有缩进结构,不需要把 pattern 和 body 包进多层括号。
315
-
316
- `match-type` 的职责是按具体 runtime type identity 分支;Enum 内部 variant 仍交给现有 `match`。例如先由 `match-type` 确认值属于某个 Enum definition,再在分支内用 `match` 解构 variant。
317
-
318
- Phase 1 不要求实现 `match-type`;但 `deftype` 的 IR 与 exhaustiveness API 不应锁死为 Struct-only。
319
-
320
- ## 7. 与 Optional、Option 和 nil 的关系
321
-
322
- union 不隐式包含 `nil`。缺失值继续由现有类型表达:
323
-
324
- ```cirru.no-check
325
- defstruct Component (:name 'Tag)
326
- :tree $ :: 'Optional 'RespoNode
327
- ```
328
-
329
- 迁移期可以使用 `Optional<RespoNode>` 保持现有 nil 表示。新 API 若要显式表达业务分支,仍优先使用 `Option<RespoNode>`。
330
-
331
- 不建议声明 `RespoNode = Component | Element | Unit` 来偷渡 nullable 语义,因为这会把“没有节点”和“函数无返回值”混在一起。
332
-
333
- ## 8. 与 trait 和 FFI 的边界
334
-
335
- ### 8.1 普通 runtime trait
336
-
337
- 若 union 所有成员 nominally implement `RenderNode`,则:
338
-
339
- - `RespoNode` 可以满足 `T: RenderNode`;
340
- - `.method` 继续根据实际 Struct/Enum 的 impl 分派;
341
- - 任一成员缺少 impl 时,整个 union 不满足该 trait;
342
- - 多成员同名 inherent method 不构成 trait 证据。
343
-
344
- 这使 union 与 runtime trait 互补,而不是竞争两套多态模型。
345
-
346
- ### 8.2 external-object trait
347
-
348
- DOM FFI 继续直接返回小型 external trait,例如 `DomElement`、`DomInput`、`DomKeyboardEvent`。不要用 union 模拟 DOM interface inheritance,也不要把宿主对象与 Respo 内部节点放进同一个 union。
349
-
350
- External trait 是 codegen-only 静态证据,不能参与 `type-match?` runtime narrowing。宿主 API 的字符串相关重载,例如 `keydown -> KeyboardEvent`,优先通过专用 wrapper 表达,不在 union 系统中增加 dependent typing。
351
-
352
- ## 9. 表示与实现建议
353
-
354
- ### 9.1 类型表示
355
-
356
- 建议新增两层表示:
357
-
358
- - `Calcit::TypeUnion` 或等价 definition value:保存名称、namespace、RHS 和 nominal identity;
359
- - `CalcitTypeAnnotation::UnionRef`:保留具名引用以及按需解析后的规范化成员。
360
-
361
- 不要在普通值上增加 `Calcit::UnionValue`。`Component` 值仍然是 `Calcit::Struct`,`Element` 值也仍然是 `Calcit::Struct`。
362
-
363
- `type-of RespoNode` 可返回 `:type-def`,`type-of component` 仍返回 `:struct`。类型自省后续可增加 `&type:members`;MVP 只需要编译器内部 lookup。
364
-
365
- ### 9.2 解析与生命周期
366
-
367
- `deftype` 应与 `defstruct`、`defenum` 一样保持 top-level definition identity,并参与 snapshot/schema 解析。RHS 解析必须延迟到 namespace definitions 可见后,支持 Struct 字段与 union 之间的递归引用。
368
-
369
- JS/native/WASM 均不需要为 union value 新增 ABI。主要后端工作是:
370
-
371
- - 保留或擦除 type definition metadata;
372
- - lower `type-match?` 与 `match-type`;
373
- - 在 codegen 前完成字段访问和 method candidate 校验。
374
-
375
- ### 9.3 类型匹配实现
376
-
377
- 建议把 assignability 写成方向明确的关系:
378
-
379
- ```text
380
- is_assignable(actual, expected)
381
- ```
382
-
383
- 核心 union 规则:
384
-
385
- ```text
386
- member M -> union U iff M -> any member of U
387
- union A -> union B iff every member of A -> B
388
- union U -> non-union T iff every member of U -> T
389
- ```
390
-
391
- 最后一条通常只有 union 归一化后所有成员都可赋给同一个 trait/宽类型时成立,不能作为 downcast。
392
-
393
- 现有 `Dynamic` 兼容规则不能用来证明 union member。若 strict schema 中 `Dynamic` 与具体成员双向匹配,联合类型仍会退化成无约束;这部分应与静态语义 RFC 一起改成方向性边界规则。
394
-
395
- ## 10. 诊断
396
-
397
- 建议新增稳定诊断码:
398
-
399
- | Code | 条件 | 建议 |
400
- | --- | --- | --- |
401
- | `E_UNION_EMPTY` | `or` 没有成员 | 至少声明两个具体类型 |
402
- | `E_UNION_SINGLE_MEMBER` | MVP 中只有一个成员 | 直接使用该类型 |
403
- | `E_UNION_DYNAMIC_MEMBER` | union 包含 `Dynamic` | 移除 `Dynamic` 或保留整个位置为显式动态边界 |
404
- | `E_UNION_ALIAS_CYCLE` | alias-only 循环 | 通过 Struct/Enum 字段建立递归 |
405
- | `W_UNION_REQUIRES_NARROWING` | 对 union 读取成员独有字段 | 使用 `struct-match`、`type-match?` 或可信 guard |
406
- | `W_UNION_NON_EXHAUSTIVE` | match 缺少成员 | 补齐 arm 或 `_` |
407
- | `W_INVALID_NARROWS_CONTRACT` | `:narrows` 与函数体/参数不一致 | 改成直接 `type-match?` guard |
408
-
409
- 诊断应显示 union 名称和剩余成员,例如:
410
-
411
- ```text
412
- W_UNION_REQUIRES_NARROWING: `RespoNode` may be Component | Element;
413
- field `:tree` only exists on Component. Narrow `node` before access.
414
- ```
415
-
416
- ## 11. Respo 迁移目标
417
-
418
- 第一轮迁移只改类型关系,不重写 renderer 架构:
419
-
420
- 1. 声明 `RespoNode = Component | Element`;
421
- 2. 把 `Component.tree`、renderer/diff/effect 参数改为 `RespoNode` 或 `Optional<RespoNode>`;
422
- 3. 增强 `struct-match` binder narrowing;
423
- 4. 给 `component?`、`element?` 增加可验证 `:narrows`;
424
- 5. 删除 `as-component`、`as-element` 以及对应的 `&struct:nth` accessor;
425
- 6. 再分别为属性值、style 值、coord key 和事件值声明小型 union;
426
- 7. DOM host object 保持 external trait,不与 `RespoNode` union 混用。
427
-
428
- 预期 diff 主干可以保持当前数据导向写法:
429
-
430
- ```cirru.no-check
431
- cond
432
- and
433
- component? old-tree
434
- component? new-tree
435
- diff-components old-tree new-tree
436
- (and (element? old-tree) (element? new-tree))
437
- diff-elements old-tree new-tree
438
- ```
439
-
440
- 这里不需要 runtime enum wrapper,也不需要把整个 diff 算法改写成 trait virtual methods。
441
-
442
- ## 12. 实施阶段
443
-
444
- ### Phase A:`deftype` 与 assignability
445
-
446
- - parser/snapshot 能加载 `deftype Name (or ...)`;
447
- - 新增具名 union annotation 与 definition lookup;
448
- - 实现成员到 union、union 到 union 的方向性匹配;
449
- - 支持 Fn 参数/返回、Struct 字段和容器 expected type;
450
- - `check-types`、`analyze weak-types` 和类型打印保留 union 名称。
451
-
452
- ### Phase B:`struct-match` 静态收窄
453
-
454
- - branch binder 得到具体 Struct 类型;
455
- - 对 union 做成员合法性和穷尽性检查;
456
- - `_` 分支获得剩余 union;
457
- - 字段读取正常 lower 到受检 `&struct:nth`。
458
-
459
- 完成 A+B 后,Respo 已可移除大部分 `Dynamic -> Component/Element` adapter。
460
-
461
- ### Phase C:predicate 与 flow facts
462
-
463
- - 实现 `type-match?`;
464
- - 实现可验证 `:narrows`;
465
- - 在 `if`、`cond`、`and`、`or` 中传播 positive/negative member sets;
466
- - 让多个 local 的 evidence 可以同时存在。
467
-
468
- ### Phase D:通用匹配与共同能力
469
-
470
- - 实现 `match-type`;
471
- - union 对共同 trait bound 的满足检查;
472
- - 按真实项目需要评估共同只读字段,不默认开放;
473
- - 再评估参数化 `deftype` 与匿名 union inference。
474
-
475
- ## 13. 验收标准
476
-
477
- 至少覆盖以下测试:
478
-
479
- 1. `Component`、`Element` 都能传入 `RespoNode` 参数;
480
- 2. 其他 Struct 不能传入;
481
- 3. `List<RespoNode>` 可构造异构列表,元素读取仍是 `RespoNode`;
482
- 4. 未收窄访问 `:tree` 给出稳定诊断;
483
- 5. `struct-match` 两个 branch binder 分别拥有具体 Struct 类型;
484
- 6. 完整分支无穷尽性告警,缺少分支会告警;
485
- 7. `component?` true/false 分支分别保留包含/排除证据;
486
- 8. `and` 能同时收窄 old/new 两个 local;
487
- 9. `or Dynamic Component` 被拒绝;
488
- 10. union 值运行时表示、相等性、hash 和序列化与原成员完全一致;
489
- 11. native 与 JS 的 `type-match?` 结果一致;
490
- 12. external-object trait 不被误当成可运行时判定的 union member。
491
-
492
- ## 14. 不采用的方案
493
-
494
- ### 14.1 保持 `Dynamic`,依靠 accessor
495
-
496
- 这会让 `as-component` 和 `&struct:nth` 只隐藏类型缺失,不提供运行时验证,也无法让容器、返回值和递归字段形成稳定关系。
497
-
498
- ### 14.2 只使用 runtime trait object
499
-
500
- Trait 适合共同方法,但 Respo diff 需要按具体节点种类读取不同字段,并同时比较 old/new 两个值。把全部逻辑改成 virtual methods 会引入大量 accessor 或双分派,复杂度高于封闭 union。
501
-
502
- ### 14.3 使用 `defenum` 包装已有 Struct
503
-
504
- 该方案类型安全,但每个节点都要额外构造和解包:
505
-
506
- ```cirru.no-check
507
- defenum RespoNode
508
- :component 'Component
509
- :element 'Element
510
- ```
511
-
512
- 这会改变 Respo 当前数据表示、相等性路径和 DSL 输出。`deftype` 的目标正是获得相同的静态分支能力,而不引入这层运行时包装。
513
-
514
- ### 14.4 自动把不同分支推断为匿名 union
515
-
516
- 全局自动合成会让 union 随控制流不断增长,并使错误信息缺少稳定领域名称。MVP 只在具名 expected type 已知时提升。
517
-
518
- ## 15. 结论
519
-
520
- 要在不依赖 `Dynamic` 的前提下保持 Calcit/Respo 的数据导向风格,`deftype` 是基础能力,flow narrowing 是不可分割的另一半。只实现声明而不实现 `struct-match` binder、predicate guard 和逻辑传播,最终仍会回到手写 cast/accessor。
521
-
522
- 建议按 A+B 先打通 RespoNode,再实现 C;`match-type`、参数化 alias 和更积极的推断放到真实迁移数据证明有必要之后。
@@ -1,27 +0,0 @@
1
- # `cr edit transaction` 第一版
2
-
3
- ## 概要
4
-
5
- - 在既有 `cr edit` 命令组中增加 `transaction`,输入复用现有 `edit`、`tree`、`config` 参数序列。
6
- - 以 Cirru EDN argument lists 为主输入,并允许在 `--code` 后直接嵌入 quoted AST;JSON 作为兼容格式保留。支持 `--dry-run`、`--expect-revision` 和 human/JSON 输出。
7
- - 所有 operation 只修改同目录 staged snapshot;全部成功、snapshot 可重新加载/序列化且原文件 revision 未变化后,才通过 rename 一次提交。
8
- - staged 文件保留原 snapshot 权限;失败、stale revision 与 dry-run 都由 guard 清理,不修改原文件。
9
- - transaction 会捕获每个子命令的 stdout/stderr,保证成功时 JSON stdout 仍是单个可解析值。
10
-
11
- ## 关键取舍
12
-
13
- - 没有立即把全部 handler 重构成新的内存 mutation API,因为这会同时改变大量稳定的 `edit/tree/config` 路径。
14
- - 第一版通过 staged snapshot 调用当前 `cr` 子命令,直接复用参数解析、namespace 边界、tree path、schema 和保存校验。
15
- - transaction 仅允许 `edit`、`tree`、`config`,拒绝嵌套 transaction 和只读/执行类命令。
16
- - snapshot revision 当前是原文件内容的 MD5 opaque ID;执行前和最终 rename 前都会检查,避免 stale write。
17
-
18
- ## 验证
19
-
20
- - 新增 JSON/Cirru 解析、Cirru EDN 内嵌 quoted code、非法 command、nested transaction、stale revision、dry-run、operation failure rollback、成功提交测试。
21
- - 真实临时 snapshot 验证了 `config version`、`edit doc` 与 `tree replace` 的组合提交及失败回滚。
22
- - `cargo fmt --all`
23
- - `cargo clippy -- -D warnings`
24
- - `cargo test`
25
- - `yarn compile`
26
- - `yarn check-agent-interface`(新增 staged transaction 场景,12/12)
27
- - `yarn check-all`
@@ -1,30 +0,0 @@
1
- # 可持续迁移的 tree cursor
2
-
3
- ## 概要
4
-
5
- - 新增 `07-28-persistent-tree-cursor-rfc.md`,将 cursor 定义为 CLI 跨调用维护的树形选择状态,而不是 snapshot 中的源码身份。
6
- - 新增 `cr cursor set/show/clear/parent/child/next/prev`,状态以 Cirru EDN 保存到 snapshot 同目录的 `.calcit-cursor.cirru`。
7
- - path-based tree 命令可通过 `--path @cursor` 引用 active cursor,显式 definition target 必须匹配。
8
- - `cursor show` 在展示副本中用 `CURSOR` 包裹目标;JSON 输出仍返回真实 subtree 与独立 cursor 元数据。
9
- - 直接 tree mutation 成功后会刷新 cursor fingerprint、preview 与 definition revision,并对插入、删除、swap、unwrap、raise、wrap、replace 等操作执行确定性 path 迁移。
10
-
11
- ## 安全边界
12
-
13
- - cursor 文件是本地状态,已加入 `.gitignore`,不会写进 snapshot 或模块内容。
14
- - 外部修改导致 path fingerprint 不匹配时,只允许通过唯一 fingerprint 命中自动重定位;零命中或多命中拒绝猜测。
15
- - snapshot 已保存但 cursor 写入失败时,错误会明确说明源码 mutation 已成功,避免误认为整体回滚。
16
- - transaction staged 子命令暂时禁用真实 cursor 写入;transaction 内 cursor 演化留到下一阶段实现。
17
-
18
- ## 验证
19
-
20
- - cursor path transform 单元测试覆盖前方插入、前方删除、删除目标、swap 与 unwrap。
21
- - Cursor Cirru EDN 文件 round-trip 测试。
22
- - 临时 snapshot 集成测试覆盖源码插入后持久化 cursor 从 `@48.1` 迁移到 `@48.2`,且 preview 仍为原来的 `true` 节点。
23
- - 手工 CLI smoke 覆盖 `cursor set/show --format json`、`tree show --path @cursor` 和 `tree insert-before --path @cursor`。
24
- - `cargo fmt --all`
25
- - `cargo clippy -- -D warnings`
26
- - `cargo test`(256 lib + 147 cr)
27
- - `yarn compile`
28
- - `yarn check-agent-interface`(12/12)
29
- - `yarn check-all`
30
- - `cr docs check-md` 验证 `docs/run/edit-tree.md` 与 `docs/CalcitAgent.md`
@@ -1,30 +0,0 @@
1
- # Cursor focus、导航栈与结构化 clipboard
2
-
3
- ## 概要
4
-
5
- - `cursor show` 基于 Cirru Parser 0.2.15 `focus_cirru_preview_with_options` 展示 definition 上下文,由 parser 直接保留 definition 签名并生成展示态 `CURSOR`。
6
- - 精确锁定 `cirru_parser = 0.2.15`。原因是 `cargo install --path` 不保证沿用仓库 lockfile;若只使用兼容版本范围,本地测试与全局安装可能获得不同的 focus marker 语义。
7
- - `.calcit-cursor.cirru` 升级到 schema v2,继续兼容读取 v1;新增普通导航 history、显式 `push/pop` stack 与保存 Cirru tree 的 clipboard。
8
- - 新增 `cursor back/push/pop/copy/cut/paste/clipboard/clear-clipboard`。cut 后选择 parent,paste 后选择新节点,clipboard 保留以支持重复粘贴。
9
- - 顶层 `--cursor-after none|summary|focus` 控制 mutation 后的 stderr 回显;默认 summary,不影响实际 cursor 维护。
10
- - `edit cp/mv/split-def` 支持 `@cursor`;definition overwrite/rename/move/delete、namespace delete 与 transaction 提交后验证会更新或明确提示 cursor 状态。
11
-
12
- ## 准确性要点
13
-
14
- - `edit mv` 按插入路径、源删除后的 index 漂移和 cursor 在源 subtree 内的相对路径做确定性迁移,不依赖可能多命中的 fingerprint 搜索。
15
- - focus、full 和 node 都只构造 presentation tree;真实 snapshot、path、fingerprint 与 JSON `tree` 不包含 `CURSOR`。
16
- - JSON `cursor.show` 分开返回真实 `tree` 和展示用 `preview_tree`,并报告 `exact`、`verified-at-path` 或 `relocated`。
17
- - sidecar 不在 `.gitignore` 时只提示建议,不自动修改用户项目。
18
-
19
- ## 验证
20
-
21
- - cursor 单元测试覆盖 v1→v2 兼容、history/stack/clipboard round-trip、focus 签名与 marker、cut/paste、前方增删、swap/unwrap,以及重复 fingerprint 下的确定性 move。
22
- - 临时 Calcit snapshot 手工验证 `cursor show --view focus`、`--cursor-after focus`、back/push/pop、copy/cut/paste 和 `edit cp/mv/split-def/rename/mv-def`。
23
- - 全局安装后的 `cr` 在 `respo-calcit-workflow` 临时副本中完成深层 cursor focus、cut/paste 原位恢复、`tree replace --path @cursor` 与 `cr js` 编译。
24
- - `cargo fmt`
25
- - `cargo clippy -- -D warnings`
26
- - `cargo test`
27
- - `yarn compile`
28
- - `yarn check-agent-interface`(12/12)
29
- - `yarn check-all`
30
- - `cr docs check-md` 验证 `docs/run/edit-tree.md` 与 `docs/CalcitAgent.md`
@@ -1,21 +0,0 @@
1
- # Cursor 多步导航与搜索选取
2
-
3
- ## 概要
4
-
5
- - `cursor child` 省略 index 时进入首子节点,`cursor child --last` 按当前树进入末子节点。
6
- - `cursor next`、`cursor prev` 与 `cursor back` 支持 `--count N`;多步移动只产生一次 history transition,参数为零或越界时不写 cursor。
7
- - `query search` 与 `query search-expr` 的每个结果获得稳定的全局 cursor index:human 输出为 `[#N]`,JSON 字段为 `cursor_index`。
8
- - 搜索命令新增 `--set-cursor N`,直接将对应结果写入项目 cursor。确认信息走 stderr,保持 JSON stdout 为单个可解析对象。
9
- - dependency-only 搜索结果不能映射到当前可编辑 snapshot 时明确报错,不将 cursor 猜测性落到同名定义。
10
-
11
- ## 验证关注点
12
-
13
- - `child --last` 必须读取当前 node 的 child count,不能把 `-1` 或陈旧 index 写入 sidecar。
14
- - sibling skip 和 multi-back 必须预先验证完整步数;失败后 active cursor 与 history 均保持不变。
15
- - human 与 JSON 的结果编号必须共享同一排序和扁平化顺序。
16
-
17
- ## 验证结果
18
-
19
- - `cargo fmt`、`cargo clippy --all-targets -- -D warnings`、`cargo test`、`yarn compile` 与 `yarn check-all` 通过。
20
- - Agent interface smoke 12/12,`docs/run/edit-tree.md` 与 `docs/CalcitAgent.md` 的可执行代码块检查通过。
21
- - 全局安装 `cr 0.12.53` 后,在 `respo-calcit-workflow` 临时副本以 `query search --set-cursor 0` 定位 `comp-runs`,随后验证 `child --last`、`prev --count 1`、`back --count 2`、focus 展示,并完成 `cr calcit.cirru js` 编译。
@@ -1,14 +0,0 @@
1
- # Agent 工具链 RFC 拆分
2
-
3
- ## 概要
4
-
5
- - 移除体量过大的 `07-26-agent-semantic-interface-roadmap-rfc.md`,按紧密关联的功能边界拆分为文档与评估、机器协议、安全结构化编辑、静态语义分析等 RFC。
6
- - 补充单项目工具契约、Git 模块存储与持久树形 cursor RFC,明确 Calcit 继续以 EDN/Cirru 树形源码、结构化文档和既有 `cr` 子命令为中心。
7
- - Git 模块仍以 tag 为最佳实践、允许分支名,不引入 registry、workspace 或 lockfile;依赖冲突采用最高版本并输出 warning。
8
- - LSP 延后到一次性解析接口足够稳定且维护成本可接受之后,不把行号作为源码或诊断的核心身份。
9
-
10
- ## 文档边界
11
-
12
- - 新 RFC 各自描述一块可独立评审和实施的能力,避免实现状态、长期设想和不适用于 Calcit 的 Cargo 风格命令混在同一文件中。
13
- - `RFCs/README.md` 更新索引,后续实现和验收可直接引用对应 RFC。
14
-
@@ -1,14 +0,0 @@
1
- # Cursor 与 transaction 使用文档
2
-
3
- ## 概要
4
-
5
- - 在 Agent 指南中补充通过搜索结果设置 cursor、用 `@cursor` 进行连续树形编辑、导航栈与结构化 clipboard 的推荐流程。
6
- - 在结构化编辑参考中完整记录 cursor sidecar、focus/node/full 展示、mutation 后坐标维护与 `--cursor-after` 回显控制。
7
- - 记录 Cirru EDN transaction 的主要输入形式、quoted code、dry-run、revision 检查与 JSON 兼容边界。
8
- - 将新增命令加入 Agent 能力地图和文档 frontmatter,便于结构化文档查询定位。
9
-
10
- ## 一致性
11
-
12
- - 文档示例沿用既有 `cr` 子命令风格,不引入 Cargo 风格命令。
13
- - 所有路径仍指向 Snapshot 中的 Cirru tree,展示用 `CURSOR` 不改变真实源码与 path。
14
-