@calcit/procs 0.12.47 → 0.12.49

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 (152) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/RFCs/07-06-semantic-tree-navigation-rfc.md +569 -0
  3. package/RFCs/07-08-ffi-features-and-js-object-type-rfc.md +223 -0
  4. package/RFCs/README.md +21 -19
  5. package/editing-history/2026-06-27-0052-cli-improvements.md +41 -0
  6. package/editing-history/2026-06-27-0202-docs-indexing-improvements.md +22 -0
  7. package/editing-history/2026-06-27-0315-file-splits.md +17 -0
  8. package/editing-history/2026-06-27-0416-agent-advanced-split.md +15 -0
  9. package/editing-history/2026-07-07-0000-semantic-tree-navigation.md +49 -0
  10. package/editing-history/2026-07-08-1650-features-and-js-object-type.md +25 -0
  11. package/editing-history/202607040040-fix-format-cirru-edn-quoting.md +14 -0
  12. package/editing-history/archived/2026-06-29-0117-upgrade-doc-snapshot-migration.md +2 -0
  13. package/editing-history/archived/2026-06-29-calcit-cli.md +80 -0
  14. package/editing-history/archived/2026-06-29-typed-calcit-cli-schemas.md +23 -0
  15. package/editing-history/archived/20260630-duplication-analysis.md +116 -0
  16. package/lib/js-cirru.mjs +2 -4
  17. package/lib/package.json +1 -1
  18. package/package.json +1 -1
  19. package/ts-src/js-cirru.mts +2 -4
  20. /package/editing-history/{2026-0213-1841-trait-origin-structural-eq.md → 2026-02-13-1841-trait-origin-structural-eq.md} +0 -0
  21. /package/editing-history/{2026-0214-2050-js-codegen-recursion-tag-migration.md → 2026-02-14-2050-js-codegen-recursion-tag-migration.md} +0 -0
  22. /package/editing-history/{2026-0214-2358-emit-js-modularization-shift-left.md → 2026-02-14-2358-emit-js-modularization-shift-left.md} +0 -0
  23. /package/editing-history/{2026-0215-0000-diagnostics-consolidated.md → 2026-02-15-0000-diagnostics-consolidated.md} +0 -0
  24. /package/editing-history/{2026-0215-1941-macro-diagnostics-refinement.md → 2026-02-15-1941-macro-diagnostics-refinement.md} +0 -0
  25. /package/editing-history/{2026-0216-2043-core-api-docs-cleanup.md → 2026-02-16-2043-core-api-docs-cleanup.md} +0 -0
  26. /package/editing-history/{2026-0223-0834-migrate-to-defstruct.md → 2026-02-23-0834-migrate-to-defstruct.md} +0 -0
  27. /package/editing-history/{2026-0223-2321-ns-imports-code-fixes.md → 2026-02-23-2321-ns-imports-code-fixes.md} +0 -0
  28. /package/editing-history/{2026-0225-0002-language-behavior-eval-mode.md → 2026-02-25-0002-language-behavior-eval-mode.md} +0 -0
  29. /package/editing-history/{2026-0225-0111-guidebook-no-check-block-upgrades.md → 2026-02-25-0111-guidebook-no-check-block-upgrades.md} +0 -0
  30. /package/editing-history/{2026-0225-0113-runtime-type-validation-and-macro-quoting.md → 2026-02-25-0113-runtime-type-validation-and-macro-quoting.md} +0 -0
  31. /package/editing-history/{2026-0225-1131-check-md-eval-improvements.md → 2026-02-25-1131-check-md-eval-improvements.md} +0 -0
  32. /package/editing-history/{2026-0226-1324-check-md-inprocess-cache-and-path-labels.md → 2026-02-26-1324-check-md-inprocess-cache-and-path-labels.md} +0 -0
  33. /package/editing-history/{2026-0227-1640-unify-markdown-readers.md → 2026-02-27-1640-unify-markdown-readers.md} +0 -0
  34. /package/editing-history/{2026-0227-1958-tree-rewrite-command-and-reference-model.md → 2026-02-27-1958-tree-rewrite-command-and-reference-model.md} +0 -0
  35. /package/editing-history/{2026-0227-2200-split-def-command.md → 2026-02-27-2200-split-def-command.md} +0 -0
  36. /package/editing-history/{2026-0227-2212-tree-raise-wrap.md → 2026-02-27-2212-tree-raise-wrap.md} +0 -0
  37. /package/editing-history/{2026-0227-2223-calcit-agent-docs-optimize.md → 2026-02-27-2223-calcit-agent-docs-optimize.md} +0 -0
  38. /package/editing-history/{2026-0301-0212-query-search-entry-and-ffi-warning.md → 2026-03-01-0212-query-search-entry-and-ffi-warning.md} +0 -0
  39. /package/editing-history/{2026-0303-1934-check-types-and-core-annotations.md → 2026-03-03-1934-check-types-and-core-annotations.md} +0 -0
  40. /package/editing-history/{2026-0304-0000-generics-fn-typevar-identity.md → 2026-03-04-0000-generics-fn-typevar-identity.md} +0 -0
  41. /package/editing-history/{2026-0304-1331-tag-call-warning-and-dot-access-migration.md → 2026-03-04-1331-tag-call-warning-and-dot-access-migration.md} +0 -0
  42. /package/editing-history/{2026-0304-1548-impl-new-dot-method-input-and-doc-hints.md → 2026-03-04-1548-impl-new-dot-method-input-and-doc-hints.md} +0 -0
  43. /package/editing-history/{2026-0304-1645-calcit-eq-contract-refactor-and-macro-tests.md → 2026-03-04-1645-calcit-eq-contract-refactor-and-macro-tests.md} +0 -0
  44. /package/editing-history/{2026-0304-2200-assert-type-assert-traits-composable-runtime-checks.md → 2026-03-04-2200-assert-type-assert-traits-composable-runtime-checks.md} +0 -0
  45. /package/editing-history/{2026-0305-0042-type-inference-argtypes-and-core-hints.md → 2026-03-05-0042-type-inference-argtypes-and-core-hints.md} +0 -0
  46. /package/editing-history/{2026-0305-0115-calcit-core-generic-refinements.md → 2026-03-05-0115-calcit-core-generic-refinements.md} +0 -0
  47. /package/editing-history/{2026-0305-1930-schema-migration-cr-edit.md → 2026-03-05-1930-schema-migration-cr-edit.md} +0 -0
  48. /package/editing-history/{2026-0305-1939-query-schema-adaptation.md → 2026-03-05-1939-query-schema-adaptation.md} +0 -0
  49. /package/editing-history/{2026-0306-0120-schema-hint-migration-batch.md → 2026-03-06-0120-schema-hint-migration-batch.md} +0 -0
  50. /package/editing-history/{2026-0306-1416-core-macro-schema-migration.md → 2026-03-06-1416-core-macro-schema-migration.md} +0 -0
  51. /package/editing-history/{2026-0306-1552-core-schema-and-hintfn-migration.md → 2026-03-06-1552-core-schema-and-hintfn-migration.md} +0 -0
  52. /package/editing-history/{2026-0306-1936-schema-normalization-and-preprocess-preload.md → 2026-03-06-1936-schema-normalization-and-preprocess-preload.md} +0 -0
  53. /package/editing-history/{2026-0307-0000-migrate-hint-fn-to-schema.md → 2026-03-07-0000-migrate-hint-fn-to-schema.md} +0 -0
  54. /package/editing-history/{2026-0307-0000-remove-enum-prototype-field.md → 2026-03-07-0000-remove-enum-prototype-field.md} +0 -0
  55. /package/editing-history/{2026-0307-0000-schema-args-type-enforcement.md → 2026-03-07-0000-schema-args-type-enforcement.md} +0 -0
  56. /package/editing-history/{2026-0307-0142-unit-type-and-builtin-schemas.md → 2026-03-07-0142-unit-type-and-builtin-schemas.md} +0 -0
  57. /package/editing-history/{2026-0307-1652-decouple-snapshot-schema-to-calcit-type.md → 2026-03-07-1652-decouple-snapshot-schema-to-calcit-type.md} +0 -0
  58. /package/editing-history/{2026-0307-1821-snapshot-schema-validation.md → 2026-03-07-1821-snapshot-schema-validation.md} +0 -0
  59. /package/editing-history/{2026-0307-1959-schema-def-kind-arity-validation.md → 2026-03-07-1959-schema-def-kind-arity-validation.md} +0 -0
  60. /package/editing-history/{2026-0308-0031-schema-generics-quote-normalization.md → 2026-03-08-0031-schema-generics-quote-normalization.md} +0 -0
  61. /package/editing-history/{2026-0308-1905-schema-typeref-and-assert-migration.md → 2026-03-08-1905-schema-typeref-and-assert-migration.md} +0 -0
  62. /package/editing-history/{2026-0308-2033-schema-wrapper-migration.md → 2026-03-08-2033-schema-wrapper-migration.md} +0 -0
  63. /package/editing-history/{2026-0308-2315-late-schema-cleanup-and-warning-compat.md → 2026-03-08-2315-late-schema-cleanup-and-warning-compat.md} +0 -0
  64. /package/editing-history/{2026-0309-1753-schema-type-fail-tests.md → 2026-03-09-1753-schema-type-fail-tests.md} +0 -0
  65. /package/editing-history/{2026-0310-1040-edit-schema-primitive-tag-support.md → 2026-03-10-1040-edit-schema-primitive-tag-support.md} +0 -0
  66. /package/editing-history/{2026-0310-1754-ns-entry-snapshot-migration.md → 2026-03-10-1754-ns-entry-snapshot-migration.md} +0 -0
  67. /package/editing-history/{2026-0313-2216-validate-struct-type-arg-arity.md → 2026-03-13-2216-validate-struct-type-arg-arity.md} +0 -0
  68. /package/editing-history/{2026-0316-2353-runtime-boundary-cleanup.md → 2026-03-16-2353-runtime-boundary-cleanup.md} +0 -0
  69. /package/editing-history/{2026-0317-0150-runtime-boundary-lookup-cleanup.md → 2026-03-17-0150-runtime-boundary-lookup-cleanup.md} +0 -0
  70. /package/editing-history/{2026-0320-0116-json-builtins-and-runtime-docs.md → 2026-03-20-0116-json-builtins-and-runtime-docs.md} +0 -0
  71. /package/editing-history/{2026-0326-2013-docs-frontmatter-and-module-search.md → 2026-03-26-2013-docs-frontmatter-and-module-search.md} +0 -0
  72. /package/editing-history/{2026-0412-1524-js-codegen-map-to-record.md → 2026-04-12-1524-js-codegen-map-to-record.md} +0 -0
  73. /package/editing-history/{2026-0412-1549-map-to-record-field-validation.md → 2026-04-12-1549-map-to-record-field-validation.md} +0 -0
  74. /package/editing-history/{2026-0413-1600-tuple-to-enum-rewrite.md → 2026-04-13-1600-tuple-to-enum-rewrite.md} +0 -0
  75. /package/editing-history/{2026-0413-2309-typeslot-enum-compile-safety.md → 2026-04-13-2309-typeslot-enum-compile-safety.md} +0 -0
  76. /package/editing-history/{2026-0414-1500-loose-record-syntax.md → 2026-04-14-1500-loose-record-syntax.md} +0 -0
  77. /package/editing-history/{2026-0414-2259-bidir-type-check-refactor.md → 2026-04-14-2259-bidir-type-check-refactor.md} +0 -0
  78. /package/editing-history/{2026-0415-0120-match-syntax-exhaustiveness.md → 2026-04-15-0120-match-syntax-exhaustiveness.md} +0 -0
  79. /package/editing-history/{202604151211-record-nth-optimization.md → 2026-04-15-1211-record-nth-optimization.md} +0 -0
  80. /package/editing-history/{20260416-1936-predicate-narrowing-expansion.md → 2026-04-16-1936-predicate-narrowing-expansion.md} +0 -0
  81. /package/editing-history/{202604170132-monomorphize-map-filter.md → 2026-04-17-0132-monomorphize-map-filter.md} +0 -0
  82. /package/editing-history/{202604170135-monomorphize-includes-reverse.md → 2026-04-17-0135-monomorphize-includes-reverse.md} +0 -0
  83. /package/editing-history/{202604170140-fold-type-predicates.md → 2026-04-17-0140-fold-type-predicates.md} +0 -0
  84. /package/editing-history/{202604170154-generic-dispatch-records-tuples.md → 2026-04-17-0154-generic-dispatch-records-tuples.md} +0 -0
  85. /package/editing-history/{202604170520-simplify-generic-defns-via-method-dispatch.md → 2026-04-17-0520-simplify-generic-defns-via-method-dispatch.md} +0 -0
  86. /package/editing-history/{202605210055-tree-show-cr-config-and-edit-cleanup.md → 2026-05-21-0055-tree-show-cr-config-and-edit-cleanup.md} +0 -0
  87. /package/editing-history/{202605312052-macro-schema-roundtrip-and-weak-types.md → 2026-05-31-2052-macro-schema-roundtrip-and-weak-types.md} +0 -0
  88. /package/editing-history/{202605312105-map-generic-weak-types-followup.md → 2026-05-31-2105-map-generic-weak-types-followup.md} +0 -0
  89. /package/editing-history/{2026-0601-0003-update-callback-field-specialization.md → 2026-06-01-0003-update-callback-field-specialization.md} +0 -0
  90. /package/editing-history/{2026-0601-2317-data-definition-where-bounds.md → 2026-06-01-2317-data-definition-where-bounds.md} +0 -0
  91. /package/editing-history/{2026-0602-0114-data-definition-where-macro-followup.md → 2026-06-02-0114-data-definition-where-macro-followup.md} +0 -0
  92. /package/editing-history/{2026-0603-check-md-edn-errors.md → 2026-06-03-0000-check-md-edn-errors.md} +0 -0
  93. /package/editing-history/{2026-0603-1600-check-md-entry-modules.md → 2026-06-03-1600-check-md-entry-modules.md} +0 -0
  94. /package/editing-history/{2026-0604-check-md-app-main-init.md → 2026-06-04-0000-check-md-app-main-init.md} +0 -0
  95. /package/editing-history/{202606042218-compiled-executable-runtime-backfill.md → 2026-06-04-2218-compiled-executable-runtime-backfill.md} +0 -0
  96. /package/editing-history/{2026-0609-with-type-slot-scoped-binding.md → 2026-06-09-0000-with-type-slot-scoped-binding.md} +0 -0
  97. /package/editing-history/{2026-0609-1241-remove-bind-type.md → 2026-06-09-1241-remove-bind-type.md} +0 -0
  98. /package/editing-history/{2026-0609-1800-core-effect-tags.md → 2026-06-09-1800-core-effect-tags.md} +0 -0
  99. /package/editing-history/{2026-0610-1200-get-def-doc-schema-builtin.md → 2026-06-10-1200-get-def-doc-schema-builtin.md} +0 -0
  100. /package/editing-history/{2026-0615-1500-effects-graph-mvp.md → 2026-06-15-1500-effects-graph-mvp.md} +0 -0
  101. /package/editing-history/{202606161700-effects-graph-ste-tree.md → 2026-06-16-1700-effects-graph-ste-tree.md} +0 -0
  102. /package/editing-history/{2025-0412-1453-map-to-record-rewrite.md → archived/2025-04-12-1453-map-to-record-rewrite.md} +0 -0
  103. /package/editing-history/{202504160117-wasm-codegen-and-catalog-update.md → archived/2025-04-16-0117-wasm-codegen-and-catalog-update.md} +0 -0
  104. /package/editing-history/{202507160207-wasm-encoder-migration.md → archived/2025-07-16-0207-wasm-encoder-migration.md} +0 -0
  105. /package/editing-history/{202507161633-wasm-data-structures.md → archived/2025-07-16-1633-wasm-data-structures.md} +0 -0
  106. /package/editing-history/{2026-0213-1926-docs-tests-followup.md → archived/2026-02-13-1926-docs-tests-followup.md} +0 -0
  107. /package/editing-history/{2026-0216-2128-docs-smoke-and-trait-errors.md → archived/2026-02-16-2128-docs-smoke-and-trait-errors.md} +0 -0
  108. /package/editing-history/{2026-0225-1234-watch-mode-default-once.md → archived/2026-02-25-1234-watch-mode-default-once.md} +0 -0
  109. /package/editing-history/{2026-0307-1302-calcit-agent-docs-update.md → archived/2026-03-07-1302-calcit-agent-docs-update.md} +0 -0
  110. /package/editing-history/{2026-0309-1819-add-test-fail-script.md → archived/2026-03-09-1819-add-test-fail-script.md} +0 -0
  111. /package/editing-history/{2026-0309-1944-split-type-fail-tests.md → archived/2026-03-09-1944-split-type-fail-tests.md} +0 -0
  112. /package/editing-history/{2026-0316-1449-profiling-tools-reorg.md → archived/2026-03-16-1449-profiling-tools-reorg.md} +0 -0
  113. /package/editing-history/{2026-0317-2026-afternoon-runtime-boundary-optimization-summary.md → archived/2026-03-17-2026-afternoon-runtime-boundary-optimization-summary.md} +0 -0
  114. /package/editing-history/{2026-0318-1802-tips-level-and-overwrite-schema-preservation.md → archived/2026-03-18-1802-tips-level-and-overwrite-schema-preservation.md} +0 -0
  115. /package/editing-history/{2026-0320-1229-query-window-3-with-parent-preview.md → archived/2026-03-20-1229-query-window-3-with-parent-preview.md} +0 -0
  116. /package/editing-history/{2026-0323-1137-command-echo-tool-output-cleanup.md → archived/2026-03-23-1137-command-echo-tool-output-cleanup.md} +0 -0
  117. /package/editing-history/{2026-0410-0011-snapshot-empty-version-pipe-marker.md → archived/2026-04-10-0011-snapshot-empty-version-pipe-marker.md} +0 -0
  118. /package/editing-history/{202604160131-wasm-math-and-test-integration.md → archived/2026-04-16-0131-wasm-math-and-test-integration.md} +0 -0
  119. /package/editing-history/{202604161507-wasm-data-structures-and-rfc-rename.md → archived/2026-04-16-1507-wasm-data-structures-and-rfc-rename.md} +0 -0
  120. /package/editing-history/{202604161520-wasm-bitwise-and-match.md → archived/2026-04-16-1520-wasm-bitwise-and-match.md} +0 -0
  121. /package/editing-history/{202604161542-wasm-cross-ns-host-imports.md → archived/2026-04-16-1542-wasm-cross-ns-host-imports.md} +0 -0
  122. /package/editing-history/{20260417-0026-wasm-rest-args.md → archived/2026-04-17-0026-wasm-rest-args.md} +0 -0
  123. /package/editing-history/{202604170048-wasm-type-of.md → archived/2026-04-17-0048-wasm-type-of.md} +0 -0
  124. /package/editing-history/{202604170051-wasm-derived-predicates.md → archived/2026-04-17-0051-wasm-derived-predicates.md} +0 -0
  125. /package/editing-history/{202604172316-wasm-do-println-fixes.md → archived/2026-04-17-2316-wasm-do-println-fixes.md} +0 -0
  126. /package/editing-history/{202604181208-split-emit-wasm-and-bump-version.md → archived/2026-04-18-1208-split-emit-wasm-and-bump-version.md} +0 -0
  127. /package/editing-history/{202604181430-wasm-list-match-and-method-dispatch.md → archived/2026-04-18-1430-wasm-list-match-and-method-dispatch.md} +0 -0
  128. /package/editing-history/{202604182041-cr-wasm-split-and-runtime-stability.md → archived/2026-04-18-2041-cr-wasm-split-and-runtime-stability.md} +0 -0
  129. /package/editing-history/{202604182045-v0.12.23-ci-wasm-fix.md → archived/2026-04-18-2045-v0.12.23-ci-wasm-fix.md} +0 -0
  130. /package/editing-history/{202604211818-wasm-string-ops-v2.md → archived/2026-04-21-1818-wasm-string-ops-v2.md} +0 -0
  131. /package/editing-history/{202604212332-split-emit-wasm.md → archived/2026-04-21-2332-split-emit-wasm.md} +0 -0
  132. /package/editing-history/{2026-0422-0114-wasm-hof-intercepts-and-set-intersection.md → archived/2026-04-22-0114-wasm-hof-intercepts-and-set-intersection.md} +0 -0
  133. /package/editing-history/{2026-0422-0136-wasm-enum-tuple-bool-str-fixes.md → archived/2026-04-22-0136-wasm-enum-tuple-bool-str-fixes.md} +0 -0
  134. /package/editing-history/{202604221340-wasm-map-diff-new-and-let-intercept.md → archived/2026-04-22-1340-wasm-map-diff-new-and-let-intercept.md} +0 -0
  135. /package/editing-history/{202604231419-v0.12.26-wasm-bisection-fixes.md → archived/2026-04-23-1419-v0.12.26-wasm-bisection-fixes.md} +0 -0
  136. /package/editing-history/{202604231645-release-conventions.md → archived/2026-04-23-1645-release-conventions.md} +0 -0
  137. /package/editing-history/{202604251940-wasm-suite-multi-module-entry.md → archived/2026-04-25-1940-wasm-suite-multi-module-entry.md} +0 -0
  138. /package/editing-history/{202604252003-wasm-method-includes-string-and-set-refactor.md → archived/2026-04-25-2003-wasm-method-includes-string-and-set-refactor.md} +0 -0
  139. /package/editing-history/{202604252010-wasm-suite-add-fn-lens-edn.md → archived/2026-04-25-2010-wasm-suite-add-fn-lens-edn.md} +0 -0
  140. /package/editing-history/{202604252051-display-by.md → archived/2026-04-25-2051-display-by.md} +0 -0
  141. /package/editing-history/{202604281728-fix-gensym-stable.md → archived/2026-04-28-1728-fix-gensym-stable.md} +0 -0
  142. /package/editing-history/{202604291400-fix-bind-type-precompile.md → archived/2026-04-29-1400-fix-bind-type-precompile.md} +0 -0
  143. /package/editing-history/{2026-0526-0957-match-docs-check-md.md → archived/2026-05-26-0957-match-docs-check-md.md} +0 -0
  144. /package/editing-history/{202605312059-ci-docs-test-and-fn-helper-tightening.md → archived/2026-05-31-2059-ci-docs-test-and-fn-helper-tightening.md} +0 -0
  145. /package/editing-history/{2026-0601-0005-release-0.12.36.md → archived/2026-06-01-0005-release-0.12.36.md} +0 -0
  146. /package/editing-history/{2026-0601-2230-enum-struct-payload-docs.md → archived/2026-06-01-2230-enum-struct-payload-docs.md} +0 -0
  147. /package/editing-history/{2026-0603-1620-release-0.12.38.md → archived/2026-06-03-1620-release-0.12.38.md} +0 -0
  148. /package/editing-history/{2026-0604-release-0.12.39.md → archived/2026-06-04-0000-release-0.12.39.md} +0 -0
  149. /package/editing-history/{202606042230-release-0.12.40.md → archived/2026-06-04-2230-release-0.12.40.md} +0 -0
  150. /package/editing-history/{202606121525-weak-types-dots-format.md → archived/2026-06-12-1525-weak-types-dots-format.md} +0 -0
  151. /package/editing-history/{202606131200_primitive_schema_tags.md → archived/2026-06-13-1200-primitive_schema_tags.md} +0 -0
  152. /package/editing-history/{202606201142-ts-declaration-d-mts.md → archived/2026-06-20-1142-ts-declaration-d-mts.md} +0 -0
