@calcit/procs 0.13.14 → 0.13.16

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 (28) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/RFCs/07-26-agent-machine-protocol-rfc.md +113 -35
  3. package/RFCs/07-28-persistent-tree-cursor-rfc.md +22 -4
  4. package/RFCs/08-05-systematic-nil-reduction-rfc.md +2 -2
  5. package/RFCs/08-14-architecture-scaffold-rfc.md +534 -0
  6. package/RFCs/08-14-todo-placeholder-rfc.md +177 -0
  7. package/RFCs/README.md +3 -1
  8. package/editing-history/20260814-1412-architecture-scaffold-rfc-and-cursor-envelope.md +46 -0
  9. package/editing-history/20260814-1640-architecture-scaffold-review-fixes.md +21 -0
  10. package/editing-history/20260814-1700-fix-bare-empty-map-js-codegen.md +10 -0
  11. package/editing-history/20260814-1710-map-codegen-callee-context.md +9 -0
  12. package/editing-history/20260814-1720-option-membership-method-guidance.md +11 -0
  13. package/editing-history/20260814-1746-pr-352-review-fix.md +8 -0
  14. package/editing-history/20260814-1858-map-wrapped-data-definitions.md +11 -0
  15. package/editing-history/20260814-1910-assert-type-struct-narrowing.md +6 -0
  16. package/editing-history/20260814-1937-assert-type-direct-definitions.md +5 -0
  17. package/editing-history/20260814-1945-applied-qualified-type-references.md +5 -0
  18. package/editing-history/20260815-0043-pr-352-assert-type-nominal-guard.md +12 -0
  19. package/history/202608131607-runtime-map-decoder.md +13 -0
  20. package/history/202608131625-core-decode-map-as-metadata.md +12 -0
  21. package/history/202608131650-release-0.13.15.md +10 -0
  22. package/lib/calcit.procs.d.mts +6 -1
  23. package/lib/calcit.procs.mjs +133 -0
  24. package/lib/package.json +1 -1
  25. package/notes/202608132206-repo-sync.md +3 -0
  26. package/notes/repos.md +177 -0
  27. package/package.json +1 -1
  28. package/ts-src/calcit.procs.mts +132 -1
Binary file
@@ -18,49 +18,101 @@ Calcit 的源码、定义元数据与编辑对象本来就是 Cirru EDN 树。Ag
18
18
  - 不以 LSP 为前置条件;只有重复解析已被基准证明确实成为瓶颈,且 LSP 的映射收益超过维护成本时,才评估薄适配层。
19
19
  - 本 RFC 不改变 snapshot 的 EDN 存储形式,也不引入 workspace。
20
20
 
21
- ## 3. Typed result JSON envelope
21
+ ## 3. Typed result 与机器 renderer
22
22
 
23
- 每个命令先产生 typed result,再由 human/JSON renderer 输出;禁止从人类文本反向解析机器数据。
23
+ 每个命令先产生 typed result,再由 human/Cirru EDN/JSON renderer 输出;禁止从人类文本反向解析机器数据。
24
24
 
25
- ```json
26
- {
27
- "schema_version": 1,
28
- "command": "query.context",
29
- "revision": "opaque-content-hash",
30
- "data": {},
31
- "diagnostics": [],
32
- "next": []
33
- }
25
+ 方向更新(2026-08-14):Calcit 自身的 Symbol、Tag、Set、Enum/Struct 和 quoted Cirru AST 在 Cirru EDN 中可以无损表达,因此新增加的丰富机器协议应优先定义 `--format edn`,并把它作为权威 schema。JSON 的优势是 `JSON.parse`、`jq`、LSP/MCP adapter 和既有 Agent 脚本兼容,不是表达 Calcit 数据的必要条件;已有 `--format json` 契约继续稳定支持,但定位为 compatibility projection,不再反向限制 typed result。
26
+
27
+ - `--format edn` 时 stdout 只能是一个带 schema version 的 Cirru EDN value;
28
+ - `--format json` 时 stdout 仍只能是一个 JSON value;非 JSON 原生类型使用稳定 tagged encoding;
29
+ - 新字段先定义 EDN 形状,再定义 JSON 投影;
30
+ - 现有只支持 JSON 的命令渐进增加 EDN renderer,不做破坏式切换。
31
+
32
+ ```cirru
33
+ {}
34
+ :schema-version 1
35
+ :command :query.context
36
+ :revision |opaque-content-hash
37
+ :data $ {}
38
+ :diagnostics $ []
39
+ :next $ []
34
40
  ```
35
41
 
36
42
  规则:
37
43
 
38
- - `--format json` 时 stdout 只能是一个 JSON value;日志、tips 与 command echo 一律去 stderr;
44
+ - `--format edn` / `--format json` 时 stdout 都只能是一个 value;日志、tips 与 command echo 一律去 stderr;
39
45
  - `revision` 是不透明内容 hash,不承诺可读或跨项目一致;
40
- - 缺失信息用 `null` 或空集合表达,不依赖缺失字段或自然语言推断;
46
+ - EDN 缺失信息用 `nil` 或空集合表达,不依赖缺失字段或自然语言推断;JSON projection 对应使用 `null`;
41
47
  - 有界列表携带 `truncated`、`next_cursor` 或可继续查询的 handle;
42
48
  - 保留兼容期 `--json`,但内部等价于 `--format json`;
43
- - 结果 schema 只能向后兼容地增加可选字段;破坏性变更升级 `schema_version`。
49
+ - 结果 schema 只能向后兼容地增加可选字段;破坏性变更升级 `:schema-version`,JSON projection 使用 `schema_version`。
50
+
51
+ ### 3.1 JSON compatibility projection
52
+
53
+ JSON 只是 EDN typed result 的兼容投影,不能把 Calcit 值压扁成容易歧义的
54
+ 字符串或普通数组。projection 使用稳定的 tagged shape;对象字段使用
55
+ snake_case,集合保持顺序,Set 额外携带 `set` 标签以区别普通数组:
56
+
57
+ | Cirru EDN | JSON projection |
58
+ |---|---|
59
+ | Symbol `foo/bar` | `{"$type":"symbol","value":"foo/bar"}` |
60
+ | Tag `:ok` | `{"$type":"tag","value":"ok"}` |
61
+ | Set `#{:a :b}` | `{"$type":"set","items":[...]}` |
62
+ | Quote `quote (...)` | `{"$type":"quote","value":...}` |
63
+ | anonymous Enum `:: :call a b` | `{"$type":"enum","variant":"call","type":null,"items":[...]}` |
64
+ | Struct | `{"$type":"struct","name":"...","fields":{...}}` |
65
+ | nested value | recursively apply the same mapping |
66
+ | `nil` | JSON `null` |
67
+ | empty collection | tagged empty collection, never `null` |
68
+
69
+ Implementations must include semantic fixtures for every row, including nested
70
+ values and `nil` versus empty collections. A fixture passes only when decoding
71
+ the projection reconstructs an EDN value equivalent to the source; a successful
72
+ `JSON.parse` alone is insufficient. The EDN renderer remains the reference for
73
+ round-trip tests, while JSON fixtures protect compatibility for `jq`, LSP/MCP
74
+ adapters and existing scripts.
75
+
76
+ 最小语义 fixture(`typed-value/nested-v1`)如下;测试同时检查 decode 后的 EDN
77
+ 等价性,而不是只检查 JSON 文本可解析:
78
+
79
+ ```cirru.no-check
80
+ {}
81
+ :value $ :: :ok
82
+ {}
83
+ :name 'calcit/demo
84
+ :items $ #{} :ready
85
+ :empty $ []
86
+ :missing nil
87
+ ```
88
+
89
+ ```json
90
+ {"value":{"$type":"enum","variant":"ok","type":null,"items":[{"$type":"struct","name":"","fields":{"name":{"$type":"symbol","value":"calcit/demo"},"items":{"$type":"set","items":[{"$type":"tag","value":"ready"}]},"empty":[],"missing":null}}]}}
91
+ ```
92
+
93
+ 实现应为 EDN/JSON 各保留一组同构 fixture,并至少覆盖该嵌套案例、空 Set/空
94
+ List、`nil`、Quote 和带类型名的 Enum/Struct。
44
95
 
45
96
  ## 4. 统一 Definition Descriptor
46
97
 
47
98
  query、docs、静态分析与 builtin fallback 应从同一只读描述视图组装结果:
48
99
 