Binary file
@@ -0,0 +1,569 @@
1
+ # RFC: 语义化树形导航与编辑
2
+
3
+ 状态:Draft
4
+ 日期:2026-07-06
5
+ 关联:`cr tree search-replace`、`cr tree show`、`cr query search`、`03-18-query-def-tree-show-chunked-display-plan.md`
6
+
7
+ ---
8
+
9
+ ## 1. 概要
10
+
11
+ 当前 `cr tree` 系列编辑命令在定位子表达式时依赖纯数字点号路径(如 `-p '0.3.2.1'`)。对于人类而言手动数坐标已经不方便,对于 LLM 而言更是结构性难题——LLM 在精确计数方面的可靠性与人类手动数行号相当。
12
+
13
+ 本 RFC 提出 **四层互补方案**,从近到远逐步提升编辑体验:
14
+
15
+ | 层级 | 方案 | 技术路径 |
16
+ | ------ | ------------------- | ------------------------------------------------------------------------------------- |
17
+ | **L1** | 展示时自动标注路径 | `tree show` 输出中为每个 list 表达式末尾追加 `; "previous node path: 1.2.3"` 注释节点 |
18
+ | **L2** | 多候选交互确认 | `search-replace` 多匹配时列出候选而非报错 |
19
+ | **L3** | 锚点 + 相对偏移搜索 | `search-replace --at ... --child N` 先定位父节点再做子节点替换 |
20
+ | **L4** | 结构化查询语言 | 语义路径表达式:`path` 开头,裸叶子 + `heading` + `nth` 三步导航 |
21
+
22
+ 核心设计原则:
23
+
24
+ - **所有查询表达式均使用 Cirru 语法**(无 Lisp 风格外层括号)
25
+ - **路径表达式中叶子字面量直接表示严格匹配**,表达式取首 token 作为语义算子(`heading` / `nth`)
26
+ - **路径注释使用 `; "previous node path: 1.2.3"` 格式**,作为 list 末尾的注释节点追加,不改变已有子节点索引
27
+ - **锚点使用已有 `calcit.core/noted` macro**,格式为 `noted @anchor:<name> expr`
28
+
29
+ ---
30
+
31
+ ## 2. 动机
32
+
33
+ ### 2.1 现状问题
34
+
35
+ 当前 LLM 编辑 Calcit 代码的标准工作流:
36
+
37
+ ```
38
+ 1. cr tree show 'app.main/main!' → 查看代码结构
39
+ 2. LLM 自己数目标表达式的坐标 → 容易数错
40
+ 3. cr tree replace 'app.main/main!' -p '...' → 可能用错路径
41
+ 4. 出错后重新数、重新试 → 迭代成本高
42
+ ```
43
+
44
+ 或者用 `search-replace`:
45
+
46
+ ```
47
+ 1. cr tree search-replace 'app.main/main!' --pattern 'old-expr' ...
48
+ → 报错:"Found 3 matches"
49
+ 2. LLM 需要切回 tree show 手动辨别是哪个匹配
50
+ 3. 回到手动数坐标模式
51
+ ```
52
+
53
+ ### 2.2 目标工作流
54
+
55
+ ```
56
+ 1. cr tree show 'app.main/main!' → 输出自动带路径注释
57
+ 2. LLM 直接从注释中复制路径 → 不需要数
58
+ 3. cr tree replace 'app.main/main!' -p '复制来的路径' ...
59
+ → 一次成功
60
+ ```
61
+
62
+ 或者在多匹配场景:
63
+
64
+ ```
65
+ 1. cr tree search-replace ... --pattern '...'
66
+ → 列出 3 个候选(带路径和上下文)
67
+ 2. LLM 用 --pick 0 或 --path 指定
68
+ → 一次成功
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 3. L1:展示时自动标注路径
74
+
75
+ ### 3.1 方案
76
+
77
+ 在 `cr tree show` 的输出中,为每个 **list 节点**的末尾追加一条路径注释。注释放在末尾而非开头,避免插入前导节点导致已有子节点索引偏移。格式为 Cirru 行注释语法:
78
+
79
+ ```cirru
80
+ defn add (a b)
81
+ &+ a b (; "previous node path: 3.2")
82
+ ; "previous node path: 3"
83
+ ```
84
+
85
+ 实现方式:**在 AST 层面操作**,为每个 `Cirru::List` 的 children 末尾 `push` 一个 comment 节点——即 `Cirru::List`,其首子节点为 `Cirru::Leaf(";")`,后续子节点为注释内容(如 `Cirru::Leaf("previous node path: 1.2.3")`)。格式化时该 list 自然渲染为行注释 `; "previous node path: 1.2.3"`。
86
+
87
+ ### 3.2 命令
88
+
89
+ ```bash
90
+ # 默认行为:纯代码展示,无路径注释
91
+ cr tree show 'app.main/main!'
92
+
93
+ # 开启路径标注(所有嵌套层级末尾标注路径)
94
+ cr tree show 'app.main/main!' --path-annotations
95
+ ```
96
+
97
+ 当展示的节点包含较多子节点(如超过阈值)时,在输出底部提示可用选项:
98
+
99
+ ```
100
+ Tip: This node has 15 children. Use --path-annotations to annotate each child
101
+ with its path index for easier editing. Use --chunked to split large
102
+ subtrees into fragments.
103
+ ```
104
+
105
+ ### 3.3 输出示例
106
+
107
+ 对于如下源码:
108
+
109
+ ```cirru
110
+ defn process (xs)
111
+ let
112
+ ys $ map xs inc
113
+ zs $ filter ys even?
114
+ foldl zs 0 add
115
+ ```
116
+
117
+ 默认 `cr tree show` 输出(无标注,保持旧行为):
118
+
119
+ ```cirru
120
+ defn process (xs)
121
+ let
122
+ ys $ map xs inc
123
+ zs $ filter ys even?
124
+ foldl zs 0 add
125
+ ```
126
+
127
+ `--path-annotations` 时(每个嵌套 list 末尾都追加路径注释):
128
+
129
+ ```cirru
130
+ defn process (xs)
131
+ let
132
+ ys $ map xs inc
133
+ ; "previous node path: 3.0.0.1.2"
134
+ ; "previous node path: 3.0.0"
135
+ zs $ filter ys even?
136
+ ; "previous node path: 3.0.1.1.2"
137
+ ; "previous node path: 3.0.1"
138
+ foldl zs 0 add
139
+ ; "previous node path: 3.2"
140
+ ; "previous node path: 3.3"
141
+ ```
142
+
143
+ ### 3.4 实现要点
144
+
145
+ - **AST 层面操作**:调用 `children.push(Cirru::List([Cirru::Leaf(";"), Cirru::Leaf(path_string)]))` 追加注释节点,而非字符串拼接
146
+ - 注释节点格式:`Cirru::List` 首子节点为 `Cirru::Leaf(";")`,后续为内容叶子(如 `"previous node path: 1.2.3"`),渲染为 `; "previous node path: 1.2.3"`
147
+ - `--path-annotations`:递归为所有嵌套 list 末尾追加注释(flag,无参数)
148
+ - 默认不追加任何注释节点,保持旧行为
149
+ - 当展示的节点子节点较多时,底部输出 tip 提示可开启 `--path-annotations` 或 `--chunked`
150
+ - 注释中的路径数字为相对于当前 `-p` 定位 path 的索引
151
+ - 使用 dimmed 颜色渲染注释行,不干扰代码阅读
152
+ - 根节点的 path 为空字符串, 不用显示
153
+ - **末尾追加不改变索引**:注释节点是最后一个 child,不影响已有子节点的相对位置
154
+
155
+ ### 3.5 与 chunked display 的关系
156
+
157
+ `--path-annotations` 与 `--chunked` 可组合使用,两者独立运作:
158
+
159
+ - `--chunked`:表达式过大时拆分展示,便于人类阅读整体结构
160
+ - `--path-annotations`:在 chunk 内部或普通展示中标注每个节点的路径坐标
161
+
162
+ 同时启用时:先分片,再在每个 fragment 内部标注路径注释。默认两个都不启用。
163
+
164
+ ---
165
+
166
+ ## 4. L2:多候选交互确认
167
+
168
+ ### 4.1 方案
169
+
170
+ 当 `search-replace` 遇到多个匹配时,**不直接报错退出**,而是:
171
+
172
+ 1. 列出所有候选匹配(带路径、上下文预览、序号)
173
+ 2. 允许用户/LLM 通过 `--pick <index>` 或 `--path <path>` 精确指定
174
+ 3. 默认行为(无 `--pick` 也无 `--path`)保持不变:报错并要求指定
175
+
176
+ ### 4.2 命令
177
+
178
+ ```bash
179
+ # 多匹配时列出候选
180
+ cr tree search-replace 'app.main/main!' \
181
+ --pattern 'old-name' \
182
+ --code 'new-name'
183
+
184
+ # 输出候选列表后,选择第 2 个候选
185
+ cr tree search-replace 'app.main/main!' \
186
+ --pattern 'old-name' \
187
+ --code 'new-name' \
188
+ --pick 2
189
+
190
+ # 或直接用路径指定
191
+ cr tree search-replace 'app.main/main!' \
192
+ --pattern 'old-name' \
193
+ --code 'new-name' \
194
+ --at '1.3.0'
195
+ ```
196
+
197
+ ### 4.3 候选展示格式
198
+
199
+ 当匹配数 > 1 且未指定 `--pick`/`--at` 时:
200
+
201
+ ```
202
+ Found 3 matches for pattern "old-name":
203
+
204
+ [0] Path [1.3.0]: "old-name"
205
+ Context: defn update $ old-name new-name
206
+ Command: cr tree search-replace 'app.main/main!' --pattern 'old-name' ... --pick 0
207
+
208
+ [1] Path [2.5.2]: "old-name"
209
+ Context: let $ old-name x $ do-something old-name
210
+ Command: cr tree search-replace 'app.main/main!' --pattern 'old-name' ... --pick 1
211
+
212
+ [2] Path [3.0.1]: "old-name"
213
+ Context: cond $ = old-name nil $ handle-nil old-name
214
+ Command: cr tree search-replace 'app.main/main!' --pattern 'old-name' ... --pick 2
215
+
216
+ Use --pick <index> to select a candidate, or --at '<path>' to specify directly.
217
+ ```
218
+
219
+ ### 4.4 实现要点
220
+
221
+ - `--pick` 和 `--at` 互斥,同时指定时报错
222
+ - 候选按路径深度优先排序(与当前遍历顺序一致)
223
+ - `--pick` 从 0 开始
224
+ - 最多展示 20 个候选,超出部分显示 `... and N more`
225
+ - 该行为同样适用于 `search-replace` 的 list-node 匹配(非仅 leaf)
226
+
227
+ ---
228
+
229
+ ## 5. L3:锚点搜索替换(`search-replace --at`)
230
+
231
+ ### 5.1 方案
232
+
233
+ 扩展 `search-replace`,允许先通过内容匹配定位一个**父节点(锚点)**,然后在锚点的第 N 个子节点中做替换。这样 LLM 只需描述"在哪个定义/哪个 let 里面改",不需要知道锚点的全局坐标。
234
+
235
+ ### 5.2 命令
236
+
237
+ ```bash
238
+ # 基本形式:在匹配 anchor 的节点的第 N 个子节点中做搜索替换
239
+ cr tree search-replace 'app.main/main!' \
240
+ --at 'defn add' \
241
+ --child 2 \
242
+ --pattern 'old-call' \
243
+ --code 'new-call'
244
+
245
+ # 多层锚定:在 anchor 内的第 N 个子节点中再锚定
246
+ cr tree search-replace 'app.main/main!' \
247
+ --at 'let' \
248
+ --child 0 \
249
+ --at 'cond' \
250
+ --child 1 \
251
+ --pattern 'old-branch' \
252
+ --code 'new-branch'
253
+ ```
254
+
255
+ ### 5.3 语义
256
+
257
+ `--at` 与 `--child` 的语义:
258
+
259
+ - `--at <quoted-code>`:在当前范围内搜索匹配该内容的节点。相当于先做 `search-replace` 的匹配逻辑,**但不替换**。
260
+ - `--child <N>`:从匹配到的锚点进入第 N 个子节点,缩小搜索范围。
261
+
262
+ 组合效果:
263
+
264
+ ```
265
+ search-replace target --at A --child 0 --at B --child 1 --pattern P --code R
266
+ ```
267
+
268
+ 等价于:
269
+
270
+ 1. 在 target 中搜索匹配 A 的节点 → 锚点 a
271
+ 2. 取 a 的第 0 个子节点 → scope₁
272
+ 3. 在 scope₁ 中搜索匹配 B 的节点 → 锚点 b
273
+ 4. 取 b 的第 1 个子节点 → scope₂
274
+ 5. 在 scope₂ 中搜索匹配 P 的节点 → 替换为 R
275
+
276
+ ### 5.4 约束
277
+
278
+ - `--at` 在目标范围内**必须唯一匹配**,否则报错列出候选(沿用 L2 的交互逻辑)
279
+ - `--child` 索引从 0 开始
280
+ - 多个 `--at` / `--child` 按出现顺序链式执行
281
+ - `--at` 的参数使用与 L4 路径表达式相同的语义:裸叶子表示严格匹配叶子,表达式取首 token 作为算子(见 §6)
282
+
283
+ ---
284
+
285
+ ## 6. L4:结构化查询语言(Cirru Path Expression)
286
+
287
+ ### 6.1 设计目标
288
+
289
+ 提供一种**完全用 Cirru 语法书写**的语义路径表达式,替代纯数字坐标,让 LLM 和人类都能直观描述"我要编辑哪个节点"。
290
+
291
+ 核心设计:
292
+
293
+ - 表达式以 `path` 开头
294
+ - **叶子字面量直接表示严格匹配**:`x`、`|hello`、`42` 等裸叶子值表示"当前节点必须是这个叶子"
295
+ - **表达式取首 token 作为语义算子**:`heading`、`nth`
296
+ - 从左到右链式执行,每个选择器在上一个匹配结果上继续缩小范围
297
+
298
+ 选择器只有三种:裸叶子精确匹配叶子值,`heading` 按前缀匹配 list 节点,`nth` 按索引进入子节点。配合 L1 的路径标注(`--path-annotations`)显示各子节点索引,无需额外的搜索型选择器。
299
+
300
+ ### 6.2 选择器类型
301
+
302
+ #### 6.2.1 叶子严格匹配(裸字面量)
303
+
304
+ 叶子节点直接书写,表示"当前节点必须精确等于此值":
305
+
306
+ ```cirru
307
+ path defn add
308
+ ```
309
+
310
+ 语义:先匹配叶子 `defn`,再匹配叶子 `add`。等价于在 AST 中找连续两个叶子 `defn` `add` 的位置。
311
+
312
+ - 标识符:`x`、`defn`、`add`
313
+ - 字符串:`|hello`
314
+ - 数字:`42`
315
+ - tag:`:name`
316
+
317
+ #### 6.2.2 `heading` — 表达式前缀匹配
318
+
319
+ 唯一的 list 节点内容匹配选择器:
320
+
321
+ ```cirru
322
+ path
323
+ heading def {} :name |add
324
+ ```
325
+
326
+ 语义:匹配任何 **前 N 个子节点** 与给定模式一致的 list 节点,允许后面有更多子节点。当无多余子节点时等同于精确匹配。
327
+
328
+ 示例:
329
+
330
+ ```cirru
331
+ ; 匹配任意以 def 开头的表达式(def, defn, defrecord, defenum ...)
332
+ path
333
+ heading def
334
+
335
+ ; 匹配 defn add (a b) (&+ a b)——有 or 没有多余子节点都命中
336
+ path
337
+ heading defn add (a b)
338
+ &+ a b
339
+ ```
340
+
341
+ 嵌套表达式内的 `(a b)` 递归地用相同规则匹配。
342
+
343
+ #### 6.2.3 `nth` — 位置导航
344
+
345
+ ```cirru
346
+ path
347
+ heading defn add (a b)
348
+ &+ a b
349
+ nth 2
350
+ ```
351
+
352
+ 语义:匹配目标后,进入其第 2 个子节点。
353
+
354
+ - `nth N`:进入当前匹配节点的第 N 个子节点(从 0 计数)
355
+
356
+ ### 6.3 组合示例
357
+
358
+ 定位 add 函数的第一个 let 绑定:
359
+
360
+ ```cirru
361
+ path
362
+ heading def {} :name |add
363
+ nth 2
364
+ heading let
365
+ nth 0
366
+ ```
367
+
368
+ 等价于:
369
+
370
+ 1. 匹配任意 `def {} :name |add ...` 表达式 → 定位 add 函数
371
+ 2. 进入第 2 个子节点(body)
372
+ 3. 匹配以 `let` 开头的表达式
373
+ 4. 进入第 0 个子节点(bindings)
374
+
375
+ ### 6.4 完整语法规范
376
+
377
+ ```
378
+ path-expr = "path" selector*
379
+
380
+ selector = leaf-literal ; 叶子严格匹配
381
+ | list-selector ; 表达式语义选择器
382
+
383
+ list-selector = "heading" children ; 表达式前缀匹配(含精确匹配)
384
+ | "nth" integer ; 位置导航
385
+
386
+ children = (leaf-literal | nested-expr)*
387
+ nested-expr = "(" children ")" ; 在 Cirru 中即缩进嵌套的 list
388
+
389
+ leaf-literal = identifier | string-literal | number | tag
390
+ integer = /\d+/
391
+ ```
392
+
393
+ ### 6.5 使用场景
394
+
395
+ #### 场景 A:定位定义
396
+
397
+ ```bash
398
+ # 搜索 add 函数的 def,拿到路径
399
+ cr query path 'app.main' \
400
+ --selector 'path
401
+ heading def {} :name |add'
402
+
403
+ # 输出: 0 (def 的顶层索引)
404
+ ```
405
+
406
+ #### 场景 B:编辑深层子表达式
407
+
408
+ ```bash
409
+ # 在 add 函数的第一个 let 绑定中搜索并替换
410
+ cr tree search-replace 'app.main/main!' \
411
+ --path-selector 'path
412
+ heading def {} :name |add
413
+ nth 2
414
+ heading let
415
+ nth 0' \
416
+ --pattern 'old-var' \
417
+ --code 'new-var'
418
+ ```
419
+
420
+ #### 场景 C:批量脚本
421
+
422
+ ```bash
423
+ # 获取路径后用于后续编辑
424
+ PATH=$(cr query path 'app.main' --selector 'path heading def {} :name |init-fn $ nth 2')
425
+ cr tree replace 'app.main/main!' -p "$PATH" --code '...'
426
+ ```
427
+
428
+ ### 6.6 与现有路径的互操作
429
+
430
+ - `cr query path` 输出标准数字路径(如 `1.3.0`),可直接用于 `-p`
431
+ - `--path-selector` 是 `-p` 的超集替代,内部先解析为数字路径再执行
432
+ - 解析失败时给出明确错误信息(哪一步匹配失败、已匹配到的范围、剩余选择器是什么)
433
+
434
+ ### 6.7 选择器语义对比
435
+
436
+ | 选择器 | 匹配方式 | 示例 |
437
+ | ------------- | ------------------------------- | ---------------------- |
438
+ | 裸叶子 `x` | 当前节点必须是叶子 `x` | `path defn add` |
439
+ | `heading ...` | 当前 list 的前 N 个子节点匹配 | `heading def {} :name` |
440
+ | `nth N` | 导航到当前 list 的第 N 个子节点 | `nth 2` |
441
+
442
+ ---
443
+
444
+ ## 7. 锚点注释(Source Annotations)
445
+
446
+ ### 7.1 方案
447
+
448
+ 使用已有的 `calcit.core/noted` macro 在源码中定义**命名锚点**,作为编辑时的稳定引用:
449
+
450
+ ```cirru
451
+ defn main! ()
452
+ noted @anchor:init-state
453
+ let
454
+ state $ load-initial-state
455
+ ; ...
456
+ ```
457
+
458
+ `noted` 是已有 macro,接受 tag 和表达式两个参数。`@anchor:<name>` 作为 tag 标记该表达式,`noted` 在运行时透传表达式的值,锚点信息不参与运行时语义。
459
+
460
+ 锚点附着在表达式上,表达式被移动/复制时锚点跟随。`cr query anchors` 遍历 AST 中所有 `noted` 调用,提取 `@anchor:` 前缀的 tag 及其路径。
461
+
462
+ ### 7.2 命令
463
+
464
+ ```bash
465
+ # 列出所有锚点
466
+ cr query anchors 'app.main'
467
+
468
+ # 输出:
469
+ # @anchor:init-state → app.main/main! [1]
470
+ # @anchor:render-loop → app.main/main! [4.2]
471
+
472
+ # 用锚点定位
473
+ cr tree show 'app.main/main!' --anchor 'init-state'
474
+
475
+ # 用锚点编辑:在锚点后插入
476
+ cr tree insert-after 'app.main/main!' \
477
+ --anchor 'init-state' \
478
+ --code 'println |loaded'
479
+ ```
480
+
481
+ ### 7.3 约束
482
+
483
+ - 锚点 tag 以 `@anchor:` 前缀标识,在同一 namespace 内必须唯一(不唯一时报错)
484
+ - `noted` 在运行时透传表达式值,锚点不参与运行时语义
485
+ - 锚点跟随表达式移动:`tree delete` / `tree insert` 等操作后,锚点随 `noted` 节点自然位移
486
+ - `cr query anchors` 遍历 AST 中所有 `noted` 调用,提取路径和名称
487
+
488
+ ### 7.4 锚点与路径的对比
489
+
490
+ | 特性 | 路径 (`-p '1.3.0'`) | 锚点 (`--anchor 'init-state'`) |
491
+ | ---------- | ---------------------- | ------------------------------ |
492
+ | 稳定性 | 编辑后可能失效 | 跟随代码移动,基本稳定 |
493
+ | 可读性 | 无意义数字 | 语义化名称 |
494
+ | 设置成本 | 零(自动标注) | 需要手动添加注释 |
495
+ | LLM 友好度 | 低(需要数坐标或复制) | 高(语义化引用) |
496
+
497
+ ---
498
+
499
+ ## 8. 实施路线
500
+
501
+ ### Phase 1(最小可行):L1 + L2
502
+
503
+ - `tree show --path-annotations`:opt-in 标志,开启后所有嵌套层级标注路径
504
+ - 大节点底部 tip 提示可开启标注或分片
505
+ - `search-replace` 多匹配候选展示(不改默认行为,仅在匹配 > 1 时改进输出)
506
+
507
+ **预计工作量**:~2-3 天
508
+ **收益**:LLM 可直接从 show 输出复制路径,多匹配时给出可操作建议
509
+
510
+ ### Phase 2:L3 锚点搜索
511
+
512
+ - `search-replace --at` / `--child` 链式锚定
513
+ - 将 `search-replace` 从仅 leaf 匹配扩展到 list-node 匹配
514
+
515
+ **预计工作量**:~3-5 天
516
+ **收益**:LLM 可用语义描述定位,不再依赖数字路径
517
+
518
+ ### Phase 3:L4 结构化查询语言
519
+
520
+ - `path` 选择器解析器
521
+ - `cr query path` 命令
522
+ - `--path-selector` 替代 `-p` 的编辑命令集成
523
+
524
+ **预计工作量**:~5-7 天
525
+ **收益**:完整的语义化树形查询能力
526
+
527
+ ### Phase 4:锚点注释
528
+
529
+ - `noted @anchor:<name>` 的识别与提取
530
+ - `cr query anchors` 命令
531
+ - `--anchor` 参数集成到编辑命令
532
+
533
+ **预计工作量**:~4-6 天
534
+ **收益**:跨编辑会话的稳定引用
535
+
536
+ ---
537
+
538
+ ## 9. 兼容性
539
+
540
+ - 所有新参数均为 **opt-in**,现有行为完全保留
541
+ - `--path-annotations` 是 flag,默认关闭,传即开启
542
+ - `--chunked` 默认关闭,需手动开启
543
+ - `--pick` 和 `--path-selector` 与现有 `-p` 互斥
544
+ - 锚点使用已有 `noted` macro,不引入新语法,对现有解析无影响
545
+
546
+ ---
547
+
548
+ ## 10. 开放问题
549
+
550
+ 1. **`--path-annotations` 是否应该默认开启?**
551
+ - 关闭(当前决定):保持旧行为,大节点时底部 tip 引导开启
552
+ - 默认开启:对 LLM 更友好,但改变默认输出
553
+ - 建议默认关闭 + tip 引导,后续根据使用反馈决定是否改为默认开启
554
+
555
+ 2. **`heading` 是否总是够用?**
556
+ - `heading` 匹配前 N 个子节点,无多余子节点时等同于精确匹配
557
+ - 裸叶子处理单值精确匹配
558
+ - 不提供独立的 `exact` 选择器——链式导航模型中没有它的位置
559
+ - 后续评估是否需要 `ends-with`、`contains` 等变体
560
+
561
+ 3. **是否需要支持通配符叶子?**
562
+ - 例:用 `_` 匹配任意单个叶子,`...` 匹配任意剩余子节点
563
+ - `path heading def _ :name` 匹配任意名称的 def
564
+ - 当前暂不支持,可作为后续增强
565
+
566
+ 4. **锚点应缓存还是每次遍历 AST?**
567
+ - 缓存:`cr query anchors` 首次解析后缓存到 snapshot 元数据,编辑后失效重算
568
+ - 实时遍历:更简单,无需维护缓存一致性
569
+ - 由于 `noted` 节点在 AST 中自然存在,遍历成本可控,建议先实时遍历