49
- ```json
50
- {
51
- "id": "calcit.core/to-js-data",
52
- "revision": "...",
53
- "kind": "proc",
54
- "source": { "scope": "core", "definition": "calcit.core/to-js-data" },
55
- "schema": null,
56
- "inferred_type": null,
57
- "doc": "...",
58
- "examples": [],
59
- "tags": ["js-ffi"],
60
- "dependencies": [],
61
- "usages": [],
62
- "diagnostics": []
63
- }
100
+ ```cirru
101
+ {}
102
+ :id 'calcit.core/to-js-data
103
+ :revision |...
104
+ :kind :proc
105
+ :source $ {}
106
+ :scope :core
107
+ :definition 'calcit.core/to-js-data
108
+ :schema nil
109
+ :inferred-type nil
110
+ :doc |...
111
+ :examples $ []
112
+ :tags $ #{} :js-ffi
113
+ :dependencies $ []
114
+ :usages $ []
115
+ :diagnostics $ []
64
116
  ```
65
117
 
66
118
  它是 provider 组合出的只读 view,不应变成 runtime 与 query 层互相依赖的巨型数据结构。builtin 与 source-backed definition 必须落入同一结果模型。
@@ -70,10 +122,10 @@ query、docs、静态分析与 builtin fallback 应从同一只读描述视图
70
122
  优先完善以下只读命令,而不是新增多套近似查询:
71
123
 
72
124
  ```bash
73
- cr capabilities --format json
74
- cr query context <ns/def> --budget 2500 --format json
75
- cr query type <type-or-definition> --format json
76
- cr query type-at <ns/def> --path code@3.2 --format json
125
+ cr capabilities --format edn
126
+ cr query context <ns/def> --budget 2500 --format edn
127
+ cr query type <type-or-definition> --format edn
128
+ cr query type-at <ns/def> --path code@3.2 --format edn
77
129
  ```
78
130
 
79
131
  `capabilities` 返回命令、参数/结果 schema、只读性、幂等性和支持的格式,使 Agent 不必加载所有 CLI help。
@@ -91,11 +143,37 @@ cr query type-at <ns/def> --path code@3.2 --format json
91
143
  3. editor/LSP 映射不把行号变成新的事实来源;
92
144
  4. 有明确维护者承担协议兼容、进程恢复和跨平台测试。
93
145
 
94
- 届时优先实现 `cr serve --stdio`,复用本 RFC JSON result;LSP/MCP 只是其上的薄映射。LSP 的 document symbol、references、hover、versioned diagnostics 与 workspace edit 可以借鉴,但内部身份仍是 definition/tree 语义。
146
+ 届时优先实现 `cr serve --stdio`,复用本 RFC typed result。stdio 使用一行一个
147
+ 请求、一行一个响应的 framing;每一行必须是一个完整 EDN value,或在握手后是
148
+ 一个完整 JSON value,禁止把日志写入 stdout。客户端首先发送:
149
+
150
+ ```cirru.no-check
151
+ {}
152
+ :protocol |calcit-agent/1
153
+ :format :edn
154
+ :request-id |hello-1
155
+ ```
156
+
157
+ 服务端响应同样带 `:request-id` 与最终选择的 `:format`。当前实现应优先选择
158
+ EDN;若客户端只声明 `:json`,服务端选择 JSON;无法满足时返回结构化错误并
159
+ 关闭会话。后续请求使用 `:request-id`、`:command`、`:params`,响应使用
160
+ `:ok`、`:result`、`:diagnostics`;错误使用 `:ok false`、`:error {:code ...
161
+ :message ... :details ...}`,EDN/JSON 两种格式字段语义完全一致。stdio 同样
162
+ 遵守“一次响应一个 stdout value”,stderr 才能承载日志和进度信息。
163
+
164
+ 协议 fixture 必须覆盖 EDN 握手、JSON 握手、格式不支持错误、请求/响应关联和
165
+ 上述 typed-value projection。LSP/MCP 只是其上的薄映射;LSP 的 document symbol、
166
+ references、hover、versioned diagnostics 与 workspace edit 可以借鉴,但内部身份
167
+ 仍是 definition/tree 语义。
168
+
169
+ 握手 fixture 至少包含两组等价请求:一组声明 `:format :edn` 并逐行传输 EDN,
170
+ 另一组声明 `:format :json` 并逐行传输 JSON;两组都必须得到相同语义的
171
+ `:request-id`、`:ok`、`:result`/`:error` 响应。
95
172
 
96
173
  ## 7. 验收
97
174
 
98
- - JSON stdout 可由 `JSON.parse` 直接解析,且版本、命令、revision、data、diagnostics 一致;
175
+ - Cirru EDN stdout 可无损 round-trip Symbol、Tag、Set、Quote、Enum/Struct,且版本、命令、revision、data、diagnostics 一致;
176
+ - compatibility JSON stdout 仍可由 `JSON.parse` 直接解析,已有调用方不被破坏;
99
177
  - Agent 能用一次 `context` 和一次可选展开完成一个 definition 的理解;
100
178
  - 对相同 revision 的重复只读调用结果稳定;
101
179
  - `yarn check-agent-interface` 覆盖并记录耗时、stdout bytes、失败原因;
@@ -19,9 +19,9 @@ Calcit 源码以 EDN tree 保存,数字 path 只是某个 snapshot revision
19
19
  ```cirru
20
20
  {}
21
21
  :schema-version 4
22
- :active :main
22
+ :active :default
23
23
  :cursors $ {}
24
- :main $ {}
24
+ :default $ {}
25
25
  :snapshot |calcit.cirru
26
26
  :target |app.main/render!
27
27
  :section :code
@@ -144,7 +144,7 @@ cr edit split-def @cursor --path @cursor --name render-items
144
144
 
145
145
  `cursor show` 默认调用 Cirru Parser 0.2.15 的 `focus_cirru_preview_with_options`,通过 `CirruFocusOptions` 在 definition 级展示副本中折叠无关分支、保留 definition 的 head/name/参数,并直接使用 `CURSOR` marker。Calcit 不再遍历重写 `'FOCUSED` 或手工拼接 definition header;该依赖使用精确版本约束,防止全局安装忽略 lockfile 时出现未经验证的展示语义漂移。目标表达式只在展示副本中渲染为:
146
146
 
147
- ```cirru
147
+ ```cirru.no-check
148
148
  CURSOR
149
149
  map items $ fn (item)
150
150
  render-item item
@@ -248,6 +248,24 @@ snapshot 与 cursor 是两个文件,无法依靠单次 rename 同时提交。
248
248
 
249
249
  当前状态只有一个 active cursor。原子 rename 保证文件完整性,但不提供多个进程共享同一 Snapshot 时的语义并发控制;并行 Agent 应使用独立 worktree/Snapshot,或改用带 precondition 的 transaction 与显式路径。marks 只能隔离导航位置,不能解决并发源码写入,因此不作为并发安全方案。
250
250
 
251
+ 兼容性更新(2026-08-14):CLI 仍只操作 `:active` 指向的 cursor,但 cursor 文档读写会保留该名称以及 `:cursors` map 中其他合法条目,不再在保存 active state 时把 map 收缩为固定的 `:main`。新建 sidecar 的默认名称改为 `:default`,读取旧 `:main` 不受影响。这只为未来 cursor user 排除有损迁移障碍,尚不提供 user 选择、lease、心跳或并发写保护。
252
+
253
+ ### 6.1 下一阶段:cursor user
254
+
255
+ CLI 将引入项目本地 `cursor user`,取代进程间共享的 active selection:
256
+
257
+ ```bash
258
+ cr --cursor-user agent-a cursor show
259
+ CALCIT_CURSOR_USER=agent-b cr tree show @cursor --path @cursor
260
+ cr cursor show # 未指定时使用 default
261
+ ```
262
+
263
+ 解析优先级为 `--cursor-user` > `CALCIT_CURSOR_USER` > `default`。`@cursor`、history、stack、anchor、marks、last-query 和 clipboard 全部按 user 隔离;`cursor whoami/users` 提供发现接口。
264
+
265
+ 后续持久化推荐使用 `.calcit/cursors/<user>.cirru`,而不是让多个进程 read-modify-rename 同一个 `:users` map;否则即使文件写入原子,仍会丢失另一个 user 的并发导航更新。`cursor users` 通过目录发现,v1-v4 的 active entry 迁入 `default` 文件,其他合法 named entry 迁入对应 user 文件。
266
+
267
+ source mutation 只立即迁移发起 user 的 cursor/anchor/marks;其他 user 下次访问时按 definition revision、same-path fingerprint 或唯一 fingerprint 懒惰恢复,无法恢复则标 stale。cursor activity、lease 和 overlap warning 不进入第一版;任务重叠由 orchestrator 比较 work item write-set,写入正确性依赖 Snapshot/definition revision precondition。完整边界见 `08-14-architecture-scaffold-rfc.md` 第 7 节。
268
+
251
269
  ## 7. 第一阶段实现范围
252
270
 
253
271
  1. Cirru EDN cursor 状态的读取、v1-v3→v4 兼容、旧路径一次性迁移、校验、64 KiB 上限和原子写入;
@@ -263,7 +281,7 @@ snapshot 与 cursor 是两个文件,无法依靠单次 rename 同时提交。
263
281
  11. leaf/expression search 都支持 `--filter @cursor` 与 `--start-path @cursor`,并继续支持 `--set-cursor`。
264
282
  12. 单一 sibling region anchor、最多 16 个 named marks,以及只保存参数的 last query / `query next/prev`。
265
283
 
266
- transaction 内逐 operation 的 cursor preview、多 active cursor、region 批量 mutation,以及跨 definition 的 clipboard 引用策略在后续阶段接入;未接入的 mutation 必须让 cursor/anchor/marks 在下次使用时经过 stale 校验,不能绕过 fingerprint。
284
+ transaction 内逐 operation 的 cursor preview、多 cursor user、region 批量 mutation,以及跨 definition 的 clipboard 引用策略在后续阶段接入;未接入的 mutation 必须让 cursor/anchor/marks 在下次使用时经过 stale 校验,不能绕过 fingerprint。
267
285
 
268
286
  ## 8. 验收
269
287
 
@@ -112,7 +112,7 @@ nil 审计也坚持证据边界:返回的 `do` 只有最后一项继承返回
112
112
 
113
113
  - 直接将原有 `find`、`find-index`、`index-of` 改为返回 `Option`,让旧调用在结果消费处产生明确的类型迁移提示;
114
114
  - 将公开 `parse-float` 改为 `String -> Result<Number,String>`,`:err` 保留原始非法输入;nullable 底层过程改名为内部 `&parse-float`;
115
- - 将公开 `get-env` 改为 `String -> Option<String>`,删除旧的第二个默认值参数;迁移时使用 `option:unwrap-or`,nullable 底层过程改名为内部 `&get-env`;
115
+ - 将公开 `get-env` 改为 `String -> Option<String>`,删除旧的第二个默认值参数;迁移时优先使用接收者方法 `.unwrap-or`,nullable 底层过程改名为内部 `&get-env`;
116
116
  - `optionally` 仅保留为 core/internal 遗留 Optional 到 Option 的桥接,不接受 JsNullish;
117
117
  - 反射 API `tuple-enum`、`impl-origin` 返回名义 `Option`,nullable 的 `&tuple:enum`、`&impl:origin` 只保留为内部原语;`record-struct` 则收紧为必然返回 `Struct`;
118
118
  - `destruct-list/map/set/str` 从匿名 `:: :some/:none` tuple 升级到参数化的名义 `*Destruct` enum,让 variant 载荷参与类型检查;
@@ -151,7 +151,7 @@ core 自举宏已经迁到明确的 `&` raw primitive,公开 `first`、`last`
151
151
  - nil 作为集合:提示在来源处处理缺失,不自动替换成空集合,因为二者业务语义不同;
152
152
  - 可省略参数处显式传 nil:提示省略参数,或修改参数值类型为 Optional;
153
153
  - 解析返回 Optional:提示改用后续的 Result API,以保留错误信息。
154
- - 名义 Option 仍用 `some?`/`nil?` 或 tuple 位置读取:提示改用 `option:some?`、`option:none?`、`option:unwrap-or` 或 `tag-match`。
154
+ - 名义 Option 仍用 `some?`/`nil?` 或 tuple 位置读取:提示改用 `.some?`、`.none?`、`.unwrap-or` 或 `tag-match`。
155
155
 
156
156
  自动修复不得把 nil 无条件替换为空集合、0、空字符串或 false。
157
157