From 7ecfe2e7568369121bb0fce5f12c35c03c6c3c0d Mon Sep 17 00:00:00 2001 From: Yao Jingxi <23722032@bjtu.edu.cn> Date: Sat, 14 Nov 2026 00:51:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor(core):=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=A4=BE=E5=8C=BA=E5=91=BD=E4=BB=A4=E3=80=81wasm=20=E5=85=A5?= =?UTF-8?q?=E5=8F=A3=E5=92=8C=E6=9C=AA=E4=BD=BF=E7=94=A8=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 community.discourse.* 七个命令、实现和 fixture,桌面端已不再调用 - lithe-core-rules 去掉 wasm 入口和 cdylib,只作为 rlib 链接进 Core - lithe-core 删除未使用的 reqwest、rsa、sha1、shell-words、toml_edit 依赖,去掉 num-bigint-dig 专用 profile - 修复工作区编译警告:host_failure 显式处理 BACKEND_EXITED(错误码保留,仍映射为 plugin.host.failed)、限定 forward_slash_path 的编译条件、收窄 network 重导出 - 新增 unparseable_requests_fail_without_an_id 测试 --- rust/Cargo.lock | 529 +--------- rust/Cargo.toml | 6 - rust/contracts/application-boundary.md | 1 - rust/contracts/rust-core-api.md | 46 +- .../fixtures/community/discourse-auth-v1.json | 34 - rust/lithe-core-rules/Cargo.toml | 6 +- rust/lithe-core-rules/src/dispatch.rs | 41 +- rust/lithe-core-rules/src/error.rs | 13 +- rust/lithe-core-rules/src/lib.rs | 15 +- rust/lithe-core-rules/src/wasm.rs | 65 -- .../tests/modifier_gesture_fixture.rs | 43 +- .../tests/visibility_fixture.rs | 21 +- .../tests/workbench_state_fixture.rs | 35 +- rust/lithe-core/Cargo.toml | 7 +- rust/lithe-core/src/community/discourse.rs | 926 ------------------ rust/lithe-core/src/community/mod.rs | 10 - rust/lithe-core/src/git/workspace_status.rs | 1 - rust/lithe-core/src/lib.rs | 1 - .../src/lsp/interface/plugin_function.rs | 1 + rust/lithe-core/src/network/mod.rs | 5 +- rust/lithe-core/src/protocol/command.rs | 36 - rust/lithe-core/src/runtime/dispatcher.rs | 127 --- rust/lithe-core/src/tests/protocol.rs | 8 + rust/lithe-git-host/src/configuration.rs | 1 + 24 files changed, 82 insertions(+), 1896 deletions(-) delete mode 100644 rust/fixtures/community/discourse-auth-v1.json delete mode 100644 rust/lithe-core-rules/src/wasm.rs delete mode 100644 rust/lithe-core/src/community/discourse.rs delete mode 100644 rust/lithe-core/src/community/mod.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 68289797..2b1ed0e9 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -117,12 +117,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - [[package]] name = "bitflags" version = "2.13.1" @@ -185,23 +179,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" - -[[package]] -name = "chacha20" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", -] - [[package]] name = "chrono" version = "0.4.45" @@ -232,12 +209,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -259,15 +230,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.5.0" @@ -323,17 +285,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - [[package]] name = "derive_arbitrary" version = "1.4.2" @@ -352,7 +303,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "const-oid", "crypto-common", ] @@ -430,7 +380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -585,10 +535,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] @@ -598,11 +546,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi", - "rand_core 0.10.1", - "wasm-bindgen", ] [[package]] @@ -700,22 +645,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.27.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - [[package]] name = "hyper-util" version = "0.1.20" @@ -923,27 +852,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - [[package]] name = "libc" version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - [[package]] name = "litemap" version = "0.8.2" @@ -976,19 +890,14 @@ dependencies = [ "lithe-ide-host", "lithe-remote", "quick-xml", - "rand 0.8.7", + "rand", "regex", - "reqwest", - "rsa", "serde", "serde_json", "serde_yaml_ng", - "sha1", "sha2", - "shell-words", "similar", "toml", - "toml_edit", "unicode-normalization", "url", "zip", @@ -1007,10 +916,10 @@ name = "lithe-git-host" version = "0.1.0" dependencies = [ "libc", - "rand 0.8.7", + "rand", "serde", "serde_json", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1055,12 +964,6 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "maplit" version = "1.0.2" @@ -1114,7 +1017,7 @@ checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "wasi", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1129,41 +1032,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.7", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-integer" -version = "0.1.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" -dependencies = [ - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1171,7 +1039,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1234,15 +1101,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -1294,27 +1152,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - [[package]] name = "potential_utf" version = "0.1.5" @@ -1357,62 +1194,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quinn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" -dependencies = [ - "bytes", - "getrandom 0.4.3", - "lru-slab", - "rand 0.10.2", - "rand_pcg", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.61.2", -] - [[package]] name = "quote" version = "1.0.47" @@ -1436,18 +1217,7 @@ checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" -dependencies = [ - "chacha20", - "getrandom 0.4.3", - "rand_core 0.10.1", + "rand_core", ] [[package]] @@ -1457,7 +1227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -1469,21 +1239,6 @@ dependencies = [ "getrandom 0.2.17", ] -[[package]] -name = "rand_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" - -[[package]] -name = "rand_pcg" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" -dependencies = [ - "rand_core 0.10.1", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1550,28 +1305,21 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", - "futures-channel", "futures-core", - "futures-util", "http", "http-body", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", "tower", "tower-http", "tower-service", @@ -1579,21 +1327,6 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted", - "windows-sys 0.52.0", ] [[package]] @@ -1617,67 +1350,12 @@ dependencies = [ "uuid", ] -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rustc-hash" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" -[[package]] -name = "rustls" -version = "0.23.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pki-types" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.23" @@ -1831,17 +1509,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha1" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest", -] - [[package]] name = "sha2" version = "0.10.9" @@ -1849,16 +1516,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", + "cpufeatures", "digest", ] -[[package]] -name = "shell-words" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" - [[package]] name = "shlex" version = "2.0.1" @@ -1875,16 +1536,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core 0.6.4", -] - [[package]] name = "simd-adler32" version = "0.3.10" @@ -1931,23 +1582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "spin" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", + "windows-sys", ] [[package]] @@ -1980,12 +1615,6 @@ dependencies = [ "quote", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "2.0.119" @@ -2095,7 +1724,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2109,16 +1738,6 @@ dependencies = [ "syn 3.0.3", ] -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.19" @@ -2155,19 +1774,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.25.13+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" -dependencies = [ - "indexmap", - "toml_datetime", - "toml_parser", - "toml_writer", - "winnow", -] - [[package]] name = "toml_parser" version = "1.1.3+spec-1.1.0" @@ -2177,12 +1783,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_writer" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" - [[package]] name = "tower" version = "0.5.3" @@ -2318,12 +1918,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.5.8" @@ -2455,16 +2049,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "web_atoms" version = "0.2.6" @@ -2477,15 +2061,6 @@ dependencies = [ "string_cache_codegen", ] -[[package]] -name = "webpki-roots" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2508,7 +2083,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2618,15 +2193,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -2636,22 +2202,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - [[package]] name = "windows-threading" version = "0.2.1" @@ -2661,62 +2211,11 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "winnow" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" -dependencies = [ - "memchr", -] [[package]] name = "writeable" @@ -2788,12 +2287,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zeroize" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" - [[package]] name = "zerotrie" version = "0.2.4" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a5b0825b..240a0472 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,9 +7,3 @@ strip = true lto = true codegen-units = 1 opt-level = "s" - -# The rsa crate documents that RSA key generation is extremely slow without -# optimizing its big-integer dependency. The Discourse sign-in flow generates -# a 2048-bit key per authorization, so debug builds and tests need this too. -[profile.dev.package.num-bigint-dig] -opt-level = 3 diff --git a/rust/contracts/application-boundary.md b/rust/contracts/application-boundary.md index 4758c4c9..9b4fdc90 100644 --- a/rust/contracts/application-boundary.md +++ b/rust/contracts/application-boundary.md @@ -62,7 +62,6 @@ this lifecycle protection; actual symbol computation remains upstream-owned. | Local History | revision metadata, text content, restore result | persistence location and file operations | | Application logging | fixed module categories, versioned event context, recursive privacy rules, bounded timeline filters and frozen diagnostic preview manifests | background queues, native file rotation/retention, effective directory fallback, crash capture, session selection, viewing and user-selected export destinations | | Modules | stable IDs, manifests, enabled state, lifecycle snapshots, dependencies, capabilities, and contributions | native factories, processes, timers, PTY/ConPTY, watchers, connections, and UI rendering | -| Community integrations | Discourse authorization sessions, RSA-OAEP callback verification, user API protocol models, and normalized community data | opening the system browser, receiving URL callbacks, and credential-vault persistence | | Updates | normalized release metadata, state names, validated `stable|autobuild` preference, explicit rolling consent, and stable error codes | update feeds, package verification, download, installation, restart, and native UI | ### Application update channels diff --git a/rust/contracts/rust-core-api.md b/rust/contracts/rust-core-api.md index b0e40751..6c9aa989 100644 --- a/rust/contracts/rust-core-api.md +++ b/rust/contracts/rust-core-api.md @@ -153,11 +153,10 @@ See `rust/fixtures/keymap/binding-conflicts-v1.json`. double-Shift gesture as a pure transition: `event` is `{kind: "keyDown"}`, `{kind: "reset"}` or `{kind: "flags", shift, otherModifiers}`; `timestamp` is seconds on a clock the host keeps; `state` is opaque host-held memory (omit it for the idle state) that the host sends back with the next event. The rule lives in the -pure crate `rust/lithe-core-rules` (no I/O, no clock) so it can run on a synchronous key path: macOS calls it -through the C ABI, and the Windows frontend runs the same source compiled to wasm (`lithe_rules_alloc`, -`lithe_rules_dealloc`, `lithe_rules_execute` over JSON envelopes), loaded asynchronously at startup. A malformed -payload is `invalid_request`. Hosts only convert native events to this input and act on `triggered`; both are -tested step by step against `rust/fixtures/keymap/modifier-gesture-v1.json`. +pure crate `rust/lithe-core-rules` (no I/O, no clock) so it can run on a synchronous key path; hosts call it +through the C ABI. A malformed payload is `invalid_request`. Hosts only convert native events to this input and act +on `triggered`; Core and the rules crate test the rule step by step against +`rust/fixtures/keymap/modifier-gesture-v1.json`. `editor.workbenchState.reduce` accepts `{state?, action}` and returns `{state, removedGroupIds}`. `state` is `{groups, focusedGroup?}`; a group is `{id, members, selected?, mru?, pinned?, preview?}` (ordered members, the shown @@ -178,8 +177,8 @@ returned as sent, so a host may send only the groups an action involves. `emptyG stale), and `focusedGroup` moves to the first remaining group when its group was removed. Actions that name an unknown group or an unknown move destination change nothing. `removedGroupIds` lists removed groups in their previous order so hosts prune their own layout tree; split directions, ratios, pixels and dragging never reach Core. A malformed payload is -`invalid_request`. It lives in `rust/lithe-core-rules` and is called synchronously: macOS through the C ABI, Windows -through the wasm build inside zustand `set()`, one call per user action. Both hosts run every case of +`invalid_request`. It lives in `rust/lithe-core-rules` and hosts call it synchronously through the C ABI, one call per +user action. Core and the rules crate run every case of `rust/fixtures/editor/workbench-state-v1.json` through it. `workspace.classifyVisibility` accepts `{hiddenDirectoryNames?, hiddenFilePatterns?, entries: [{path, isDirectory?}]}` @@ -192,8 +191,8 @@ Local History leave the path out; `watchedDespiteHiding` marks the hidden projec events must still be delivered, except the built-in noise below it such as `.lithe/run/local.json`. Hosts send all children of a directory in one call. `workspace.visibilityDefaults` takes `{}` and returns the built-in lists (`hiddenDirectoryNames`, `hiddenFilePatterns`, `builtInPatterns`, `configurationDirectory`, `configurationPattern`) so hosts -display them without keeping a copy. Both live in `rust/lithe-core-rules` like `keymap.modifierGestureStep`, run in wasm on -Windows, and are tested against `rust/fixtures/workspace/visibility-v1.json`. +display them without keeping a copy. Both live in `rust/lithe-core-rules` like `keymap.modifierGestureStep` and are tested +against `rust/fixtures/workspace/visibility-v1.json`. ## Terminal link targets @@ -227,7 +226,7 @@ int32_t lithe_core_remove_log_waker(void *context); The macOS package uses the small C bridge in `macos/Sources/LitheRustCore/`. The canonical C declarations are in `rust/lithe-core/include/lithe_core.h`. -Native clients can link the same `staticlib` or `cdylib`; Rust hosts call +Native clients link the `staticlib`; Rust hosts call `lithe_core::execute_json` and `lithe_core::cancel_operation` directly. Strings returned by the core are UTF-8 JSON allocated by Rust. The caller must release response strings with `lithe_core_free_string`. @@ -457,13 +456,6 @@ or removing a command fails until the table changes in the same commit. | `plugins.marketplace.validateIndex` | Validate a marketplace index and report each plugin's availability for one platform | | `plugins.marketplace.resolveSource` | Resolve a user-entered marketplace source to the index URL to fetch | | `plugins.marketplace.installReview` | List a package's permissions and programs, and those not yet approved | -| `community.discourse.auth.begin` | Create an ephemeral RSA-OAEP authorization session and return the Discourse browser URL | -| `community.discourse.auth.complete` | Decrypt, validate, and consume one Discourse user API key callback | -| `community.discourse.topics` | List normalized latest or top topic summaries | -| `community.discourse.topic` | Read one topic with ordered, sanitized post HTML | -| `community.discourse.categories` | List normalized visible categories | -| `community.discourse.search` | Search normalized topics and sanitized posts | -| `community.discourse.auth.revoke` | Revoke the current Discourse user API key | | `workspace.snapshot` | Enumerate visible workspace nodes and relative file paths; `nestedWorktrees` lists linked worktrees checked out inside their own repository, which are left out of the tree, files, and search index; the built-in hidden names are skipped without being read, and include `node_modules`, Python virtual environments (`.venv`, `venv`), `__pycache__` and `*.pyc` files; `includeTree: false` returns only `files` and a childless `root`; `files` (and the tree, when included) keep the lowercase traversal order that bounded consumers such as Windows Quick Open rely on, not the natural display order of `workspace.listDirectories` | | `workspace.releaseIndexing` | Retire a policy and clear index/cache data at project close; accepts `root`, optional `ownerId`, and that owner's last observed `revision`, returns `released`; an old close must not retire a new generation | | `workspace.configureIndexing` | Install a process-local, canonical-root indexing policy before workspace consumers run; returns a monotonic revision, effective directory reasons and Git failure state; see `rust/fixtures/workspace/indexing-policy-v1.json` | @@ -852,26 +844,6 @@ GitHub command shapes, authorization behavior, and supported pull-request operations are documented in [`github.md`](github.md). Rust Core performs no network or credential I/O for these commands. -`community.discourse.auth.begin` accepts an HTTPS `origin`, stable `clientId`, -user-visible `applicationName`, platform-owned `authRedirect`, and a non-empty -array of supported `scopes`. It returns an opaque `flowId`, an -`authorizationUrl` that requests RSA-OAEP padding, and an `expiresAt` Unix -timestamp. The private key and nonce remain in Rust memory and expire after ten -minutes. `community.discourse.auth.complete` accepts that `flowId` and the full -`callbackUrl`; it consumes the flow, verifies the callback target, decrypts the -payload, and checks the nonce before returning `userApiKey` and `apiVersion`. -Platform hosts open the browser, receive their registered URL scheme, and store -the returned credential in Keychain or Windows Credential Manager. They do not -implement Discourse cryptography or callback validation. - -The authenticated community commands accept `origin`, `userApiKey`, and -`clientId` plus their operation-specific fields. Rust owns HTTPS requests, -authentication headers, a 30-second request timeout, a 5 MB response limit, -Discourse JSON decoding, deterministic post ordering, and HTML sanitization. -Platform clients never issue a parallel Discourse request or parse a second -response shape. Credential vault reads and writes remain native adapters; the -credential is passed to Core only for the duration of one command. - `git.watchContext` accepts `{ "root": string }`. When `root` is not inside a Git repository, it returns `null`. Otherwise it returns `{ "repositoryRoot": string, "gitDirectory": string, "gitCommonDirectory": string }`; diff --git a/rust/fixtures/community/discourse-auth-v1.json b/rust/fixtures/community/discourse-auth-v1.json deleted file mode 100644 index 2dc92769..00000000 --- a/rust/fixtures/community/discourse-auth-v1.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "version": 1, - "begin": { - "command": "community.discourse.auth.begin", - "payload": { - "origin": "https://linux.do", - "clientId": "app.lithe.linux-do", - "applicationName": "Lithe", - "authRedirect": "lithe://auth/linux-do", - "scopes": ["read", "session_info"] - }, - "expected": { - "authorizationPath": "/user-api-key/new", - "padding": "oaep", - "scopes": "read,session_info" - } - }, - "complete": { - "command": "community.discourse.auth.complete", - "payloadFields": ["flowId", "callbackUrl"], - "responseFields": ["apiVersion", "userApiKey"] - }, - "authenticatedCommands": [ - "community.discourse.auth.revoke", - "community.discourse.categories", - "community.discourse.search", - "community.discourse.topic", - "community.discourse.topics" - ], - "limits": { - "requestTimeoutSeconds": 30, - "responseBytes": 5242880 - } -} diff --git a/rust/lithe-core-rules/Cargo.toml b/rust/lithe-core-rules/Cargo.toml index 1388a9f2..f11f11d2 100644 --- a/rust/lithe-core-rules/Cargo.toml +++ b/rust/lithe-core-rules/Cargo.toml @@ -3,11 +3,7 @@ name = "lithe-core-rules" version = "0.1.0" edition = "2021" license = "Apache-2.0" -description = "Pure synchronous rules shared by Lithe Core and the Windows frontend (compiled to wasm)" - -[lib] -# `rlib` is linked into lithe-core; `cdylib` produces the wasm module on wasm32 targets. -crate-type = ["rlib", "cdylib"] +description = "Pure synchronous rules linked into Lithe Core" [dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/rust/lithe-core-rules/src/dispatch.rs b/rust/lithe-core-rules/src/dispatch.rs index 599d600b..656e5c3f 100644 --- a/rust/lithe-core-rules/src/dispatch.rs +++ b/rust/lithe-core-rules/src/dispatch.rs @@ -1,8 +1,7 @@ -//! Command routing and the JSON envelope shared with `lithe-core`. +//! Command routing for the rules `lithe-core` forwards to this crate. use crate::{editor, keymap, visibility, workbench, RuleError, RuleErrorCode}; -use serde::Deserialize; -use serde_json::{json, Value}; +use serde_json::Value; /// Every command name this crate owns. `lithe-core` routes exactly these names here. pub const COMMANDS: &[&str] = &[ @@ -13,11 +12,6 @@ pub const COMMANDS: &[&str] = &[ workbench::REDUCE_CHROME_LAYOUT, ]; -/// Reports whether `command` is owned by this crate. -pub fn is_rule_command(command: &str) -> bool { - COMMANDS.contains(&command) -} - /// Runs one rule on an already decoded payload. pub fn execute(command: &str, payload: Value) -> Result { match command { @@ -32,34 +26,3 @@ pub fn execute(command: &str, payload: Value) -> Result { )), } } - -#[derive(Deserialize)] -struct Request { - id: Option, - command: String, - #[serde(default)] - payload: Value, -} - -/// Executes one Core-style JSON request and returns the JSON response envelope. -/// -/// Unknown envelope fields (`operationId`, `origin`, ...) are ignored so hosts can send the -/// same request object they send to `lithe-core`. -pub fn execute_json(request: &str) -> String { - let parsed: Request = match serde_json::from_str(request) { - Ok(parsed) => parsed, - Err(error) => { - let error = RuleError::new(RuleErrorCode::InvalidRequest, "Invalid JSON request") - .with_details(error.to_string()); - return failure(None, &error); - } - }; - match execute(&parsed.command, parsed.payload) { - Ok(data) => json!({"id": parsed.id, "ok": true, "data": data}).to_string(), - Err(error) => failure(parsed.id, &error), - } -} - -fn failure(id: Option, error: &RuleError) -> String { - json!({"id": id, "ok": false, "error": error}).to_string() -} diff --git a/rust/lithe-core-rules/src/error.rs b/rust/lithe-core-rules/src/error.rs index 74e5a60c..5aa65a08 100644 --- a/rust/lithe-core-rules/src/error.rs +++ b/rust/lithe-core-rules/src/error.rs @@ -1,10 +1,7 @@ -//! Failure type whose JSON shape matches the Core error envelope. +//! Failure type that `lithe-core` maps one to one onto its error envelope. -use serde::Serialize; - -/// Stable failure categories. Names serialize exactly like the matching `lithe-core` codes. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] -#[serde(rename_all = "snake_case")] +/// Stable failure categories, each matching the `lithe-core` error code of the same name. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RuleErrorCode { /// The request envelope or payload does not match the command contract. InvalidRequest, @@ -13,15 +10,13 @@ pub enum RuleErrorCode { } /// A rule failure with a stable category and a message that is safe to display. -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] -#[serde(rename_all = "camelCase")] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct RuleError { /// Machine-readable category. pub code: RuleErrorCode, /// Short summary of the failure. pub message: String, /// Optional diagnostic context; never contains secrets. - #[serde(skip_serializing_if = "Option::is_none")] pub details: Option, } diff --git a/rust/lithe-core-rules/src/lib.rs b/rust/lithe-core-rules/src/lib.rs index bedb58ca..a438b298 100644 --- a/rust/lithe-core-rules/src/lib.rs +++ b/rust/lithe-core-rules/src/lib.rs @@ -4,23 +4,16 @@ //! (for example a gesture recognizer that runs on every native key event). It performs no //! file-system, process, thread or clock access: time is always supplied by the caller. //! -//! The same source is consumed twice: -//! - `lithe-core` links it as a normal dependency and exposes each rule through its JSON -//! command dispatch, so macOS and the Windows backend reach it over the usual Core channel. -//! - On `wasm32` it is built as a `cdylib` whose `extern "C"` exports (see the private `wasm` module) let the -//! Windows frontend call the very same rules synchronously, without a Tauri IPC round trip. -//! -//! Requests and responses reuse the Core envelope: `{id, command, payload}` in and -//! `{id, ok, data | error}` out, with the same stable error codes. +//! `lithe-core` links this crate as a normal dependency and exposes each rule through its JSON +//! command dispatch, so hosts reach the rules over the usual Core C ABI. Rule failures use +//! [`RuleError`], which `lithe-core` maps one to one onto its stable error codes. mod dispatch; pub mod editor; mod error; pub mod keymap; pub mod visibility; -#[cfg(target_arch = "wasm32")] -mod wasm; pub mod workbench; -pub use dispatch::{execute, execute_json, is_rule_command, COMMANDS}; +pub use dispatch::{execute, COMMANDS}; pub use error::{RuleError, RuleErrorCode}; diff --git a/rust/lithe-core-rules/src/wasm.rs b/rust/lithe-core-rules/src/wasm.rs deleted file mode 100644 index aa3f0c41..00000000 --- a/rust/lithe-core-rules/src/wasm.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Minimal C ABI exported by the wasm build, without `wasm-bindgen`. -//! -//! The host copies a UTF-8 JSON request into memory obtained from `lithe_rules_alloc`, calls -//! `lithe_rules_execute`, reads the response bytes from the returned pointer (its length comes -//! from `lithe_rules_result_len`), and frees both buffers with `lithe_rules_dealloc`. -//! Requests and responses use the Core envelope, see [`crate::execute_json`]. -//! -//! wasm32-unknown-unknown modules are single threaded, so the last-result length lives in a plain -//! atomic rather than behind a lock. - -use std::sync::atomic::{AtomicUsize, Ordering}; - -static LAST_RESULT_LEN: AtomicUsize = AtomicUsize::new(0); - -/// Allocates `len` writable bytes for the host and returns their address. -#[no_mangle] -pub extern "C" fn lithe_rules_alloc(len: usize) -> *mut u8 { - Box::into_raw(vec![0u8; len.max(1)].into_boxed_slice()).cast::() -} - -/// Releases a buffer previously handed out by `lithe_rules_alloc` or `lithe_rules_execute`. -/// -/// # Safety -/// -/// `pointer` and `len` must be exactly the address and requested length of a live buffer from -/// this module, and the buffer must not be used afterwards. -#[no_mangle] -pub unsafe extern "C" fn lithe_rules_dealloc(pointer: *mut u8, len: usize) { - if !pointer.is_null() { - drop(Box::from_raw(std::ptr::slice_from_raw_parts_mut( - pointer, - len.max(1), - ))); - } -} - -/// Runs one JSON request and returns the address of the JSON response. -/// -/// The response length is available from `lithe_rules_result_len` until the next call. -/// -/// # Safety -/// -/// `pointer` must address `len` initialized bytes inside this module's memory. -#[no_mangle] -pub unsafe extern "C" fn lithe_rules_execute(pointer: *const u8, len: usize) -> *mut u8 { - let request = std::slice::from_raw_parts(pointer, len); - let response = match std::str::from_utf8(request) { - Ok(text) => crate::execute_json(text), - Err(_) => r#"{"id":null,"ok":false,"error":{"code":"invalid_request","message":"Request is not valid UTF-8"}}"#.to_string(), - }; - let bytes = response.into_bytes(); - let response_len = bytes.len(); - // Copy into a buffer sized exactly like the host-visible length, so `lithe_rules_dealloc` - // can release it with that length. - let output = lithe_rules_alloc(response_len); - std::ptr::copy_nonoverlapping(bytes.as_ptr(), output, response_len); - LAST_RESULT_LEN.store(response_len, Ordering::Relaxed); - output -} - -/// Length in bytes of the response returned by the most recent `lithe_rules_execute` call. -#[no_mangle] -pub extern "C" fn lithe_rules_result_len() -> usize { - LAST_RESULT_LEN.load(Ordering::Relaxed) -} diff --git a/rust/lithe-core-rules/tests/modifier_gesture_fixture.rs b/rust/lithe-core-rules/tests/modifier_gesture_fixture.rs index 0ed3b6b1..61e70e9e 100644 --- a/rust/lithe-core-rules/tests/modifier_gesture_fixture.rs +++ b/rust/lithe-core-rules/tests/modifier_gesture_fixture.rs @@ -1,20 +1,16 @@ -//! Drives the shared double-Shift fixture through the JSON envelope, exactly like the hosts do. +//! Drives the shared double-Shift fixture through the rule dispatch that `lithe-core` forwards to. -use lithe_core_rules::{execute_json, keymap::THRESHOLD_SECONDS}; +use lithe_core_rules::{execute, keymap::THRESHOLD_SECONDS, RuleErrorCode}; use serde_json::{json, Value}; const FIXTURE: &str = include_str!("../../fixtures/keymap/modifier-gesture-v1.json"); fn step(state: &Value, event: Value, timestamp: f64) -> Value { - let request = json!({ - "id": "fixture", - "command": "keymap.modifierGestureStep", - "payload": {"state": state, "event": event, "timestamp": timestamp}, - }); - let response: Value = serde_json::from_str(&execute_json(&request.to_string())).unwrap(); - assert_eq!(response["ok"], true, "{response}"); - assert_eq!(response["id"], "fixture"); - response["data"].clone() + execute( + "keymap.modifierGestureStep", + json!({"state": state, "event": event, "timestamp": timestamp}), + ) + .unwrap() } #[test] @@ -57,22 +53,13 @@ fn every_fixture_sequence_matches_step_by_step() { #[test] fn malformed_requests_use_core_error_codes() { - let unknown: Value = serde_json::from_str(&execute_json( - r#"{"id":"a","command":"keymap.nope","payload":{}}"#, - )) - .unwrap(); - assert_eq!(unknown["ok"], false); - assert_eq!(unknown["error"]["code"], "not_supported"); + let unknown = execute("keymap.nope", json!({})).unwrap_err(); + assert_eq!(unknown.code, RuleErrorCode::NotSupported); - let bad_payload: Value = serde_json::from_str(&execute_json( - r#"{"id":"b","command":"keymap.modifierGestureStep","payload":{"event":{"kind":"flags"}}}"#, - )) - .unwrap(); - assert_eq!(bad_payload["ok"], false); - assert_eq!(bad_payload["error"]["code"], "invalid_request"); - assert_eq!(bad_payload["id"], "b"); - - let not_json: Value = serde_json::from_str(&execute_json("{")).unwrap(); - assert_eq!(not_json["error"]["code"], "invalid_request"); - assert!(not_json["id"].is_null()); + let bad_payload = execute( + "keymap.modifierGestureStep", + json!({"event": {"kind": "flags"}}), + ) + .unwrap_err(); + assert_eq!(bad_payload.code, RuleErrorCode::InvalidRequest); } diff --git a/rust/lithe-core-rules/tests/visibility_fixture.rs b/rust/lithe-core-rules/tests/visibility_fixture.rs index aa61e282..53bc1ef4 100644 --- a/rust/lithe-core-rules/tests/visibility_fixture.rs +++ b/rust/lithe-core-rules/tests/visibility_fixture.rs @@ -1,15 +1,12 @@ -//! Drives the shared hidden-path fixture through the JSON envelope, exactly like the hosts do. +//! Drives the shared hidden-path fixture through the rule dispatch that `lithe-core` forwards to. -use lithe_core_rules::execute_json; +use lithe_core_rules::{execute, RuleErrorCode}; use serde_json::{json, Value}; const FIXTURE: &str = include_str!("../../fixtures/workspace/visibility-v1.json"); fn call(command: &str, payload: Value) -> Value { - let request = json!({"id": "fixture", "command": command, "payload": payload}); - let response: Value = serde_json::from_str(&execute_json(&request.to_string())).unwrap(); - assert_eq!(response["ok"], true, "{response}"); - response["data"].clone() + execute(command, payload).unwrap() } #[test] @@ -52,10 +49,10 @@ fn every_case_is_classified_in_one_batch() { #[test] fn malformed_requests_use_core_error_codes() { - let response: Value = serde_json::from_str(&execute_json( - r#"{"id":"a","command":"workspace.classifyVisibility","payload":{"entries":[{"path":1}]}}"#, - )) - .unwrap(); - assert_eq!(response["ok"], false); - assert_eq!(response["error"]["code"], "invalid_request"); + let error = execute( + "workspace.classifyVisibility", + json!({"entries": [{"path": 1}]}), + ) + .unwrap_err(); + assert_eq!(error.code, RuleErrorCode::InvalidRequest); } diff --git a/rust/lithe-core-rules/tests/workbench_state_fixture.rs b/rust/lithe-core-rules/tests/workbench_state_fixture.rs index 05d9787f..0cd6647a 100644 --- a/rust/lithe-core-rules/tests/workbench_state_fixture.rs +++ b/rust/lithe-core-rules/tests/workbench_state_fixture.rs @@ -1,19 +1,18 @@ -//! Drives the shared workbench-state fixture through the JSON envelope, exactly like the hosts do. +//! Drives the shared workbench-state fixture through the rule dispatch that `lithe-core` forwards to. -use lithe_core_rules::{execute_json, is_rule_command}; +use lithe_core_rules::{execute, RuleError, RuleErrorCode, COMMANDS}; use serde_json::{json, Value}; const FIXTURE: &str = include_str!("../../fixtures/editor/workbench-state-v1.json"); const COMMAND: &str = "editor.workbenchState.reduce"; -fn call(payload: Value) -> Value { - let request = json!({"id": "fixture", "command": COMMAND, "payload": payload}); - serde_json::from_str(&execute_json(&request.to_string())).unwrap() +fn call(payload: Value) -> Result { + execute(COMMAND, payload) } #[test] fn command_is_owned_by_the_rules_crate() { - assert!(is_rule_command(COMMAND)); + assert!(COMMANDS.contains(&COMMAND)); } #[test] @@ -24,15 +23,11 @@ fn every_fixture_case_matches() { assert!(cases.len() >= 40, "fixture should keep its coverage"); for case in cases { let name = case["name"].as_str().unwrap(); - let response = call(json!({"state": case["state"], "action": case["action"]})); - assert_eq!(response["ok"], true, "{name}: {response}"); - assert_eq!(response["id"], "fixture"); + let data = call(json!({"state": case["state"], "action": case["action"]})) + .unwrap_or_else(|error| panic!("{name}: {error:?}")); + assert_eq!(data["state"], case["expected"]["state"], "{name}"); assert_eq!( - response["data"]["state"], case["expected"]["state"], - "{name}" - ); - assert_eq!( - response["data"]["removedGroupIds"], case["expected"]["removedGroupIds"], + data["removedGroupIds"], case["expected"]["removedGroupIds"], "{name}" ); } @@ -44,11 +39,12 @@ fn reducing_a_result_again_changes_nothing_for_normalizing_actions() { for case in fixture["cases"].as_array().unwrap() { let name = case["name"].as_str().unwrap(); let again = - call(json!({"state": case["expected"]["state"], "action": {"kind": "normalize"}})); + call(json!({"state": case["expected"]["state"], "action": {"kind": "normalize"}})) + .unwrap_or_else(|error| panic!("{name}: {error:?}")); // Re-normalizing a reducer result is idempotent: the reducer never emits a state it // would repair. - assert_eq!(again["data"]["state"], case["expected"]["state"], "{name}"); - assert_eq!(again["data"]["removedGroupIds"], json!([]), "{name}"); + assert_eq!(again["state"], case["expected"]["state"], "{name}"); + assert_eq!(again["removedGroupIds"], json!([]), "{name}"); } } @@ -62,8 +58,7 @@ fn malformed_requests_are_invalid() { json!({"state": {"groups": [{"members": []}]}, "action": {"kind": "normalize"}}), json!({"action": {"kind": "close", "group": "g", "member": "a", "emptyGroups": "nope"}}), ] { - let response = call(payload.clone()); - assert_eq!(response["ok"], false, "{payload}"); - assert_eq!(response["error"]["code"], "invalid_request", "{payload}"); + let error = call(payload.clone()).expect_err(&payload.to_string()); + assert_eq!(error.code, RuleErrorCode::InvalidRequest, "{payload}"); } } diff --git a/rust/lithe-core/Cargo.toml b/rust/lithe-core/Cargo.toml index e84cef93..1bb3a9d2 100644 --- a/rust/lithe-core/Cargo.toml +++ b/rust/lithe-core/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" description = "Cross-platform application core for Lithe" [lib] -crate-type = ["rlib", "staticlib", "cdylib"] +crate-type = ["rlib", "staticlib"] [features] # Builds the plugin SDK end-to-end tests in shared/plugins/sdk/e2e; run them @@ -27,15 +27,10 @@ comrak = { version = "0.54.0", default-features = false, features = ["shortcodes rand = "0.8" regex = "1.11" quick-xml = "0.37" -reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] } -rsa = { version = "0.9", features = ["pem"] } serde = { version = "1.0", features = ["derive", "rc"] } serde_json = { version = "1.0", features = ["preserve_order"] } -sha1 = "0.10" sha2 = "0.10" -shell-words = "=1.1.1" toml = { version = "1.1.4", default-features = false, features = ["parse", "serde"] } -toml_edit = "0.25" serde_yaml_ng = "0.10.0" similar = { version = "3.2", default-features = false, features = ["std"] } zip = { version = "2.4", default-features = false, features = ["deflate"] } diff --git a/rust/lithe-core/src/community/discourse.rs b/rust/lithe-core/src/community/discourse.rs deleted file mode 100644 index 37cbf622..00000000 --- a/rust/lithe-core/src/community/discourse.rs +++ /dev/null @@ -1,926 +0,0 @@ -//! Discourse user API key authorization shared by every platform host. - -use crate::protocol::{CoreError, ErrorCode}; -use base64::engine::general_purpose::{STANDARD, URL_SAFE, URL_SAFE_NO_PAD}; -use base64::Engine; -use rand::rngs::OsRng; -use rand::RngCore; -use reqwest::blocking::{Client, Response}; -use reqwest::header::{ACCEPT, CONTENT_LENGTH, USER_AGENT}; -use rsa::pkcs1::{EncodeRsaPublicKey, LineEnding}; -use rsa::{Oaep, RsaPrivateKey, RsaPublicKey}; -use serde::{Deserialize, Serialize}; -use sha1::Sha1; -use std::collections::HashMap; -use std::io::Read; -use std::sync::{Mutex, OnceLock}; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use url::Url; - -const AUTHORIZATION_PATH: &str = "user-api-key/new"; -const AUTHORIZATION_LIFETIME: Duration = Duration::from_secs(10 * 60); -const RSA_BITS: usize = 2048; -const MAX_RESPONSE_BYTES: u64 = 5 * 1024 * 1024; -const REQUEST_TIMEOUT: Duration = Duration::from_secs(30); -const CLIENT_USER_AGENT: &str = "Lithe/0.1 DiscourseClient"; - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Parameters needed to begin an external-browser Discourse authorization. -pub(crate) struct DiscourseAuthorizationBeginRequest { - /// HTTPS origin of the Discourse installation, without credentials. - origin: String, - /// Stable application identifier recorded by Discourse. - client_id: String, - /// User-visible application name shown on the approval screen. - application_name: String, - /// Platform callback URL that receives the encrypted payload. - auth_redirect: String, - /// Least-privilege user API key scopes requested from the user. - scopes: Vec, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -/// Browser URL and opaque flow identifier returned to a platform host. -pub(crate) struct DiscourseAuthorizationBeginResponse { - /// Opaque identifier needed to complete this in-memory authorization flow. - flow_id: String, - /// Fully encoded URL that the platform must open in the default browser. - authorization_url: String, - /// Unix timestamp after which the callback is rejected. - expires_at: u64, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Callback submitted by a platform after its URL scheme is invoked. -pub(crate) struct DiscourseAuthorizationCompleteRequest { - /// Opaque identifier returned by the begin command. - flow_id: String, - /// Complete callback URL received from the operating system. - callback_url: String, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -/// Verified credential returned for storage in the platform credential vault. -pub(crate) struct DiscourseAuthorizationCredential { - /// Per-user API key issued and revocable by the Discourse installation. - user_api_key: String, - /// User API protocol version reported by the server payload. - api_version: u64, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Shared authentication and site fields used by Discourse API commands. -struct DiscourseAPIContext { - /// HTTPS origin of the Discourse installation. - origin: String, - /// Per-user API key loaded from the platform credential vault. - user_api_key: String, - /// Stable client identifier used during authorization. - client_id: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Request for latest or top topic summaries. -pub(crate) struct DiscourseTopicsRequest { - #[serde(flatten)] - context: DiscourseAPIContext, - /// Feed kind: `latest` or `top`. - feed: String, - /// Optional top period such as `daily`, `weekly`, or `monthly`. - #[serde(default)] - period: Option, - /// Optional zero-based Discourse pagination index. - #[serde(default)] - page: Option, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Request for one topic and its currently returned post stream. -pub(crate) struct DiscourseTopicRequest { - #[serde(flatten)] - context: DiscourseAPIContext, - /// Positive Discourse topic identifier. - topic_id: u64, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Request for the visible category catalog. -pub(crate) struct DiscourseCategoriesRequest { - #[serde(flatten)] - context: DiscourseAPIContext, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Request for a bounded Discourse search page. -pub(crate) struct DiscourseSearchRequest { - #[serde(flatten)] - context: DiscourseAPIContext, - /// Search syntax accepted by the Discourse installation. - query: String, - /// Optional one-based search result page. - #[serde(default)] - page: Option, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -/// Request to revoke a user API key on its issuing site. -pub(crate) struct DiscourseRevokeRequest { - #[serde(flatten)] - context: DiscourseAPIContext, -} - -#[derive(Debug, Clone, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -/// Stable topic summary rendered by both platform clients. -pub(crate) struct DiscourseTopicSummary { - id: u64, - slug: String, - title: String, - #[serde(default)] - posts_count: u64, - #[serde(default)] - reply_count: u64, - #[serde(default)] - views: u64, - #[serde(default)] - like_count: u64, - #[serde(default)] - category_id: Option, - #[serde(default)] - created_at: Option, - #[serde(default)] - last_posted_at: Option, - #[serde(default)] - last_poster_username: Option, - #[serde(default)] - pinned: bool, - #[serde(default)] - closed: bool, - #[serde(default)] - archived: bool, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -/// Normalized topic page returned by latest and top feeds. -pub(crate) struct DiscourseTopicsResponse { - topics: Vec, - more_topics_url: Option, -} - -#[derive(Debug, Deserialize)] -struct TopicListEnvelope { - topic_list: TopicList, -} - -#[derive(Debug, Deserialize)] -struct TopicList { - #[serde(default)] - topics: Vec, - #[serde(default)] - more_topics_url: Option, -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -/// Stable category metadata independent of Discourse theme fields. -pub(crate) struct DiscourseCategory { - id: u64, - name: String, - slug: String, - #[serde(default)] - color: Option, - #[serde(default)] - topic_count: u64, - #[serde(default)] - description_text: Option, -} - -#[derive(Debug, Deserialize)] -struct CategoryEnvelope { - category_list: CategoryList, -} - -#[derive(Debug, Deserialize)] -struct CategoryList { - #[serde(default)] - categories: Vec, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -/// Deterministically ordered visible category catalog. -pub(crate) struct DiscourseCategoriesResponse { - categories: Vec, -} - -#[derive(Debug, Deserialize)] -struct TopicEnvelope { - id: u64, - title: String, - slug: String, - post_stream: PostStream, -} - -#[derive(Debug, Deserialize)] -struct PostStream { - #[serde(default)] - posts: Vec, -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -/// Sanitized post content and attribution for a topic stream. -pub(crate) struct DiscoursePost { - id: u64, - post_number: u64, - username: String, - #[serde(default)] - name: Option, - cooked: String, - #[serde(default)] - created_at: Option, - #[serde(default)] - updated_at: Option, - #[serde(default)] - reply_count: u64, - #[serde(default)] - reads: u64, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -/// One topic with sanitized post HTML in ascending post order. -pub(crate) struct DiscourseTopicResponse { - id: u64, - title: String, - slug: String, - posts: Vec, -} - -#[derive(Debug, Deserialize)] -struct SearchEnvelope { - #[serde(default)] - topics: Vec, - #[serde(default)] - posts: Vec, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -/// Normalized topic and sanitized post matches from a search page. -pub(crate) struct DiscourseSearchResponse { - topics: Vec, - posts: Vec, -} - -/// Lists latest or top topics through the Rust-owned HTTP client. -pub(crate) fn topics( - request: DiscourseTopicsRequest, -) -> Result { - let mut url = api_url( - &request.context, - match request.feed.as_str() { - "latest" => "latest.json", - "top" => "top.json", - _ => { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Topic feed must be latest or top", - )) - } - }, - )?; - if request.feed == "top" { - if let Some(period) = request.period { - const PERIODS: &[&str] = &["all", "yearly", "quarterly", "monthly", "weekly", "daily"]; - if !PERIODS.contains(&period.as_str()) { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Unsupported top topic period", - )); - } - url.query_pairs_mut().append_pair("period", &period); - } - } - if let Some(page) = request.page { - url.query_pairs_mut().append_pair("page", &page.to_string()); - } - let envelope: TopicListEnvelope = get_json(&request.context, url)?; - Ok(DiscourseTopicsResponse { - topics: envelope.topic_list.topics, - more_topics_url: envelope.topic_list.more_topics_url, - }) -} - -/// Reads and sanitizes one topic stream through the Rust-owned HTTP client. -pub(crate) fn topic(request: DiscourseTopicRequest) -> Result { - if request.topic_id == 0 { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Topic ID must be positive", - )); - } - let envelope: TopicEnvelope = get_json( - &request.context, - api_url(&request.context, &format!("t/{}.json", request.topic_id))?, - )?; - Ok(DiscourseTopicResponse { - id: envelope.id, - title: envelope.title, - slug: envelope.slug, - posts: sanitize_posts(envelope.post_stream.posts), - }) -} - -/// Lists visible categories through the Rust-owned HTTP client. -pub(crate) fn categories( - request: DiscourseCategoriesRequest, -) -> Result { - let envelope: CategoryEnvelope = get_json( - &request.context, - api_url(&request.context, "categories.json")?, - )?; - Ok(DiscourseCategoriesResponse { - categories: envelope.category_list.categories, - }) -} - -/// Searches topics and posts through the Rust-owned HTTP client. -pub(crate) fn search( - request: DiscourseSearchRequest, -) -> Result { - let query = required_single_line(&request.query, "query")?; - let mut url = api_url(&request.context, "search.json")?; - url.query_pairs_mut().append_pair("q", query); - if let Some(page) = request.page { - url.query_pairs_mut().append_pair("page", &page.to_string()); - } - let envelope: SearchEnvelope = get_json(&request.context, url)?; - Ok(DiscourseSearchResponse { - topics: envelope.topics, - posts: sanitize_posts(envelope.posts), - }) -} - -/// Revokes the credential on the issuing Discourse installation. -pub(crate) fn revoke(request: DiscourseRevokeRequest) -> Result { - let url = api_url(&request.context, "user-api-key/revoke")?; - let response = authenticated_request(&request.context, reqwest::Method::POST, url)?.send(); - checked_response(response)?; - Ok(serde_json::json!({})) -} - -struct PendingAuthorization { - private_key: RsaPrivateKey, - nonce: String, - auth_redirect: String, - expires_at: u64, -} - -#[derive(Deserialize)] -struct EncryptedAuthorizationPayload { - key: String, - nonce: String, - api: u64, -} - -fn pending_authorizations() -> &'static Mutex> { - static PENDING: OnceLock>> = OnceLock::new(); - PENDING.get_or_init(|| Mutex::new(HashMap::new())) -} - -/// Creates an ephemeral RSA key and returns a browser authorization URL. -pub(crate) fn begin_authorization( - request: DiscourseAuthorizationBeginRequest, -) -> Result { - let origin = validated_origin(&request.origin)?; - let auth_redirect = validated_redirect(&request.auth_redirect)?; - let client_id = required_single_line(&request.client_id, "clientId")?; - let application_name = required_single_line(&request.application_name, "applicationName")?; - let scopes = validated_scopes(request.scopes)?; - let now = unix_timestamp()?; - - let private_key = RsaPrivateKey::new(&mut OsRng, RSA_BITS).map_err(|error| { - CoreError::new(ErrorCode::Unknown, "Could not create an authorization key") - .with_details(error.to_string()) - })?; - let public_key = RsaPublicKey::from(&private_key) - .to_pkcs1_pem(LineEnding::LF) - .map_err(|error| { - CoreError::new(ErrorCode::Unknown, "Could not encode the authorization key") - .with_details(error.to_string()) - })?; - let flow_id = random_identifier(16); - let nonce = random_identifier(32); - let expires_at = now + AUTHORIZATION_LIFETIME.as_secs(); - let authorization_url = build_authorization_url( - origin, - client_id, - application_name, - &auth_redirect, - &scopes, - &nonce, - public_key.as_str(), - ); - - let mut pending = pending_authorizations() - .lock() - .map_err(|_| CoreError::new(ErrorCode::Unknown, "Authorization state is unavailable"))?; - pending.retain(|_, authorization| authorization.expires_at > now); - pending.insert( - flow_id.clone(), - PendingAuthorization { - private_key, - nonce, - auth_redirect, - expires_at, - }, - ); - - Ok(DiscourseAuthorizationBeginResponse { - flow_id, - authorization_url, - expires_at, - }) -} - -/// Decrypts one callback and consumes its authorization flow to prevent replay. -pub(crate) fn complete_authorization( - request: DiscourseAuthorizationCompleteRequest, -) -> Result { - let callback = Url::parse(&request.callback_url).map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid authorization callback URL", - ) - .with_details(error.to_string()) - })?; - let now = unix_timestamp()?; - let authorization = pending_authorizations() - .lock() - .map_err(|_| CoreError::new(ErrorCode::Unknown, "Authorization state is unavailable"))? - .remove(&request.flow_id) - .ok_or_else(|| { - CoreError::new( - ErrorCode::InvalidRequest, - "Authorization session was not found or was already used", - ) - })?; - if authorization.expires_at <= now { - return Err(CoreError::new( - ErrorCode::TimedOut, - "Authorization session expired", - )); - } - if !same_callback_target(&callback, &authorization.auth_redirect) { - return Err(CoreError::new( - ErrorCode::PermissionDenied, - "Authorization callback target did not match the requested redirect", - )); - } - let encrypted_payload = callback - .query_pairs() - .find_map(|(name, value)| (name == "payload").then(|| value.into_owned())) - .ok_or_else(|| { - CoreError::new( - ErrorCode::InvalidRequest, - "Authorization callback did not contain a payload", - ) - })?; - let encrypted_payload = decode_payload(&encrypted_payload)?; - let decrypted = authorization - .private_key - .decrypt(Oaep::new::(), &encrypted_payload) - .map_err(|_| { - CoreError::new( - ErrorCode::PermissionDenied, - "Authorization payload could not be decrypted", - ) - })?; - let payload: EncryptedAuthorizationPayload = - serde_json::from_slice(&decrypted).map_err(|error| { - CoreError::new(ErrorCode::ParseFailed, "Authorization payload was invalid") - .with_details(error.to_string()) - })?; - if payload.nonce != authorization.nonce { - return Err(CoreError::new( - ErrorCode::PermissionDenied, - "Authorization nonce did not match", - )); - } - if payload.key.trim().is_empty() { - return Err(CoreError::new( - ErrorCode::ParseFailed, - "Authorization payload did not contain a user API key", - )); - } - - Ok(DiscourseAuthorizationCredential { - user_api_key: payload.key, - api_version: payload.api, - }) -} - -fn validated_origin(value: &str) -> Result { - let mut url = Url::parse(value).map_err(|error| { - CoreError::new(ErrorCode::InvalidRequest, "Invalid Discourse origin") - .with_details(error.to_string()) - })?; - if url.scheme() != "https" - || url.host_str().is_none() - || !url.username().is_empty() - || url.password().is_some() - || url.path() != "/" - || url.query().is_some() - || url.fragment().is_some() - { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Discourse origin must be an HTTPS origin without credentials", - )); - } - url.set_path("/"); - Ok(url) -} - -fn validated_redirect(value: &str) -> Result { - let url = Url::parse(value).map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid authorization redirect URL", - ) - .with_details(error.to_string()) - })?; - if url.scheme().is_empty() - || url.host_str().is_none() - || url.query().is_some() - || url.fragment().is_some() - { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Authorization redirect must contain a scheme and host without query parameters", - )); - } - Ok(url.to_string()) -} - -fn required_single_line<'a>(value: &'a str, field: &str) -> Result<&'a str, CoreError> { - let trimmed = value.trim(); - if trimmed.is_empty() || trimmed.contains(['\r', '\n']) { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - format!("{field} must be a non-empty single-line value"), - )); - } - Ok(trimmed) -} - -fn validated_scopes(scopes: Vec) -> Result { - const ALLOWED: &[&str] = &[ - "bookmarks_calendar", - "message_bus", - "notifications", - "one_time_password", - "push", - "read", - "session_info", - "user_status", - "write", - ]; - let mut scopes = scopes - .into_iter() - .map(|scope| scope.trim().to_string()) - .collect::>(); - scopes.sort(); - scopes.dedup(); - if scopes.is_empty() - || scopes - .iter() - .any(|scope| !ALLOWED.contains(&scope.as_str())) - { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Authorization scopes contained an unsupported value", - )); - } - Ok(scopes.join(",")) -} - -fn build_authorization_url( - mut origin: Url, - client_id: &str, - application_name: &str, - auth_redirect: &str, - scopes: &str, - nonce: &str, - public_key: &str, -) -> String { - origin.set_path(AUTHORIZATION_PATH); - origin - .query_pairs_mut() - .append_pair("application_name", application_name) - .append_pair("client_id", client_id) - .append_pair("auth_redirect", auth_redirect) - .append_pair("scopes", scopes) - .append_pair("nonce", nonce) - .append_pair("public_key", public_key) - .append_pair("padding", "oaep"); - origin.into() -} - -fn same_callback_target(callback: &Url, expected: &str) -> bool { - Url::parse(expected).is_ok_and(|expected| { - callback.scheme() == expected.scheme() - && callback.host_str() == expected.host_str() - && callback.port_or_known_default() == expected.port_or_known_default() - && callback.path() == expected.path() - }) -} - -fn decode_payload(value: &str) -> Result, CoreError> { - let normalized = value.replace('-', "+").replace('_', "/"); - let padded = format!("{normalized}{}", "=".repeat((4 - normalized.len() % 4) % 4)); - STANDARD - .decode(&padded) - .or_else(|_| URL_SAFE.decode(value)) - .map_err(|error| { - CoreError::new( - ErrorCode::ParseFailed, - "Authorization payload was not valid Base64", - ) - .with_details(error.to_string()) - }) -} - -fn random_identifier(byte_count: usize) -> String { - let mut bytes = vec![0_u8; byte_count]; - OsRng.fill_bytes(&mut bytes); - URL_SAFE_NO_PAD.encode(bytes) -} - -fn unix_timestamp() -> Result { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|duration| duration.as_secs()) - .map_err(|error| { - CoreError::new(ErrorCode::Unknown, "System clock is before the Unix epoch") - .with_details(error.to_string()) - }) -} - -fn api_url(context: &DiscourseAPIContext, path: &str) -> Result { - if context.user_api_key.trim().is_empty() || context.client_id.trim().is_empty() { - return Err(CoreError::new( - ErrorCode::InvalidRequest, - "Discourse credential and client ID are required", - )); - } - validated_origin(&context.origin)? - .join(path) - .map_err(|error| { - CoreError::new(ErrorCode::InvalidRequest, "Invalid Discourse API path") - .with_details(error.to_string()) - }) -} - -fn authenticated_request( - context: &DiscourseAPIContext, - method: reqwest::Method, - url: Url, -) -> Result { - let client = Client::builder() - .timeout(REQUEST_TIMEOUT) - .build() - .map_err(|error| network_error("Could not initialize the Discourse client", error))?; - Ok(client - .request(method, url) - .header(ACCEPT, "application/json") - .header(USER_AGENT, CLIENT_USER_AGENT) - .header("User-Api-Key", context.user_api_key.trim()) - .header("User-Api-Client-Id", context.client_id.trim())) -} - -fn get_json Deserialize<'de>>( - context: &DiscourseAPIContext, - url: Url, -) -> Result { - let response = authenticated_request(context, reqwest::Method::GET, url)?.send(); - let bytes = read_limited_response(checked_response(response)?)?; - serde_json::from_slice(&bytes).map_err(|error| { - CoreError::new(ErrorCode::ParseFailed, "Discourse returned invalid JSON") - .with_details(error.to_string()) - }) -} - -fn checked_response(response: Result) -> Result { - let response = response.map_err(|error| network_error("Discourse request failed", error))?; - let status = response.status(); - if status.is_success() { - return Ok(response); - } - let (code, message) = match status.as_u16() { - 401 | 403 => ( - ErrorCode::PermissionDenied, - "LINUX DO authorization was rejected or has expired", - ), - 404 => ( - ErrorCode::InvalidRequest, - "Discourse resource was not found", - ), - 429 => (ErrorCode::TimedOut, "Discourse rate limit was reached"), - _ => (ErrorCode::Unknown, "Discourse request was unsuccessful"), - }; - Err(CoreError::new(code, message).with_details(status.as_u16().to_string())) -} - -fn read_limited_response(response: Response) -> Result, CoreError> { - if response - .headers() - .get(CONTENT_LENGTH) - .and_then(|value| value.to_str().ok()) - .and_then(|value| value.parse::().ok()) - .is_some_and(|length| length > MAX_RESPONSE_BYTES) - { - return Err(CoreError::new( - ErrorCode::ParseFailed, - "Discourse response exceeded the 5 MB limit", - )); - } - let mut bytes = Vec::new(); - response - .take(MAX_RESPONSE_BYTES + 1) - .read_to_end(&mut bytes) - .map_err(|error| { - CoreError::new(ErrorCode::Unknown, "Could not read the Discourse response") - .with_details(error.to_string()) - })?; - if bytes.len() as u64 > MAX_RESPONSE_BYTES { - return Err(CoreError::new( - ErrorCode::ParseFailed, - "Discourse response exceeded the 5 MB limit", - )); - } - Ok(bytes) -} - -fn sanitize_posts(mut posts: Vec) -> Vec { - for post in &mut posts { - post.cooked = ammonia::clean(&post.cooked); - } - posts.sort_by_key(|post| post.post_number); - posts -} - -fn network_error(message: &str, error: reqwest::Error) -> CoreError { - let code = if error.is_timeout() { - ErrorCode::TimedOut - } else { - ErrorCode::Unknown - }; - // Library diagnostics can include the request URL but never request headers. - CoreError::new(code, message).with_details(error.to_string()) -} - -#[cfg(test)] -mod tests { - use super::*; - use rsa::pkcs1::DecodeRsaPublicKey; - use serde_json::json; - - #[test] - fn begin_builds_a_least_privilege_oaep_authorization_url() { - let result = begin_authorization(DiscourseAuthorizationBeginRequest { - origin: "https://linux.do".into(), - client_id: "app.lithe.linux-do".into(), - application_name: "Lithe".into(), - auth_redirect: "lithe://auth/linux-do".into(), - scopes: vec!["session_info".into(), "read".into(), "read".into()], - }) - .unwrap(); - let url = Url::parse(&result.authorization_url).unwrap(); - let query = url.query_pairs().collect::>(); - - assert_eq!( - url.as_str().split('?').next().unwrap(), - "https://linux.do/user-api-key/new" - ); - assert_eq!(query["scopes"], "read,session_info"); - assert_eq!(query["padding"], "oaep"); - assert_eq!(query["auth_redirect"], "lithe://auth/linux-do"); - RsaPublicKey::from_pkcs1_pem(&query["public_key"]).unwrap(); - } - - #[test] - fn rejects_insecure_origins_and_unknown_scopes() { - for request in [ - DiscourseAuthorizationBeginRequest { - origin: "http://linux.do".into(), - client_id: "client".into(), - application_name: "Lithe".into(), - auth_redirect: "lithe://auth/linux-do".into(), - scopes: vec!["read".into()], - }, - DiscourseAuthorizationBeginRequest { - origin: "https://linux.do".into(), - client_id: "client".into(), - application_name: "Lithe".into(), - auth_redirect: "lithe://auth/linux-do".into(), - scopes: vec!["admin".into()], - }, - ] { - assert!(begin_authorization(request).is_err()); - } - } - - #[test] - fn completes_an_oaep_callback_once_and_verifies_the_nonce() { - let begun = begin_authorization(DiscourseAuthorizationBeginRequest { - origin: "https://linux.do".into(), - client_id: "app.lithe.linux-do".into(), - application_name: "Lithe".into(), - auth_redirect: "lithe://auth/linux-do".into(), - scopes: vec!["read".into()], - }) - .unwrap(); - let (public_key, nonce) = { - let pending = pending_authorizations().lock().unwrap(); - let authorization = pending.get(&begun.flow_id).unwrap(); - ( - RsaPublicKey::from(&authorization.private_key), - authorization.nonce.clone(), - ) - }; - let cleartext = serde_json::to_vec(&json!({ - "key": "test-user-api-key", - "nonce": nonce, - "api": 4 - })) - .unwrap(); - let encrypted = public_key - .encrypt(&mut OsRng, Oaep::new::(), &cleartext) - .unwrap(); - let mut callback = Url::parse("lithe://auth/linux-do").unwrap(); - callback - .query_pairs_mut() - .append_pair("payload", &URL_SAFE_NO_PAD.encode(encrypted)); - - let completed = complete_authorization(DiscourseAuthorizationCompleteRequest { - flow_id: begun.flow_id.clone(), - callback_url: callback.to_string(), - }) - .unwrap(); - - assert_eq!(completed.user_api_key, "test-user-api-key"); - assert_eq!(completed.api_version, 4); - assert!( - complete_authorization(DiscourseAuthorizationCompleteRequest { - flow_id: begun.flow_id, - callback_url: callback.to_string(), - }) - .is_err() - ); - } - - #[test] - fn sanitizes_and_orders_post_html() { - let posts = sanitize_posts(vec![ - DiscoursePost { - id: 2, - post_number: 2, - username: "second".into(), - name: None, - cooked: "

Safe

".into(), - created_at: None, - updated_at: None, - reply_count: 0, - reads: 0, - }, - DiscoursePost { - id: 1, - post_number: 1, - username: "first".into(), - name: None, - cooked: "

First

".into(), - created_at: None, - updated_at: None, - reply_count: 0, - reads: 0, - }, - ]); - - assert_eq!(posts[0].post_number, 1); - assert!(!posts[1].cooked.contains("script")); - assert!(posts[1].cooked.contains("Safe")); - } -} diff --git a/rust/lithe-core/src/community/mod.rs b/rust/lithe-core/src/community/mod.rs deleted file mode 100644 index c2408ff3..00000000 --- a/rust/lithe-core/src/community/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Shared community integrations and their cross-platform protocol boundaries. - -mod discourse; - -pub(crate) use discourse::{ - begin_authorization, categories, complete_authorization, revoke, search, topic, topics, - DiscourseAuthorizationBeginRequest, DiscourseAuthorizationCompleteRequest, - DiscourseCategoriesRequest, DiscourseRevokeRequest, DiscourseSearchRequest, - DiscourseTopicRequest, DiscourseTopicsRequest, -}; diff --git a/rust/lithe-core/src/git/workspace_status.rs b/rust/lithe-core/src/git/workspace_status.rs index 5e2c17d0..70918a07 100644 --- a/rust/lithe-core/src/git/workspace_status.rs +++ b/rust/lithe-core/src/git/workspace_status.rs @@ -99,7 +99,6 @@ pub(crate) fn plan(request: Request) -> Result { #[cfg(test)] mod tests { - use super::*; use serde_json::json; fn call(payload: serde_json::Value) -> serde_json::Value { diff --git a/rust/lithe-core/src/lib.rs b/rust/lithe-core/src/lib.rs index 3a87ef85..5713371e 100644 --- a/rust/lithe-core/src/lib.rs +++ b/rust/lithe-core/src/lib.rs @@ -2,7 +2,6 @@ mod action_search; mod build; -mod community; mod debug; pub mod diagnostics; mod diff; diff --git a/rust/lithe-core/src/lsp/interface/plugin_function.rs b/rust/lithe-core/src/lsp/interface/plugin_function.rs index 22bf0deb..3c55dabe 100644 --- a/rust/lithe-core/src/lsp/interface/plugin_function.rs +++ b/rust/lithe-core/src/lsp/interface/plugin_function.rs @@ -1774,6 +1774,7 @@ pub(crate) fn host_failure(code: Option<&str>) -> (&'static str, i64) { Some(codes::HOST_TOOL_UNRESOLVED) => codes::HOST_TOOL_UNRESOLVED, Some(codes::HOST_FOREIGN_CONTRIBUTION) => codes::HOST_FOREIGN_CONTRIBUTION, // A backend exit is reported to pages, never to the backend itself. + Some(codes::BACKEND_EXITED) => codes::HOST_FAILED, _ => codes::HOST_FAILED, }; (code, host_rpc_code(code)) diff --git a/rust/lithe-core/src/network/mod.rs b/rust/lithe-core/src/network/mod.rs index 4b2dc987..153267b1 100644 --- a/rust/lithe-core/src/network/mod.rs +++ b/rust/lithe-core/src/network/mod.rs @@ -8,10 +8,7 @@ pub(crate) mod proxy; -pub(crate) use proxy::{ - proxy_policy, NetworkProxyMode, NetworkProxyPolicy, NetworkProxyPolicyKind, - NetworkProxyPolicyRequest, NetworkProxyType, -}; +pub(crate) use proxy::{proxy_policy, NetworkProxyPolicyRequest}; #[cfg(test)] mod tests; diff --git a/rust/lithe-core/src/protocol/command.rs b/rust/lithe-core/src/protocol/command.rs index 02619e61..f5d6c5a0 100644 --- a/rust/lithe-core/src/protocol/command.rs +++ b/rust/lithe-core/src/protocol/command.rs @@ -274,20 +274,6 @@ pub enum CoreCommand { PluginsMarketplaceResolveSource, /// Lists a package's permissions and programs before installation (`plugins.marketplace.installReview`). PluginsMarketplaceInstallReview, - /// Starts a Discourse user API key authorization (`community.discourse.auth.begin`). - CommunityDiscourseAuthBegin, - /// Decrypts and verifies a Discourse authorization callback (`community.discourse.auth.complete`). - CommunityDiscourseAuthComplete, - /// Lists normalized latest or top Discourse topics (`community.discourse.topics`). - CommunityDiscourseTopics, - /// Reads one normalized Discourse topic (`community.discourse.topic`). - CommunityDiscourseTopic, - /// Lists normalized Discourse categories (`community.discourse.categories`). - CommunityDiscourseCategories, - /// Searches Discourse topics and posts (`community.discourse.search`). - CommunityDiscourseSearch, - /// Revokes the current Discourse user API key (`community.discourse.auth.revoke`). - CommunityDiscourseAuthRevoke, /// Builds the visible project tree (`workspace.snapshot`). WorkspaceSnapshot, /// Configure workspace indexing independently of tree visibility. @@ -946,13 +932,6 @@ impl CoreCommand { "plugins.marketplace.validateIndex" => Some(Self::PluginsMarketplaceValidateIndex), "plugins.marketplace.resolveSource" => Some(Self::PluginsMarketplaceResolveSource), "plugins.marketplace.installReview" => Some(Self::PluginsMarketplaceInstallReview), - "community.discourse.auth.begin" => Some(Self::CommunityDiscourseAuthBegin), - "community.discourse.auth.complete" => Some(Self::CommunityDiscourseAuthComplete), - "community.discourse.topics" => Some(Self::CommunityDiscourseTopics), - "community.discourse.topic" => Some(Self::CommunityDiscourseTopic), - "community.discourse.categories" => Some(Self::CommunityDiscourseCategories), - "community.discourse.search" => Some(Self::CommunityDiscourseSearch), - "community.discourse.auth.revoke" => Some(Self::CommunityDiscourseAuthRevoke), "workspace.snapshot" => Some(Self::WorkspaceSnapshot), "workspace.releaseIndexing" => Some(Self::WorkspaceReleaseIndexing), "workspace.configureIndexing" => Some(Self::WorkspaceConfigureIndexing), @@ -1327,21 +1306,6 @@ mod tests { } } - #[test] - fn parses_discourse_authorization_commands() { - for command in [ - "community.discourse.auth.begin", - "community.discourse.auth.complete", - "community.discourse.auth.revoke", - "community.discourse.categories", - "community.discourse.search", - "community.discourse.topic", - "community.discourse.topics", - ] { - assert!(CoreCommand::parse(command).is_some(), "missing {command}"); - } - } - #[test] fn parses_network_proxy_policy_command() { assert!(CoreCommand::parse("network.proxyPolicy").is_some()); diff --git a/rust/lithe-core/src/runtime/dispatcher.rs b/rust/lithe-core/src/runtime/dispatcher.rs index d96c4323..8d6b8f9a 100644 --- a/rust/lithe-core/src/runtime/dispatcher.rs +++ b/rust/lithe-core/src/runtime/dispatcher.rs @@ -1,10 +1,5 @@ //! Validation and routing from versioned command names to their owning domains. -use crate::community::{ - self, DiscourseAuthorizationBeginRequest, DiscourseAuthorizationCompleteRequest, - DiscourseCategoriesRequest, DiscourseRevokeRequest, DiscourseSearchRequest, - DiscourseTopicRequest, DiscourseTopicsRequest, -}; use crate::diagnostics::{BuildManifestRequest, RedactTextRequest}; use crate::git::{ self, GitApplyRequest, GitBlameRequest, GitBranchNamePreviewRequest, @@ -684,128 +679,6 @@ fn execute_parsed(mut parsed: CoreRequest, document: Option<&str>) -> CoreRespon parsed.payload, crate::plugins::marketplace::install_review_command, ), - CoreCommand::CommunityDiscourseAuthBegin => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid Discourse authorization request", - ) - .with_details(error.to_string()) - }) - .and_then(community::begin_authorization) - { - Ok(data) => CoreResponse::success( - id, - serde_json::to_value(data) - .expect("Discourse authorization response should encode"), - ), - Err(error) => CoreResponse::failure(id, error), - } - } - CoreCommand::CommunityDiscourseAuthComplete => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid Discourse authorization callback", - ) - .with_details(error.to_string()) - }) - .and_then(community::complete_authorization) - { - Ok(data) => CoreResponse::success( - id, - serde_json::to_value(data) - .expect("Discourse authorization credential should encode"), - ), - Err(error) => CoreResponse::failure(id, error), - } - } - CoreCommand::CommunityDiscourseTopics => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid Discourse topics request", - ) - .with_details(error.to_string()) - }) - .and_then(community::topics) - { - Ok(data) => CoreResponse::success( - id, - serde_json::to_value(data).expect("Discourse topics should encode"), - ), - Err(error) => CoreResponse::failure(id, error), - } - } - CoreCommand::CommunityDiscourseTopic => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new(ErrorCode::InvalidRequest, "Invalid Discourse topic request") - .with_details(error.to_string()) - }) - .and_then(community::topic) - { - Ok(data) => CoreResponse::success( - id, - serde_json::to_value(data).expect("Discourse topic should encode"), - ), - Err(error) => CoreResponse::failure(id, error), - } - } - CoreCommand::CommunityDiscourseCategories => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid Discourse categories request", - ) - .with_details(error.to_string()) - }) - .and_then(community::categories) - { - Ok(data) => CoreResponse::success( - id, - serde_json::to_value(data).expect("Discourse categories should encode"), - ), - Err(error) => CoreResponse::failure(id, error), - } - } - CoreCommand::CommunityDiscourseSearch => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid Discourse search request", - ) - .with_details(error.to_string()) - }) - .and_then(community::search) - { - Ok(data) => CoreResponse::success( - id, - serde_json::to_value(data).expect("Discourse search should encode"), - ), - Err(error) => CoreResponse::failure(id, error), - } - } - CoreCommand::CommunityDiscourseAuthRevoke => { - match serde_json::from_value::(parsed.payload) - .map_err(|error| { - CoreError::new( - ErrorCode::InvalidRequest, - "Invalid Discourse revoke request", - ) - .with_details(error.to_string()) - }) - .and_then(community::revoke) - { - Ok(data) => CoreResponse::success(id, data), - Err(error) => CoreResponse::failure(id, error), - } - } CoreCommand::WorkspaceReleaseIndexing => { match serde_json::from_value::( parsed.payload, diff --git a/rust/lithe-core/src/tests/protocol.rs b/rust/lithe-core/src/tests/protocol.rs index 16bf67f3..7810893a 100644 --- a/rust/lithe-core/src/tests/protocol.rs +++ b/rust/lithe-core/src/tests/protocol.rs @@ -516,6 +516,14 @@ fn every_ai_crate_command_is_routed_by_core() { assert_eq!(budgets["data"]["files"][0]["characters"], 20); } +#[test] +fn unparseable_requests_fail_without_an_id() { + let response: Value = serde_json::from_str(&execute_json("{")).unwrap(); + assert_eq!(response["ok"], false); + assert_eq!(response["error"]["code"], "invalid_request"); + assert!(response["id"].is_null()); +} + #[test] fn terminal_link_fixtures_cross_the_json_boundary() { let fixture: Value = serde_json::from_str(include_str!( diff --git a/rust/lithe-git-host/src/configuration.rs b/rust/lithe-git-host/src/configuration.rs index 62107550..427b28ce 100644 --- a/rust/lithe-git-host/src/configuration.rs +++ b/rust/lithe-git-host/src/configuration.rs @@ -49,6 +49,7 @@ fn launch_path(path: PathBuf) -> PathBuf { } /// Verbatim (`\\?\`) and UNC (`\\server`) paths keep their native form because `/` is not valid there. +#[cfg(any(windows, test))] fn forward_slash_path(path: &str) -> String { if path.starts_with(r"\\") { path.to_owned() From 8a89a0f139240e4f3d06de7aa4c5ca32643fd3d0 Mon Sep 17 00:00:00 2001 From: Yao Jingxi <23722032@bjtu.edu.cn> Date: Sat, 14 Nov 2026 01:13:22 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor(core):=20crate=20=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E6=94=BE=E5=88=B0=20rust/crates/=EF=BC=8C=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E9=97=A8=E7=A6=81=E8=A6=86=E7=9B=96=E5=85=A8=E9=83=A8?= =?UTF-8?q?=20crate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 六个 crate 从 rust/lithe-*/ 移到 rust/crates/<包名去掉 lithe- 前缀>/,包名不变;工作区成员改为 crates/* - 同步更新路径引用:Cargo 路径依赖、SDK e2e 测试路径、fixture 和契约文档里的源码路径、README 目录表 - C 头文件的位置变为 rust/crates/core/include/lithe_core.h - 注释门禁改为遍历 rust/crates/ 下的全部 crate;lithe-remote 缺 404 处公开项文档(1lck/Lithe-IDEA#1863),暂时只跳过它的 missing_docs,链接检查照常进行 - 为 lithe-git-host、lithe-ide-host 的公开项补齐文档,把 log-exempt 注释改成英文 - search_index 测试的权限写成八进制 0o000,修复 clippy 的 deny 级 lint --- README.md | 16 +++-- rust/Cargo.toml | 2 +- rust/contracts/ai-commit.md | 2 +- rust/contracts/ai-generation-requests.md | 2 +- rust/contracts/ide-api/v1.md | 2 +- .../contracts/remote-workspace-protocol-v1.md | 2 +- rust/contracts/rust-core-api.md | 10 +-- rust/{lithe-ai => crates/ai}/Cargo.toml | 0 .../ai}/src/agent_configuration.rs | 0 rust/{lithe-ai => crates/ai}/src/commands.rs | 0 .../ai}/src/configuration.rs | 0 rust/{lithe-ai => crates/ai}/src/dispatch.rs | 0 rust/{lithe-ai => crates/ai}/src/error.rs | 0 .../{lithe-ai => crates/ai}/src/generation.rs | 0 .../ai}/src/inline_edit.rs | 0 rust/{lithe-ai => crates/ai}/src/lib.rs | 0 .../ai}/src/provider_request.rs | 0 .../ai}/src/pull_request.rs | 0 .../ai}/src/request_tests.rs | 4 +- rust/{lithe-ai => crates/ai}/src/tests.rs | 11 ++- .../core-rules}/Cargo.toml | 0 .../core-rules}/src/dispatch.rs | 0 .../core-rules}/src/editor/mod.rs | 0 .../core-rules}/src/editor/workbench_state.rs | 0 .../core-rules}/src/error.rs | 0 .../core-rules}/src/keymap/mod.rs | 0 .../src/keymap/modifier_gesture.rs | 0 .../core-rules}/src/lib.rs | 0 .../core-rules}/src/visibility.rs | 0 .../src/workbench/chrome_layout.rs | 0 .../core-rules}/src/workbench/mod.rs | 0 .../tests/modifier_gesture_fixture.rs | 2 +- .../core-rules}/tests/visibility_fixture.rs | 2 +- .../tests/workbench_state_fixture.rs | 2 +- rust/{lithe-core => crates/core}/Cargo.toml | 20 +++--- .../core}/include/lithe_core.h | 0 .../core}/src/action_search/mod.rs | 2 +- .../core}/src/build/commands.rs | 0 .../core}/src/build/configuration.rs | 0 .../core}/src/build/debug_preparation.rs | 0 .../core}/src/build/decode.rs | 0 .../core}/src/build/detect.rs | 0 .../core}/src/build/invocation.rs | 0 .../core}/src/build/manifest.rs | 0 .../core}/src/build/mod.rs | 0 .../core}/src/build/model.rs | 0 .../core}/src/build/model_inputs.rs | 0 .../core}/src/build/options.rs | 0 .../core}/src/build/outputs.rs | 0 .../core}/src/build/plans.rs | 0 .../core}/src/build/project_options.rs | 0 .../core}/src/build/run_preparation.rs | 0 .../core}/src/build/run_start.rs | 0 .../core}/src/build/select.rs | 0 .../core}/src/build/stored_options.rs | 0 .../core}/src/build/template.rs | 0 .../core}/src/build/test_discovery.rs | 0 .../core}/src/build/test_outcome.rs | 2 +- .../core}/src/build/test_outcome_merge.rs | 2 +- .../core}/src/debug/adapters.rs | 0 .../core}/src/debug/backend_start.rs | 0 .../core}/src/debug/breakpoint_relocation.rs | 0 .../core}/src/debug/capabilities.rs | 0 .../core}/src/debug/disassembly_paging.rs | 2 +- .../core}/src/debug/endpoint.rs | 2 +- .../core}/src/debug/engine.rs | 24 +++---- .../core}/src/debug/memory_window.rs | 2 +- .../core}/src/debug/mod.rs | 0 .../core}/src/debug/projection_v2.rs | 2 +- .../core}/src/debug/protocol.rs | 0 .../core}/src/debug/shortcut.rs | 0 .../core}/src/debug/transport_lifecycle.rs | 2 +- .../core}/src/debug/types.rs | 0 .../core}/src/debug/variable_paging.rs | 2 +- .../core}/src/diagnostics/catalog.rs | 0 .../src/diagnostics/catalog_generated.rs | 0 .../core}/src/diagnostics/channel.rs | 0 .../core}/src/diagnostics/collection.rs | 2 +- .../core}/src/diagnostics/core_events.rs | 0 .../core}/src/diagnostics/filter.rs | 0 .../core}/src/diagnostics/format.rs | 0 .../core}/src/diagnostics/helper_failures.rs | 0 .../core}/src/diagnostics/logging.rs | 4 +- .../core}/src/diagnostics/manifest.rs | 0 .../core}/src/diagnostics/mod.rs | 0 .../src/diagnostics/plugin_operations.rs | 2 +- .../core}/src/diagnostics/query_v2.rs | 0 .../core}/src/diagnostics/record.rs | 2 +- .../core}/src/diagnostics/redaction.rs | 0 .../core}/src/diagnostics/request_trace.rs | 0 .../core}/src/diagnostics/retention.rs | 0 .../core}/src/diff/mod.rs | 0 .../core}/src/diff/tests.rs | 2 +- .../core}/src/editor/find.rs | 0 .../core}/src/editor/line_edit.rs | 0 .../core}/src/editor/mod.rs | 0 .../core}/src/editor/navigation_history.rs | 0 .../core}/src/editor/navigation_input.rs | 0 .../core}/src/editor/preferences.rs | 0 .../core}/src/editor/recent.rs | 0 .../core}/src/editor/recovery.rs | 0 .../core}/src/editor/tests.rs | 8 +-- .../core}/src/editor/text_edit_plan.rs | 0 .../core}/src/execution/argument_text.rs | 4 +- .../core}/src/execution/configuration.rs | 0 .../configuration/project_toolchain.rs | 0 .../core}/src/execution/context_selection.rs | 2 +- .../core}/src/execution/detectors/cargo.rs | 0 .../core}/src/execution/detectors/compose.rs | 0 .../core}/src/execution/detectors/go.rs | 0 .../core}/src/execution/detectors/make.rs | 0 .../core}/src/execution/detectors/mod.rs | 0 .../core}/src/execution/detectors/npm.rs | 0 .../core}/src/execution/detectors/procfile.rs | 0 .../core}/src/execution/detectors/python.rs | 0 .../core}/src/execution/detectors/scan.rs | 0 .../core}/src/execution/detectors/shell.rs | 0 .../core}/src/execution/environment.rs | 4 +- .../core}/src/execution/generated_layer.rs | 0 .../core}/src/execution/mod.rs | 0 .../src/execution/provider_run_options.rs | 0 .../core}/src/execution/provider_runs.rs | 0 .../core}/src/execution/title_action.rs | 2 +- .../core}/src/execution/types.rs | 0 .../core}/src/execution/workspace_scan.rs | 0 .../core}/src/git/authentication_failure.rs | 2 +- .../core}/src/git/branch_names.rs | 0 .../core}/src/git/catalog.rs | 0 .../core}/src/git/change_targets.rs | 7 +- .../core}/src/git/changelists.rs | 2 +- .../core}/src/git/command_trace.rs | 0 .../core}/src/git/commit_message_context.rs | 0 .../core}/src/git/commit_selection.rs | 2 +- .../core}/src/git/commit_state.rs | 0 .../core}/src/git/configuration.rs | 7 +- .../core}/src/git/console/command.rs | 0 .../core}/src/git/console/mod.rs | 0 .../core}/src/git/console/output.rs | 0 .../core}/src/git/console/tests.rs | 2 +- .../core}/src/git/console/types.rs | 0 .../core}/src/git/deleted_selection.rs | 0 .../core}/src/git/diff_blocks.rs | 0 .../core}/src/git/execution_events.rs | 2 +- .../core}/src/git/execution_policy.rs | 4 +- .../core}/src/git/fetch.rs | 2 +- .../core}/src/git/fetch_execution.rs | 0 .../core}/src/git/file_context.rs | 0 .../core}/src/git/github_checkout.rs | 0 .../core}/src/git/graph.rs | 0 .../core}/src/git/graph_tests.rs | 4 +- .../core}/src/git/history.rs | 9 +-- .../core}/src/git/history_query.rs | 0 .../core}/src/git/history_window.rs | 7 +- .../core}/src/git/metadata_watch.rs | 0 .../core}/src/git/mod.rs | 21 +++--- .../core}/src/git/mutations.rs | 0 .../core}/src/git/patch_exchange.rs | 0 .../core}/src/git/progress.rs | 2 +- .../core}/src/git/rebase_session.rs | 4 +- .../core}/src/git/reference_tree.rs | 7 +- .../core}/src/git/remote_history.rs | 0 .../core}/src/git/remote_process.rs | 0 .../core}/src/git/repository_colors.rs | 0 .../core}/src/git/rewrite.rs | 0 .../core}/src/git/rollback.rs | 0 .../core}/src/git/setup.rs | 0 .../core}/src/git/shelf.rs | 0 .../core}/src/git/untracked_directories.rs | 0 .../core}/src/git/update_plan.rs | 2 +- .../core}/src/git/workspace_commit.rs | 0 .../src/git/workspace_commit/path_scope.rs | 0 .../core}/src/git/workspace_commit/tests.rs | 4 +- .../core}/src/git/workspace_status.rs | 0 .../core}/src/github/mod.rs | 0 .../core}/src/keymap/bindings.rs | 0 .../core}/src/keymap/mod.rs | 0 .../core}/src/keymap/schemes.rs | 0 rust/{lithe-core => crates/core}/src/lib.rs | 2 +- .../core}/src/lsp/declaration_or_usages.rs | 2 +- .../core}/src/lsp/document_identity.rs | 2 +- .../core}/src/lsp/host_policy/activation.rs | 0 .../src/lsp/host_policy/completion_merge.rs | 0 .../core}/src/lsp/host_policy/mod.rs | 0 .../core}/src/lsp/host_policy/problems.rs | 0 .../core}/src/lsp/host_policy/tests.rs | 8 +-- .../core}/src/lsp/interface/build_provider.rs | 2 +- .../core}/src/lsp/interface/client.rs | 4 +- .../core}/src/lsp/interface/document_uri.rs | 0 .../core}/src/lsp/interface/engine.rs | 10 +-- .../lsp/interface/engine_function_provider.rs | 2 +- .../lsp/interface/engine_function_relay.rs | 0 .../interface/engine_function_relay_tests.rs | 0 .../core}/src/lsp/interface/engine_logging.rs | 0 .../core}/src/lsp/interface/function_relay.rs | 0 .../src/lsp/interface/keymap_provider.rs | 2 +- .../core}/src/lsp/interface/mod.rs | 0 .../src/lsp/interface/plugin_function.rs | 2 +- .../core}/src/lsp/interface/plugin_logging.rs | 2 +- .../core}/src/lsp/interface/plugin_server.rs | 0 .../core}/src/lsp/interface/process.rs | 0 .../core}/src/lsp/interface/remote_process.rs | 0 .../core}/src/lsp/interface/scripted.rs | 0 .../src/lsp/interface/toolchain_provider.rs | 0 .../core}/src/lsp/interface/transport.rs | 0 .../core}/src/lsp/interface/types.rs | 0 .../core}/src/lsp/interface/vcs_provider.rs | 0 .../core}/src/lsp/languages/indexing.rs | 0 .../core}/src/lsp/languages/mod.rs | 0 .../core}/src/lsp/languages/swift.rs | 0 .../core}/src/lsp/lightweight/edits.rs | 0 .../core}/src/lsp/lightweight/mod.rs | 0 .../core}/src/lsp/lightweight/snippets.rs | 0 .../core}/src/lsp/lightweight/symbols.rs | 0 .../core}/src/lsp/mod.rs | 0 .../core}/src/lsp/navigation_target.rs | 2 +- .../core}/src/lsp/tests.rs | 18 +++-- .../core}/src/lsp/workspace_edit_plan.rs | 2 +- .../core}/src/lsp/workspace_scope.rs | 0 .../core}/src/network/mod.rs | 0 .../core}/src/network/proxy.rs | 0 .../core}/src/network/tests.rs | 2 +- .../core}/src/plugins/backend.rs | 0 .../core}/src/plugins/capabilities.rs | 0 .../core}/src/plugins/content_providers.rs | 0 .../core}/src/plugins/declarative.rs | 0 .../core}/src/plugins/editor_actions.rs | 2 +- .../core}/src/plugins/editor_providers.rs | 2 +- .../core}/src/plugins/executables.rs | 0 .../core}/src/plugins/grammar.rs | 0 .../core}/src/plugins/host_api.rs | 7 +- .../core}/src/plugins/installed.rs | 2 +- .../core}/src/plugins/keymap_import.rs | 19 +++--- .../src/plugins/language_server_sessions.rs | 0 .../core}/src/plugins/marketplace.rs | 0 .../core}/src/plugins/mod.rs | 0 .../core}/src/plugins/native_ui.rs | 0 .../core}/src/plugins/output_links.rs | 0 .../core}/src/plugins/plugin_functions.rs | 0 .../core}/src/plugins/settings.rs | 0 .../src/plugins/settings_document_tests.rs | 18 ++--- .../core}/src/plugins/settings_documents.rs | 0 .../core}/src/plugins/settings_pages.rs | 0 .../core}/src/plugins/settings_surfaces.rs | 0 .../core}/src/plugins/web_content.rs | 0 .../core}/src/plugins/web_content_tests.rs | 2 +- .../core}/src/process/inventory.rs | 2 +- .../core}/src/process/lifecycle.rs | 4 +- .../core}/src/process/mod.rs | 0 .../core}/src/project/directory_actions.rs | 0 .../core}/src/project/document_lifecycle.rs | 0 .../core}/src/project/document_save_batch.rs | 0 .../core}/src/project/encoding.rs | 0 .../core}/src/project/file_name_order.rs | 0 .../core}/src/project/file_operations.rs | 0 .../core}/src/project/files.rs | 4 +- .../core}/src/project/history.rs | 0 .../core}/src/project/indexing.rs | 4 +- .../core}/src/project/markdown.rs | 4 +- .../core}/src/project/mod.rs | 0 .../core}/src/project/name_matching.rs | 2 +- .../core}/src/project/name_ranking.rs | 0 .../core}/src/project/recent_projects.rs | 0 .../core}/src/project/search_index.rs | 5 +- .../core}/src/project/search_paging.rs | 0 .../core}/src/project_generators/archive.rs | 0 .../core}/src/project_generators/commands.rs | 0 .../core}/src/project_generators/form.rs | 0 .../core}/src/project_generators/manifest.rs | 0 .../core}/src/project_generators/mod.rs | 0 .../core}/src/project_generators/plan.rs | 0 .../core}/src/project_generators/template.rs | 0 .../core}/src/protocol/cancellation.rs | 0 .../core}/src/protocol/command.rs | 2 +- .../core}/src/protocol/contracts.rs | 0 .../core}/src/protocol/error.rs | 0 .../core}/src/protocol/event.rs | 0 .../core}/src/protocol/json_document.rs | 0 .../core}/src/protocol/mod.rs | 0 .../core}/src/remote/mod.rs | 0 .../core}/src/remote/sessions.rs | 0 .../src/remote/sessions_integration_tests.rs | 4 +- .../core}/src/remote/tests.rs | 0 .../core}/src/remote/upload.rs | 0 .../core}/src/remote/workspace.rs | 0 .../core}/src/remote/workspace_host.rs | 0 .../core}/src/remote/workspace_host/tests.rs | 0 .../core}/src/remote/workspace_io.rs | 0 .../core}/src/runtime/dispatcher.rs | 0 .../core}/src/runtime/ffi.rs | 4 +- .../core}/src/runtime/mod.rs | 0 .../core}/src/terminal/link.rs | 0 .../core}/src/terminal/mod.rs | 0 .../core}/src/tests/build_configuration.rs | 4 +- .../core}/src/tests/build_project_options.rs | 8 +-- .../core}/src/tests/build_runtime_versions.rs | 2 +- .../core}/src/tests/build_systems.rs | 2 +- .../src/tests/community_build_plugins.rs | 0 .../core}/src/tests/core_request_traces.rs | 0 .../core}/src/tests/declarative_plugins.rs | 2 +- .../core}/src/tests/detectors.rs | 0 .../core}/src/tests/directory_actions.rs | 4 +- .../core}/src/tests/file_name_order.rs | 4 +- .../core}/src/tests/file_operations.rs | 2 +- .../branch-name-cleanup-parity-v1.json | 0 .../gradle/app-dependencies.json | 0 .../gradle/dependencies.json | 0 .../community_build_plugins/gradle/model.json | 0 .../gradle/plugin.json | 0 .../maven/app-dependencies.json | 0 .../maven/dependencies.json | 0 .../community_build_plugins/maven/model.json | 0 .../community_build_plugins/maven/plugin.json | 0 .../core}/src/tests/git.rs | 24 ++++--- .../core}/src/tests/git_diff_blocks.rs | 2 +- .../core}/src/tests/git_fetch.rs | 2 +- .../core}/src/tests/git_history_rewrite.rs | 4 +- .../core}/src/tests/git_patch_exchange.rs | 21 +++--- .../core}/src/tests/git_remote_checkout.rs | 2 +- .../src/tests/git_repository_discovery.rs | 2 +- .../core}/src/tests/git_repository_setup.rs | 0 .../src/tests/git_untracked_directories.rs | 0 .../core}/src/tests/git_workspace_commit.rs | 2 +- .../core}/src/tests/github.rs | 4 +- .../core}/src/tests/history_events.rs | 6 +- .../src/tests/language_server_sessions.rs | 2 +- .../core}/src/tests/marketplace_plugins.rs | 2 +- .../core}/src/tests/mod.rs | 0 .../src/tests/plugin_editor_resources.rs | 2 +- .../core}/src/tests/plugin_run_debug.rs | 2 +- .../core}/src/tests/project.rs | 34 ++++++---- .../core}/src/tests/project_generators.rs | 12 ++-- .../core}/src/tests/protocol.rs | 22 +++--- .../core}/src/tests/rank_names.rs | 9 +-- .../core}/src/tests/run_configuration.rs | 17 ++--- .../core}/src/tests/support.rs | 2 +- .../core}/src/tests/toolchain_definitions.rs | 8 +-- .../core}/src/tests/toolchain_pins.rs | 2 +- .../core}/src/tests/toolchain_queries.rs | 6 +- .../core}/src/tests/toolchain_resolution.rs | 4 +- .../core}/src/tests/toolchain_vectors.rs | 2 +- .../core}/src/tests/vcs.rs | 4 +- .../core}/src/toolchain/definitions.rs | 0 .../core}/src/toolchain/fixed.rs | 0 .../core}/src/toolchain/mod.rs | 0 .../core}/src/toolchain/paths.rs | 0 .../core}/src/toolchain/pin_sources.rs | 7 +- .../core}/src/toolchain/pins.rs | 0 .../core}/src/toolchain/preferences.rs | 2 +- .../core}/src/toolchain/query.rs | 0 .../core}/src/toolchain/resolution.rs | 0 .../core}/src/vcs/commands.rs | 0 .../core}/src/vcs/manifest.rs | 0 .../core}/src/vcs/mod.rs | 0 .../core}/src/vcs/model.rs | 0 .../core}/src/vcs/requests.rs | 0 .../core}/src/vcs/roots.rs | 0 .../core}/tests/core_log_waker.rs | 0 .../core}/tests/git_push.rs | 0 .../core}/tests/git_watch_context.rs | 0 .../git-host}/Cargo.toml | 0 .../git-host}/src/authentication.rs | 9 +++ .../git-host}/src/configuration.rs | 0 .../git-host}/src/failure_log.rs | 6 +- .../git-host}/src/lib.rs | 11 +++ .../git-host}/tests/authentication.rs | 0 .../git-host}/tests/process.rs | 0 .../ide-host}/Cargo.toml | 1 + .../ide-host}/src/bin/lithe-mcp.rs | 0 .../ide-host}/src/catalog.rs | 8 ++- .../ide-host}/src/failure_log.rs | 0 .../ide-host}/src/lib.rs | 14 ++-- .../remote}/Cargo.toml | 0 .../remote}/src/bin/lithe-remote-server.rs | 0 .../remote}/src/client/api.rs | 0 .../remote}/src/client/bootstrap.rs | 0 .../remote}/src/client/command.rs | 2 +- .../remote}/src/client/forward.rs | 4 +- .../remote}/src/client/launch.rs | 0 .../remote}/src/client/mod.rs | 0 .../remote}/src/client/session.rs | 8 +-- .../remote}/src/client/transport.rs | 0 .../remote}/src/failure_log.rs | 14 ++-- .../remote}/src/lib.rs | 0 .../remote}/src/protocol/frame.rs | 0 .../remote}/src/protocol/message.rs | 0 .../remote}/src/protocol/methods.rs | 0 .../remote}/src/protocol/mod.rs | 0 .../remote}/src/server/connection.rs | 0 .../remote}/src/server/connection/tests.rs | 0 .../remote}/src/server/daemon.rs | 0 .../remote}/src/server/environment.rs | 0 .../remote}/src/server/fs.rs | 0 .../remote}/src/server/link.rs | 0 .../remote}/src/server/mod.rs | 0 .../remote}/src/server/platform/linux.rs | 0 .../src/server/platform/linux_watch.rs | 0 .../remote}/src/server/platform/macos.rs | 0 .../src/server/platform/macos_watch.rs | 0 .../remote}/src/server/platform/mod.rs | 0 .../remote}/src/server/platform/unix.rs | 0 .../remote}/src/server/ports.rs | 0 .../remote}/src/server/process.rs | 0 .../remote}/src/server/resources.rs | 0 .../remote}/src/server/run_directory.rs | 0 .../remote}/src/server/session.rs | 0 .../remote}/src/server/spawner.rs | 0 .../remote}/src/server/terminal.rs | 0 .../remote}/src/server/tunnel.rs | 0 .../remote}/src/server/upload.rs | 0 .../remote}/src/server/upload/tests.rs | 0 .../remote}/src/server/walk.rs | 0 .../remote}/src/server/watch.rs | 0 .../remote}/tests/persistence.rs | 0 .../remote}/tests/processes.rs | 0 .../remote}/tests/run_directories.rs | 0 .../remote}/tests/server.rs | 0 .../remote}/tests/support/mod.rs | 0 .../remote}/tests/terminals.rs | 0 .../remote}/tests/tunnels.rs | 0 .../remote}/tests/watch_and_walk.rs | 0 rust/fixtures/debug/v1-baseline.json | 68 +++++++++---------- rust/logging/README.md | 14 ++-- scripts/rust-core/README.md | 5 +- .../rust-core/verify-rust-core-comments.sh | 31 +++++++-- shared/plugins/contract/v1/README.md | 6 +- .../plugins/contract/v1/toolchains/README.md | 4 +- .../reference/capabilities-and-versions.md | 4 +- .../plugins/reference/domains/toolchains.md | 4 +- .../plugins/reference/protocol-changelog.md | 4 +- shared/plugins/scripts/sdk-e2e.mjs | 2 +- shared/plugins/sdk/e2e/plugin_sdk/mod.rs | 2 +- .../github/litheidea/plugin/sdk/Protocol.java | 2 +- shared/plugins/sdk/node/src/protocol.mjs | 4 +- .../sdk/rust/plugin-sdk/src/protocol.rs | 2 +- 434 files changed, 473 insertions(+), 382 deletions(-) rename rust/{lithe-ai => crates/ai}/Cargo.toml (100%) rename rust/{lithe-ai => crates/ai}/src/agent_configuration.rs (100%) rename rust/{lithe-ai => crates/ai}/src/commands.rs (100%) rename rust/{lithe-ai => crates/ai}/src/configuration.rs (100%) rename rust/{lithe-ai => crates/ai}/src/dispatch.rs (100%) rename rust/{lithe-ai => crates/ai}/src/error.rs (100%) rename rust/{lithe-ai => crates/ai}/src/generation.rs (100%) rename rust/{lithe-ai => crates/ai}/src/inline_edit.rs (100%) rename rust/{lithe-ai => crates/ai}/src/lib.rs (100%) rename rust/{lithe-ai => crates/ai}/src/provider_request.rs (100%) rename rust/{lithe-ai => crates/ai}/src/pull_request.rs (100%) rename rust/{lithe-ai => crates/ai}/src/request_tests.rs (98%) rename rust/{lithe-ai => crates/ai}/src/tests.rs (99%) rename rust/{lithe-core-rules => crates/core-rules}/Cargo.toml (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/dispatch.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/editor/mod.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/editor/workbench_state.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/error.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/keymap/mod.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/keymap/modifier_gesture.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/lib.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/visibility.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/workbench/chrome_layout.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/src/workbench/mod.rs (100%) rename rust/{lithe-core-rules => crates/core-rules}/tests/modifier_gesture_fixture.rs (96%) rename rust/{lithe-core-rules => crates/core-rules}/tests/visibility_fixture.rs (95%) rename rust/{lithe-core-rules => crates/core-rules}/tests/workbench_state_fixture.rs (96%) rename rust/{lithe-core => crates/core}/Cargo.toml (70%) rename rust/{lithe-core => crates/core}/include/lithe_core.h (100%) rename rust/{lithe-core => crates/core}/src/action_search/mod.rs (98%) rename rust/{lithe-core => crates/core}/src/build/commands.rs (100%) rename rust/{lithe-core => crates/core}/src/build/configuration.rs (100%) rename rust/{lithe-core => crates/core}/src/build/debug_preparation.rs (100%) rename rust/{lithe-core => crates/core}/src/build/decode.rs (100%) rename rust/{lithe-core => crates/core}/src/build/detect.rs (100%) rename rust/{lithe-core => crates/core}/src/build/invocation.rs (100%) rename rust/{lithe-core => crates/core}/src/build/manifest.rs (100%) rename rust/{lithe-core => crates/core}/src/build/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/build/model.rs (100%) rename rust/{lithe-core => crates/core}/src/build/model_inputs.rs (100%) rename rust/{lithe-core => crates/core}/src/build/options.rs (100%) rename rust/{lithe-core => crates/core}/src/build/outputs.rs (100%) rename rust/{lithe-core => crates/core}/src/build/plans.rs (100%) rename rust/{lithe-core => crates/core}/src/build/project_options.rs (100%) rename rust/{lithe-core => crates/core}/src/build/run_preparation.rs (100%) rename rust/{lithe-core => crates/core}/src/build/run_start.rs (100%) rename rust/{lithe-core => crates/core}/src/build/select.rs (100%) rename rust/{lithe-core => crates/core}/src/build/stored_options.rs (100%) rename rust/{lithe-core => crates/core}/src/build/template.rs (100%) rename rust/{lithe-core => crates/core}/src/build/test_discovery.rs (100%) rename rust/{lithe-core => crates/core}/src/build/test_outcome.rs (99%) rename rust/{lithe-core => crates/core}/src/build/test_outcome_merge.rs (98%) rename rust/{lithe-core => crates/core}/src/debug/adapters.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/backend_start.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/breakpoint_relocation.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/capabilities.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/disassembly_paging.rs (99%) rename rust/{lithe-core => crates/core}/src/debug/endpoint.rs (97%) rename rust/{lithe-core => crates/core}/src/debug/engine.rs (99%) rename rust/{lithe-core => crates/core}/src/debug/memory_window.rs (99%) rename rust/{lithe-core => crates/core}/src/debug/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/projection_v2.rs (99%) rename rust/{lithe-core => crates/core}/src/debug/protocol.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/shortcut.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/transport_lifecycle.rs (99%) rename rust/{lithe-core => crates/core}/src/debug/types.rs (100%) rename rust/{lithe-core => crates/core}/src/debug/variable_paging.rs (99%) rename rust/{lithe-core => crates/core}/src/diagnostics/catalog.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/catalog_generated.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/channel.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/collection.rs (99%) rename rust/{lithe-core => crates/core}/src/diagnostics/core_events.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/filter.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/format.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/helper_failures.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/logging.rs (99%) rename rust/{lithe-core => crates/core}/src/diagnostics/manifest.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/plugin_operations.rs (99%) rename rust/{lithe-core => crates/core}/src/diagnostics/query_v2.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/record.rs (99%) rename rust/{lithe-core => crates/core}/src/diagnostics/redaction.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/request_trace.rs (100%) rename rust/{lithe-core => crates/core}/src/diagnostics/retention.rs (100%) rename rust/{lithe-core => crates/core}/src/diff/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/diff/tests.rs (98%) rename rust/{lithe-core => crates/core}/src/editor/find.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/line_edit.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/navigation_history.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/navigation_input.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/preferences.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/recent.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/recovery.rs (100%) rename rust/{lithe-core => crates/core}/src/editor/tests.rs (99%) rename rust/{lithe-core => crates/core}/src/editor/text_edit_plan.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/argument_text.rs (95%) rename rust/{lithe-core => crates/core}/src/execution/configuration.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/configuration/project_toolchain.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/context_selection.rs (97%) rename rust/{lithe-core => crates/core}/src/execution/detectors/cargo.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/compose.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/go.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/make.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/npm.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/procfile.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/python.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/scan.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/detectors/shell.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/environment.rs (97%) rename rust/{lithe-core => crates/core}/src/execution/generated_layer.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/provider_run_options.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/provider_runs.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/title_action.rs (98%) rename rust/{lithe-core => crates/core}/src/execution/types.rs (100%) rename rust/{lithe-core => crates/core}/src/execution/workspace_scan.rs (100%) rename rust/{lithe-core => crates/core}/src/git/authentication_failure.rs (99%) rename rust/{lithe-core => crates/core}/src/git/branch_names.rs (100%) rename rust/{lithe-core => crates/core}/src/git/catalog.rs (100%) rename rust/{lithe-core => crates/core}/src/git/change_targets.rs (96%) rename rust/{lithe-core => crates/core}/src/git/changelists.rs (99%) rename rust/{lithe-core => crates/core}/src/git/command_trace.rs (100%) rename rust/{lithe-core => crates/core}/src/git/commit_message_context.rs (100%) rename rust/{lithe-core => crates/core}/src/git/commit_selection.rs (99%) rename rust/{lithe-core => crates/core}/src/git/commit_state.rs (100%) rename rust/{lithe-core => crates/core}/src/git/configuration.rs (99%) rename rust/{lithe-core => crates/core}/src/git/console/command.rs (100%) rename rust/{lithe-core => crates/core}/src/git/console/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/git/console/output.rs (100%) rename rust/{lithe-core => crates/core}/src/git/console/tests.rs (99%) rename rust/{lithe-core => crates/core}/src/git/console/types.rs (100%) rename rust/{lithe-core => crates/core}/src/git/deleted_selection.rs (100%) rename rust/{lithe-core => crates/core}/src/git/diff_blocks.rs (100%) rename rust/{lithe-core => crates/core}/src/git/execution_events.rs (99%) rename rust/{lithe-core => crates/core}/src/git/execution_policy.rs (98%) rename rust/{lithe-core => crates/core}/src/git/fetch.rs (98%) rename rust/{lithe-core => crates/core}/src/git/fetch_execution.rs (100%) rename rust/{lithe-core => crates/core}/src/git/file_context.rs (100%) rename rust/{lithe-core => crates/core}/src/git/github_checkout.rs (100%) rename rust/{lithe-core => crates/core}/src/git/graph.rs (100%) rename rust/{lithe-core => crates/core}/src/git/graph_tests.rs (99%) rename rust/{lithe-core => crates/core}/src/git/history.rs (99%) rename rust/{lithe-core => crates/core}/src/git/history_query.rs (100%) rename rust/{lithe-core => crates/core}/src/git/history_window.rs (98%) rename rust/{lithe-core => crates/core}/src/git/metadata_watch.rs (100%) rename rust/{lithe-core => crates/core}/src/git/mod.rs (99%) rename rust/{lithe-core => crates/core}/src/git/mutations.rs (100%) rename rust/{lithe-core => crates/core}/src/git/patch_exchange.rs (100%) rename rust/{lithe-core => crates/core}/src/git/progress.rs (97%) rename rust/{lithe-core => crates/core}/src/git/rebase_session.rs (99%) rename rust/{lithe-core => crates/core}/src/git/reference_tree.rs (97%) rename rust/{lithe-core => crates/core}/src/git/remote_history.rs (100%) rename rust/{lithe-core => crates/core}/src/git/remote_process.rs (100%) rename rust/{lithe-core => crates/core}/src/git/repository_colors.rs (100%) rename rust/{lithe-core => crates/core}/src/git/rewrite.rs (100%) rename rust/{lithe-core => crates/core}/src/git/rollback.rs (100%) rename rust/{lithe-core => crates/core}/src/git/setup.rs (100%) rename rust/{lithe-core => crates/core}/src/git/shelf.rs (100%) rename rust/{lithe-core => crates/core}/src/git/untracked_directories.rs (100%) rename rust/{lithe-core => crates/core}/src/git/update_plan.rs (99%) rename rust/{lithe-core => crates/core}/src/git/workspace_commit.rs (100%) rename rust/{lithe-core => crates/core}/src/git/workspace_commit/path_scope.rs (100%) rename rust/{lithe-core => crates/core}/src/git/workspace_commit/tests.rs (98%) rename rust/{lithe-core => crates/core}/src/git/workspace_status.rs (100%) rename rust/{lithe-core => crates/core}/src/github/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/keymap/bindings.rs (100%) rename rust/{lithe-core => crates/core}/src/keymap/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/keymap/schemes.rs (100%) rename rust/{lithe-core => crates/core}/src/lib.rs (97%) rename rust/{lithe-core => crates/core}/src/lsp/declaration_or_usages.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/document_identity.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/host_policy/activation.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/host_policy/completion_merge.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/host_policy/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/host_policy/problems.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/host_policy/tests.rs (89%) rename rust/{lithe-core => crates/core}/src/lsp/interface/build_provider.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/interface/client.rs (99%) rename rust/{lithe-core => crates/core}/src/lsp/interface/document_uri.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/engine.rs (99%) rename rust/{lithe-core => crates/core}/src/lsp/interface/engine_function_provider.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/interface/engine_function_relay.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/engine_function_relay_tests.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/engine_logging.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/function_relay.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/keymap_provider.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/interface/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/plugin_function.rs (99%) rename rust/{lithe-core => crates/core}/src/lsp/interface/plugin_logging.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/interface/plugin_server.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/process.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/remote_process.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/scripted.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/toolchain_provider.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/transport.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/types.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/interface/vcs_provider.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/languages/indexing.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/languages/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/languages/swift.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/lightweight/edits.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/lightweight/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/lightweight/snippets.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/lightweight/symbols.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/lsp/navigation_target.rs (98%) rename rust/{lithe-core => crates/core}/src/lsp/tests.rs (99%) rename rust/{lithe-core => crates/core}/src/lsp/workspace_edit_plan.rs (99%) rename rust/{lithe-core => crates/core}/src/lsp/workspace_scope.rs (100%) rename rust/{lithe-core => crates/core}/src/network/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/network/proxy.rs (100%) rename rust/{lithe-core => crates/core}/src/network/tests.rs (98%) rename rust/{lithe-core => crates/core}/src/plugins/backend.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/capabilities.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/content_providers.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/declarative.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/editor_actions.rs (99%) rename rust/{lithe-core => crates/core}/src/plugins/editor_providers.rs (99%) rename rust/{lithe-core => crates/core}/src/plugins/executables.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/grammar.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/host_api.rs (96%) rename rust/{lithe-core => crates/core}/src/plugins/installed.rs (98%) rename rust/{lithe-core => crates/core}/src/plugins/keymap_import.rs (97%) rename rust/{lithe-core => crates/core}/src/plugins/language_server_sessions.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/marketplace.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/native_ui.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/output_links.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/plugin_functions.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/settings.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/settings_document_tests.rs (96%) rename rust/{lithe-core => crates/core}/src/plugins/settings_documents.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/settings_pages.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/settings_surfaces.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/web_content.rs (100%) rename rust/{lithe-core => crates/core}/src/plugins/web_content_tests.rs (99%) rename rust/{lithe-core => crates/core}/src/process/inventory.rs (99%) rename rust/{lithe-core => crates/core}/src/process/lifecycle.rs (99%) rename rust/{lithe-core => crates/core}/src/process/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/project/directory_actions.rs (100%) rename rust/{lithe-core => crates/core}/src/project/document_lifecycle.rs (100%) rename rust/{lithe-core => crates/core}/src/project/document_save_batch.rs (100%) rename rust/{lithe-core => crates/core}/src/project/encoding.rs (100%) rename rust/{lithe-core => crates/core}/src/project/file_name_order.rs (100%) rename rust/{lithe-core => crates/core}/src/project/file_operations.rs (100%) rename rust/{lithe-core => crates/core}/src/project/files.rs (99%) rename rust/{lithe-core => crates/core}/src/project/history.rs (100%) rename rust/{lithe-core => crates/core}/src/project/indexing.rs (99%) rename rust/{lithe-core => crates/core}/src/project/markdown.rs (98%) rename rust/{lithe-core => crates/core}/src/project/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/project/name_matching.rs (99%) rename rust/{lithe-core => crates/core}/src/project/name_ranking.rs (100%) rename rust/{lithe-core => crates/core}/src/project/recent_projects.rs (100%) rename rust/{lithe-core => crates/core}/src/project/search_index.rs (99%) rename rust/{lithe-core => crates/core}/src/project/search_paging.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/archive.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/commands.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/form.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/manifest.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/plan.rs (100%) rename rust/{lithe-core => crates/core}/src/project_generators/template.rs (100%) rename rust/{lithe-core => crates/core}/src/protocol/cancellation.rs (100%) rename rust/{lithe-core => crates/core}/src/protocol/command.rs (99%) rename rust/{lithe-core => crates/core}/src/protocol/contracts.rs (100%) rename rust/{lithe-core => crates/core}/src/protocol/error.rs (100%) rename rust/{lithe-core => crates/core}/src/protocol/event.rs (100%) rename rust/{lithe-core => crates/core}/src/protocol/json_document.rs (100%) rename rust/{lithe-core => crates/core}/src/protocol/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/sessions.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/sessions_integration_tests.rs (99%) rename rust/{lithe-core => crates/core}/src/remote/tests.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/upload.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/workspace.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/workspace_host.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/workspace_host/tests.rs (100%) rename rust/{lithe-core => crates/core}/src/remote/workspace_io.rs (100%) rename rust/{lithe-core => crates/core}/src/runtime/dispatcher.rs (100%) rename rust/{lithe-core => crates/core}/src/runtime/ffi.rs (98%) rename rust/{lithe-core => crates/core}/src/runtime/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/terminal/link.rs (100%) rename rust/{lithe-core => crates/core}/src/terminal/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/build_configuration.rs (97%) rename rust/{lithe-core => crates/core}/src/tests/build_project_options.rs (94%) rename rust/{lithe-core => crates/core}/src/tests/build_runtime_versions.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/build_systems.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/community_build_plugins.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/core_request_traces.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/declarative_plugins.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/detectors.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/directory_actions.rs (96%) rename rust/{lithe-core => crates/core}/src/tests/file_name_order.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/file_operations.rs (97%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/branch-name-cleanup-parity-v1.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/gradle/app-dependencies.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/gradle/dependencies.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/gradle/model.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/gradle/plugin.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/maven/app-dependencies.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/maven/dependencies.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/maven/model.json (100%) rename rust/{lithe-core => crates/core}/src/tests/fixtures/community_build_plugins/maven/plugin.json (100%) rename rust/{lithe-core => crates/core}/src/tests/git.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/git_diff_blocks.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/git_fetch.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/git_history_rewrite.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/git_patch_exchange.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/git_remote_checkout.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/git_repository_discovery.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/git_repository_setup.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/git_untracked_directories.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/git_workspace_commit.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/github.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/history_events.rs (89%) rename rust/{lithe-core => crates/core}/src/tests/language_server_sessions.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/marketplace_plugins.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/tests/plugin_editor_resources.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/plugin_run_debug.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/project.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/project_generators.rs (97%) rename rust/{lithe-core => crates/core}/src/tests/protocol.rs (96%) rename rust/{lithe-core => crates/core}/src/tests/rank_names.rs (92%) rename rust/{lithe-core => crates/core}/src/tests/run_configuration.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/support.rs (95%) rename rust/{lithe-core => crates/core}/src/tests/toolchain_definitions.rs (97%) rename rust/{lithe-core => crates/core}/src/tests/toolchain_pins.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/toolchain_queries.rs (98%) rename rust/{lithe-core => crates/core}/src/tests/toolchain_resolution.rs (99%) rename rust/{lithe-core => crates/core}/src/tests/toolchain_vectors.rs (97%) rename rust/{lithe-core => crates/core}/src/tests/vcs.rs (99%) rename rust/{lithe-core => crates/core}/src/toolchain/definitions.rs (100%) rename rust/{lithe-core => crates/core}/src/toolchain/fixed.rs (100%) rename rust/{lithe-core => crates/core}/src/toolchain/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/toolchain/paths.rs (100%) rename rust/{lithe-core => crates/core}/src/toolchain/pin_sources.rs (98%) rename rust/{lithe-core => crates/core}/src/toolchain/pins.rs (100%) rename rust/{lithe-core => crates/core}/src/toolchain/preferences.rs (99%) rename rust/{lithe-core => crates/core}/src/toolchain/query.rs (100%) rename rust/{lithe-core => crates/core}/src/toolchain/resolution.rs (100%) rename rust/{lithe-core => crates/core}/src/vcs/commands.rs (100%) rename rust/{lithe-core => crates/core}/src/vcs/manifest.rs (100%) rename rust/{lithe-core => crates/core}/src/vcs/mod.rs (100%) rename rust/{lithe-core => crates/core}/src/vcs/model.rs (100%) rename rust/{lithe-core => crates/core}/src/vcs/requests.rs (100%) rename rust/{lithe-core => crates/core}/src/vcs/roots.rs (100%) rename rust/{lithe-core => crates/core}/tests/core_log_waker.rs (100%) rename rust/{lithe-core => crates/core}/tests/git_push.rs (100%) rename rust/{lithe-core => crates/core}/tests/git_watch_context.rs (100%) rename rust/{lithe-git-host => crates/git-host}/Cargo.toml (100%) rename rust/{lithe-git-host => crates/git-host}/src/authentication.rs (94%) rename rust/{lithe-git-host => crates/git-host}/src/configuration.rs (100%) rename rust/{lithe-git-host => crates/git-host}/src/failure_log.rs (91%) rename rust/{lithe-git-host => crates/git-host}/src/lib.rs (96%) rename rust/{lithe-git-host => crates/git-host}/tests/authentication.rs (100%) rename rust/{lithe-git-host => crates/git-host}/tests/process.rs (100%) rename rust/{lithe-ide-host => crates/ide-host}/Cargo.toml (91%) rename rust/{lithe-ide-host => crates/ide-host}/src/bin/lithe-mcp.rs (100%) rename rust/{lithe-ide-host => crates/ide-host}/src/catalog.rs (97%) rename rust/{lithe-ide-host => crates/ide-host}/src/failure_log.rs (100%) rename rust/{lithe-ide-host => crates/ide-host}/src/lib.rs (97%) rename rust/{lithe-remote => crates/remote}/Cargo.toml (100%) rename rust/{lithe-remote => crates/remote}/src/bin/lithe-remote-server.rs (100%) rename rust/{lithe-remote => crates/remote}/src/client/api.rs (100%) rename rust/{lithe-remote => crates/remote}/src/client/bootstrap.rs (100%) rename rust/{lithe-remote => crates/remote}/src/client/command.rs (97%) rename rust/{lithe-remote => crates/remote}/src/client/forward.rs (96%) rename rust/{lithe-remote => crates/remote}/src/client/launch.rs (100%) rename rust/{lithe-remote => crates/remote}/src/client/mod.rs (100%) rename rust/{lithe-remote => crates/remote}/src/client/session.rs (98%) rename rust/{lithe-remote => crates/remote}/src/client/transport.rs (100%) rename rust/{lithe-remote => crates/remote}/src/failure_log.rs (88%) rename rust/{lithe-remote => crates/remote}/src/lib.rs (100%) rename rust/{lithe-remote => crates/remote}/src/protocol/frame.rs (100%) rename rust/{lithe-remote => crates/remote}/src/protocol/message.rs (100%) rename rust/{lithe-remote => crates/remote}/src/protocol/methods.rs (100%) rename rust/{lithe-remote => crates/remote}/src/protocol/mod.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/connection.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/connection/tests.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/daemon.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/environment.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/fs.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/link.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/mod.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/platform/linux.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/platform/linux_watch.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/platform/macos.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/platform/macos_watch.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/platform/mod.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/platform/unix.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/ports.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/process.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/resources.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/run_directory.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/session.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/spawner.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/terminal.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/tunnel.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/upload.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/upload/tests.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/walk.rs (100%) rename rust/{lithe-remote => crates/remote}/src/server/watch.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/persistence.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/processes.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/run_directories.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/server.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/support/mod.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/terminals.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/tunnels.rs (100%) rename rust/{lithe-remote => crates/remote}/tests/watch_and_walk.rs (100%) diff --git a/README.md b/README.md index 5c0f90fc..744682d9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,10 @@ Lithe 的跨平台应用内核,以及插件契约、插件开发资料和官 | 目录 | 内容 | | --- | --- | -| [`rust/`](rust) | Rust Core 各 crate,以及 Core 自己的接口契约 `rust/contracts/`、测试数据 `rust/fixtures/` 和日志事件目录 `rust/logging/` | +| [`rust/crates/`](rust/crates) | Rust Core 的 crate,每个子目录是一个 crate,目录名是包名去掉 `lithe-` 前缀 | +| [`rust/contracts/`](rust/contracts) | Core 命令的接口契约和 schema | +| [`rust/fixtures/`](rust/fixtures) | Core 命令的测试数据,Core 测试和桌面端测试共用 | +| [`rust/logging/`](rust/logging) | 日志事件目录 | | [`shared/plugins/`](shared/plugins) | 插件契约 `contract/v1/`、开发指南 `guides/`、参考 `reference/`、官方 SDK `sdk/{node,java,rust}` 和它们的端到端测试 | | [`scripts/rust-core/`](scripts/rust-core) | Rust Core 注释规范检查(模块文档、英文注释、`unsafe` 安全说明、导出项 Rustdoc) | @@ -19,8 +22,8 @@ node shared/plugins/scripts/verify-docs.mjs # 契约 $id 与文档 node shared/plugins/scripts/sdk-e2e.mjs # 三个 SDK 对当前 Core 的端到端测试 ``` -修改 `shared/plugins/contract/v1/`、`rust/lithe-core/src/plugins/capabilities.rs` 或 -`rust/lithe-core/src/lsp/interface/plugin_function.rs` 的 PR,要在同一个 PR 里更新 +修改 `shared/plugins/contract/v1/`、`rust/crates/core/src/plugins/capabilities.rs` 或 +`rust/crates/core/src/lsp/interface/plugin_function.rs` 的 PR,要在同一个 PR 里更新 [协议更新记录](shared/plugins/reference/protocol-changelog.md)。 --- @@ -31,10 +34,13 @@ Lithe's cross-platform application core, and the single source of the plugin con | Directory | Contents | | --- | --- | -| [`rust/`](rust) | The Rust Core crates, plus Core's own interface contracts `rust/contracts/`, test data `rust/fixtures/` and logging event catalog `rust/logging/` | +| [`rust/crates/`](rust/crates) | The Rust Core crates; each directory is one crate, named after its package without the `lithe-` prefix | +| [`rust/contracts/`](rust/contracts) | Interface contracts and schemas for Core commands | +| [`rust/fixtures/`](rust/fixtures) | Test data for Core commands, shared by the Core and desktop tests | +| [`rust/logging/`](rust/logging) | The logging event catalog | | [`shared/plugins/`](shared/plugins) | The plugin contract `contract/v1/`, guides `guides/`, reference `reference/`, the official SDKs `sdk/{node,java,rust}` and their end-to-end tests | | [`scripts/rust-core/`](scripts/rust-core) | The Rust Core comment rules check (module docs, English comments, `unsafe` safety sections, Rustdoc on exported items) | **Plugin authors** start at [`shared/plugins/README.md`](shared/plugins/README.md) and never need to clone the Lithe application repository. -A pull request that changes `shared/plugins/contract/v1/`, `rust/lithe-core/src/plugins/capabilities.rs` or `rust/lithe-core/src/lsp/interface/plugin_function.rs` updates the [protocol changelog](shared/plugins/reference/protocol-changelog.md) in the same pull request. +A pull request that changes `shared/plugins/contract/v1/`, `rust/crates/core/src/plugins/capabilities.rs` or `rust/crates/core/src/lsp/interface/plugin_function.rs` updates the [protocol changelog](shared/plugins/reference/protocol-changelog.md) in the same pull request. diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 240a0472..6d952b72 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["lithe-ai", "lithe-core", "lithe-core-rules", "lithe-git-host", "lithe-ide-host", "lithe-remote"] +members = ["crates/*"] resolver = "2" [profile.release] diff --git a/rust/contracts/ai-commit.md b/rust/contracts/ai-commit.md index 8dfd1f51..b6d86af0 100644 --- a/rust/contracts/ai-commit.md +++ b/rust/contracts/ai-commit.md @@ -2,7 +2,7 @@ Version: 1. Behavioral fixture: `rust/fixtures/ai/commit-generation-v1.json`. -Every `ai.*` command is implemented in the `lithe-ai` crate (`rust/lithe-ai`), which +Every `ai.*` command is implemented in the `lithe-ai` crate (`rust/crates/ai`), which `lithe-core` routes to and re-exports as `lithe_core::ai`. Windows consumes the typed Rust API in `lithe_core::ai`; macOS uses the same planner diff --git a/rust/contracts/ai-generation-requests.md b/rust/contracts/ai-generation-requests.md index de1bf7df..463b96a5 100644 --- a/rust/contracts/ai-generation-requests.md +++ b/rust/contracts/ai-generation-requests.md @@ -3,7 +3,7 @@ Version: 1. Behavioral fixtures: `rust/fixtures/ai/pull-request-description-v1.json` and `rust/fixtures/ai/inline-edit-v1.json`. -Both are implemented in the `lithe-ai` crate (`rust/lithe-ai`), like every `ai.*` command. +Both are implemented in the `lithe-ai` crate (`rust/crates/ai`), like every `ai.*` command. Both features reuse the credential-free provider request model of [AI commit generation](ai-commit.md): Core validates the endpoint, appends the diff --git a/rust/contracts/ide-api/v1.md b/rust/contracts/ide-api/v1.md index 4d3de7c1..20d1d99d 100644 --- a/rust/contracts/ide-api/v1.md +++ b/rust/contracts/ide-api/v1.md @@ -7,7 +7,7 @@ project preparation, saved toolchain selection and native execution ownership. ## Ownership and connections -`rust/lithe-ide-host/src/catalog.rs` owns the tool names, schemas, validation, +`rust/crates/ide-host/src/catalog.rs` owns the tool names, schemas, validation, permission classification and UTF-8 output paging. `lithe-ide-host` owns the local broker and private connection descriptor; the `lithe-mcp` binary uses the official `rmcp` SDK for stdio MCP. HTTP here is an internal authenticated loopback diff --git a/rust/contracts/remote-workspace-protocol-v1.md b/rust/contracts/remote-workspace-protocol-v1.md index 042a03a4..f14b41c6 100644 --- a/rust/contracts/remote-workspace-protocol-v1.md +++ b/rust/contracts/remote-workspace-protocol-v1.md @@ -2,7 +2,7 @@ The protocol between a Lithe client and `lithe-remote-server`, which runs at the end of a transport chain (SSH host, container, or a chain of both). The -Rust types in `rust/lithe-remote/src/protocol/` are the reference +Rust types in `rust/crates/remote/src/protocol/` are the reference implementation; this document is the compatibility surface for other clients. Design rationale lives in `.agents/notes/proposed/architecture/2026-10-24-remote-development-workspace-host.md`. diff --git a/rust/contracts/rust-core-api.md b/rust/contracts/rust-core-api.md index 6c9aa989..58d4a623 100644 --- a/rust/contracts/rust-core-api.md +++ b/rust/contracts/rust-core-api.md @@ -153,7 +153,7 @@ See `rust/fixtures/keymap/binding-conflicts-v1.json`. double-Shift gesture as a pure transition: `event` is `{kind: "keyDown"}`, `{kind: "reset"}` or `{kind: "flags", shift, otherModifiers}`; `timestamp` is seconds on a clock the host keeps; `state` is opaque host-held memory (omit it for the idle state) that the host sends back with the next event. The rule lives in the -pure crate `rust/lithe-core-rules` (no I/O, no clock) so it can run on a synchronous key path; hosts call it +pure crate `rust/crates/core-rules` (no I/O, no clock) so it can run on a synchronous key path; hosts call it through the C ABI. A malformed payload is `invalid_request`. Hosts only convert native events to this input and act on `triggered`; Core and the rules crate test the rule step by step against `rust/fixtures/keymap/modifier-gesture-v1.json`. @@ -177,7 +177,7 @@ returned as sent, so a host may send only the groups an action involves. `emptyG stale), and `focusedGroup` moves to the first remaining group when its group was removed. Actions that name an unknown group or an unknown move destination change nothing. `removedGroupIds` lists removed groups in their previous order so hosts prune their own layout tree; split directions, ratios, pixels and dragging never reach Core. A malformed payload is -`invalid_request`. It lives in `rust/lithe-core-rules` and hosts call it synchronously through the C ABI, one call per +`invalid_request`. It lives in `rust/crates/core-rules` and hosts call it synchronously through the C ABI, one call per user action. Core and the rules crate run every case of `rust/fixtures/editor/workbench-state-v1.json` through it. @@ -191,7 +191,7 @@ Local History leave the path out; `watchedDespiteHiding` marks the hidden projec events must still be delivered, except the built-in noise below it such as `.lithe/run/local.json`. Hosts send all children of a directory in one call. `workspace.visibilityDefaults` takes `{}` and returns the built-in lists (`hiddenDirectoryNames`, `hiddenFilePatterns`, `builtInPatterns`, `configurationDirectory`, `configurationPattern`) so hosts -display them without keeping a copy. Both live in `rust/lithe-core-rules` like `keymap.modifierGestureStep` and are tested +display them without keeping a copy. Both live in `rust/crates/core-rules` like `keymap.modifierGestureStep` and are tested against `rust/fixtures/workspace/visibility-v1.json`. ## Terminal link targets @@ -225,7 +225,7 @@ int32_t lithe_core_remove_log_waker(void *context); ``` The macOS package uses the small C bridge in `macos/Sources/LitheRustCore/`. The -canonical C declarations are in `rust/lithe-core/include/lithe_core.h`. +canonical C declarations are in `rust/crates/core/include/lithe_core.h`. Native clients link the `staticlib`; Rust hosts call `lithe_core::execute_json` and `lithe_core::cancel_operation` directly. Strings returned by the core are UTF-8 JSON allocated by Rust. The caller must @@ -3684,7 +3684,7 @@ Windows consumes the original fields and may ignore this marker. ### AI configuration These commands, like every `ai.*` command, are implemented in the `lithe-ai` crate -(`rust/lithe-ai`); `lithe-core` only routes them. +(`rust/crates/ai`); `lithe-core` only routes them. `ai.configuration.sources` takes `{source, home, environment}` (`source` is `codex` or `claude`, `home` an absolute path, `environment` only the directory diff --git a/rust/lithe-ai/Cargo.toml b/rust/crates/ai/Cargo.toml similarity index 100% rename from rust/lithe-ai/Cargo.toml rename to rust/crates/ai/Cargo.toml diff --git a/rust/lithe-ai/src/agent_configuration.rs b/rust/crates/ai/src/agent_configuration.rs similarity index 100% rename from rust/lithe-ai/src/agent_configuration.rs rename to rust/crates/ai/src/agent_configuration.rs diff --git a/rust/lithe-ai/src/commands.rs b/rust/crates/ai/src/commands.rs similarity index 100% rename from rust/lithe-ai/src/commands.rs rename to rust/crates/ai/src/commands.rs diff --git a/rust/lithe-ai/src/configuration.rs b/rust/crates/ai/src/configuration.rs similarity index 100% rename from rust/lithe-ai/src/configuration.rs rename to rust/crates/ai/src/configuration.rs diff --git a/rust/lithe-ai/src/dispatch.rs b/rust/crates/ai/src/dispatch.rs similarity index 100% rename from rust/lithe-ai/src/dispatch.rs rename to rust/crates/ai/src/dispatch.rs diff --git a/rust/lithe-ai/src/error.rs b/rust/crates/ai/src/error.rs similarity index 100% rename from rust/lithe-ai/src/error.rs rename to rust/crates/ai/src/error.rs diff --git a/rust/lithe-ai/src/generation.rs b/rust/crates/ai/src/generation.rs similarity index 100% rename from rust/lithe-ai/src/generation.rs rename to rust/crates/ai/src/generation.rs diff --git a/rust/lithe-ai/src/inline_edit.rs b/rust/crates/ai/src/inline_edit.rs similarity index 100% rename from rust/lithe-ai/src/inline_edit.rs rename to rust/crates/ai/src/inline_edit.rs diff --git a/rust/lithe-ai/src/lib.rs b/rust/crates/ai/src/lib.rs similarity index 100% rename from rust/lithe-ai/src/lib.rs rename to rust/crates/ai/src/lib.rs diff --git a/rust/lithe-ai/src/provider_request.rs b/rust/crates/ai/src/provider_request.rs similarity index 100% rename from rust/lithe-ai/src/provider_request.rs rename to rust/crates/ai/src/provider_request.rs diff --git a/rust/lithe-ai/src/pull_request.rs b/rust/crates/ai/src/pull_request.rs similarity index 100% rename from rust/lithe-ai/src/pull_request.rs rename to rust/crates/ai/src/pull_request.rs diff --git a/rust/lithe-ai/src/request_tests.rs b/rust/crates/ai/src/request_tests.rs similarity index 98% rename from rust/lithe-ai/src/request_tests.rs rename to rust/crates/ai/src/request_tests.rs index 8cfc05d6..13becb5d 100644 --- a/rust/lithe-ai/src/request_tests.rs +++ b/rust/crates/ai/src/request_tests.rs @@ -8,13 +8,13 @@ use serde_json::{json, Value}; fn pull_request_fixture() -> Value { serde_json::from_str(include_str!( - "../../fixtures/ai/pull-request-description-v1.json" + "../../../fixtures/ai/pull-request-description-v1.json" )) .unwrap() } fn inline_edit_fixture() -> Value { - serde_json::from_str(include_str!("../../fixtures/ai/inline-edit-v1.json")).unwrap() + serde_json::from_str(include_str!("../../../fixtures/ai/inline-edit-v1.json")).unwrap() } fn typed(fixture: &Value) -> (Provider, PullRequestOptions, PullRequestComparison) { diff --git a/rust/lithe-ai/src/tests.rs b/rust/crates/ai/src/tests.rs similarity index 99% rename from rust/lithe-ai/src/tests.rs rename to rust/crates/ai/src/tests.rs index 1a6587e9..064b2ad9 100644 --- a/rust/lithe-ai/src/tests.rs +++ b/rust/crates/ai/src/tests.rs @@ -5,7 +5,10 @@ use serde_json::{json, Value}; use std::collections::BTreeMap; fn configuration_fixture() -> Value { - serde_json::from_str(include_str!("../../fixtures/ai/cli-configuration-v1.json")).unwrap() + serde_json::from_str(include_str!( + "../../../fixtures/ai/cli-configuration-v1.json" + )) + .unwrap() } fn execute(command: &str, payload: &Value) -> Value { @@ -192,8 +195,10 @@ fn configuration_parse_errors_are_stable_codes_without_input() { } fn fixture() -> (Provider, CommitOptions, Vec, Value) { - let value: Value = - serde_json::from_str(include_str!("../../fixtures/ai/commit-generation-v1.json")).unwrap(); + let value: Value = serde_json::from_str(include_str!( + "../../../fixtures/ai/commit-generation-v1.json" + )) + .unwrap(); ( serde_json::from_value(value["provider"].clone()).unwrap(), serde_json::from_value(value["options"].clone()).unwrap(), diff --git a/rust/lithe-core-rules/Cargo.toml b/rust/crates/core-rules/Cargo.toml similarity index 100% rename from rust/lithe-core-rules/Cargo.toml rename to rust/crates/core-rules/Cargo.toml diff --git a/rust/lithe-core-rules/src/dispatch.rs b/rust/crates/core-rules/src/dispatch.rs similarity index 100% rename from rust/lithe-core-rules/src/dispatch.rs rename to rust/crates/core-rules/src/dispatch.rs diff --git a/rust/lithe-core-rules/src/editor/mod.rs b/rust/crates/core-rules/src/editor/mod.rs similarity index 100% rename from rust/lithe-core-rules/src/editor/mod.rs rename to rust/crates/core-rules/src/editor/mod.rs diff --git a/rust/lithe-core-rules/src/editor/workbench_state.rs b/rust/crates/core-rules/src/editor/workbench_state.rs similarity index 100% rename from rust/lithe-core-rules/src/editor/workbench_state.rs rename to rust/crates/core-rules/src/editor/workbench_state.rs diff --git a/rust/lithe-core-rules/src/error.rs b/rust/crates/core-rules/src/error.rs similarity index 100% rename from rust/lithe-core-rules/src/error.rs rename to rust/crates/core-rules/src/error.rs diff --git a/rust/lithe-core-rules/src/keymap/mod.rs b/rust/crates/core-rules/src/keymap/mod.rs similarity index 100% rename from rust/lithe-core-rules/src/keymap/mod.rs rename to rust/crates/core-rules/src/keymap/mod.rs diff --git a/rust/lithe-core-rules/src/keymap/modifier_gesture.rs b/rust/crates/core-rules/src/keymap/modifier_gesture.rs similarity index 100% rename from rust/lithe-core-rules/src/keymap/modifier_gesture.rs rename to rust/crates/core-rules/src/keymap/modifier_gesture.rs diff --git a/rust/lithe-core-rules/src/lib.rs b/rust/crates/core-rules/src/lib.rs similarity index 100% rename from rust/lithe-core-rules/src/lib.rs rename to rust/crates/core-rules/src/lib.rs diff --git a/rust/lithe-core-rules/src/visibility.rs b/rust/crates/core-rules/src/visibility.rs similarity index 100% rename from rust/lithe-core-rules/src/visibility.rs rename to rust/crates/core-rules/src/visibility.rs diff --git a/rust/lithe-core-rules/src/workbench/chrome_layout.rs b/rust/crates/core-rules/src/workbench/chrome_layout.rs similarity index 100% rename from rust/lithe-core-rules/src/workbench/chrome_layout.rs rename to rust/crates/core-rules/src/workbench/chrome_layout.rs diff --git a/rust/lithe-core-rules/src/workbench/mod.rs b/rust/crates/core-rules/src/workbench/mod.rs similarity index 100% rename from rust/lithe-core-rules/src/workbench/mod.rs rename to rust/crates/core-rules/src/workbench/mod.rs diff --git a/rust/lithe-core-rules/tests/modifier_gesture_fixture.rs b/rust/crates/core-rules/tests/modifier_gesture_fixture.rs similarity index 96% rename from rust/lithe-core-rules/tests/modifier_gesture_fixture.rs rename to rust/crates/core-rules/tests/modifier_gesture_fixture.rs index 61e70e9e..afec1997 100644 --- a/rust/lithe-core-rules/tests/modifier_gesture_fixture.rs +++ b/rust/crates/core-rules/tests/modifier_gesture_fixture.rs @@ -3,7 +3,7 @@ use lithe_core_rules::{execute, keymap::THRESHOLD_SECONDS, RuleErrorCode}; use serde_json::{json, Value}; -const FIXTURE: &str = include_str!("../../fixtures/keymap/modifier-gesture-v1.json"); +const FIXTURE: &str = include_str!("../../../fixtures/keymap/modifier-gesture-v1.json"); fn step(state: &Value, event: Value, timestamp: f64) -> Value { execute( diff --git a/rust/lithe-core-rules/tests/visibility_fixture.rs b/rust/crates/core-rules/tests/visibility_fixture.rs similarity index 95% rename from rust/lithe-core-rules/tests/visibility_fixture.rs rename to rust/crates/core-rules/tests/visibility_fixture.rs index 53bc1ef4..03584fc9 100644 --- a/rust/lithe-core-rules/tests/visibility_fixture.rs +++ b/rust/crates/core-rules/tests/visibility_fixture.rs @@ -3,7 +3,7 @@ use lithe_core_rules::{execute, RuleErrorCode}; use serde_json::{json, Value}; -const FIXTURE: &str = include_str!("../../fixtures/workspace/visibility-v1.json"); +const FIXTURE: &str = include_str!("../../../fixtures/workspace/visibility-v1.json"); fn call(command: &str, payload: Value) -> Value { execute(command, payload).unwrap() diff --git a/rust/lithe-core-rules/tests/workbench_state_fixture.rs b/rust/crates/core-rules/tests/workbench_state_fixture.rs similarity index 96% rename from rust/lithe-core-rules/tests/workbench_state_fixture.rs rename to rust/crates/core-rules/tests/workbench_state_fixture.rs index 0cd6647a..07a67164 100644 --- a/rust/lithe-core-rules/tests/workbench_state_fixture.rs +++ b/rust/crates/core-rules/tests/workbench_state_fixture.rs @@ -3,7 +3,7 @@ use lithe_core_rules::{execute, RuleError, RuleErrorCode, COMMANDS}; use serde_json::{json, Value}; -const FIXTURE: &str = include_str!("../../fixtures/editor/workbench-state-v1.json"); +const FIXTURE: &str = include_str!("../../../fixtures/editor/workbench-state-v1.json"); const COMMAND: &str = "editor.workbenchState.reduce"; fn call(payload: Value) -> Result { diff --git a/rust/lithe-core/Cargo.toml b/rust/crates/core/Cargo.toml similarity index 70% rename from rust/lithe-core/Cargo.toml rename to rust/crates/core/Cargo.toml index 1bb3a9d2..51561e34 100644 --- a/rust/lithe-core/Cargo.toml +++ b/rust/crates/core/Cargo.toml @@ -14,11 +14,11 @@ crate-type = ["rlib", "staticlib"] plugin-sdk-e2e = [] [dependencies] -lithe-ai = { path = "../lithe-ai" } -lithe-core-rules = { path = "../lithe-core-rules" } -lithe-git-host = { path = "../lithe-git-host" } -lithe-ide-host = { path = "../lithe-ide-host" } -lithe-remote = { path = "../lithe-remote", default-features = false, features = ["client"] } +lithe-ai = { path = "../ai" } +lithe-core-rules = { path = "../core-rules" } +lithe-git-host = { path = "../git-host" } +lithe-ide-host = { path = "../ide-host" } +lithe-remote = { path = "../remote", default-features = false, features = ["client"] } ammonia = "4.1.4" base64 = "0.22" chrono = { version = "0.4", default-features = false, features = ["std", "clock"] } @@ -39,24 +39,24 @@ unicode-normalization = "0.1" ignore = "=0.4.33" [target.'cfg(unix)'.dev-dependencies] -lithe-remote = { path = "../lithe-remote", default-features = false, features = ["server"] } +lithe-remote = { path = "../remote", default-features = false, features = ["server"] } [[test]] name = "plugin_sdk_node" -path = "../../shared/plugins/sdk/e2e/plugin_sdk_node.rs" +path = "../../../shared/plugins/sdk/e2e/plugin_sdk_node.rs" required-features = ["plugin-sdk-e2e"] [[test]] name = "plugin_sdk_java" -path = "../../shared/plugins/sdk/e2e/plugin_sdk_java.rs" +path = "../../../shared/plugins/sdk/e2e/plugin_sdk_java.rs" required-features = ["plugin-sdk-e2e"] [[test]] name = "plugin_sdk_rust" -path = "../../shared/plugins/sdk/e2e/plugin_sdk_rust.rs" +path = "../../../shared/plugins/sdk/e2e/plugin_sdk_rust.rs" required-features = ["plugin-sdk-e2e"] [[test]] name = "plugin_sdk_build" -path = "../../shared/plugins/sdk/e2e/plugin_sdk_build.rs" +path = "../../../shared/plugins/sdk/e2e/plugin_sdk_build.rs" required-features = ["plugin-sdk-e2e"] diff --git a/rust/lithe-core/include/lithe_core.h b/rust/crates/core/include/lithe_core.h similarity index 100% rename from rust/lithe-core/include/lithe_core.h rename to rust/crates/core/include/lithe_core.h diff --git a/rust/lithe-core/src/action_search/mod.rs b/rust/crates/core/src/action_search/mod.rs similarity index 98% rename from rust/lithe-core/src/action_search/mod.rs rename to rust/crates/core/src/action_search/mod.rs index b21c84ee..2864edec 100644 --- a/rust/lithe-core/src/action_search/mod.rs +++ b/rust/crates/core/src/action_search/mod.rs @@ -83,7 +83,7 @@ mod tests { fn fixture_matches_localized_and_original_text_without_reordering() { let fixture: serde_json::Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/search/actions-v1.json" + "/../../fixtures/search/actions-v1.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/build/commands.rs b/rust/crates/core/src/build/commands.rs similarity index 100% rename from rust/lithe-core/src/build/commands.rs rename to rust/crates/core/src/build/commands.rs diff --git a/rust/lithe-core/src/build/configuration.rs b/rust/crates/core/src/build/configuration.rs similarity index 100% rename from rust/lithe-core/src/build/configuration.rs rename to rust/crates/core/src/build/configuration.rs diff --git a/rust/lithe-core/src/build/debug_preparation.rs b/rust/crates/core/src/build/debug_preparation.rs similarity index 100% rename from rust/lithe-core/src/build/debug_preparation.rs rename to rust/crates/core/src/build/debug_preparation.rs diff --git a/rust/lithe-core/src/build/decode.rs b/rust/crates/core/src/build/decode.rs similarity index 100% rename from rust/lithe-core/src/build/decode.rs rename to rust/crates/core/src/build/decode.rs diff --git a/rust/lithe-core/src/build/detect.rs b/rust/crates/core/src/build/detect.rs similarity index 100% rename from rust/lithe-core/src/build/detect.rs rename to rust/crates/core/src/build/detect.rs diff --git a/rust/lithe-core/src/build/invocation.rs b/rust/crates/core/src/build/invocation.rs similarity index 100% rename from rust/lithe-core/src/build/invocation.rs rename to rust/crates/core/src/build/invocation.rs diff --git a/rust/lithe-core/src/build/manifest.rs b/rust/crates/core/src/build/manifest.rs similarity index 100% rename from rust/lithe-core/src/build/manifest.rs rename to rust/crates/core/src/build/manifest.rs diff --git a/rust/lithe-core/src/build/mod.rs b/rust/crates/core/src/build/mod.rs similarity index 100% rename from rust/lithe-core/src/build/mod.rs rename to rust/crates/core/src/build/mod.rs diff --git a/rust/lithe-core/src/build/model.rs b/rust/crates/core/src/build/model.rs similarity index 100% rename from rust/lithe-core/src/build/model.rs rename to rust/crates/core/src/build/model.rs diff --git a/rust/lithe-core/src/build/model_inputs.rs b/rust/crates/core/src/build/model_inputs.rs similarity index 100% rename from rust/lithe-core/src/build/model_inputs.rs rename to rust/crates/core/src/build/model_inputs.rs diff --git a/rust/lithe-core/src/build/options.rs b/rust/crates/core/src/build/options.rs similarity index 100% rename from rust/lithe-core/src/build/options.rs rename to rust/crates/core/src/build/options.rs diff --git a/rust/lithe-core/src/build/outputs.rs b/rust/crates/core/src/build/outputs.rs similarity index 100% rename from rust/lithe-core/src/build/outputs.rs rename to rust/crates/core/src/build/outputs.rs diff --git a/rust/lithe-core/src/build/plans.rs b/rust/crates/core/src/build/plans.rs similarity index 100% rename from rust/lithe-core/src/build/plans.rs rename to rust/crates/core/src/build/plans.rs diff --git a/rust/lithe-core/src/build/project_options.rs b/rust/crates/core/src/build/project_options.rs similarity index 100% rename from rust/lithe-core/src/build/project_options.rs rename to rust/crates/core/src/build/project_options.rs diff --git a/rust/lithe-core/src/build/run_preparation.rs b/rust/crates/core/src/build/run_preparation.rs similarity index 100% rename from rust/lithe-core/src/build/run_preparation.rs rename to rust/crates/core/src/build/run_preparation.rs diff --git a/rust/lithe-core/src/build/run_start.rs b/rust/crates/core/src/build/run_start.rs similarity index 100% rename from rust/lithe-core/src/build/run_start.rs rename to rust/crates/core/src/build/run_start.rs diff --git a/rust/lithe-core/src/build/select.rs b/rust/crates/core/src/build/select.rs similarity index 100% rename from rust/lithe-core/src/build/select.rs rename to rust/crates/core/src/build/select.rs diff --git a/rust/lithe-core/src/build/stored_options.rs b/rust/crates/core/src/build/stored_options.rs similarity index 100% rename from rust/lithe-core/src/build/stored_options.rs rename to rust/crates/core/src/build/stored_options.rs diff --git a/rust/lithe-core/src/build/template.rs b/rust/crates/core/src/build/template.rs similarity index 100% rename from rust/lithe-core/src/build/template.rs rename to rust/crates/core/src/build/template.rs diff --git a/rust/lithe-core/src/build/test_discovery.rs b/rust/crates/core/src/build/test_discovery.rs similarity index 100% rename from rust/lithe-core/src/build/test_discovery.rs rename to rust/crates/core/src/build/test_discovery.rs diff --git a/rust/lithe-core/src/build/test_outcome.rs b/rust/crates/core/src/build/test_outcome.rs similarity index 99% rename from rust/lithe-core/src/build/test_outcome.rs rename to rust/crates/core/src/build/test_outcome.rs index e7bc7113..94d20bf9 100644 --- a/rust/lithe-core/src/build/test_outcome.rs +++ b/rust/crates/core/src/build/test_outcome.rs @@ -146,7 +146,7 @@ mod tests { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/build/test-run-outcome-v1.json" + "../../../../fixtures/build/test-run-outcome-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/build/test_outcome_merge.rs b/rust/crates/core/src/build/test_outcome_merge.rs similarity index 98% rename from rust/lithe-core/src/build/test_outcome_merge.rs rename to rust/crates/core/src/build/test_outcome_merge.rs index afd88b24..2bf703dc 100644 --- a/rust/lithe-core/src/build/test_outcome_merge.rs +++ b/rust/crates/core/src/build/test_outcome_merge.rs @@ -121,7 +121,7 @@ mod tests { #[test] fn shared_fixture_cases_merge_to_their_expected_history() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/build/test-outcome-merge-v1.json" + "../../../../fixtures/build/test-outcome-merge-v1.json" )) .unwrap(); let cases = fixture["cases"].as_array().unwrap(); diff --git a/rust/lithe-core/src/debug/adapters.rs b/rust/crates/core/src/debug/adapters.rs similarity index 100% rename from rust/lithe-core/src/debug/adapters.rs rename to rust/crates/core/src/debug/adapters.rs diff --git a/rust/lithe-core/src/debug/backend_start.rs b/rust/crates/core/src/debug/backend_start.rs similarity index 100% rename from rust/lithe-core/src/debug/backend_start.rs rename to rust/crates/core/src/debug/backend_start.rs diff --git a/rust/lithe-core/src/debug/breakpoint_relocation.rs b/rust/crates/core/src/debug/breakpoint_relocation.rs similarity index 100% rename from rust/lithe-core/src/debug/breakpoint_relocation.rs rename to rust/crates/core/src/debug/breakpoint_relocation.rs diff --git a/rust/lithe-core/src/debug/capabilities.rs b/rust/crates/core/src/debug/capabilities.rs similarity index 100% rename from rust/lithe-core/src/debug/capabilities.rs rename to rust/crates/core/src/debug/capabilities.rs diff --git a/rust/lithe-core/src/debug/disassembly_paging.rs b/rust/crates/core/src/debug/disassembly_paging.rs similarity index 99% rename from rust/lithe-core/src/debug/disassembly_paging.rs rename to rust/crates/core/src/debug/disassembly_paging.rs index 2e9a4de8..17d7f1d8 100644 --- a/rust/lithe-core/src/debug/disassembly_paging.rs +++ b/rust/crates/core/src/debug/disassembly_paging.rs @@ -376,7 +376,7 @@ mod tests { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/debug/disassembly-paging-v1.json" + "../../../../fixtures/debug/disassembly-paging-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/debug/endpoint.rs b/rust/crates/core/src/debug/endpoint.rs similarity index 97% rename from rust/lithe-core/src/debug/endpoint.rs rename to rust/crates/core/src/debug/endpoint.rs index cf8cb4e3..e520c3d8 100644 --- a/rust/lithe-core/src/debug/endpoint.rs +++ b/rust/crates/core/src/debug/endpoint.rs @@ -42,7 +42,7 @@ mod tests { fn dap_endpoint_contract_fixtures_match_validation_and_consent_classification() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/adapter-endpoints-v1.json" + "/../../fixtures/debug/adapter-endpoints-v1.json" ))) .expect("endpoint fixture is JSON"); for case in fixture["cases"].as_array().expect("fixture cases") { diff --git a/rust/lithe-core/src/debug/engine.rs b/rust/crates/core/src/debug/engine.rs similarity index 99% rename from rust/lithe-core/src/debug/engine.rs rename to rust/crates/core/src/debug/engine.rs index 2775393e..faf077b7 100644 --- a/rust/lithe-core/src/debug/engine.rs +++ b/rust/crates/core/src/debug/engine.rs @@ -3249,7 +3249,7 @@ mod tests { #[test] fn delayed_launch_response_preserves_a_newer_stopped_or_terminal_event() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/debug/launch-event-order.json" + "../../../../fixtures/debug/launch-event-order.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -3382,7 +3382,7 @@ mod tests { fn hot_replace_normalizes_success_empty_and_error_bodies() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/hot-code-replace-v1.json" + "/../../fixtures/debug/hot-code-replace-v1.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -3575,7 +3575,7 @@ mod tests { fn disconnect_policy_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/disconnect-policy-v1.json" + "/../../fixtures/debug/disconnect-policy-v1.json" ))) .unwrap(); @@ -4205,7 +4205,7 @@ mod tests { fn source_breakpoint_binding_preserves_requested_identity_and_rejects_stale_replies() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/breakpoint-binding-v1.json" + "/../../fixtures/debug/breakpoint-binding-v1.json" ))) .unwrap(); let session_id = "source-breakpoint-binding"; @@ -4300,7 +4300,7 @@ mod tests { fn start_debugging_request_is_normalized_completed_and_stale_safe() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/start-debugging-v1.json" + "/../../fixtures/debug/start-debugging-v1.json" ))) .unwrap(); let session_id = "debug-start-debugging"; @@ -4368,7 +4368,7 @@ mod tests { fn start_debugging_failure_and_unsupported_hosts_answer_the_adapter() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/start-debugging-v1.json" + "/../../fixtures/debug/start-debugging-v1.json" ))) .unwrap(); for (session_id, supported) in [ @@ -4424,7 +4424,7 @@ mod tests { fn disconnect_fails_a_pending_start_debugging_request() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/start-debugging-v1.json" + "/../../fixtures/debug/start-debugging-v1.json" ))) .unwrap(); let session_id = "debug-start-debugging-disconnect"; @@ -4458,7 +4458,7 @@ mod tests { fn node_source_mapped_locations_pass_through_unchanged() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/node-source-map-v1.json" + "/../../fixtures/debug/node-source-map-v1.json" ))) .unwrap(); let session_id = "debug-node-source-map"; @@ -5407,7 +5407,7 @@ mod tests { fn exception_information_is_capability_gated_and_normalized() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/exception-info-v1.json" + "/../../fixtures/debug/exception-info-v1.json" ))) .unwrap(); let session_id = "debug-exception-info"; @@ -5520,7 +5520,7 @@ mod tests { fn variable_paging_is_forwarded_and_normalized_from_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/variable-paging-v1.json" + "/../../fixtures/debug/variable-paging-v1.json" ))) .unwrap(); let session_id = "debug-variable-paging"; @@ -5694,7 +5694,7 @@ mod tests { fn run_in_terminal_request_is_normalized_completed_and_stale_safe() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/run-in-terminal-v1.json" + "/../../fixtures/debug/run-in-terminal-v1.json" ))) .unwrap(); let session_id = "debug-run-in-terminal"; @@ -6219,7 +6219,7 @@ mod tests { fn stale_reference_fixture_matches_core_behavior() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/stale-reference-v1.json" + "/../../fixtures/debug/stale-reference-v1.json" ))) .unwrap(); let session_id = "debug-stale-fixture"; diff --git a/rust/lithe-core/src/debug/memory_window.rs b/rust/crates/core/src/debug/memory_window.rs similarity index 99% rename from rust/lithe-core/src/debug/memory_window.rs rename to rust/crates/core/src/debug/memory_window.rs index ea2c9c8d..19b9b416 100644 --- a/rust/lithe-core/src/debug/memory_window.rs +++ b/rust/crates/core/src/debug/memory_window.rs @@ -178,7 +178,7 @@ mod tests { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/debug/memory-window-v1.json" + "../../../../fixtures/debug/memory-window-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/debug/mod.rs b/rust/crates/core/src/debug/mod.rs similarity index 100% rename from rust/lithe-core/src/debug/mod.rs rename to rust/crates/core/src/debug/mod.rs diff --git a/rust/lithe-core/src/debug/projection_v2.rs b/rust/crates/core/src/debug/projection_v2.rs similarity index 99% rename from rust/lithe-core/src/debug/projection_v2.rs rename to rust/crates/core/src/debug/projection_v2.rs index 8736369a..399aef73 100644 --- a/rust/lithe-core/src/debug/projection_v2.rs +++ b/rust/crates/core/src/debug/projection_v2.rs @@ -512,7 +512,7 @@ mod tests { fn examples() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/debug/projection-v2-examples.json" + "../../../../fixtures/debug/projection-v2-examples.json" )) .unwrap() } diff --git a/rust/lithe-core/src/debug/protocol.rs b/rust/crates/core/src/debug/protocol.rs similarity index 100% rename from rust/lithe-core/src/debug/protocol.rs rename to rust/crates/core/src/debug/protocol.rs diff --git a/rust/lithe-core/src/debug/shortcut.rs b/rust/crates/core/src/debug/shortcut.rs similarity index 100% rename from rust/lithe-core/src/debug/shortcut.rs rename to rust/crates/core/src/debug/shortcut.rs diff --git a/rust/lithe-core/src/debug/transport_lifecycle.rs b/rust/crates/core/src/debug/transport_lifecycle.rs similarity index 99% rename from rust/lithe-core/src/debug/transport_lifecycle.rs rename to rust/crates/core/src/debug/transport_lifecycle.rs index 33dd8127..0b029566 100644 --- a/rust/lithe-core/src/debug/transport_lifecycle.rs +++ b/rust/crates/core/src/debug/transport_lifecycle.rs @@ -784,7 +784,7 @@ mod tests { fn lifecycle_fixture_scenarios_match_expected_steps() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/transport-lifecycle-v1.json" + "/../../fixtures/debug/transport-lifecycle-v1.json" ))) .expect("transport lifecycle fixture is JSON"); for scenario in fixture["scenarios"].as_array().expect("scenarios") { diff --git a/rust/lithe-core/src/debug/types.rs b/rust/crates/core/src/debug/types.rs similarity index 100% rename from rust/lithe-core/src/debug/types.rs rename to rust/crates/core/src/debug/types.rs diff --git a/rust/lithe-core/src/debug/variable_paging.rs b/rust/crates/core/src/debug/variable_paging.rs similarity index 99% rename from rust/lithe-core/src/debug/variable_paging.rs rename to rust/crates/core/src/debug/variable_paging.rs index d7831535..a97da541 100644 --- a/rust/lithe-core/src/debug/variable_paging.rs +++ b/rust/crates/core/src/debug/variable_paging.rs @@ -288,7 +288,7 @@ mod tests { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/debug/variable-page-plan-v1.json" + "../../../../fixtures/debug/variable-page-plan-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/diagnostics/catalog.rs b/rust/crates/core/src/diagnostics/catalog.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/catalog.rs rename to rust/crates/core/src/diagnostics/catalog.rs diff --git a/rust/lithe-core/src/diagnostics/catalog_generated.rs b/rust/crates/core/src/diagnostics/catalog_generated.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/catalog_generated.rs rename to rust/crates/core/src/diagnostics/catalog_generated.rs diff --git a/rust/lithe-core/src/diagnostics/channel.rs b/rust/crates/core/src/diagnostics/channel.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/channel.rs rename to rust/crates/core/src/diagnostics/channel.rs diff --git a/rust/lithe-core/src/diagnostics/collection.rs b/rust/crates/core/src/diagnostics/collection.rs similarity index 99% rename from rust/lithe-core/src/diagnostics/collection.rs rename to rust/crates/core/src/diagnostics/collection.rs index 401cec49..5d935f8b 100644 --- a/rust/lithe-core/src/diagnostics/collection.rs +++ b/rust/crates/core/src/diagnostics/collection.rs @@ -261,7 +261,7 @@ mod tests { #[test] fn shared_collection_fixture_keeps_active_channels_and_category_compatibility() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/diagnostics/logging-v2.json" + "../../../../fixtures/diagnostics/logging-v2.json" )) .unwrap(); for case in fixture["collection"].as_array().unwrap() { diff --git a/rust/lithe-core/src/diagnostics/core_events.rs b/rust/crates/core/src/diagnostics/core_events.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/core_events.rs rename to rust/crates/core/src/diagnostics/core_events.rs diff --git a/rust/lithe-core/src/diagnostics/filter.rs b/rust/crates/core/src/diagnostics/filter.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/filter.rs rename to rust/crates/core/src/diagnostics/filter.rs diff --git a/rust/lithe-core/src/diagnostics/format.rs b/rust/crates/core/src/diagnostics/format.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/format.rs rename to rust/crates/core/src/diagnostics/format.rs diff --git a/rust/lithe-core/src/diagnostics/helper_failures.rs b/rust/crates/core/src/diagnostics/helper_failures.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/helper_failures.rs rename to rust/crates/core/src/diagnostics/helper_failures.rs diff --git a/rust/lithe-core/src/diagnostics/logging.rs b/rust/crates/core/src/diagnostics/logging.rs similarity index 99% rename from rust/lithe-core/src/diagnostics/logging.rs rename to rust/crates/core/src/diagnostics/logging.rs index c544c20f..8e623da5 100644 --- a/rust/lithe-core/src/diagnostics/logging.rs +++ b/rust/crates/core/src/diagnostics/logging.rs @@ -440,7 +440,7 @@ mod tests { #[test] fn time_filters_and_ordering_compare_instants_from_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/diagnostics/logging-v1.json" + "../../../../fixtures/diagnostics/logging-v1.json" )) .unwrap(); for case in fixture["timeQueries"].as_array().unwrap() { @@ -457,7 +457,7 @@ mod tests { #[test] fn shared_fixture_pins_domains_and_budgets() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/diagnostics/logging-v1.json" + "../../../../fixtures/diagnostics/logging-v1.json" )) .unwrap(); assert_eq!(fixture["categories"], serde_json::json!(LOG_CATEGORIES)); diff --git a/rust/lithe-core/src/diagnostics/manifest.rs b/rust/crates/core/src/diagnostics/manifest.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/manifest.rs rename to rust/crates/core/src/diagnostics/manifest.rs diff --git a/rust/lithe-core/src/diagnostics/mod.rs b/rust/crates/core/src/diagnostics/mod.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/mod.rs rename to rust/crates/core/src/diagnostics/mod.rs diff --git a/rust/lithe-core/src/diagnostics/plugin_operations.rs b/rust/crates/core/src/diagnostics/plugin_operations.rs similarity index 99% rename from rust/lithe-core/src/diagnostics/plugin_operations.rs rename to rust/crates/core/src/diagnostics/plugin_operations.rs index 92ad3217..2bb8b912 100644 --- a/rust/lithe-core/src/diagnostics/plugin_operations.rs +++ b/rust/crates/core/src/diagnostics/plugin_operations.rs @@ -527,7 +527,7 @@ mod tests { #[test] fn diagnostics_host_plugin_operations_match_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/diagnostics/engine-logging-v2.json" + "../../../../fixtures/diagnostics/engine-logging-v2.json" )) .unwrap(); for case in fixture["hostOperations"].as_array().unwrap() { diff --git a/rust/lithe-core/src/diagnostics/query_v2.rs b/rust/crates/core/src/diagnostics/query_v2.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/query_v2.rs rename to rust/crates/core/src/diagnostics/query_v2.rs diff --git a/rust/lithe-core/src/diagnostics/record.rs b/rust/crates/core/src/diagnostics/record.rs similarity index 99% rename from rust/lithe-core/src/diagnostics/record.rs rename to rust/crates/core/src/diagnostics/record.rs index 7ca5bf6a..3ec41249 100644 --- a/rust/lithe-core/src/diagnostics/record.rs +++ b/rust/crates/core/src/diagnostics/record.rs @@ -791,7 +791,7 @@ mod tests { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/diagnostics/logging-v2.json" + "../../../../fixtures/diagnostics/logging-v2.json" )) .unwrap() } diff --git a/rust/lithe-core/src/diagnostics/redaction.rs b/rust/crates/core/src/diagnostics/redaction.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/redaction.rs rename to rust/crates/core/src/diagnostics/redaction.rs diff --git a/rust/lithe-core/src/diagnostics/request_trace.rs b/rust/crates/core/src/diagnostics/request_trace.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/request_trace.rs rename to rust/crates/core/src/diagnostics/request_trace.rs diff --git a/rust/lithe-core/src/diagnostics/retention.rs b/rust/crates/core/src/diagnostics/retention.rs similarity index 100% rename from rust/lithe-core/src/diagnostics/retention.rs rename to rust/crates/core/src/diagnostics/retention.rs diff --git a/rust/lithe-core/src/diff/mod.rs b/rust/crates/core/src/diff/mod.rs similarity index 100% rename from rust/lithe-core/src/diff/mod.rs rename to rust/crates/core/src/diff/mod.rs diff --git a/rust/lithe-core/src/diff/tests.rs b/rust/crates/core/src/diff/tests.rs similarity index 98% rename from rust/lithe-core/src/diff/tests.rs rename to rust/crates/core/src/diff/tests.rs index d895e440..ec0c15d3 100644 --- a/rust/lithe-core/src/diff/tests.rs +++ b/rust/crates/core/src/diff/tests.rs @@ -8,7 +8,7 @@ use serde_json::{json, Value}; fn fixture() -> Value { serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/diff/compare-texts-v1.json" + "/../../fixtures/diff/compare-texts-v1.json" ))) .expect("compare-texts fixture should parse") } diff --git a/rust/lithe-core/src/editor/find.rs b/rust/crates/core/src/editor/find.rs similarity index 100% rename from rust/lithe-core/src/editor/find.rs rename to rust/crates/core/src/editor/find.rs diff --git a/rust/lithe-core/src/editor/line_edit.rs b/rust/crates/core/src/editor/line_edit.rs similarity index 100% rename from rust/lithe-core/src/editor/line_edit.rs rename to rust/crates/core/src/editor/line_edit.rs diff --git a/rust/lithe-core/src/editor/mod.rs b/rust/crates/core/src/editor/mod.rs similarity index 100% rename from rust/lithe-core/src/editor/mod.rs rename to rust/crates/core/src/editor/mod.rs diff --git a/rust/lithe-core/src/editor/navigation_history.rs b/rust/crates/core/src/editor/navigation_history.rs similarity index 100% rename from rust/lithe-core/src/editor/navigation_history.rs rename to rust/crates/core/src/editor/navigation_history.rs diff --git a/rust/lithe-core/src/editor/navigation_input.rs b/rust/crates/core/src/editor/navigation_input.rs similarity index 100% rename from rust/lithe-core/src/editor/navigation_input.rs rename to rust/crates/core/src/editor/navigation_input.rs diff --git a/rust/lithe-core/src/editor/preferences.rs b/rust/crates/core/src/editor/preferences.rs similarity index 100% rename from rust/lithe-core/src/editor/preferences.rs rename to rust/crates/core/src/editor/preferences.rs diff --git a/rust/lithe-core/src/editor/recent.rs b/rust/crates/core/src/editor/recent.rs similarity index 100% rename from rust/lithe-core/src/editor/recent.rs rename to rust/crates/core/src/editor/recent.rs diff --git a/rust/lithe-core/src/editor/recovery.rs b/rust/crates/core/src/editor/recovery.rs similarity index 100% rename from rust/lithe-core/src/editor/recovery.rs rename to rust/crates/core/src/editor/recovery.rs diff --git a/rust/lithe-core/src/editor/tests.rs b/rust/crates/core/src/editor/tests.rs similarity index 99% rename from rust/lithe-core/src/editor/tests.rs rename to rust/crates/core/src/editor/tests.rs index 3b889e65..a389ec04 100644 --- a/rust/lithe-core/src/editor/tests.rs +++ b/rust/crates/core/src/editor/tests.rs @@ -9,7 +9,7 @@ use super::line_edit::{line_comment_token, line_edit, LineCommentTokenRequest, L #[test] fn navigation_input_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/navigation-input-v1.json" + "../../../../fixtures/editor/navigation-input-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -32,7 +32,7 @@ fn navigation_input_matches_shared_fixture() { #[test] fn text_edit_plan_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/text-edit-plan-v1.json" + "../../../../fixtures/editor/text-edit-plan-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -90,7 +90,7 @@ fn navigation_history(payload: Value) -> Value { #[test] fn navigation_history_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/navigation-history-v1.json" + "../../../../fixtures/editor/navigation-history-v1.json" )) .unwrap(); assert_eq!( @@ -782,7 +782,7 @@ fn every_operation_maps_selections_inside_the_edited_document() { fn shared_fixture_cases_match_core_outcomes() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/editor/line-edit-v1.json" + "/../../fixtures/editor/line-edit-v1.json" ))) .expect("line edit fixture should be valid JSON"); for case_value in fixture["cases"].as_array().expect("cases") { diff --git a/rust/lithe-core/src/editor/text_edit_plan.rs b/rust/crates/core/src/editor/text_edit_plan.rs similarity index 100% rename from rust/lithe-core/src/editor/text_edit_plan.rs rename to rust/crates/core/src/editor/text_edit_plan.rs diff --git a/rust/lithe-core/src/execution/argument_text.rs b/rust/crates/core/src/execution/argument_text.rs similarity index 95% rename from rust/lithe-core/src/execution/argument_text.rs rename to rust/crates/core/src/execution/argument_text.rs index 582b906c..be010c2e 100644 --- a/rust/lithe-core/src/execution/argument_text.rs +++ b/rust/crates/core/src/execution/argument_text.rs @@ -45,7 +45,7 @@ mod tests { #[test] fn argument_text_command_formats_a_batch_from_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/argument-text.json" + "../../../../fixtures/run-configuration/argument-text.json" )) .unwrap(); let cases = fixture["cases"].as_array().unwrap(); @@ -64,7 +64,7 @@ mod tests { #[test] fn argument_text_matches_the_shared_roundtrip_examples() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/argument-text.json" + "../../../../fixtures/run-configuration/argument-text.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/execution/configuration.rs b/rust/crates/core/src/execution/configuration.rs similarity index 100% rename from rust/lithe-core/src/execution/configuration.rs rename to rust/crates/core/src/execution/configuration.rs diff --git a/rust/lithe-core/src/execution/configuration/project_toolchain.rs b/rust/crates/core/src/execution/configuration/project_toolchain.rs similarity index 100% rename from rust/lithe-core/src/execution/configuration/project_toolchain.rs rename to rust/crates/core/src/execution/configuration/project_toolchain.rs diff --git a/rust/lithe-core/src/execution/context_selection.rs b/rust/crates/core/src/execution/context_selection.rs similarity index 97% rename from rust/lithe-core/src/execution/context_selection.rs rename to rust/crates/core/src/execution/context_selection.rs index 63aa4df4..ddafbe6e 100644 --- a/rust/lithe-core/src/execution/context_selection.rs +++ b/rust/crates/core/src/execution/context_selection.rs @@ -67,7 +67,7 @@ mod tests { #[test] fn context_selection_command_matches_shared_provider_neutral_cases() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/context-selection.json" + "../../../../fixtures/run-configuration/context-selection.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/execution/detectors/cargo.rs b/rust/crates/core/src/execution/detectors/cargo.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/cargo.rs rename to rust/crates/core/src/execution/detectors/cargo.rs diff --git a/rust/lithe-core/src/execution/detectors/compose.rs b/rust/crates/core/src/execution/detectors/compose.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/compose.rs rename to rust/crates/core/src/execution/detectors/compose.rs diff --git a/rust/lithe-core/src/execution/detectors/go.rs b/rust/crates/core/src/execution/detectors/go.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/go.rs rename to rust/crates/core/src/execution/detectors/go.rs diff --git a/rust/lithe-core/src/execution/detectors/make.rs b/rust/crates/core/src/execution/detectors/make.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/make.rs rename to rust/crates/core/src/execution/detectors/make.rs diff --git a/rust/lithe-core/src/execution/detectors/mod.rs b/rust/crates/core/src/execution/detectors/mod.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/mod.rs rename to rust/crates/core/src/execution/detectors/mod.rs diff --git a/rust/lithe-core/src/execution/detectors/npm.rs b/rust/crates/core/src/execution/detectors/npm.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/npm.rs rename to rust/crates/core/src/execution/detectors/npm.rs diff --git a/rust/lithe-core/src/execution/detectors/procfile.rs b/rust/crates/core/src/execution/detectors/procfile.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/procfile.rs rename to rust/crates/core/src/execution/detectors/procfile.rs diff --git a/rust/lithe-core/src/execution/detectors/python.rs b/rust/crates/core/src/execution/detectors/python.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/python.rs rename to rust/crates/core/src/execution/detectors/python.rs diff --git a/rust/lithe-core/src/execution/detectors/scan.rs b/rust/crates/core/src/execution/detectors/scan.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/scan.rs rename to rust/crates/core/src/execution/detectors/scan.rs diff --git a/rust/lithe-core/src/execution/detectors/shell.rs b/rust/crates/core/src/execution/detectors/shell.rs similarity index 100% rename from rust/lithe-core/src/execution/detectors/shell.rs rename to rust/crates/core/src/execution/detectors/shell.rs diff --git a/rust/lithe-core/src/execution/environment.rs b/rust/crates/core/src/execution/environment.rs similarity index 97% rename from rust/lithe-core/src/execution/environment.rs rename to rust/crates/core/src/execution/environment.rs index 3bd4066d..1e667648 100644 --- a/rust/lithe-core/src/execution/environment.rs +++ b/rust/crates/core/src/execution/environment.rs @@ -105,7 +105,7 @@ mod tests { #[test] fn search_path_command_follows_the_shared_order_and_identity_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/execution/search-path-v1.json" + "../../../../fixtures/execution/search-path-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -120,7 +120,7 @@ mod tests { #[test] fn environment_command_follows_the_shared_precedence_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/execution/launch-environment-v1.json" + "../../../../fixtures/execution/launch-environment-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/execution/generated_layer.rs b/rust/crates/core/src/execution/generated_layer.rs similarity index 100% rename from rust/lithe-core/src/execution/generated_layer.rs rename to rust/crates/core/src/execution/generated_layer.rs diff --git a/rust/lithe-core/src/execution/mod.rs b/rust/crates/core/src/execution/mod.rs similarity index 100% rename from rust/lithe-core/src/execution/mod.rs rename to rust/crates/core/src/execution/mod.rs diff --git a/rust/lithe-core/src/execution/provider_run_options.rs b/rust/crates/core/src/execution/provider_run_options.rs similarity index 100% rename from rust/lithe-core/src/execution/provider_run_options.rs rename to rust/crates/core/src/execution/provider_run_options.rs diff --git a/rust/lithe-core/src/execution/provider_runs.rs b/rust/crates/core/src/execution/provider_runs.rs similarity index 100% rename from rust/lithe-core/src/execution/provider_runs.rs rename to rust/crates/core/src/execution/provider_runs.rs diff --git a/rust/lithe-core/src/execution/title_action.rs b/rust/crates/core/src/execution/title_action.rs similarity index 98% rename from rust/lithe-core/src/execution/title_action.rs rename to rust/crates/core/src/execution/title_action.rs index 6a82c161..f02b7f17 100644 --- a/rust/lithe-core/src/execution/title_action.rs +++ b/rust/crates/core/src/execution/title_action.rs @@ -122,7 +122,7 @@ mod tests { #[test] fn title_actions_match_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/title-action-v1.json" + "../../../../fixtures/run-configuration/title-action-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/execution/types.rs b/rust/crates/core/src/execution/types.rs similarity index 100% rename from rust/lithe-core/src/execution/types.rs rename to rust/crates/core/src/execution/types.rs diff --git a/rust/lithe-core/src/execution/workspace_scan.rs b/rust/crates/core/src/execution/workspace_scan.rs similarity index 100% rename from rust/lithe-core/src/execution/workspace_scan.rs rename to rust/crates/core/src/execution/workspace_scan.rs diff --git a/rust/lithe-core/src/git/authentication_failure.rs b/rust/crates/core/src/git/authentication_failure.rs similarity index 99% rename from rust/lithe-core/src/git/authentication_failure.rs rename to rust/crates/core/src/git/authentication_failure.rs index f936af48..9a34be85 100644 --- a/rust/lithe-core/src/git/authentication_failure.rs +++ b/rust/crates/core/src/git/authentication_failure.rs @@ -117,7 +117,7 @@ mod tests { #[test] fn shared_fixture_samples_classify_as_documented() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/authentication-failure-v1.json" + "../../../../fixtures/git/authentication-failure-v1.json" )) .unwrap(); for (key, expected) in [("failures", true), ("unrelated", false)] { diff --git a/rust/lithe-core/src/git/branch_names.rs b/rust/crates/core/src/git/branch_names.rs similarity index 100% rename from rust/lithe-core/src/git/branch_names.rs rename to rust/crates/core/src/git/branch_names.rs diff --git a/rust/lithe-core/src/git/catalog.rs b/rust/crates/core/src/git/catalog.rs similarity index 100% rename from rust/lithe-core/src/git/catalog.rs rename to rust/crates/core/src/git/catalog.rs diff --git a/rust/lithe-core/src/git/change_targets.rs b/rust/crates/core/src/git/change_targets.rs similarity index 96% rename from rust/lithe-core/src/git/change_targets.rs rename to rust/crates/core/src/git/change_targets.rs index ae255525..098a3665 100644 --- a/rust/lithe-core/src/git/change_targets.rs +++ b/rust/crates/core/src/git/change_targets.rs @@ -114,9 +114,10 @@ mod tests { #[test] fn shared_fixture_cases_keep_only_operation_targets() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/change-targets-v1.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/change-targets-v1.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response = call(case["request"].clone()); assert_eq!(response["ok"], true, "{}: {response}", case["name"]); diff --git a/rust/lithe-core/src/git/changelists.rs b/rust/crates/core/src/git/changelists.rs similarity index 99% rename from rust/lithe-core/src/git/changelists.rs rename to rust/crates/core/src/git/changelists.rs index 98969e94..bf959513 100644 --- a/rust/lithe-core/src/git/changelists.rs +++ b/rust/crates/core/src/git/changelists.rs @@ -353,7 +353,7 @@ mod tests { #[test] fn shared_fixture_matches_the_reducer() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/changelists-reducer-v1.json" + "../../../../fixtures/git/changelists-reducer-v1.json" )) .unwrap(); assert_eq!( diff --git a/rust/lithe-core/src/git/command_trace.rs b/rust/crates/core/src/git/command_trace.rs similarity index 100% rename from rust/lithe-core/src/git/command_trace.rs rename to rust/crates/core/src/git/command_trace.rs diff --git a/rust/lithe-core/src/git/commit_message_context.rs b/rust/crates/core/src/git/commit_message_context.rs similarity index 100% rename from rust/lithe-core/src/git/commit_message_context.rs rename to rust/crates/core/src/git/commit_message_context.rs diff --git a/rust/lithe-core/src/git/commit_selection.rs b/rust/crates/core/src/git/commit_selection.rs similarity index 99% rename from rust/lithe-core/src/git/commit_selection.rs rename to rust/crates/core/src/git/commit_selection.rs index 25182224..dd9b41e5 100644 --- a/rust/lithe-core/src/git/commit_selection.rs +++ b/rust/crates/core/src/git/commit_selection.rs @@ -489,7 +489,7 @@ mod tests { #[test] fn shared_fixture_plans_without_overwriting_selected_index_content() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/commit-selection-plan-v1.json" + "../../../../fixtures/git/commit-selection-plan-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/git/commit_state.rs b/rust/crates/core/src/git/commit_state.rs similarity index 100% rename from rust/lithe-core/src/git/commit_state.rs rename to rust/crates/core/src/git/commit_state.rs diff --git a/rust/lithe-core/src/git/configuration.rs b/rust/crates/core/src/git/configuration.rs similarity index 99% rename from rust/lithe-core/src/git/configuration.rs rename to rust/crates/core/src/git/configuration.rs index d4e8e70a..16e0a27a 100644 --- a/rust/lithe-core/src/git/configuration.rs +++ b/rust/crates/core/src/git/configuration.rs @@ -598,9 +598,10 @@ mod tests { use super::*; #[test] fn resolved_fetch_behavior_matches_shared_fixture() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/fetch-behavior-v1.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/fetch-behavior-v1.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let entries: Vec = serde_json::from_value(case["request"]["entries"].clone()).unwrap(); diff --git a/rust/lithe-core/src/git/console/command.rs b/rust/crates/core/src/git/console/command.rs similarity index 100% rename from rust/lithe-core/src/git/console/command.rs rename to rust/crates/core/src/git/console/command.rs diff --git a/rust/lithe-core/src/git/console/mod.rs b/rust/crates/core/src/git/console/mod.rs similarity index 100% rename from rust/lithe-core/src/git/console/mod.rs rename to rust/crates/core/src/git/console/mod.rs diff --git a/rust/lithe-core/src/git/console/output.rs b/rust/crates/core/src/git/console/output.rs similarity index 100% rename from rust/lithe-core/src/git/console/output.rs rename to rust/crates/core/src/git/console/output.rs diff --git a/rust/lithe-core/src/git/console/tests.rs b/rust/crates/core/src/git/console/tests.rs similarity index 99% rename from rust/lithe-core/src/git/console/tests.rs rename to rust/crates/core/src/git/console/tests.rs index c515d3d4..59a28daa 100644 --- a/rust/lithe-core/src/git/console/tests.rs +++ b/rust/crates/core/src/git/console/tests.rs @@ -5,7 +5,7 @@ use serde_json::{json, Value}; #[test] fn presentation_matches_shared_console_cases_without_rewriting_retained_output() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../fixtures/git/console-presentation-v1.json" + "../../../../../fixtures/git/console-presentation-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/git/console/types.rs b/rust/crates/core/src/git/console/types.rs similarity index 100% rename from rust/lithe-core/src/git/console/types.rs rename to rust/crates/core/src/git/console/types.rs diff --git a/rust/lithe-core/src/git/deleted_selection.rs b/rust/crates/core/src/git/deleted_selection.rs similarity index 100% rename from rust/lithe-core/src/git/deleted_selection.rs rename to rust/crates/core/src/git/deleted_selection.rs diff --git a/rust/lithe-core/src/git/diff_blocks.rs b/rust/crates/core/src/git/diff_blocks.rs similarity index 100% rename from rust/lithe-core/src/git/diff_blocks.rs rename to rust/crates/core/src/git/diff_blocks.rs diff --git a/rust/lithe-core/src/git/execution_events.rs b/rust/crates/core/src/git/execution_events.rs similarity index 99% rename from rust/lithe-core/src/git/execution_events.rs rename to rust/crates/core/src/git/execution_events.rs index 22b9e282..c31b947f 100644 --- a/rust/lithe-core/src/git/execution_events.rs +++ b/rust/crates/core/src/git/execution_events.rs @@ -820,7 +820,7 @@ mod tests { } } let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/execution-events-v1.json" + "../../../../fixtures/git/execution-events-v1.json" )) .unwrap(); assert_eq!(serde_json::json!(events), fixture["events"]); diff --git a/rust/lithe-core/src/git/execution_policy.rs b/rust/crates/core/src/git/execution_policy.rs similarity index 98% rename from rust/lithe-core/src/git/execution_policy.rs rename to rust/crates/core/src/git/execution_policy.rs index f0ff69c6..523d335b 100644 --- a/rust/lithe-core/src/git/execution_policy.rs +++ b/rust/crates/core/src/git/execution_policy.rs @@ -174,7 +174,7 @@ mod tests { #[test] fn console_projection_preserves_raw_arguments_and_folds_only_global_options() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/console-command-v1.json" + "../../../../fixtures/git/console-command-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -216,7 +216,7 @@ mod tests { fn named_defaults_are_scoped_and_do_not_duplicate_transfer_progress() { let before = current(); let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/execution-policy-v1.json" + "../../../../fixtures/git/execution-policy-v1.json" )) .unwrap(); assert_eq!( diff --git a/rust/lithe-core/src/git/fetch.rs b/rust/crates/core/src/git/fetch.rs similarity index 98% rename from rust/lithe-core/src/git/fetch.rs rename to rust/crates/core/src/git/fetch.rs index 06eabf31..87b6f43a 100644 --- a/rust/lithe-core/src/git/fetch.rs +++ b/rust/crates/core/src/git/fetch.rs @@ -174,7 +174,7 @@ mod tests { use serde_json::{json, Value}; fn fixture() -> Value { - serde_json::from_str(include_str!("../../../fixtures/git/fetch-plan-v1.json")).unwrap() + serde_json::from_str(include_str!("../../../../fixtures/git/fetch-plan-v1.json")).unwrap() } fn request(payload: Value) -> Value { diff --git a/rust/lithe-core/src/git/fetch_execution.rs b/rust/crates/core/src/git/fetch_execution.rs similarity index 100% rename from rust/lithe-core/src/git/fetch_execution.rs rename to rust/crates/core/src/git/fetch_execution.rs diff --git a/rust/lithe-core/src/git/file_context.rs b/rust/crates/core/src/git/file_context.rs similarity index 100% rename from rust/lithe-core/src/git/file_context.rs rename to rust/crates/core/src/git/file_context.rs diff --git a/rust/lithe-core/src/git/github_checkout.rs b/rust/crates/core/src/git/github_checkout.rs similarity index 100% rename from rust/lithe-core/src/git/github_checkout.rs rename to rust/crates/core/src/git/github_checkout.rs diff --git a/rust/lithe-core/src/git/graph.rs b/rust/crates/core/src/git/graph.rs similarity index 100% rename from rust/lithe-core/src/git/graph.rs rename to rust/crates/core/src/git/graph.rs diff --git a/rust/lithe-core/src/git/graph_tests.rs b/rust/crates/core/src/git/graph_tests.rs similarity index 99% rename from rust/lithe-core/src/git/graph_tests.rs rename to rust/crates/core/src/git/graph_tests.rs index cadc9e61..b5d47287 100644 --- a/rust/lithe-core/src/git/graph_tests.rs +++ b/rust/crates/core/src/git/graph_tests.rs @@ -56,7 +56,7 @@ fn call(payload: Value) -> Value { fn root_path(relative: &str) -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../..") + .join("../../..") .join(relative) } @@ -66,7 +66,7 @@ fn read_fixture(relative: &str) -> String { fn shared_fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/git/graph-projection-v1.json" + "../../../../fixtures/git/graph-projection-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/git/history.rs b/rust/crates/core/src/git/history.rs similarity index 99% rename from rust/lithe-core/src/git/history.rs rename to rust/crates/core/src/git/history.rs index 4433b899..866d59e0 100644 --- a/rust/lithe-core/src/git/history.rs +++ b/rust/crates/core/src/git/history.rs @@ -1432,7 +1432,7 @@ mod tests { .collect() }; let request: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/history-page-date-request-v1.json" + "../../../../fixtures/git/history-page-date-request-v1.json" )) .expect("portable date-order request"); let first = page(request.clone()); @@ -1477,9 +1477,10 @@ mod tests { use serde_json::Value; use std::collections::BTreeSet; - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/history-locate-v1.json")) - .expect("history locate fixture should be valid JSON"); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/history-locate-v1.json" + )) + .expect("history locate fixture should be valid JSON"); let minimal: super::GitHistoryLocateRequest = serde_json::from_value(fixture["minimalRequest"].clone()) diff --git a/rust/lithe-core/src/git/history_query.rs b/rust/crates/core/src/git/history_query.rs similarity index 100% rename from rust/lithe-core/src/git/history_query.rs rename to rust/crates/core/src/git/history_query.rs diff --git a/rust/lithe-core/src/git/history_window.rs b/rust/crates/core/src/git/history_window.rs similarity index 98% rename from rust/lithe-core/src/git/history_window.rs rename to rust/crates/core/src/git/history_window.rs index a804ff75..5d8b5976 100644 --- a/rust/lithe-core/src/git/history_window.rs +++ b/rust/crates/core/src/git/history_window.rs @@ -243,9 +243,10 @@ mod tests { #[test] fn shared_fixture_windows_keep_depth_and_selection() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/history-window-v1.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/history-window-v1.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response = call(case["request"].clone()); assert_eq!(response["ok"], true, "{}: {response}", case["name"]); diff --git a/rust/lithe-core/src/git/metadata_watch.rs b/rust/crates/core/src/git/metadata_watch.rs similarity index 100% rename from rust/lithe-core/src/git/metadata_watch.rs rename to rust/crates/core/src/git/metadata_watch.rs diff --git a/rust/lithe-core/src/git/mod.rs b/rust/crates/core/src/git/mod.rs similarity index 99% rename from rust/lithe-core/src/git/mod.rs rename to rust/crates/core/src/git/mod.rs index 657ff6c3..6dd5b08d 100644 --- a/rust/lithe-core/src/git/mod.rs +++ b/rust/crates/core/src/git/mod.rs @@ -9064,7 +9064,8 @@ mod tests { #[test] fn windows_git_paths_follow_shared_identity_policy() { let cases: Value = - serde_json::from_str(include_str!("../../../fixtures/git/windows-paths.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/git/windows-paths.json")) + .unwrap(); for case in cases["accepted"].as_array().unwrap() { let path = simplified_canonical_path(PathBuf::from(case["input"].as_str().unwrap())).unwrap(); @@ -9287,7 +9288,7 @@ mod tests { // including the combinations that must fail before any subprocess. let fixture: TagWriteFixture = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/tag-write-v1.json" + "/../../fixtures/git/tag-write-v1.json" ))) .expect("tag write fixture should be valid JSON"); for case in &fixture.cases { @@ -9462,7 +9463,7 @@ mod tests { fn command_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/command-response-v1.json" + "/../../fixtures/git/command-response-v1.json" ))) .expect("Git command response fixture should be valid JSON"); let response = GitCommandResponse { @@ -9545,7 +9546,7 @@ mod tests { fn history_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/history-response-v1.json" + "/../../fixtures/git/history-response-v1.json" ))) .expect("Git history response fixture should be valid JSON"); let feature = GitReferenceResponse { @@ -9598,7 +9599,7 @@ mod tests { fn references_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/references-response-v1.json" + "/../../fixtures/git/references-response-v1.json" ))) .expect("Git references response fixture should be valid JSON"); let feature = GitReferenceResponse { @@ -9638,7 +9639,7 @@ mod tests { fn history_page_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/history-page-response-v1.json" + "/../../fixtures/git/history-page-response-v1.json" ))) .expect("Git history page response fixture should be valid JSON"); let response = GitHistoryPageResponse { @@ -9669,7 +9670,7 @@ mod tests { fn commit_lookup_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/commit-lookup-response-v1.json" + "/../../fixtures/git/commit-lookup-response-v1.json" ))) .expect("Git commit lookup response fixture should be valid JSON"); let response = GitCommitLookupResponse { @@ -9718,7 +9719,7 @@ mod tests { fn push_preview_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/push-preview-v1.json" + "/../../fixtures/git/push-preview-v1.json" ))) .expect("Git push preview fixture should be valid JSON"); let response = GitPushPreviewResponse { @@ -9759,7 +9760,7 @@ mod tests { fn command_error_response_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/command-error-response-v1.json" + "/../../fixtures/git/command-error-response-v1.json" ))) .expect("Git command error response fixture should be valid JSON"); let response = GitCommandResponse { @@ -9808,7 +9809,7 @@ mod tests { fn structured_diff_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/diff.json" + "/../../fixtures/git/diff.json" ))) .expect("diff fixture should be valid JSON"); let patch = fixture["patch"] diff --git a/rust/lithe-core/src/git/mutations.rs b/rust/crates/core/src/git/mutations.rs similarity index 100% rename from rust/lithe-core/src/git/mutations.rs rename to rust/crates/core/src/git/mutations.rs diff --git a/rust/lithe-core/src/git/patch_exchange.rs b/rust/crates/core/src/git/patch_exchange.rs similarity index 100% rename from rust/lithe-core/src/git/patch_exchange.rs rename to rust/crates/core/src/git/patch_exchange.rs diff --git a/rust/lithe-core/src/git/progress.rs b/rust/crates/core/src/git/progress.rs similarity index 97% rename from rust/lithe-core/src/git/progress.rs rename to rust/crates/core/src/git/progress.rs index 5d8b2493..bfcd6881 100644 --- a/rust/lithe-core/src/git/progress.rs +++ b/rust/crates/core/src/git/progress.rs @@ -49,7 +49,7 @@ mod tests { #[test] fn progress_matches_shared_phases_without_treating_errors_as_percentages() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/execution-policy-v1.json" + "../../../../fixtures/git/execution-policy-v1.json" )) .unwrap(); for case in fixture["progress"].as_array().unwrap() { diff --git a/rust/lithe-core/src/git/rebase_session.rs b/rust/crates/core/src/git/rebase_session.rs similarity index 99% rename from rust/lithe-core/src/git/rebase_session.rs rename to rust/crates/core/src/git/rebase_session.rs index 21493a1f..c1136286 100644 --- a/rust/lithe-core/src/git/rebase_session.rs +++ b/rust/crates/core/src/git/rebase_session.rs @@ -1239,7 +1239,7 @@ mod plan_preview_tests { #[test] fn shared_fixture_drafts_match_start_semantics() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/rebase-plan-preview-v1.json" + "../../../../fixtures/git/rebase-plan-preview-v1.json" )) .unwrap(); let commits = &fixture["commits"]; @@ -1257,7 +1257,7 @@ mod plan_preview_tests { #[test] fn issue_free_preview_is_accepted_by_the_start_planner() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/rebase-plan-preview-v1.json" + "../../../../fixtures/git/rebase-plan-preview-v1.json" )) .unwrap(); let commits = fixture["commits"] diff --git a/rust/lithe-core/src/git/reference_tree.rs b/rust/crates/core/src/git/reference_tree.rs similarity index 97% rename from rust/lithe-core/src/git/reference_tree.rs rename to rust/crates/core/src/git/reference_tree.rs index e2bdff59..0ab20a8f 100644 --- a/rust/lithe-core/src/git/reference_tree.rs +++ b/rust/crates/core/src/git/reference_tree.rs @@ -164,9 +164,10 @@ mod tests { #[test] fn shared_fixture_trees_have_one_grouping_and_order() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/reference-tree-v1.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/reference-tree-v1.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response = call(case["request"].clone()); assert_eq!(response["ok"], true, "{}: {response}", case["name"]); diff --git a/rust/lithe-core/src/git/remote_history.rs b/rust/crates/core/src/git/remote_history.rs similarity index 100% rename from rust/lithe-core/src/git/remote_history.rs rename to rust/crates/core/src/git/remote_history.rs diff --git a/rust/lithe-core/src/git/remote_process.rs b/rust/crates/core/src/git/remote_process.rs similarity index 100% rename from rust/lithe-core/src/git/remote_process.rs rename to rust/crates/core/src/git/remote_process.rs diff --git a/rust/lithe-core/src/git/repository_colors.rs b/rust/crates/core/src/git/repository_colors.rs similarity index 100% rename from rust/lithe-core/src/git/repository_colors.rs rename to rust/crates/core/src/git/repository_colors.rs diff --git a/rust/lithe-core/src/git/rewrite.rs b/rust/crates/core/src/git/rewrite.rs similarity index 100% rename from rust/lithe-core/src/git/rewrite.rs rename to rust/crates/core/src/git/rewrite.rs diff --git a/rust/lithe-core/src/git/rollback.rs b/rust/crates/core/src/git/rollback.rs similarity index 100% rename from rust/lithe-core/src/git/rollback.rs rename to rust/crates/core/src/git/rollback.rs diff --git a/rust/lithe-core/src/git/setup.rs b/rust/crates/core/src/git/setup.rs similarity index 100% rename from rust/lithe-core/src/git/setup.rs rename to rust/crates/core/src/git/setup.rs diff --git a/rust/lithe-core/src/git/shelf.rs b/rust/crates/core/src/git/shelf.rs similarity index 100% rename from rust/lithe-core/src/git/shelf.rs rename to rust/crates/core/src/git/shelf.rs diff --git a/rust/lithe-core/src/git/untracked_directories.rs b/rust/crates/core/src/git/untracked_directories.rs similarity index 100% rename from rust/lithe-core/src/git/untracked_directories.rs rename to rust/crates/core/src/git/untracked_directories.rs diff --git a/rust/lithe-core/src/git/update_plan.rs b/rust/crates/core/src/git/update_plan.rs similarity index 99% rename from rust/lithe-core/src/git/update_plan.rs rename to rust/crates/core/src/git/update_plan.rs index 4dc39675..4a77a885 100644 --- a/rust/lithe-core/src/git/update_plan.rs +++ b/rust/crates/core/src/git/update_plan.rs @@ -324,7 +324,7 @@ mod tests { #[test] fn shared_fixture_steps_are_the_only_update_rules() { let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/update-plan-v1.json")) + serde_json::from_str(include_str!("../../../../fixtures/git/update-plan-v1.json")) .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response = call(case["request"].clone()); diff --git a/rust/lithe-core/src/git/workspace_commit.rs b/rust/crates/core/src/git/workspace_commit.rs similarity index 100% rename from rust/lithe-core/src/git/workspace_commit.rs rename to rust/crates/core/src/git/workspace_commit.rs diff --git a/rust/lithe-core/src/git/workspace_commit/path_scope.rs b/rust/crates/core/src/git/workspace_commit/path_scope.rs similarity index 100% rename from rust/lithe-core/src/git/workspace_commit/path_scope.rs rename to rust/crates/core/src/git/workspace_commit/path_scope.rs diff --git a/rust/lithe-core/src/git/workspace_commit/tests.rs b/rust/crates/core/src/git/workspace_commit/tests.rs similarity index 98% rename from rust/lithe-core/src/git/workspace_commit/tests.rs rename to rust/crates/core/src/git/workspace_commit/tests.rs index a60fc4f5..9a2f04c7 100644 --- a/rust/lithe-core/src/git/workspace_commit/tests.rs +++ b/rust/crates/core/src/git/workspace_commit/tests.rs @@ -172,7 +172,7 @@ fn missing_unfinished_roots_and_cycles_fail_closed() { #[test] fn shared_workflow_fixture_is_the_complete_portable_contract() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../../fixtures/git/workspace-commit-workflow-v1.json" + "../../../../../fixtures/git/workspace-commit-workflow-v1.json" )) .unwrap(); let request = serde_json::from_value(fixture["request"].clone()).unwrap(); @@ -275,7 +275,7 @@ fn changelist_scope_is_checked_on_continuations_and_compared_during_review() { #[test] fn local_changelist_scope_fixture_defines_default_and_custom_membership() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../../fixtures/git/local-changelist-scope-v1.json" + "../../../../../fixtures/git/local-changelist-scope-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/git/workspace_status.rs b/rust/crates/core/src/git/workspace_status.rs similarity index 100% rename from rust/lithe-core/src/git/workspace_status.rs rename to rust/crates/core/src/git/workspace_status.rs diff --git a/rust/lithe-core/src/github/mod.rs b/rust/crates/core/src/github/mod.rs similarity index 100% rename from rust/lithe-core/src/github/mod.rs rename to rust/crates/core/src/github/mod.rs diff --git a/rust/lithe-core/src/keymap/bindings.rs b/rust/crates/core/src/keymap/bindings.rs similarity index 100% rename from rust/lithe-core/src/keymap/bindings.rs rename to rust/crates/core/src/keymap/bindings.rs diff --git a/rust/lithe-core/src/keymap/mod.rs b/rust/crates/core/src/keymap/mod.rs similarity index 100% rename from rust/lithe-core/src/keymap/mod.rs rename to rust/crates/core/src/keymap/mod.rs diff --git a/rust/lithe-core/src/keymap/schemes.rs b/rust/crates/core/src/keymap/schemes.rs similarity index 100% rename from rust/lithe-core/src/keymap/schemes.rs rename to rust/crates/core/src/keymap/schemes.rs diff --git a/rust/lithe-core/src/lib.rs b/rust/crates/core/src/lib.rs similarity index 97% rename from rust/lithe-core/src/lib.rs rename to rust/crates/core/src/lib.rs index 5713371e..318230fe 100644 --- a/rust/lithe-core/src/lib.rs +++ b/rust/crates/core/src/lib.rs @@ -28,7 +28,7 @@ pub use protocol::{ CoreCommand, CoreError, CoreEvent, CoreRequest, CoreResponse, ErrorCode, ResponseData, }; -/// The `ai.*` commands, kept in their own crate (`rust/lithe-ai`); re-exported so the former +/// The `ai.*` commands, kept in their own crate (`rust/crates/ai`); re-exported so the former /// `lithe_core::ai` paths keep resolving. pub use lithe_ai as ai; diff --git a/rust/lithe-core/src/lsp/declaration_or_usages.rs b/rust/crates/core/src/lsp/declaration_or_usages.rs similarity index 98% rename from rust/lithe-core/src/lsp/declaration_or_usages.rs rename to rust/crates/core/src/lsp/declaration_or_usages.rs index 44e3c61e..38324bf2 100644 --- a/rust/lithe-core/src/lsp/declaration_or_usages.rs +++ b/rust/crates/core/src/lsp/declaration_or_usages.rs @@ -94,7 +94,7 @@ mod tests { #[test] fn matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/lsp/declaration-or-usages-v1.json" + "../../../../fixtures/lsp/declaration-or-usages-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/document_identity.rs b/rust/crates/core/src/lsp/document_identity.rs similarity index 98% rename from rust/lithe-core/src/lsp/document_identity.rs rename to rust/crates/core/src/lsp/document_identity.rs index 4335d55b..0fb71cb7 100644 --- a/rust/lithe-core/src/lsp/document_identity.rs +++ b/rust/crates/core/src/lsp/document_identity.rs @@ -114,7 +114,7 @@ mod tests { #[test] fn matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/lsp/document-identity-v1.json" + "../../../../fixtures/lsp/document-identity-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/host_policy/activation.rs b/rust/crates/core/src/lsp/host_policy/activation.rs similarity index 100% rename from rust/lithe-core/src/lsp/host_policy/activation.rs rename to rust/crates/core/src/lsp/host_policy/activation.rs diff --git a/rust/lithe-core/src/lsp/host_policy/completion_merge.rs b/rust/crates/core/src/lsp/host_policy/completion_merge.rs similarity index 100% rename from rust/lithe-core/src/lsp/host_policy/completion_merge.rs rename to rust/crates/core/src/lsp/host_policy/completion_merge.rs diff --git a/rust/lithe-core/src/lsp/host_policy/mod.rs b/rust/crates/core/src/lsp/host_policy/mod.rs similarity index 100% rename from rust/lithe-core/src/lsp/host_policy/mod.rs rename to rust/crates/core/src/lsp/host_policy/mod.rs diff --git a/rust/lithe-core/src/lsp/host_policy/problems.rs b/rust/crates/core/src/lsp/host_policy/problems.rs similarity index 100% rename from rust/lithe-core/src/lsp/host_policy/problems.rs rename to rust/crates/core/src/lsp/host_policy/problems.rs diff --git a/rust/lithe-core/src/lsp/host_policy/tests.rs b/rust/crates/core/src/lsp/host_policy/tests.rs similarity index 89% rename from rust/lithe-core/src/lsp/host_policy/tests.rs rename to rust/crates/core/src/lsp/host_policy/tests.rs index e12e46bc..0c6e9bea 100644 --- a/rust/lithe-core/src/lsp/host_policy/tests.rs +++ b/rust/crates/core/src/lsp/host_policy/tests.rs @@ -23,14 +23,14 @@ fn run_fixture(command: &str, fixture: &str) { fn problems_query_matches_shared_fixture() { run_fixture( "lsp.problems.query", - include_str!("../../../../fixtures/lsp/problems-query-v1.json"), + include_str!("../../../../../fixtures/lsp/problems-query-v1.json"), ); } #[test] fn activation_policy_matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../fixtures/lsp/activation-policy-v1.json" + "../../../../../fixtures/lsp/activation-policy-v1.json" )) .unwrap(); // The fixture documents the budget; keep it pinned to the constants. @@ -44,7 +44,7 @@ fn activation_policy_matches_shared_fixture() { ); run_fixture( "lsp.activationPolicy", - include_str!("../../../../fixtures/lsp/activation-policy-v1.json"), + include_str!("../../../../../fixtures/lsp/activation-policy-v1.json"), ); } @@ -52,7 +52,7 @@ fn activation_policy_matches_shared_fixture() { fn completion_merge_matches_shared_fixture() { run_fixture( "lsp.mergeCompletions", - include_str!("../../../../fixtures/lsp/completion-merge-v1.json"), + include_str!("../../../../../fixtures/lsp/completion-merge-v1.json"), ); } diff --git a/rust/lithe-core/src/lsp/interface/build_provider.rs b/rust/crates/core/src/lsp/interface/build_provider.rs similarity index 98% rename from rust/lithe-core/src/lsp/interface/build_provider.rs rename to rust/crates/core/src/lsp/interface/build_provider.rs index 26677205..01da9cf6 100644 --- a/rust/lithe-core/src/lsp/interface/build_provider.rs +++ b/rust/crates/core/src/lsp/interface/build_provider.rs @@ -221,7 +221,7 @@ mod tests { #[test] fn execution_replies_and_progress_match_the_shared_contract() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-execution-protocol.json" + "../../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-execution-protocol.json" )) .unwrap(); assert_eq!( diff --git a/rust/lithe-core/src/lsp/interface/client.rs b/rust/crates/core/src/lsp/interface/client.rs similarity index 99% rename from rust/lithe-core/src/lsp/interface/client.rs rename to rust/crates/core/src/lsp/interface/client.rs index ebbef4b5..a4e21cff 100644 --- a/rust/lithe-core/src/lsp/interface/client.rs +++ b/rust/crates/core/src/lsp/interface/client.rs @@ -2367,7 +2367,7 @@ mod semantic_tests { #[test] fn semantic_tokens_decode_relative_utf16_positions_and_reject_malformed_data() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../fixtures/lsp/semantic-tokens-v1.json" + "../../../../../fixtures/lsp/semantic-tokens-v1.json" )) .unwrap(); let options = fixture["serverOptions"].clone(); @@ -2546,7 +2546,7 @@ mod formatting_and_completion_tests { #[test] fn document_symbol_golden_fixture_matches_normalization() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../fixtures/lsp/document-symbols-v1.json" + "../../../../../fixtures/lsp/document-symbols-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/interface/document_uri.rs b/rust/crates/core/src/lsp/interface/document_uri.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/document_uri.rs rename to rust/crates/core/src/lsp/interface/document_uri.rs diff --git a/rust/lithe-core/src/lsp/interface/engine.rs b/rust/crates/core/src/lsp/interface/engine.rs similarity index 99% rename from rust/lithe-core/src/lsp/interface/engine.rs rename to rust/crates/core/src/lsp/interface/engine.rs index 6d833b5a..1a0c1390 100644 --- a/rust/lithe-core/src/lsp/interface/engine.rs +++ b/rust/crates/core/src/lsp/interface/engine.rs @@ -6516,7 +6516,7 @@ mod tests { #[test] fn engine_logging_wire_fixture_preserves_defaults_and_routes_new_commands() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../fixtures/diagnostics/engine-logging-v2.json" + "../../../../../fixtures/diagnostics/engine-logging-v2.json" )) .unwrap(); let request: StartServerRequest = serde_json::from_value(fixture["start"].clone()).unwrap(); @@ -8234,7 +8234,7 @@ mod tests { fn document_saves_honor_server_options_and_never_replace_newer_editor_text() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/lsp/document-save-v1.json" + "/../../fixtures/lsp/document-save-v1.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -8583,7 +8583,7 @@ mod tests { #[test] fn provider_run_options_reach_the_wire_for_run_preparation_only() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-run-options.json" + "../../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-run-options.json" )) .unwrap(); let params = json!({"launchOptions":fixture["launchOptions"]}); @@ -8616,7 +8616,7 @@ mod tests { #[test] fn provider_connection_debug_options_reach_the_wire() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-connection-debug-options.json" + "../../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-connection-debug-options.json" )) .unwrap(); let params = json!({"launchOptions":fixture["launchOptions"]}); @@ -8645,7 +8645,7 @@ mod tests { .await_request("lithe/build/prepareRun") .unwrap(); let fixture: Value = serde_json::from_str(include_str!( - "../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-run-preparation.json" + "../../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-run-preparation.json" )) .unwrap(); harness diff --git a/rust/lithe-core/src/lsp/interface/engine_function_provider.rs b/rust/crates/core/src/lsp/interface/engine_function_provider.rs similarity index 98% rename from rust/lithe-core/src/lsp/interface/engine_function_provider.rs rename to rust/crates/core/src/lsp/interface/engine_function_provider.rs index 4933ae76..0d36d1c4 100644 --- a/rust/lithe-core/src/lsp/interface/engine_function_provider.rs +++ b/rust/crates/core/src/lsp/interface/engine_function_provider.rs @@ -151,7 +151,7 @@ mod tests { fn function_provider_selection_matches_shared_workspace_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-function-provider.json" + "/../../fixtures/plugins/settings-function-provider.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/interface/engine_function_relay.rs b/rust/crates/core/src/lsp/interface/engine_function_relay.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/engine_function_relay.rs rename to rust/crates/core/src/lsp/interface/engine_function_relay.rs diff --git a/rust/lithe-core/src/lsp/interface/engine_function_relay_tests.rs b/rust/crates/core/src/lsp/interface/engine_function_relay_tests.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/engine_function_relay_tests.rs rename to rust/crates/core/src/lsp/interface/engine_function_relay_tests.rs diff --git a/rust/lithe-core/src/lsp/interface/engine_logging.rs b/rust/crates/core/src/lsp/interface/engine_logging.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/engine_logging.rs rename to rust/crates/core/src/lsp/interface/engine_logging.rs diff --git a/rust/lithe-core/src/lsp/interface/function_relay.rs b/rust/crates/core/src/lsp/interface/function_relay.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/function_relay.rs rename to rust/crates/core/src/lsp/interface/function_relay.rs diff --git a/rust/lithe-core/src/lsp/interface/keymap_provider.rs b/rust/crates/core/src/lsp/interface/keymap_provider.rs similarity index 98% rename from rust/lithe-core/src/lsp/interface/keymap_provider.rs rename to rust/crates/core/src/lsp/interface/keymap_provider.rs index bb2e58fb..0e798a09 100644 --- a/rust/lithe-core/src/lsp/interface/keymap_provider.rs +++ b/rust/crates/core/src/lsp/interface/keymap_provider.rs @@ -67,7 +67,7 @@ mod tests { #[test] fn shortcut_providers_negotiate_only_an_offered_subset() { let fixtures: Value = serde_json::from_str(include_str!( - "../../../../fixtures/keymap/provider-negotiation-v1.json" + "../../../../../fixtures/keymap/provider-negotiation-v1.json" )) .unwrap(); for case in fixtures["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/interface/mod.rs b/rust/crates/core/src/lsp/interface/mod.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/mod.rs rename to rust/crates/core/src/lsp/interface/mod.rs diff --git a/rust/lithe-core/src/lsp/interface/plugin_function.rs b/rust/crates/core/src/lsp/interface/plugin_function.rs similarity index 99% rename from rust/lithe-core/src/lsp/interface/plugin_function.rs rename to rust/crates/core/src/lsp/interface/plugin_function.rs index 3c55dabe..1e160c6f 100644 --- a/rust/lithe-core/src/lsp/interface/plugin_function.rs +++ b/rust/crates/core/src/lsp/interface/plugin_function.rs @@ -1895,7 +1895,7 @@ mod tests { const FIXTURE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/backend/function-protocol.json" + "/../../../shared/plugins/contract/v1/fixtures/backend/function-protocol.json" )); fn fixture() -> Value { diff --git a/rust/lithe-core/src/lsp/interface/plugin_logging.rs b/rust/crates/core/src/lsp/interface/plugin_logging.rs similarity index 98% rename from rust/lithe-core/src/lsp/interface/plugin_logging.rs rename to rust/crates/core/src/lsp/interface/plugin_logging.rs index b68b8301..9ff58cab 100644 --- a/rust/lithe-core/src/lsp/interface/plugin_logging.rs +++ b/rust/crates/core/src/lsp/interface/plugin_logging.rs @@ -134,7 +134,7 @@ mod tests { #[test] fn shared_plugin_logging_fixture_matches_ingress_and_catalog() { let fixture: Value = serde_json::from_str(include_str!( - "../../../../../shared/plugins/contract/v1/fixtures/backend/plugin-logging.json" + "../../../../../../shared/plugins/contract/v1/fixtures/backend/plugin-logging.json" )) .unwrap(); let functions = fixture["registeredFunctions"] diff --git a/rust/lithe-core/src/lsp/interface/plugin_server.rs b/rust/crates/core/src/lsp/interface/plugin_server.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/plugin_server.rs rename to rust/crates/core/src/lsp/interface/plugin_server.rs diff --git a/rust/lithe-core/src/lsp/interface/process.rs b/rust/crates/core/src/lsp/interface/process.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/process.rs rename to rust/crates/core/src/lsp/interface/process.rs diff --git a/rust/lithe-core/src/lsp/interface/remote_process.rs b/rust/crates/core/src/lsp/interface/remote_process.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/remote_process.rs rename to rust/crates/core/src/lsp/interface/remote_process.rs diff --git a/rust/lithe-core/src/lsp/interface/scripted.rs b/rust/crates/core/src/lsp/interface/scripted.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/scripted.rs rename to rust/crates/core/src/lsp/interface/scripted.rs diff --git a/rust/lithe-core/src/lsp/interface/toolchain_provider.rs b/rust/crates/core/src/lsp/interface/toolchain_provider.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/toolchain_provider.rs rename to rust/crates/core/src/lsp/interface/toolchain_provider.rs diff --git a/rust/lithe-core/src/lsp/interface/transport.rs b/rust/crates/core/src/lsp/interface/transport.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/transport.rs rename to rust/crates/core/src/lsp/interface/transport.rs diff --git a/rust/lithe-core/src/lsp/interface/types.rs b/rust/crates/core/src/lsp/interface/types.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/types.rs rename to rust/crates/core/src/lsp/interface/types.rs diff --git a/rust/lithe-core/src/lsp/interface/vcs_provider.rs b/rust/crates/core/src/lsp/interface/vcs_provider.rs similarity index 100% rename from rust/lithe-core/src/lsp/interface/vcs_provider.rs rename to rust/crates/core/src/lsp/interface/vcs_provider.rs diff --git a/rust/lithe-core/src/lsp/languages/indexing.rs b/rust/crates/core/src/lsp/languages/indexing.rs similarity index 100% rename from rust/lithe-core/src/lsp/languages/indexing.rs rename to rust/crates/core/src/lsp/languages/indexing.rs diff --git a/rust/lithe-core/src/lsp/languages/mod.rs b/rust/crates/core/src/lsp/languages/mod.rs similarity index 100% rename from rust/lithe-core/src/lsp/languages/mod.rs rename to rust/crates/core/src/lsp/languages/mod.rs diff --git a/rust/lithe-core/src/lsp/languages/swift.rs b/rust/crates/core/src/lsp/languages/swift.rs similarity index 100% rename from rust/lithe-core/src/lsp/languages/swift.rs rename to rust/crates/core/src/lsp/languages/swift.rs diff --git a/rust/lithe-core/src/lsp/lightweight/edits.rs b/rust/crates/core/src/lsp/lightweight/edits.rs similarity index 100% rename from rust/lithe-core/src/lsp/lightweight/edits.rs rename to rust/crates/core/src/lsp/lightweight/edits.rs diff --git a/rust/lithe-core/src/lsp/lightweight/mod.rs b/rust/crates/core/src/lsp/lightweight/mod.rs similarity index 100% rename from rust/lithe-core/src/lsp/lightweight/mod.rs rename to rust/crates/core/src/lsp/lightweight/mod.rs diff --git a/rust/lithe-core/src/lsp/lightweight/snippets.rs b/rust/crates/core/src/lsp/lightweight/snippets.rs similarity index 100% rename from rust/lithe-core/src/lsp/lightweight/snippets.rs rename to rust/crates/core/src/lsp/lightweight/snippets.rs diff --git a/rust/lithe-core/src/lsp/lightweight/symbols.rs b/rust/crates/core/src/lsp/lightweight/symbols.rs similarity index 100% rename from rust/lithe-core/src/lsp/lightweight/symbols.rs rename to rust/crates/core/src/lsp/lightweight/symbols.rs diff --git a/rust/lithe-core/src/lsp/mod.rs b/rust/crates/core/src/lsp/mod.rs similarity index 100% rename from rust/lithe-core/src/lsp/mod.rs rename to rust/crates/core/src/lsp/mod.rs diff --git a/rust/lithe-core/src/lsp/navigation_target.rs b/rust/crates/core/src/lsp/navigation_target.rs similarity index 98% rename from rust/lithe-core/src/lsp/navigation_target.rs rename to rust/crates/core/src/lsp/navigation_target.rs index 60d19f79..a140fde0 100644 --- a/rust/lithe-core/src/lsp/navigation_target.rs +++ b/rust/crates/core/src/lsp/navigation_target.rs @@ -102,7 +102,7 @@ mod tests { #[test] fn matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/lsp/navigation-target-v1.json" + "../../../../fixtures/lsp/navigation-target-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/tests.rs b/rust/crates/core/src/lsp/tests.rs similarity index 99% rename from rust/lithe-core/src/lsp/tests.rs rename to rust/crates/core/src/lsp/tests.rs index 6ab260ee..bd0e37a9 100644 --- a/rust/lithe-core/src/lsp/tests.rs +++ b/rust/crates/core/src/lsp/tests.rs @@ -194,8 +194,10 @@ fn file_uri_paths_decode_spaces_and_utf8_characters() { #[test] fn document_uri_matches_shared_fixture() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/lsp/document-uri-v1.json")).unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/lsp/document-uri-v1.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response: Value = serde_json::from_str(&crate::execute_json( &json!({"command":"lsp.documentUri", "payload":{ @@ -260,8 +262,10 @@ fn document_uri_accepts_non_ascii_windows_extended_length_paths() { #[test] fn document_uri_identity_keeps_reserved_characters_distinct() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/lsp/document-uri-v1.json")).unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/lsp/document-uri-v1.json" + )) + .unwrap(); for case in fixture["identityCases"].as_array().unwrap() { let opened_uri = case["opened"].as_str().unwrap(); let published_uri = case["published"].as_str().unwrap(); @@ -2478,7 +2482,7 @@ fn client_core_rejects_unknown_server_requests_with_method_not_found() { #[test] fn client_diagnostic_code_action_fixture_preserves_core_fields() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/lsp/diagnostic-code-actions-v1.json" + "../../../../fixtures/lsp/diagnostic-code-actions-v1.json" )) .unwrap(); for case in fixture["severityCases"].as_array().unwrap() { @@ -2535,7 +2539,7 @@ fn client_diagnostic_code_action_fixture_preserves_core_fields() { #[test] fn client_completion_preserves_refresh_context_and_incomplete_lists() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/lsp/completion-refresh-v1.json" + "../../../../fixtures/lsp/completion-refresh-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -2601,7 +2605,7 @@ fn client_completion_rejects_invalid_trigger_context() { #[test] fn text_edits_follow_shared_windows_fixture() { let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/lsp/text-edits-v1.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/lsp/text-edits-v1.json")).unwrap(); for case in fixture["cases"].as_array().unwrap() { let edits: Vec = case["edits"].as_array().unwrap().iter().map(|edit| serde_json::json!({ "range": { "start": { "line": edit["range"]["start"]["line"], "utf16Column": edit["range"]["start"]["character"] }, diff --git a/rust/lithe-core/src/lsp/workspace_edit_plan.rs b/rust/crates/core/src/lsp/workspace_edit_plan.rs similarity index 99% rename from rust/lithe-core/src/lsp/workspace_edit_plan.rs rename to rust/crates/core/src/lsp/workspace_edit_plan.rs index 47274c92..960e017e 100644 --- a/rust/lithe-core/src/lsp/workspace_edit_plan.rs +++ b/rust/crates/core/src/lsp/workspace_edit_plan.rs @@ -168,7 +168,7 @@ mod tests { #[test] fn matches_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/lsp/workspace-edit-plan-v1.json" + "../../../../fixtures/lsp/workspace-edit-plan-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/lsp/workspace_scope.rs b/rust/crates/core/src/lsp/workspace_scope.rs similarity index 100% rename from rust/lithe-core/src/lsp/workspace_scope.rs rename to rust/crates/core/src/lsp/workspace_scope.rs diff --git a/rust/lithe-core/src/network/mod.rs b/rust/crates/core/src/network/mod.rs similarity index 100% rename from rust/lithe-core/src/network/mod.rs rename to rust/crates/core/src/network/mod.rs diff --git a/rust/lithe-core/src/network/proxy.rs b/rust/crates/core/src/network/proxy.rs similarity index 100% rename from rust/lithe-core/src/network/proxy.rs rename to rust/crates/core/src/network/proxy.rs diff --git a/rust/lithe-core/src/network/tests.rs b/rust/crates/core/src/network/tests.rs similarity index 98% rename from rust/lithe-core/src/network/tests.rs rename to rust/crates/core/src/network/tests.rs index 3e4cf099..2c7a122b 100644 --- a/rust/lithe-core/src/network/tests.rs +++ b/rust/crates/core/src/network/tests.rs @@ -16,7 +16,7 @@ fn policy_for(request: Value) -> Value { fn fixture_cases_match_the_shared_contract() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/network/proxy-policy-v1.json" + "/../../fixtures/network/proxy-policy-v1.json" ))) .expect("proxy policy fixture is JSON"); for case in fixture["cases"].as_array().expect("fixture cases") { diff --git a/rust/lithe-core/src/plugins/backend.rs b/rust/crates/core/src/plugins/backend.rs similarity index 100% rename from rust/lithe-core/src/plugins/backend.rs rename to rust/crates/core/src/plugins/backend.rs diff --git a/rust/lithe-core/src/plugins/capabilities.rs b/rust/crates/core/src/plugins/capabilities.rs similarity index 100% rename from rust/lithe-core/src/plugins/capabilities.rs rename to rust/crates/core/src/plugins/capabilities.rs diff --git a/rust/lithe-core/src/plugins/content_providers.rs b/rust/crates/core/src/plugins/content_providers.rs similarity index 100% rename from rust/lithe-core/src/plugins/content_providers.rs rename to rust/crates/core/src/plugins/content_providers.rs diff --git a/rust/lithe-core/src/plugins/declarative.rs b/rust/crates/core/src/plugins/declarative.rs similarity index 100% rename from rust/lithe-core/src/plugins/declarative.rs rename to rust/crates/core/src/plugins/declarative.rs diff --git a/rust/lithe-core/src/plugins/editor_actions.rs b/rust/crates/core/src/plugins/editor_actions.rs similarity index 99% rename from rust/lithe-core/src/plugins/editor_actions.rs rename to rust/crates/core/src/plugins/editor_actions.rs index 6d475448..097f25c7 100644 --- a/rust/lithe-core/src/plugins/editor_actions.rs +++ b/rust/crates/core/src/plugins/editor_actions.rs @@ -650,7 +650,7 @@ mod tests { fn contract_fixture_cases() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/editor/editor-actions.json" + "/../../../shared/plugins/contract/v1/fixtures/editor/editor-actions.json" ))) .unwrap(); let host: EditorHostOptions = serde_json::from_value(fixture["host"].clone()).unwrap(); diff --git a/rust/lithe-core/src/plugins/editor_providers.rs b/rust/crates/core/src/plugins/editor_providers.rs similarity index 99% rename from rust/lithe-core/src/plugins/editor_providers.rs rename to rust/crates/core/src/plugins/editor_providers.rs index e9844e7e..53d9de79 100644 --- a/rust/lithe-core/src/plugins/editor_providers.rs +++ b/rust/crates/core/src/plugins/editor_providers.rs @@ -867,7 +867,7 @@ mod tests { fn contract_fixture_cases() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/editor/editor-providers.json" + "/../../../shared/plugins/contract/v1/fixtures/editor/editor-providers.json" ))) .unwrap(); let types = &fixture["host"]["providerTypes"]; diff --git a/rust/lithe-core/src/plugins/executables.rs b/rust/crates/core/src/plugins/executables.rs similarity index 100% rename from rust/lithe-core/src/plugins/executables.rs rename to rust/crates/core/src/plugins/executables.rs diff --git a/rust/lithe-core/src/plugins/grammar.rs b/rust/crates/core/src/plugins/grammar.rs similarity index 100% rename from rust/lithe-core/src/plugins/grammar.rs rename to rust/crates/core/src/plugins/grammar.rs diff --git a/rust/lithe-core/src/plugins/host_api.rs b/rust/crates/core/src/plugins/host_api.rs similarity index 96% rename from rust/lithe-core/src/plugins/host_api.rs rename to rust/crates/core/src/plugins/host_api.rs index 883c24cb..54939340 100644 --- a/rust/lithe-core/src/plugins/host_api.rs +++ b/rust/crates/core/src/plugins/host_api.rs @@ -104,9 +104,10 @@ mod tests { #[test] fn authorization_does_not_widen_metadata_grants_or_accept_spoofed_services() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/plugins/host-api-v1.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/plugins/host-api-v1.json" + )) + .unwrap(); for case in fixture["authorization"].as_array().unwrap() { assert_eq!( authorize_command(case["input"].clone()).unwrap(), diff --git a/rust/lithe-core/src/plugins/installed.rs b/rust/crates/core/src/plugins/installed.rs similarity index 98% rename from rust/lithe-core/src/plugins/installed.rs rename to rust/crates/core/src/plugins/installed.rs index 30b98a3d..59604425 100644 --- a/rust/lithe-core/src/plugins/installed.rs +++ b/rust/crates/core/src/plugins/installed.rs @@ -90,7 +90,7 @@ mod tests { fn shared_installed_version_fixture_uses_the_existing_numeric_comparator() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/installed-versions.json" + "/../../fixtures/plugins/installed-versions.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/plugins/keymap_import.rs b/rust/crates/core/src/plugins/keymap_import.rs similarity index 97% rename from rust/lithe-core/src/plugins/keymap_import.rs rename to rust/crates/core/src/plugins/keymap_import.rs index 17162127..c68c782a 100644 --- a/rust/lithe-core/src/plugins/keymap_import.rs +++ b/rust/crates/core/src/plugins/keymap_import.rs @@ -458,9 +458,10 @@ mod tests { #[test] fn import_binding_plans_follow_shared_fixtures() { - let fixtures: Value = - serde_json::from_str(include_str!("../../../fixtures/keymap/import-plan-v1.json")) - .unwrap(); + let fixtures: Value = serde_json::from_str(include_str!( + "../../../../fixtures/keymap/import-plan-v1.json" + )) + .unwrap(); for case in fixtures["cases"].as_array().unwrap() { let request = json!({"id": "fixture", "command": "keymap.planImportBindings", "payload": case["request"]}); let response: Value = @@ -478,7 +479,7 @@ mod tests { #[test] fn normalized_import_provider_replies_follow_shared_fixtures() { let fixtures: Value = serde_json::from_str(include_str!( - "../../../fixtures/keymap/import-provider-v1.json" + "../../../../fixtures/keymap/import-provider-v1.json" )) .unwrap(); for case in fixtures["cases"].as_array().unwrap() { @@ -499,7 +500,7 @@ mod tests { #[test] fn dispatcher_returns_the_validated_reply_without_partial_results() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/keymap/import-provider-v1.json" + "../../../../fixtures/keymap/import-provider-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -548,7 +549,7 @@ mod tests { #[test] fn import_provider_manifest_is_generic_bounded_and_permission_checked() { let plugin: Value = serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/keymap-import/keymap-import-provider.plugin.json" + "../../../../../shared/plugins/contract/v1/fixtures/keymap-import/keymap-import-provider.plugin.json" )) .unwrap(); let validate = crate::plugins::declarative::validate_manifest_value; @@ -648,11 +649,11 @@ mod tests { #[test] fn source_plans_only_expose_inputs_of_the_requested_provider() { let plugin: Value = serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/keymap-import/keymap-import-provider.plugin.json" + "../../../../../shared/plugins/contract/v1/fixtures/keymap-import/keymap-import-provider.plugin.json" )) .unwrap(); let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/keymap/source-plans-v1.json" + "../../../../fixtures/keymap/source-plans-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -673,7 +674,7 @@ mod tests { plan_sources_command(json!({"manifest": invalid, "providerID": "second"})).is_err() ); let mut invalid: Value = serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/keymap-import/keymap-import-provider.plugin.json" + "../../../../../shared/plugins/contract/v1/fixtures/keymap-import/keymap-import-provider.plugin.json" )) .unwrap(); invalid["keymapImportProviders"][1]["recognition"][0]["path"] = json!("../private"); diff --git a/rust/lithe-core/src/plugins/language_server_sessions.rs b/rust/crates/core/src/plugins/language_server_sessions.rs similarity index 100% rename from rust/lithe-core/src/plugins/language_server_sessions.rs rename to rust/crates/core/src/plugins/language_server_sessions.rs diff --git a/rust/lithe-core/src/plugins/marketplace.rs b/rust/crates/core/src/plugins/marketplace.rs similarity index 100% rename from rust/lithe-core/src/plugins/marketplace.rs rename to rust/crates/core/src/plugins/marketplace.rs diff --git a/rust/lithe-core/src/plugins/mod.rs b/rust/crates/core/src/plugins/mod.rs similarity index 100% rename from rust/lithe-core/src/plugins/mod.rs rename to rust/crates/core/src/plugins/mod.rs diff --git a/rust/lithe-core/src/plugins/native_ui.rs b/rust/crates/core/src/plugins/native_ui.rs similarity index 100% rename from rust/lithe-core/src/plugins/native_ui.rs rename to rust/crates/core/src/plugins/native_ui.rs diff --git a/rust/lithe-core/src/plugins/output_links.rs b/rust/crates/core/src/plugins/output_links.rs similarity index 100% rename from rust/lithe-core/src/plugins/output_links.rs rename to rust/crates/core/src/plugins/output_links.rs diff --git a/rust/lithe-core/src/plugins/plugin_functions.rs b/rust/crates/core/src/plugins/plugin_functions.rs similarity index 100% rename from rust/lithe-core/src/plugins/plugin_functions.rs rename to rust/crates/core/src/plugins/plugin_functions.rs diff --git a/rust/lithe-core/src/plugins/settings.rs b/rust/crates/core/src/plugins/settings.rs similarity index 100% rename from rust/lithe-core/src/plugins/settings.rs rename to rust/crates/core/src/plugins/settings.rs diff --git a/rust/lithe-core/src/plugins/settings_document_tests.rs b/rust/crates/core/src/plugins/settings_document_tests.rs similarity index 96% rename from rust/lithe-core/src/plugins/settings_document_tests.rs rename to rust/crates/core/src/plugins/settings_document_tests.rs index 109a5177..7789193b 100644 --- a/rust/lithe-core/src/plugins/settings_document_tests.rs +++ b/rust/crates/core/src/plugins/settings_document_tests.rs @@ -5,7 +5,7 @@ use serde_json::{json, Value}; fn manifest() -> Value { serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/settings/settings.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/settings/settings.plugin.json" ))) .unwrap() } @@ -83,7 +83,7 @@ fn settings_state_dispatches_with_core_owned_sources_and_normalized_scope() { fn complete_edit_fixture_preserves_types_siblings_and_atomic_rejection() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-documents.json" + "/../../fixtures/plugins/settings-documents.json" ))) .unwrap(); for case in fixture["editCases"].as_array().unwrap() { @@ -141,7 +141,7 @@ fn complete_edit_fixture_preserves_types_siblings_and_atomic_rejection() { fn missing_files_are_empty_but_empty_existing_documents_are_rejected() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-documents.json" + "/../../fixtures/plugins/settings-documents.json" ))) .unwrap(); let valid = execute( @@ -163,7 +163,7 @@ fn missing_files_are_empty_but_empty_existing_documents_are_rejected() { fn invalid_stored_values_fall_back_without_hiding_raw_executable_overrides() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-documents.json" + "/../../fixtures/plugins/settings-documents.json" ))) .unwrap(); let result = execute( @@ -193,7 +193,7 @@ fn invalid_stored_values_fall_back_without_hiding_raw_executable_overrides() { fn document_size_and_batch_limits_reject_before_returning_replacement_text() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-documents.json" + "/../../fixtures/plugins/settings-documents.json" ))) .unwrap(); let oversized = execute( @@ -223,7 +223,7 @@ fn document_size_and_batch_limits_reject_before_returning_replacement_text() { fn plugins_without_setting_declarations_do_not_request_native_document_reads() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-documents.json" + "/../../fixtures/plugins/settings-documents.json" ))) .unwrap(); let mut manifest = fixture["manifest"].clone(); @@ -245,7 +245,7 @@ fn plugins_without_setting_declarations_do_not_request_native_document_reads() { fn editor_projection_owns_scope_reset_values_and_section_grouping() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-documents.json" + "/../../fixtures/plugins/settings-documents.json" ))) .unwrap(); let mut manifest = fixture["manifest"].clone(); @@ -297,7 +297,7 @@ fn editor_projection_owns_scope_reset_values_and_section_grouping() { fn setting_action_plans_match_shared_fixture_without_starting_a_process() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-actions.json" + "/../../fixtures/plugins/settings-actions.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -323,7 +323,7 @@ fn setting_action_plans_match_shared_fixture_without_starting_a_process() { fn settings_surfaces_shared_vectors() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/plugins/settings-surfaces.json" + "/../../fixtures/plugins/settings-surfaces.json" ))) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/plugins/settings_documents.rs b/rust/crates/core/src/plugins/settings_documents.rs similarity index 100% rename from rust/lithe-core/src/plugins/settings_documents.rs rename to rust/crates/core/src/plugins/settings_documents.rs diff --git a/rust/lithe-core/src/plugins/settings_pages.rs b/rust/crates/core/src/plugins/settings_pages.rs similarity index 100% rename from rust/lithe-core/src/plugins/settings_pages.rs rename to rust/crates/core/src/plugins/settings_pages.rs diff --git a/rust/lithe-core/src/plugins/settings_surfaces.rs b/rust/crates/core/src/plugins/settings_surfaces.rs similarity index 100% rename from rust/lithe-core/src/plugins/settings_surfaces.rs rename to rust/crates/core/src/plugins/settings_surfaces.rs diff --git a/rust/lithe-core/src/plugins/web_content.rs b/rust/crates/core/src/plugins/web_content.rs similarity index 100% rename from rust/lithe-core/src/plugins/web_content.rs rename to rust/crates/core/src/plugins/web_content.rs diff --git a/rust/lithe-core/src/plugins/web_content_tests.rs b/rust/crates/core/src/plugins/web_content_tests.rs similarity index 99% rename from rust/lithe-core/src/plugins/web_content_tests.rs rename to rust/crates/core/src/plugins/web_content_tests.rs index c2e80df1..0026dcf0 100644 --- a/rust/lithe-core/src/plugins/web_content_tests.rs +++ b/rust/crates/core/src/plugins/web_content_tests.rs @@ -4,7 +4,7 @@ use super::*; fn manifest() -> Value { serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/ui/web-panel.plugin.json" + "../../../../../shared/plugins/contract/v1/fixtures/ui/web-panel.plugin.json" )) .expect("fixture") } diff --git a/rust/lithe-core/src/process/inventory.rs b/rust/crates/core/src/process/inventory.rs similarity index 99% rename from rust/lithe-core/src/process/inventory.rs rename to rust/crates/core/src/process/inventory.rs index 55f41295..163ce5ea 100644 --- a/rust/lithe-core/src/process/inventory.rs +++ b/rust/crates/core/src/process/inventory.rs @@ -582,7 +582,7 @@ mod tests { #[test] fn shared_fixture_inventories_match() { let fixture: Fixture = serde_json::from_str(include_str!( - "../../../fixtures/process-lifecycle/inventory-v1.json" + "../../../../fixtures/process-lifecycle/inventory-v1.json" )) .expect("fixture should parse"); assert_eq!(fixture.schema_version, 1); diff --git a/rust/lithe-core/src/process/lifecycle.rs b/rust/crates/core/src/process/lifecycle.rs similarity index 99% rename from rust/lithe-core/src/process/lifecycle.rs rename to rust/crates/core/src/process/lifecycle.rs index b94245db..75437971 100644 --- a/rust/lithe-core/src/process/lifecycle.rs +++ b/rust/crates/core/src/process/lifecycle.rs @@ -636,7 +636,7 @@ mod tests { #[test] fn shared_fixture_decisions_match() { let fixture: Fixture = serde_json::from_str(include_str!( - "../../../fixtures/process-lifecycle/exit-plan-v1.json" + "../../../../fixtures/process-lifecycle/exit-plan-v1.json" )) .expect("fixture should parse"); assert_eq!(fixture.schema_version, 1); @@ -651,7 +651,7 @@ mod tests { #[test] fn shared_fixture_settlements_match() { let fixture: Fixture = serde_json::from_str(include_str!( - "../../../fixtures/process-lifecycle/settle-v1.json" + "../../../../fixtures/process-lifecycle/settle-v1.json" )) .expect("fixture should parse"); assert_eq!(fixture.schema_version, 1); diff --git a/rust/lithe-core/src/process/mod.rs b/rust/crates/core/src/process/mod.rs similarity index 100% rename from rust/lithe-core/src/process/mod.rs rename to rust/crates/core/src/process/mod.rs diff --git a/rust/lithe-core/src/project/directory_actions.rs b/rust/crates/core/src/project/directory_actions.rs similarity index 100% rename from rust/lithe-core/src/project/directory_actions.rs rename to rust/crates/core/src/project/directory_actions.rs diff --git a/rust/lithe-core/src/project/document_lifecycle.rs b/rust/crates/core/src/project/document_lifecycle.rs similarity index 100% rename from rust/lithe-core/src/project/document_lifecycle.rs rename to rust/crates/core/src/project/document_lifecycle.rs diff --git a/rust/lithe-core/src/project/document_save_batch.rs b/rust/crates/core/src/project/document_save_batch.rs similarity index 100% rename from rust/lithe-core/src/project/document_save_batch.rs rename to rust/crates/core/src/project/document_save_batch.rs diff --git a/rust/lithe-core/src/project/encoding.rs b/rust/crates/core/src/project/encoding.rs similarity index 100% rename from rust/lithe-core/src/project/encoding.rs rename to rust/crates/core/src/project/encoding.rs diff --git a/rust/lithe-core/src/project/file_name_order.rs b/rust/crates/core/src/project/file_name_order.rs similarity index 100% rename from rust/lithe-core/src/project/file_name_order.rs rename to rust/crates/core/src/project/file_name_order.rs diff --git a/rust/lithe-core/src/project/file_operations.rs b/rust/crates/core/src/project/file_operations.rs similarity index 100% rename from rust/lithe-core/src/project/file_operations.rs rename to rust/crates/core/src/project/file_operations.rs diff --git a/rust/lithe-core/src/project/files.rs b/rust/crates/core/src/project/files.rs similarity index 99% rename from rust/lithe-core/src/project/files.rs rename to rust/crates/core/src/project/files.rs index a98fa3f0..07d96aae 100644 --- a/rust/lithe-core/src/project/files.rs +++ b/rust/crates/core/src/project/files.rs @@ -2280,7 +2280,7 @@ mod event_filter_tests { #[test] fn shared_text_snapshot_contract_fixture() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/search/text-snapshot-v1.json" + "../../../../fixtures/search/text-snapshot-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -2376,7 +2376,7 @@ mod event_filter_tests { #[test] fn shared_workspace_change_fixture() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/change-filter-v1.json" + "../../../../fixtures/workspace/change-filter-v1.json" )) .unwrap(); let paths: Vec = serde_json::from_value(fixture["paths"].clone()).unwrap(); diff --git a/rust/lithe-core/src/project/history.rs b/rust/crates/core/src/project/history.rs similarity index 100% rename from rust/lithe-core/src/project/history.rs rename to rust/crates/core/src/project/history.rs diff --git a/rust/lithe-core/src/project/indexing.rs b/rust/crates/core/src/project/indexing.rs similarity index 99% rename from rust/lithe-core/src/project/indexing.rs rename to rust/crates/core/src/project/indexing.rs index f66fb1ae..b21dca31 100644 --- a/rust/lithe-core/src/project/indexing.rs +++ b/rust/crates/core/src/project/indexing.rs @@ -868,7 +868,7 @@ mod tests { #[test] fn directory_action_fixture_preserves_real_git_search_eligibility() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/directory-actions-v1.json" + "../../../../fixtures/workspace/directory-actions-v1.json" )) .unwrap(); let workspace = Workspace::new(); @@ -1155,7 +1155,7 @@ mod tests { parent.configure(&[], &[], false); nested.configure(&["deep"], &[], false); let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/indexing-policy-v1.json" + "../../../../fixtures/workspace/indexing-policy-v1.json" )) .unwrap(); for case in fixture["ownershipCases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/project/markdown.rs b/rust/crates/core/src/project/markdown.rs similarity index 98% rename from rust/lithe-core/src/project/markdown.rs rename to rust/crates/core/src/project/markdown.rs index 6c63ca85..ba85d5b8 100644 --- a/rust/lithe-core/src/project/markdown.rs +++ b/rust/crates/core/src/project/markdown.rs @@ -174,7 +174,7 @@ mod tests { #[test] fn preserves_rich_content_for_offline_preview() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/markdown-rich-content-v1.json" + "../../../../fixtures/editor/markdown-rich-content-v1.json" )) .expect("rich Markdown fixture should decode"); let output = html(fixture["source"].as_str().expect("fixture source")); @@ -194,7 +194,7 @@ mod tests { #[test] fn preserves_html_alignment_and_inline_badges_without_allowing_styles() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/markdown-html-v1.json" + "../../../../fixtures/editor/markdown-html-v1.json" )) .expect("Markdown HTML fixture should decode"); let output = html(fixture["source"].as_str().expect("fixture source")); diff --git a/rust/lithe-core/src/project/mod.rs b/rust/crates/core/src/project/mod.rs similarity index 100% rename from rust/lithe-core/src/project/mod.rs rename to rust/crates/core/src/project/mod.rs diff --git a/rust/lithe-core/src/project/name_matching.rs b/rust/crates/core/src/project/name_matching.rs similarity index 99% rename from rust/lithe-core/src/project/name_matching.rs rename to rust/crates/core/src/project/name_matching.rs index fa974557..887e5a65 100644 --- a/rust/lithe-core/src/project/name_matching.rs +++ b/rust/crates/core/src/project/name_matching.rs @@ -192,7 +192,7 @@ mod tests { #[test] fn unicode_contiguous_matches_map_back_to_original_utf16() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/search/unicode-contiguous.json" + "../../../../fixtures/search/unicode-contiguous.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/project/name_ranking.rs b/rust/crates/core/src/project/name_ranking.rs similarity index 100% rename from rust/lithe-core/src/project/name_ranking.rs rename to rust/crates/core/src/project/name_ranking.rs diff --git a/rust/lithe-core/src/project/recent_projects.rs b/rust/crates/core/src/project/recent_projects.rs similarity index 100% rename from rust/lithe-core/src/project/recent_projects.rs rename to rust/crates/core/src/project/recent_projects.rs diff --git a/rust/lithe-core/src/project/search_index.rs b/rust/crates/core/src/project/search_index.rs similarity index 99% rename from rust/lithe-core/src/project/search_index.rs rename to rust/crates/core/src/project/search_index.rs index 65dc3cf4..17d9c1b4 100644 --- a/rust/lithe-core/src/project/search_index.rs +++ b/rust/crates/core/src/project/search_index.rs @@ -757,7 +757,7 @@ mod tests { } } let _cleanup = Cleanup(root.clone()); - fs::set_permissions(&blocked, fs::Permissions::from_mode(0)).unwrap(); + fs::set_permissions(&blocked, fs::Permissions::from_mode(0o000)).unwrap(); if fs::read_dir(&blocked).is_ok() { // Privileged test runners bypass Unix mode bits; do not claim a permission regression ran. eprintln!("Skipping permission fixture: runner can enumerate mode-000 directories"); @@ -826,7 +826,8 @@ mod tests { fs::write(file, "Name before").unwrap(); } let fixture: serde_json::Value = - serde_json::from_str(include_str!("../../../fixtures/search/exclusions.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/search/exclusions.json")) + .unwrap(); // The patterns come from the shared fixture, so Rust and Swift always // judge the same list. let rules = VisibilityRules { diff --git a/rust/lithe-core/src/project/search_paging.rs b/rust/crates/core/src/project/search_paging.rs similarity index 100% rename from rust/lithe-core/src/project/search_paging.rs rename to rust/crates/core/src/project/search_paging.rs diff --git a/rust/lithe-core/src/project_generators/archive.rs b/rust/crates/core/src/project_generators/archive.rs similarity index 100% rename from rust/lithe-core/src/project_generators/archive.rs rename to rust/crates/core/src/project_generators/archive.rs diff --git a/rust/lithe-core/src/project_generators/commands.rs b/rust/crates/core/src/project_generators/commands.rs similarity index 100% rename from rust/lithe-core/src/project_generators/commands.rs rename to rust/crates/core/src/project_generators/commands.rs diff --git a/rust/lithe-core/src/project_generators/form.rs b/rust/crates/core/src/project_generators/form.rs similarity index 100% rename from rust/lithe-core/src/project_generators/form.rs rename to rust/crates/core/src/project_generators/form.rs diff --git a/rust/lithe-core/src/project_generators/manifest.rs b/rust/crates/core/src/project_generators/manifest.rs similarity index 100% rename from rust/lithe-core/src/project_generators/manifest.rs rename to rust/crates/core/src/project_generators/manifest.rs diff --git a/rust/lithe-core/src/project_generators/mod.rs b/rust/crates/core/src/project_generators/mod.rs similarity index 100% rename from rust/lithe-core/src/project_generators/mod.rs rename to rust/crates/core/src/project_generators/mod.rs diff --git a/rust/lithe-core/src/project_generators/plan.rs b/rust/crates/core/src/project_generators/plan.rs similarity index 100% rename from rust/lithe-core/src/project_generators/plan.rs rename to rust/crates/core/src/project_generators/plan.rs diff --git a/rust/lithe-core/src/project_generators/template.rs b/rust/crates/core/src/project_generators/template.rs similarity index 100% rename from rust/lithe-core/src/project_generators/template.rs rename to rust/crates/core/src/project_generators/template.rs diff --git a/rust/lithe-core/src/protocol/cancellation.rs b/rust/crates/core/src/protocol/cancellation.rs similarity index 100% rename from rust/lithe-core/src/protocol/cancellation.rs rename to rust/crates/core/src/protocol/cancellation.rs diff --git a/rust/lithe-core/src/protocol/command.rs b/rust/crates/core/src/protocol/command.rs similarity index 99% rename from rust/lithe-core/src/protocol/command.rs rename to rust/crates/core/src/protocol/command.rs index f5d6c5a0..c806e3a3 100644 --- a/rust/lithe-core/src/protocol/command.rs +++ b/rust/crates/core/src/protocol/command.rs @@ -1242,7 +1242,7 @@ mod tests { let crate_root = Path::new(env!("CARGO_MANIFEST_DIR")); let source = std::fs::read_to_string(crate_root.join("src/protocol/command.rs")) .expect("read command.rs"); - let document = std::fs::read_to_string(crate_root.join("../contracts/rust-core-api.md")) + let document = std::fs::read_to_string(crate_root.join("../../contracts/rust-core-api.md")) .expect("read rust-core-api.md"); let parsed = parsed_command_names(&source); let documented = documented_command_names(&document); diff --git a/rust/lithe-core/src/protocol/contracts.rs b/rust/crates/core/src/protocol/contracts.rs similarity index 100% rename from rust/lithe-core/src/protocol/contracts.rs rename to rust/crates/core/src/protocol/contracts.rs diff --git a/rust/lithe-core/src/protocol/error.rs b/rust/crates/core/src/protocol/error.rs similarity index 100% rename from rust/lithe-core/src/protocol/error.rs rename to rust/crates/core/src/protocol/error.rs diff --git a/rust/lithe-core/src/protocol/event.rs b/rust/crates/core/src/protocol/event.rs similarity index 100% rename from rust/lithe-core/src/protocol/event.rs rename to rust/crates/core/src/protocol/event.rs diff --git a/rust/lithe-core/src/protocol/json_document.rs b/rust/crates/core/src/protocol/json_document.rs similarity index 100% rename from rust/lithe-core/src/protocol/json_document.rs rename to rust/crates/core/src/protocol/json_document.rs diff --git a/rust/lithe-core/src/protocol/mod.rs b/rust/crates/core/src/protocol/mod.rs similarity index 100% rename from rust/lithe-core/src/protocol/mod.rs rename to rust/crates/core/src/protocol/mod.rs diff --git a/rust/lithe-core/src/remote/mod.rs b/rust/crates/core/src/remote/mod.rs similarity index 100% rename from rust/lithe-core/src/remote/mod.rs rename to rust/crates/core/src/remote/mod.rs diff --git a/rust/lithe-core/src/remote/sessions.rs b/rust/crates/core/src/remote/sessions.rs similarity index 100% rename from rust/lithe-core/src/remote/sessions.rs rename to rust/crates/core/src/remote/sessions.rs diff --git a/rust/lithe-core/src/remote/sessions_integration_tests.rs b/rust/crates/core/src/remote/sessions_integration_tests.rs similarity index 99% rename from rust/lithe-core/src/remote/sessions_integration_tests.rs rename to rust/crates/core/src/remote/sessions_integration_tests.rs index 28ddc82f..de6447fa 100644 --- a/rust/lithe-core/src/remote/sessions_integration_tests.rs +++ b/rust/crates/core/src/remote/sessions_integration_tests.rs @@ -104,7 +104,7 @@ fn remote_build_detects_host_models_normalizes_diagnostics_and_invalidates_sync( .unwrap(); let manifest: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/build-systems/build-static-file.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/build-systems/build-static-file.plugin.json" ))) .unwrap(); let detection = host.request( @@ -179,7 +179,7 @@ fn remote_build_detects_a_root_opened_through_a_host_symbolic_link() { std::os::unix::fs::symlink(&root, &link).unwrap(); let manifest: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/build-systems/build-static-file.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/build-systems/build-static-file.plugin.json" ))) .unwrap(); let detection = host.request_at( diff --git a/rust/lithe-core/src/remote/tests.rs b/rust/crates/core/src/remote/tests.rs similarity index 100% rename from rust/lithe-core/src/remote/tests.rs rename to rust/crates/core/src/remote/tests.rs diff --git a/rust/lithe-core/src/remote/upload.rs b/rust/crates/core/src/remote/upload.rs similarity index 100% rename from rust/lithe-core/src/remote/upload.rs rename to rust/crates/core/src/remote/upload.rs diff --git a/rust/lithe-core/src/remote/workspace.rs b/rust/crates/core/src/remote/workspace.rs similarity index 100% rename from rust/lithe-core/src/remote/workspace.rs rename to rust/crates/core/src/remote/workspace.rs diff --git a/rust/lithe-core/src/remote/workspace_host.rs b/rust/crates/core/src/remote/workspace_host.rs similarity index 100% rename from rust/lithe-core/src/remote/workspace_host.rs rename to rust/crates/core/src/remote/workspace_host.rs diff --git a/rust/lithe-core/src/remote/workspace_host/tests.rs b/rust/crates/core/src/remote/workspace_host/tests.rs similarity index 100% rename from rust/lithe-core/src/remote/workspace_host/tests.rs rename to rust/crates/core/src/remote/workspace_host/tests.rs diff --git a/rust/lithe-core/src/remote/workspace_io.rs b/rust/crates/core/src/remote/workspace_io.rs similarity index 100% rename from rust/lithe-core/src/remote/workspace_io.rs rename to rust/crates/core/src/remote/workspace_io.rs diff --git a/rust/lithe-core/src/runtime/dispatcher.rs b/rust/crates/core/src/runtime/dispatcher.rs similarity index 100% rename from rust/lithe-core/src/runtime/dispatcher.rs rename to rust/crates/core/src/runtime/dispatcher.rs diff --git a/rust/lithe-core/src/runtime/ffi.rs b/rust/crates/core/src/runtime/ffi.rs similarity index 98% rename from rust/lithe-core/src/runtime/ffi.rs rename to rust/crates/core/src/runtime/ffi.rs index 25e721dd..7472e9d3 100644 --- a/rust/lithe-core/src/runtime/ffi.rs +++ b/rust/crates/core/src/runtime/ffi.rs @@ -209,7 +209,7 @@ mod text_content_tests { #[test] fn decoded_text_contract_matches_c_abi_and_json() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/text-content-v1.json" + "../../../../fixtures/editor/text-content-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -256,7 +256,7 @@ mod editor_essentials_tests { #[test] fn borrowed_document_abi_matches_shared_vectors() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/ide-essentials-v1.json" + "../../../../fixtures/editor/ide-essentials-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/runtime/mod.rs b/rust/crates/core/src/runtime/mod.rs similarity index 100% rename from rust/lithe-core/src/runtime/mod.rs rename to rust/crates/core/src/runtime/mod.rs diff --git a/rust/lithe-core/src/terminal/link.rs b/rust/crates/core/src/terminal/link.rs similarity index 100% rename from rust/lithe-core/src/terminal/link.rs rename to rust/crates/core/src/terminal/link.rs diff --git a/rust/lithe-core/src/terminal/mod.rs b/rust/crates/core/src/terminal/mod.rs similarity index 100% rename from rust/lithe-core/src/terminal/mod.rs rename to rust/crates/core/src/terminal/mod.rs diff --git a/rust/lithe-core/src/tests/build_configuration.rs b/rust/crates/core/src/tests/build_configuration.rs similarity index 97% rename from rust/lithe-core/src/tests/build_configuration.rs rename to rust/crates/core/src/tests/build_configuration.rs index ca4456ae..7401a583 100644 --- a/rust/lithe-core/src/tests/build_configuration.rs +++ b/rust/crates/core/src/tests/build_configuration.rs @@ -9,13 +9,13 @@ use serde_json::{json, Value}; fn manifest() -> Value { serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/build-providers/build-provider-configuration.plugin.json" + "../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-provider-configuration.plugin.json" )) .unwrap() } fn snapshot() -> Value { let mut value: Value = serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/build-providers/build-configuration.json" + "../../../../../shared/plugins/contract/v1/fixtures/build-providers/build-configuration.json" )) .unwrap(); if cfg!(windows) { diff --git a/rust/lithe-core/src/tests/build_project_options.rs b/rust/crates/core/src/tests/build_project_options.rs similarity index 94% rename from rust/lithe-core/src/tests/build_project_options.rs rename to rust/crates/core/src/tests/build_project_options.rs index 55cfb88f..27d1b198 100644 --- a/rust/lithe-core/src/tests/build_project_options.rs +++ b/rust/crates/core/src/tests/build_project_options.rs @@ -6,11 +6,11 @@ use serde_json::{json, Value}; #[test] fn local_option_edits_check_declarations_preserve_siblings_and_reset_to_team_values() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/build-project-options/local-edits.json" + "../../../../fixtures/build-project-options/local-edits.json" )) .unwrap(); let mut manifest: Value = serde_json::from_str(include_str!( - "../../../../shared/plugins/contract/v1/fixtures/build-systems/build-instance-options.plugin.json" + "../../../../../shared/plugins/contract/v1/fixtures/build-systems/build-instance-options.plugin.json" )) .unwrap(); // Exercise a workspace option with model-owned choices as well as the @@ -129,7 +129,7 @@ fn local_option_edits_check_declarations_preserve_siblings_and_reset_to_team_val #[test] fn native_build_options_validate_the_shared_cases_without_dropping_custom_values() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/build-project-options/validation.json" + "../../../../fixtures/build-project-options/validation.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -151,7 +151,7 @@ fn native_build_options_validate_the_shared_cases_without_dropping_custom_values assert_eq!(case["document"], original); } let defaults: Value = serde_json::from_str(include_str!( - "../../../fixtures/build-project-options/shared-defaults.json" + "../../../../fixtures/build-project-options/shared-defaults.json" )) .unwrap(); let result = project_options_command(json!({"document":defaults})).unwrap(); diff --git a/rust/lithe-core/src/tests/build_runtime_versions.rs b/rust/crates/core/src/tests/build_runtime_versions.rs similarity index 98% rename from rust/lithe-core/src/tests/build_runtime_versions.rs rename to rust/crates/core/src/tests/build_runtime_versions.rs index 65eb71b7..58c100a5 100644 --- a/rust/lithe-core/src/tests/build_runtime_versions.rs +++ b/rust/crates/core/src/tests/build_runtime_versions.rs @@ -7,7 +7,7 @@ use serde_json::{json, Value}; fn manifest() -> Value { serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/build-systems/build-toolchains.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/build-systems/build-toolchains.plugin.json" ))) .expect("Cargo fixture is valid JSON") } diff --git a/rust/lithe-core/src/tests/build_systems.rs b/rust/crates/core/src/tests/build_systems.rs similarity index 99% rename from rust/lithe-core/src/tests/build_systems.rs rename to rust/crates/core/src/tests/build_systems.rs index 58090479..c03b8d86 100644 --- a/rust/lithe-core/src/tests/build_systems.rs +++ b/rust/crates/core/src/tests/build_systems.rs @@ -22,7 +22,7 @@ macro_rules! contract_file { ($path:literal) => { include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/", + "/../../../shared/plugins/contract/v1/", $path )) }; diff --git a/rust/lithe-core/src/tests/community_build_plugins.rs b/rust/crates/core/src/tests/community_build_plugins.rs similarity index 100% rename from rust/lithe-core/src/tests/community_build_plugins.rs rename to rust/crates/core/src/tests/community_build_plugins.rs diff --git a/rust/lithe-core/src/tests/core_request_traces.rs b/rust/crates/core/src/tests/core_request_traces.rs similarity index 100% rename from rust/lithe-core/src/tests/core_request_traces.rs rename to rust/crates/core/src/tests/core_request_traces.rs diff --git a/rust/lithe-core/src/tests/declarative_plugins.rs b/rust/crates/core/src/tests/declarative_plugins.rs similarity index 99% rename from rust/lithe-core/src/tests/declarative_plugins.rs rename to rust/crates/core/src/tests/declarative_plugins.rs index e5f5a95d..78bf79a4 100644 --- a/rust/lithe-core/src/tests/declarative_plugins.rs +++ b/rust/crates/core/src/tests/declarative_plugins.rs @@ -8,7 +8,7 @@ macro_rules! contract_file { ($path:literal) => { include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/", + "/../../../shared/plugins/contract/v1/", $path )) }; diff --git a/rust/lithe-core/src/tests/detectors.rs b/rust/crates/core/src/tests/detectors.rs similarity index 100% rename from rust/lithe-core/src/tests/detectors.rs rename to rust/crates/core/src/tests/detectors.rs diff --git a/rust/lithe-core/src/tests/directory_actions.rs b/rust/crates/core/src/tests/directory_actions.rs similarity index 96% rename from rust/lithe-core/src/tests/directory_actions.rs rename to rust/crates/core/src/tests/directory_actions.rs index c1ef9250..f17a2eb0 100644 --- a/rust/lithe-core/src/tests/directory_actions.rs +++ b/rust/crates/core/src/tests/directory_actions.rs @@ -10,7 +10,7 @@ fn execute(command: &str, payload: Value) -> Value { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/workspace/directory-rules-v1.json" + "../../../../fixtures/workspace/directory-rules-v1.json" )) .expect("directory rules fixture should be JSON") } @@ -75,7 +75,7 @@ fn invalid_requests_are_rejected() { #[test] fn action_sequences_reach_the_documented_role_and_inclusion() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/directory-actions-v1.json" + "../../../../fixtures/workspace/directory-actions-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/tests/file_name_order.rs b/rust/crates/core/src/tests/file_name_order.rs similarity index 98% rename from rust/lithe-core/src/tests/file_name_order.rs rename to rust/crates/core/src/tests/file_name_order.rs index 0eff4bfc..27cdec7e 100644 --- a/rust/lithe-core/src/tests/file_name_order.rs +++ b/rust/crates/core/src/tests/file_name_order.rs @@ -7,7 +7,7 @@ use std::fs; fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/workspace/file-name-order-v1.json" + "../../../../fixtures/workspace/file-name-order-v1.json" )) .expect("file-name order fixture should be JSON") } @@ -209,7 +209,7 @@ fn execute(command: &str, payload: Value) -> Value { #[test] fn order_entries_matches_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/entry-order-v1.json" + "../../../../fixtures/workspace/entry-order-v1.json" )) .expect("entry-order fixture should be JSON"); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/tests/file_operations.rs b/rust/crates/core/src/tests/file_operations.rs similarity index 97% rename from rust/lithe-core/src/tests/file_operations.rs rename to rust/crates/core/src/tests/file_operations.rs index 0adf61f6..42e0b753 100644 --- a/rust/lithe-core/src/tests/file_operations.rs +++ b/rust/crates/core/src/tests/file_operations.rs @@ -10,7 +10,7 @@ fn execute(command: &str, payload: Value) -> Value { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/workspace/file-copy-names-v1.json" + "../../../../fixtures/workspace/file-copy-names-v1.json" )) .expect("file copy names fixture should be JSON") } diff --git a/rust/lithe-core/src/tests/fixtures/branch-name-cleanup-parity-v1.json b/rust/crates/core/src/tests/fixtures/branch-name-cleanup-parity-v1.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/branch-name-cleanup-parity-v1.json rename to rust/crates/core/src/tests/fixtures/branch-name-cleanup-parity-v1.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/app-dependencies.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/app-dependencies.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/app-dependencies.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/app-dependencies.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/dependencies.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/dependencies.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/dependencies.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/dependencies.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/model.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/model.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/model.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/model.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/plugin.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/plugin.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/gradle/plugin.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/gradle/plugin.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/app-dependencies.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/maven/app-dependencies.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/app-dependencies.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/maven/app-dependencies.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/dependencies.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/maven/dependencies.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/dependencies.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/maven/dependencies.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/model.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/maven/model.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/model.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/maven/model.json diff --git a/rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/plugin.json b/rust/crates/core/src/tests/fixtures/community_build_plugins/maven/plugin.json similarity index 100% rename from rust/lithe-core/src/tests/fixtures/community_build_plugins/maven/plugin.json rename to rust/crates/core/src/tests/fixtures/community_build_plugins/maven/plugin.json diff --git a/rust/lithe-core/src/tests/git.rs b/rust/crates/core/src/tests/git.rs similarity index 99% rename from rust/lithe-core/src/tests/git.rs rename to rust/crates/core/src/tests/git.rs index 170171d8..6358abfe 100644 --- a/rust/lithe-core/src/tests/git.rs +++ b/rust/crates/core/src/tests/git.rs @@ -9,7 +9,7 @@ use std::time::{Duration, UNIX_EPOCH}; #[test] fn repository_color_assignments_match_shared_pages() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/repository-colors-v1.json" + "../../../../fixtures/git/repository-colors-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -45,7 +45,7 @@ fn repository_color_assignments_reject_invalid_pages() { #[test] fn git_checkout_metadata_and_gitdir_pointer_match_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/checkout-metadata-v1.json" + "../../../../fixtures/git/checkout-metadata-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -127,7 +127,7 @@ fn git_remote_and_tag_catalog_returns_unambiguous_typed_data() { ]); let commit = run(&["rev-parse", "HEAD"]); let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/remote-tag-catalog-v1.json" + "../../../../fixtures/git/remote-tag-catalog-v1.json" )) .unwrap(); let call = |command: &str| -> Value { @@ -193,7 +193,7 @@ fn git_comparison_can_include_untracked_worktree_files() { fs::write(root.join("tracked.txt"), "after\n").unwrap(); fs::write(root.join("a-untracked.txt"), "new\n").unwrap(); let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/comparison-untracked-v1.json" + "../../../../fixtures/git/comparison-untracked-v1.json" )) .unwrap(); let mut payload = fixture["request"].clone(); @@ -2354,7 +2354,7 @@ fn git_write_creates_deletes_and_records_tags() { // plain invalid_request envelope. let tag_names: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/tag-names.json" + "/../../fixtures/git/tag-names.json" ))) .expect("tag name fixture should be valid JSON"); let empty = request( @@ -6319,8 +6319,10 @@ fn git_line_history_merge_rename_edit_keeps_previous_path_and_ranges() { #[test] fn rollback_plan_matches_shared_fixture_and_rejects_unsafe_paths() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/rollback-plan-v1.json")).unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/rollback-plan-v1.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response: Value = serde_json::from_str(&execute_json( &serde_json::json!({ @@ -6812,7 +6814,7 @@ fn prepare_commit_selection_allows_a_tracked_submodule_reference() { #[test] fn git_history_query_compares_absolute_instants_with_half_open_bounds() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/history-date-query-v1.json" + "../../../../fixtures/git/history-date-query-v1.json" )) .unwrap(); let result: Value = serde_json::from_str(&execute_json( @@ -6982,7 +6984,7 @@ fn reconcile_deleted_selection_works_before_the_first_commit() { fn git_branch_name_preview_matches_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/git/branch-name-preview-v1.json" + "/../../fixtures/git/branch-name-preview-v1.json" ))) .expect("branch name preview fixture should be valid JSON"); for case in fixture["cases"].as_array().expect("fixture cases") { @@ -7353,7 +7355,7 @@ fn git_create_tag_applies_the_explicit_lightweight_form() { #[test] fn git_metadata_classification_matches_shared_fixture() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/metadata-classification-v1.json" + "../../../../fixtures/git/metadata-classification-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -7382,7 +7384,7 @@ fn git_metadata_classification_matches_shared_fixture() { #[test] fn git_metadata_classification_rejects_invalid_or_unbounded_pages() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/git/metadata-classification-v1.json" + "../../../../fixtures/git/metadata-classification-v1.json" )) .unwrap(); let context = &fixture["contexts"]["main"]; diff --git a/rust/lithe-core/src/tests/git_diff_blocks.rs b/rust/crates/core/src/tests/git_diff_blocks.rs similarity index 99% rename from rust/lithe-core/src/tests/git_diff_blocks.rs rename to rust/crates/core/src/tests/git_diff_blocks.rs index 2604765f..8d33fba4 100644 --- a/rust/lithe-core/src/tests/git_diff_blocks.rs +++ b/rust/crates/core/src/tests/git_diff_blocks.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use std::process::Command; fn fixture() -> Value { - serde_json::from_str(include_str!("../../../fixtures/git/diff-blocks-v1.json")) + serde_json::from_str(include_str!("../../../../fixtures/git/diff-blocks-v1.json")) .expect("diff block fixture should be JSON") } diff --git a/rust/lithe-core/src/tests/git_fetch.rs b/rust/crates/core/src/tests/git_fetch.rs similarity index 98% rename from rust/lithe-core/src/tests/git_fetch.rs rename to rust/crates/core/src/tests/git_fetch.rs index e7dc7824..4903334b 100644 --- a/rust/lithe-core/src/tests/git_fetch.rs +++ b/rust/crates/core/src/tests/git_fetch.rs @@ -62,7 +62,7 @@ impl Drop for Repository { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/git/fetch-skip-boolean-v1.json" + "../../../../fixtures/git/fetch-skip-boolean-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/tests/git_history_rewrite.rs b/rust/crates/core/src/tests/git_history_rewrite.rs similarity index 99% rename from rust/lithe-core/src/tests/git_history_rewrite.rs rename to rust/crates/core/src/tests/git_history_rewrite.rs index 160b278c..5bbd23e9 100644 --- a/rust/lithe-core/src/tests/git_history_rewrite.rs +++ b/rust/crates/core/src/tests/git_history_rewrite.rs @@ -112,7 +112,7 @@ fn history_action_capabilities_use_real_head_and_complete_first_parent_chain() { let side = repo.commit("side.txt", "side\n", "side"); repo.git(&["checkout", "-q", "main"]); let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/history-action-capabilities-v1.json" + "../../../../fixtures/git/history-action-capabilities-v1.json" )) .unwrap(); let capabilities = |revisions: Vec<&str>| { @@ -988,7 +988,7 @@ fn native_rebase_large_escaped_manifest_remains_readable_through_abort() { #[test] fn github_pr_checkout_rejects_conflicts_and_stale_review_before_creating_branch() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/github/pr-checkout-plan-v1.json" + "../../../../fixtures/github/pr-checkout-plan-v1.json" )) .unwrap(); let codes = &fixture["errorCodes"]; diff --git a/rust/lithe-core/src/tests/git_patch_exchange.rs b/rust/crates/core/src/tests/git_patch_exchange.rs similarity index 98% rename from rust/lithe-core/src/tests/git_patch_exchange.rs rename to rust/crates/core/src/tests/git_patch_exchange.rs index 42830ce9..1820b693 100644 --- a/rust/lithe-core/src/tests/git_patch_exchange.rs +++ b/rust/crates/core/src/tests/git_patch_exchange.rs @@ -58,9 +58,10 @@ impl PatchRepository { } fn export_shelf_working_layer(&self) -> Value { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/patch-exchange-v1.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/patch-exchange-v1.json" + )) + .unwrap(); self.data( "git.patchExport", fixture["unstagedWithUntrackedRequest"].clone(), @@ -100,8 +101,10 @@ fn patch_exchange_reverse_roundtrip_preserves_both_versions_and_untracked_bytes( .unwrap() .to_string(); let mut checked_direction = false; - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/patch-exchange-v1.json")).unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/git/patch-exchange-v1.json" + )) + .unwrap(); let mut apply = |patch: &str, target: &str, reverse: bool| { let index_before = fs::read(repository.0.join(".git/index")).unwrap(); let mut payload = fixture[if reverse { @@ -275,7 +278,7 @@ fn saved_stash_diff_returns_file_sections_and_core_documents() { repository.write("text.txt", b"newer stash\n"); repository.git(&["stash", "push", "-m", "newer"]); let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/saved-stash-v1.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/git/saved-stash-v1.json")).unwrap(); let mut request = fixture["sectionRequest"].clone(); request["stashReference"] = json!(oid); let saved = repository.data("git.diff", request); @@ -350,7 +353,7 @@ fn structured_patch_and_git_diff_preserve_file_identity_and_writable_hunks() { .unwrap() .to_owned(); let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/parsed-diff-v1.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/git/parsed-diff-v1.json")).unwrap(); let mut request = fixture["parseRequest"].clone(); request["patch"] = json!(patch); let parsed = repository.data("git.parsePatch", request); @@ -957,7 +960,7 @@ fn shelf_clean_and_retry_restore_preserve_staged_working_and_untracked() { "capture must not refresh the real index" ); let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/git/shelf-v1.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/git/shelf-v1.json")).unwrap(); assert_eq!( repository.data("git.shelf", json!({"action":"plan", "phase":"clean"})), fixture["cleanPlan"] @@ -1085,7 +1088,7 @@ fn commit_message_context_rejects_new_index_content_at_the_same_path() { let selection = json!([{ "root": repository.0, "files": [{"path":"text.txt", "changeKind":"modified"}] }]); let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/commit-message-context-v1.json" + "../../../../fixtures/git/commit-message-context-v1.json" )) .unwrap(); let mut request = fixture["captureRequest"].clone(); diff --git a/rust/lithe-core/src/tests/git_remote_checkout.rs b/rust/crates/core/src/tests/git_remote_checkout.rs similarity index 99% rename from rust/lithe-core/src/tests/git_remote_checkout.rs rename to rust/crates/core/src/tests/git_remote_checkout.rs index 11c15fcd..5ab68758 100644 --- a/rust/lithe-core/src/tests/git_remote_checkout.rs +++ b/rust/crates/core/src/tests/git_remote_checkout.rs @@ -133,7 +133,7 @@ fn assert_success(response: &Value) { fn contract() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/git/remote-checkout-v1.json" + "../../../../fixtures/git/remote-checkout-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/tests/git_repository_discovery.rs b/rust/crates/core/src/tests/git_repository_discovery.rs similarity index 98% rename from rust/lithe-core/src/tests/git_repository_discovery.rs rename to rust/crates/core/src/tests/git_repository_discovery.rs index ae3b5669..dcd9d286 100644 --- a/rust/lithe-core/src/tests/git_repository_discovery.rs +++ b/rust/crates/core/src/tests/git_repository_discovery.rs @@ -68,7 +68,7 @@ fn canonical(root: &Path) -> String { fn fixture() -> Value { serde_json::from_str(include_str!( - "../../../fixtures/workspace/repository-visibility-v1.json" + "../../../../fixtures/workspace/repository-visibility-v1.json" )) .unwrap() } diff --git a/rust/lithe-core/src/tests/git_repository_setup.rs b/rust/crates/core/src/tests/git_repository_setup.rs similarity index 100% rename from rust/lithe-core/src/tests/git_repository_setup.rs rename to rust/crates/core/src/tests/git_repository_setup.rs diff --git a/rust/lithe-core/src/tests/git_untracked_directories.rs b/rust/crates/core/src/tests/git_untracked_directories.rs similarity index 100% rename from rust/lithe-core/src/tests/git_untracked_directories.rs rename to rust/crates/core/src/tests/git_untracked_directories.rs diff --git a/rust/lithe-core/src/tests/git_workspace_commit.rs b/rust/crates/core/src/tests/git_workspace_commit.rs similarity index 99% rename from rust/lithe-core/src/tests/git_workspace_commit.rs rename to rust/crates/core/src/tests/git_workspace_commit.rs index 112e9544..24d008ce 100644 --- a/rust/lithe-core/src/tests/git_workspace_commit.rs +++ b/rust/crates/core/src/tests/git_workspace_commit.rs @@ -330,7 +330,7 @@ fn git_workspace_commit_unstage_preserves_edits_after_initial_staging() { #[test] fn git_workspace_commit_state_matches_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/git/workspace-commit-v1.json" + "../../../../fixtures/git/workspace-commit-v1.json" )) .unwrap(); let state: crate::git::GitCommitState = diff --git a/rust/lithe-core/src/tests/github.rs b/rust/crates/core/src/tests/github.rs similarity index 99% rename from rust/lithe-core/src/tests/github.rs rename to rust/crates/core/src/tests/github.rs index 522b7e55..10c2a7a6 100644 --- a/rust/lithe-core/src/tests/github.rs +++ b/rust/crates/core/src/tests/github.rs @@ -228,7 +228,7 @@ fn github_http_failures_use_stable_error_categories_without_response_bodies_in_d #[test] fn device_authorization_transition_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/github/device-authorization-transition-v1.json" + "../../../../fixtures/github/device-authorization-transition-v1.json" )) .expect("device authorization fixture must be valid JSON"); for case in fixture["cases"].as_array().expect("fixture cases") { @@ -244,7 +244,7 @@ fn device_authorization_transition_shared_fixture() { #[test] fn pull_request_checkout_plan_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/github/pr-checkout-plan-v1.json" + "../../../../fixtures/github/pr-checkout-plan-v1.json" )) .expect("checkout fixture must be valid JSON"); for case in fixture["cases"].as_array().expect("fixture cases") { diff --git a/rust/lithe-core/src/tests/history_events.rs b/rust/crates/core/src/tests/history_events.rs similarity index 89% rename from rust/lithe-core/src/tests/history_events.rs rename to rust/crates/core/src/tests/history_events.rs index 6ae518e9..0a634030 100644 --- a/rust/lithe-core/src/tests/history_events.rs +++ b/rust/crates/core/src/tests/history_events.rs @@ -10,8 +10,10 @@ fn execute(payload: Value) -> Value { } fn fixture() -> Value { - serde_json::from_str(include_str!("../../../fixtures/history/event-plan-v1.json")) - .expect("history event fixture should be JSON") + serde_json::from_str(include_str!( + "../../../../fixtures/history/event-plan-v1.json" + )) + .expect("history event fixture should be JSON") } #[test] diff --git a/rust/lithe-core/src/tests/language_server_sessions.rs b/rust/crates/core/src/tests/language_server_sessions.rs similarity index 99% rename from rust/lithe-core/src/tests/language_server_sessions.rs rename to rust/crates/core/src/tests/language_server_sessions.rs index 6644f660..85864d12 100644 --- a/rust/lithe-core/src/tests/language_server_sessions.rs +++ b/rust/crates/core/src/tests/language_server_sessions.rs @@ -14,7 +14,7 @@ macro_rules! contract_file { ($path:literal) => { include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/", + "/../../../shared/plugins/contract/v1/", $path )) }; diff --git a/rust/lithe-core/src/tests/marketplace_plugins.rs b/rust/crates/core/src/tests/marketplace_plugins.rs similarity index 99% rename from rust/lithe-core/src/tests/marketplace_plugins.rs rename to rust/crates/core/src/tests/marketplace_plugins.rs index 9b888e16..8e85fe7f 100644 --- a/rust/lithe-core/src/tests/marketplace_plugins.rs +++ b/rust/crates/core/src/tests/marketplace_plugins.rs @@ -7,7 +7,7 @@ macro_rules! contract_file { ($path:literal) => { include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/", + "/../../../shared/plugins/contract/v1/", $path )) }; diff --git a/rust/lithe-core/src/tests/mod.rs b/rust/crates/core/src/tests/mod.rs similarity index 100% rename from rust/lithe-core/src/tests/mod.rs rename to rust/crates/core/src/tests/mod.rs diff --git a/rust/lithe-core/src/tests/plugin_editor_resources.rs b/rust/crates/core/src/tests/plugin_editor_resources.rs similarity index 99% rename from rust/lithe-core/src/tests/plugin_editor_resources.rs rename to rust/crates/core/src/tests/plugin_editor_resources.rs index 2df1bb6c..1bada685 100644 --- a/rust/lithe-core/src/tests/plugin_editor_resources.rs +++ b/rust/crates/core/src/tests/plugin_editor_resources.rs @@ -7,7 +7,7 @@ macro_rules! contract_file { ($path:literal) => { include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/", + "/../../../shared/plugins/contract/v1/", $path )) }; diff --git a/rust/lithe-core/src/tests/plugin_run_debug.rs b/rust/crates/core/src/tests/plugin_run_debug.rs similarity index 99% rename from rust/lithe-core/src/tests/plugin_run_debug.rs rename to rust/crates/core/src/tests/plugin_run_debug.rs index 02bbe5a7..4aab9a51 100644 --- a/rust/lithe-core/src/tests/plugin_run_debug.rs +++ b/rust/crates/core/src/tests/plugin_run_debug.rs @@ -18,7 +18,7 @@ macro_rules! contract_file { ($path:literal) => { include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/", + "/../../../shared/plugins/contract/v1/", $path )) }; diff --git a/rust/lithe-core/src/tests/project.rs b/rust/crates/core/src/tests/project.rs similarity index 98% rename from rust/lithe-core/src/tests/project.rs rename to rust/crates/core/src/tests/project.rs index 5c68f4a1..24ae4cb7 100644 --- a/rust/lithe-core/src/tests/project.rs +++ b/rust/crates/core/src/tests/project.rs @@ -149,7 +149,7 @@ fn search_everywhere_uses_git_ignore_rules_for_filename_foreground() { #[test] fn search_everywhere_preserves_unicode_contiguous_filename_matches() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/search/unicode-contiguous.json" + "../../../../fixtures/search/unicode-contiguous.json" )) .unwrap(); let root = temporary_root("unicode-contiguous-names"); @@ -189,8 +189,10 @@ fn search_everywhere_preserves_unicode_contiguous_filename_matches() { #[test] fn search_everywhere_preserves_directory_fallback_below_basename_matches() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/search/path-fallback.json")).unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/search/path-fallback.json" + )) + .unwrap(); let root = temporary_root("search-path-fallback"); struct Cleanup(std::path::PathBuf); impl Drop for Cleanup { @@ -250,8 +252,10 @@ fn search_everywhere_matches_names_before_limits_and_shares_utf16_fragments() { } } let _cleanup = Cleanup(root.clone()); - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/search/name-matching.json")).unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/search/name-matching.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let path = root.join(case["path"].as_str().unwrap()); fs::create_dir_all(path.parent().unwrap()).unwrap(); @@ -1108,7 +1112,7 @@ fn search_pages_apply_path_filters_before_the_page_limit() { fs::write(root.join(file), " 😀needle\n").unwrap(); } let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/search/text-snapshot-v1.json" + "../../../../fixtures/search/text-snapshot-v1.json" )) .unwrap(); let case = &fixture["filteredPage"]; @@ -1232,8 +1236,10 @@ fn preserve_case_matches_original_occurrence_shape() { #[test] fn local_history_relocates_excluded_files_and_subtrees_from_retained_metadata() { - let cases: Value = - serde_json::from_str(include_str!("../../../fixtures/history/relocation-v1.json")).unwrap(); + let cases: Value = serde_json::from_str(include_str!( + "../../../../fixtures/history/relocation-v1.json" + )) + .unwrap(); for case in cases["cases"].as_array().unwrap() { let root = temporary_root("excluded-history-relocation"); struct Cleanup(std::path::PathBuf, Option); @@ -1633,7 +1639,7 @@ fn file_commands_round_trip_and_reject_traversal() { #[test] fn document_lifecycle_matches_the_cross_platform_fixture() { let fixture_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/documents/lifecycle-v1.json"); + .join("../../fixtures/documents/lifecycle-v1.json"); let fixture: Value = serde_json::from_str( &fs::read_to_string(fixture_path).expect("document lifecycle fixture should be readable"), ) @@ -1666,7 +1672,7 @@ fn document_lifecycle_matches_the_cross_platform_fixture() { #[test] fn document_save_batch_matches_the_cross_platform_fixture() { let fixture_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/documents/save-batch-v1.json"); + .join("../../fixtures/documents/save-batch-v1.json"); let fixture: Value = serde_json::from_str( &fs::read_to_string(fixture_path).expect("save batch fixture should be readable"), ) @@ -1921,7 +1927,7 @@ fn search_everywhere_pages_all_sources_past_200_without_duplicates_or_missing_ma #[test] fn recent_project_reductions_match_shared_fixture() { let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/recent-projects-v1.json" + "../../../../fixtures/workspace/recent-projects-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -1953,7 +1959,7 @@ fn recent_projects_default_capacity_keeps_the_newest_unpinned_projects() { // The fixture documents the default; this guards the shared constant // without a 21-entry JSON case. let fixture: serde_json::Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/recent-projects-v1.json" + "../../../../fixtures/workspace/recent-projects-v1.json" )) .unwrap(); let capacity = crate::project::recent_projects::DEFAULT_RECENT_PROJECT_CAPACITY; @@ -1992,7 +1998,7 @@ fn call(command: &str, payload: Value) -> Value { #[test] fn file_encoding_matches_the_golden_fixture() { let fixture_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/editor/file-encoding-v1.json"); + .join("../../fixtures/editor/file-encoding-v1.json"); let fixture: Value = serde_json::from_str(&fs::read_to_string(fixture_path).unwrap()).unwrap(); let root = temporary_root("file-encoding"); fs::create_dir_all(&root).unwrap(); @@ -2067,7 +2073,7 @@ fn text_commands_match_the_golden_fixture_without_files() { use base64::Engine as _; let base64 = base64::engine::general_purpose::STANDARD; let fixture_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/editor/file-encoding-v1.json"); + .join("../../fixtures/editor/file-encoding-v1.json"); let fixture: Value = serde_json::from_str(&fs::read_to_string(fixture_path).unwrap()).unwrap(); for case in fixture["cases"].as_array().unwrap() { let name = case["name"].as_str().unwrap(); diff --git a/rust/lithe-core/src/tests/project_generators.rs b/rust/crates/core/src/tests/project_generators.rs similarity index 97% rename from rust/lithe-core/src/tests/project_generators.rs rename to rust/crates/core/src/tests/project_generators.rs index 7cc41777..ff51c855 100644 --- a/rust/lithe-core/src/tests/project_generators.rs +++ b/rust/crates/core/src/tests/project_generators.rs @@ -9,23 +9,23 @@ use std::path::PathBuf; const FIXTURE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/project-generators/project-generator.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/project-generators/project-generator.plugin.json" )); const PLANS: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/project-generators/project-plans.json" + "/../../../shared/plugins/contract/v1/fixtures/project-generators/project-plans.json" )); const TOOL_FIELD_FIXTURE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/project-generators/project-generator-tool-field.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/project-generators/project-generator-tool-field.plugin.json" )); const TOOL_DEFINITION_FIXTURE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" )); const BUILD_FIXTURE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/build-systems/build-static-file.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/build-systems/build-static-file.plugin.json" )); fn json(source: &str) -> Value { @@ -34,7 +34,7 @@ fn json(source: &str) -> Value { fn repository_path(relative: &str) -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../..") + .join("../../..") .join(relative) } diff --git a/rust/lithe-core/src/tests/protocol.rs b/rust/crates/core/src/tests/protocol.rs similarity index 96% rename from rust/lithe-core/src/tests/protocol.rs rename to rust/crates/core/src/tests/protocol.rs index 7810893a..3f4ab24b 100644 --- a/rust/lithe-core/src/tests/protocol.rs +++ b/rust/crates/core/src/tests/protocol.rs @@ -6,7 +6,7 @@ use serde_json::Value; #[test] fn keymap_context_fixtures_cross_the_json_boundary() { let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/keymap/context-v1.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/keymap/context-v1.json")).unwrap(); let call = |command: &str, payload: Value| -> Value { serde_json::from_str(&execute_json( &serde_json::json!({ @@ -77,7 +77,7 @@ fn action_search_crosses_the_json_boundary() { fn debug_adapter_endpoint_validation_crosses_the_json_boundary() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/adapter-endpoints-v1.json" + "/../../fixtures/debug/adapter-endpoints-v1.json" ))) .expect("endpoint fixture is JSON"); for case in fixture["cases"].as_array().expect("endpoint cases") { @@ -147,7 +147,7 @@ fn ping_exposes_protocol_version() { fn debug_create_and_destroy_commands_cross_the_json_boundary() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/dap-session-v1.json" + "/../../fixtures/debug/dap-session-v1.json" ))) .expect("debug fixture should be valid JSON"); let session = &fixture["session"]; @@ -192,7 +192,7 @@ fn debug_create_and_destroy_commands_cross_the_json_boundary() { fn debug_run_in_terminal_response_crosses_the_json_boundary() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/run-in-terminal-v1.json" + "/../../fixtures/debug/run-in-terminal-v1.json" ))) .expect("debug run-in-terminal fixture should be valid JSON"); let session_id = "debug-terminal-protocol-boundary"; @@ -284,7 +284,7 @@ fn debug_run_in_terminal_response_crosses_the_json_boundary() { fn debug_stepping_filters_match_the_shared_contract_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/stepping-filters-v1.json" + "/../../fixtures/debug/stepping-filters-v1.json" ))) .expect("debug stepping-filter fixture should be valid JSON"); @@ -313,7 +313,7 @@ fn debug_stepping_filters_match_the_shared_contract_fixture() { fn debug_breakpoint_relocation_matches_the_shared_contract_fixture() { let fixture: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/debug/breakpoint-relocation-v1.json" + "/../../fixtures/debug/breakpoint-relocation-v1.json" ))) .expect("debug breakpoint-relocation fixture should be valid JSON"); @@ -348,7 +348,7 @@ fn call_fixture_command(command: &str, payload: Value) -> Value { #[test] fn keymap_conflict_fixtures_cross_the_json_boundary() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/keymap/binding-conflicts-v1.json" + "../../../../fixtures/keymap/binding-conflicts-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -372,7 +372,7 @@ fn keymap_conflict_fixtures_cross_the_json_boundary() { #[test] fn modifier_gesture_fixture_runs_through_core_dispatch() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/keymap/modifier-gesture-v1.json" + "../../../../fixtures/keymap/modifier-gesture-v1.json" )) .unwrap(); for sequence in fixture["sequences"].as_array().unwrap() { @@ -413,7 +413,7 @@ fn modifier_gesture_fixture_runs_through_core_dispatch() { #[test] fn workbench_state_fixture_runs_through_core_dispatch() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/editor/workbench-state-v1.json" + "../../../../fixtures/editor/workbench-state-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { @@ -444,7 +444,7 @@ fn workbench_state_fixture_runs_through_core_dispatch() { #[test] fn visibility_fixture_crosses_the_core_json_boundary() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/workspace/visibility-v1.json" + "../../../../fixtures/workspace/visibility-v1.json" )) .unwrap(); let defaults = call_fixture_command("workspace.visibilityDefaults", serde_json::json!({})); @@ -527,7 +527,7 @@ fn unparseable_requests_fail_without_an_id() { #[test] fn terminal_link_fixtures_cross_the_json_boundary() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/terminal/link-target-v1.json" + "../../../../fixtures/terminal/link-target-v1.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/tests/rank_names.rs b/rust/crates/core/src/tests/rank_names.rs similarity index 92% rename from rust/lithe-core/src/tests/rank_names.rs rename to rust/crates/core/src/tests/rank_names.rs index afc9f7ac..be5faede 100644 --- a/rust/lithe-core/src/tests/rank_names.rs +++ b/rust/crates/core/src/tests/rank_names.rs @@ -17,9 +17,10 @@ fn execute(payload: Value) -> Value { #[test] fn rank_names_matches_the_shared_fixture() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/search/rank-names-v1.json")) - .expect("rank-names fixture should be JSON"); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/search/rank-names-v1.json" + )) + .expect("rank-names fixture should be JSON"); for case in fixture["cases"].as_array().unwrap() { let response = execute(case["request"].clone()); assert_eq!(response["ok"], true, "{}: {response}", case["id"]); @@ -54,7 +55,7 @@ fn rank_names_rejects_oversized_input_instead_of_truncating() { #[test] fn search_everywhere_context_matches_the_shared_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/search/search-everywhere-context-v1.json" + "../../../../fixtures/search/search-everywhere-context-v1.json" )) .expect("search context fixture should be JSON"); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/tests/run_configuration.rs b/rust/crates/core/src/tests/run_configuration.rs similarity index 99% rename from rust/lithe-core/src/tests/run_configuration.rs rename to rust/crates/core/src/tests/run_configuration.rs index 746b71ab..aceda01d 100644 --- a/rust/lithe-core/src/tests/run_configuration.rs +++ b/rust/crates/core/src/tests/run_configuration.rs @@ -131,7 +131,7 @@ fn project_tool_preferences_preserve_symbolic_choices_across_legacy_editor_saves } let _cleanup = Cleanup(root.clone()); let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/toolchains/consumer-preferences.json" + "../../../../fixtures/toolchains/consumer-preferences.json" )) .unwrap(); let call = |command: &str, payload: Value| -> Value { @@ -209,7 +209,7 @@ fn project_tool_preferences_reject_invalid_references_in_reads_and_edits_without #[test] fn argument_editor_text_roundtrips_the_shared_argv_fixture() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/argument-text.json" + "../../../../fixtures/run-configuration/argument-text.json" )) .unwrap(); let root = temporary_root("run-argument-text"); @@ -624,7 +624,8 @@ fn legacy_v2_runtime_requirements_are_reconciled_without_regeneration() { #[test] fn shared_run_configuration_fixtures_have_the_versioned_contract_shape() { - let directory = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../fixtures/run-configuration"); + let directory = + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../fixtures/run-configuration"); let mut fixture_count = 0; for entry in fs::read_dir(directory).unwrap() { let path = entry.unwrap().path(); @@ -646,7 +647,7 @@ fn shared_run_configuration_fixtures_have_the_versioned_contract_shape() { #[test] fn shared_hybrid_fixture_executes_scoped_toolchain_expectations() { let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/run-configuration/hybrid-service-web.json"); + .join("../../fixtures/run-configuration/hybrid-service-web.json"); let fixture: Value = serde_json::from_str(&fs::read_to_string(fixture_path).unwrap()).unwrap(); let root = temporary_root("run-config-hybrid-fixture"); fs::create_dir_all(root.join(".lithe/run")).unwrap(); @@ -708,7 +709,7 @@ fn shared_hybrid_fixture_executes_scoped_toolchain_expectations() { #[test] fn shared_editor_save_fixture_executes_the_document_contract() { let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("../fixtures/run-configuration/editor-save.json"); + .join("../../fixtures/run-configuration/editor-save.json"); let fixture: Value = serde_json::from_str(&fs::read_to_string(fixture_path).unwrap()).unwrap(); let root = temporary_root("run-config-editor-fixture"); fs::create_dir_all(root.join(".lithe/run")).unwrap(); @@ -1258,7 +1259,7 @@ fn shared_run_scan_excludes_caches_and_keeps_hidden_sources() { #[test] fn build_provider_configurations_persist_before_generation_and_reuse_identity() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/build-provider.json" + "../../../../fixtures/run-configuration/build-provider.json" )) .unwrap(); let root = temporary_root("saved-build-provider"); @@ -1400,7 +1401,7 @@ fn build_provider_configurations_persist_before_generation_and_reuse_identity() #[test] fn explicit_provider_references_keep_arbitrary_ids_and_shadow_only_current_selector() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/build-provider-stable-identities.json" + "../../../../fixtures/run-configuration/build-provider-stable-identities.json" )) .unwrap(); let root = temporary_root("provider-stable-identity"); @@ -1527,7 +1528,7 @@ fn explicit_provider_references_keep_arbitrary_ids_and_shadow_only_current_selec #[test] fn provider_run_options_preserve_exact_arguments_and_layered_build_choices() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/run-configuration/build-provider-options.json" + "../../../../fixtures/run-configuration/build-provider-options.json" )) .unwrap(); let root = temporary_root("provider-run-options"); diff --git a/rust/lithe-core/src/tests/support.rs b/rust/crates/core/src/tests/support.rs similarity index 95% rename from rust/lithe-core/src/tests/support.rs rename to rust/crates/core/src/tests/support.rs index 5ea8f5ce..b64e4d51 100644 --- a/rust/lithe-core/src/tests/support.rs +++ b/rust/crates/core/src/tests/support.rs @@ -9,7 +9,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; pub(super) fn fixture() -> Value { let fixture_path = - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../fixtures/search/basic.json"); + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../fixtures/search/basic.json"); serde_json::from_str(&fs::read_to_string(fixture_path).expect("fixture should be readable")) .expect("fixture should be valid JSON") } diff --git a/rust/lithe-core/src/tests/toolchain_definitions.rs b/rust/crates/core/src/tests/toolchain_definitions.rs similarity index 97% rename from rust/lithe-core/src/tests/toolchain_definitions.rs rename to rust/crates/core/src/tests/toolchain_definitions.rs index b6f47f72..582ae279 100644 --- a/rust/lithe-core/src/tests/toolchain_definitions.rs +++ b/rust/crates/core/src/tests/toolchain_definitions.rs @@ -277,7 +277,7 @@ fn a_definition_plugin_may_provide_installations_of_its_own_tool() { fn build_toolchain_consumers_reference_definitions_without_owning_them() { let mut plugin: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/build-systems/build-toolchains.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/build-systems/build-toolchains.plugin.json" ))) .unwrap(); assert!(validate_manifest_value(plugin.clone()).is_ok()); @@ -293,7 +293,7 @@ fn build_toolchain_consumers_reference_definitions_without_owning_them() { fn tool_definitions_do_not_enable_toolchain_layers_in_build_executable_sets() { let mut plugin: Value = serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/build-systems/build-tool-path.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/build-systems/build-tool-path.plugin.json" ))) .unwrap(); plugin["requires"]["toolDefinitions"] = json!(0); @@ -309,14 +309,14 @@ fn production_toolchain_fixtures_require_explicit_host_capabilities() { ( include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" )), "requires.toolDefinitions", ), ( include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/toolchain-provider.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/toolchain-provider.plugin.json" )), "requires.toolchainProviders", ), diff --git a/rust/lithe-core/src/tests/toolchain_pins.rs b/rust/crates/core/src/tests/toolchain_pins.rs similarity index 99% rename from rust/lithe-core/src/tests/toolchain_pins.rs rename to rust/crates/core/src/tests/toolchain_pins.rs index b66657be..36f959bc 100644 --- a/rust/lithe-core/src/tests/toolchain_pins.rs +++ b/rust/crates/core/src/tests/toolchain_pins.rs @@ -342,7 +342,7 @@ fn toolchain_pin_edits_prune_empty_containers_and_leave_absent_removals_inert() #[test] fn toolchain_pin_edits_match_the_shared_boundary_fixture() { let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/toolchain-pin-edit.json")).unwrap(); + serde_json::from_str(include_str!("../../../../fixtures/toolchain-pin-edit.json")).unwrap(); let response = edit(fixture["request"].clone()); assert_eq!(response["data"]["edit"]["document"], fixture["document"]); } diff --git a/rust/lithe-core/src/tests/toolchain_queries.rs b/rust/crates/core/src/tests/toolchain_queries.rs similarity index 98% rename from rust/lithe-core/src/tests/toolchain_queries.rs rename to rust/crates/core/src/tests/toolchain_queries.rs index 000a2f60..bffea902 100644 --- a/rust/lithe-core/src/tests/toolchain_queries.rs +++ b/rust/crates/core/src/tests/toolchain_queries.rs @@ -8,11 +8,11 @@ fn contract(name: &str) -> Value { let source = match name { "java" => include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" )), "mise" => include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/toolchain-provider.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/toolchain-provider.plugin.json" )), _ => panic!("unknown contract fixture"), }; @@ -53,7 +53,7 @@ fn toolchain_queries_decode_installed_contract_reply_without_native_io() { #[test] fn toolchain_queries_preserve_bounded_string_and_numeric_wire_identities() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/toolchains/rpc-id-cases.json" + "../../../../fixtures/toolchains/rpc-id-cases.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/tests/toolchain_resolution.rs b/rust/crates/core/src/tests/toolchain_resolution.rs similarity index 99% rename from rust/lithe-core/src/tests/toolchain_resolution.rs rename to rust/crates/core/src/tests/toolchain_resolution.rs index 71af6c22..0fa78a27 100644 --- a/rust/lithe-core/src/tests/toolchain_resolution.rs +++ b/rust/crates/core/src/tests/toolchain_resolution.rs @@ -16,11 +16,11 @@ fn contract(name: &str) -> Value { let source = match name { "java" => include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" )), "mise" => include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/toolchain-provider.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/toolchain-provider.plugin.json" )), _ => panic!("unknown fixture"), }; diff --git a/rust/lithe-core/src/tests/toolchain_vectors.rs b/rust/crates/core/src/tests/toolchain_vectors.rs similarity index 97% rename from rust/lithe-core/src/tests/toolchain_vectors.rs rename to rust/crates/core/src/tests/toolchain_vectors.rs index 28e8083a..f0433f32 100644 --- a/rust/lithe-core/src/tests/toolchain_vectors.rs +++ b/rust/crates/core/src/tests/toolchain_vectors.rs @@ -9,7 +9,7 @@ use serde_json::{json, Value}; /// Tool-definition fixture whose single tool every vector queries and pins. const TOOL_DEFINITION: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/toolchains/tool-definition.plugin.json" )); /// Home of the tool that the query reply reports and the root pin selects. diff --git a/rust/lithe-core/src/tests/vcs.rs b/rust/crates/core/src/tests/vcs.rs similarity index 99% rename from rust/lithe-core/src/tests/vcs.rs rename to rust/crates/core/src/tests/vcs.rs index 2394b947..0e14fe43 100644 --- a/rust/lithe-core/src/tests/vcs.rs +++ b/rust/crates/core/src/tests/vcs.rs @@ -17,11 +17,11 @@ use std::path::{Path, PathBuf}; const MODEL: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../fixtures/vcs/model-v1.json" + "/../../fixtures/vcs/model-v1.json" )); const SVN_PROVIDER: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../shared/plugins/contract/v1/fixtures/vcs/vcs-provider.plugin.json" + "/../../../shared/plugins/contract/v1/fixtures/vcs/vcs-provider.plugin.json" )); fn model() -> Value { diff --git a/rust/lithe-core/src/toolchain/definitions.rs b/rust/crates/core/src/toolchain/definitions.rs similarity index 100% rename from rust/lithe-core/src/toolchain/definitions.rs rename to rust/crates/core/src/toolchain/definitions.rs diff --git a/rust/lithe-core/src/toolchain/fixed.rs b/rust/crates/core/src/toolchain/fixed.rs similarity index 100% rename from rust/lithe-core/src/toolchain/fixed.rs rename to rust/crates/core/src/toolchain/fixed.rs diff --git a/rust/lithe-core/src/toolchain/mod.rs b/rust/crates/core/src/toolchain/mod.rs similarity index 100% rename from rust/lithe-core/src/toolchain/mod.rs rename to rust/crates/core/src/toolchain/mod.rs diff --git a/rust/lithe-core/src/toolchain/paths.rs b/rust/crates/core/src/toolchain/paths.rs similarity index 100% rename from rust/lithe-core/src/toolchain/paths.rs rename to rust/crates/core/src/toolchain/paths.rs diff --git a/rust/lithe-core/src/toolchain/pin_sources.rs b/rust/crates/core/src/toolchain/pin_sources.rs similarity index 98% rename from rust/lithe-core/src/toolchain/pin_sources.rs rename to rust/crates/core/src/toolchain/pin_sources.rs index b30ea288..a02263f1 100644 --- a/rust/lithe-core/src/toolchain/pin_sources.rs +++ b/rust/crates/core/src/toolchain/pin_sources.rs @@ -192,9 +192,10 @@ mod tests { #[test] fn source_edits_match_shared_fixture() { - let fixture: Value = - serde_json::from_str(include_str!("../../../fixtures/toolchain-pin-storage.json")) - .unwrap(); + let fixture: Value = serde_json::from_str(include_str!( + "../../../../fixtures/toolchain-pin-storage.json" + )) + .unwrap(); for case in fixture["cases"].as_array().unwrap() { let response: Value = serde_json::from_str(&crate::execute_json( &json!({"command": case["command"], "payload": case["input"]}).to_string(), diff --git a/rust/lithe-core/src/toolchain/pins.rs b/rust/crates/core/src/toolchain/pins.rs similarity index 100% rename from rust/lithe-core/src/toolchain/pins.rs rename to rust/crates/core/src/toolchain/pins.rs diff --git a/rust/lithe-core/src/toolchain/preferences.rs b/rust/crates/core/src/toolchain/preferences.rs similarity index 99% rename from rust/lithe-core/src/toolchain/preferences.rs rename to rust/crates/core/src/toolchain/preferences.rs index edbd25ba..914695e4 100644 --- a/rust/lithe-core/src/toolchain/preferences.rs +++ b/rust/crates/core/src/toolchain/preferences.rs @@ -346,7 +346,7 @@ mod tests { #[test] fn shared_preferences_fixture_resolves_without_native_or_domain_facts() { let fixture: Value = serde_json::from_str(include_str!( - "../../../fixtures/toolchains/consumer-preferences.json" + "../../../../fixtures/toolchains/consumer-preferences.json" )) .unwrap(); for case in fixture["cases"].as_array().unwrap() { diff --git a/rust/lithe-core/src/toolchain/query.rs b/rust/crates/core/src/toolchain/query.rs similarity index 100% rename from rust/lithe-core/src/toolchain/query.rs rename to rust/crates/core/src/toolchain/query.rs diff --git a/rust/lithe-core/src/toolchain/resolution.rs b/rust/crates/core/src/toolchain/resolution.rs similarity index 100% rename from rust/lithe-core/src/toolchain/resolution.rs rename to rust/crates/core/src/toolchain/resolution.rs diff --git a/rust/lithe-core/src/vcs/commands.rs b/rust/crates/core/src/vcs/commands.rs similarity index 100% rename from rust/lithe-core/src/vcs/commands.rs rename to rust/crates/core/src/vcs/commands.rs diff --git a/rust/lithe-core/src/vcs/manifest.rs b/rust/crates/core/src/vcs/manifest.rs similarity index 100% rename from rust/lithe-core/src/vcs/manifest.rs rename to rust/crates/core/src/vcs/manifest.rs diff --git a/rust/lithe-core/src/vcs/mod.rs b/rust/crates/core/src/vcs/mod.rs similarity index 100% rename from rust/lithe-core/src/vcs/mod.rs rename to rust/crates/core/src/vcs/mod.rs diff --git a/rust/lithe-core/src/vcs/model.rs b/rust/crates/core/src/vcs/model.rs similarity index 100% rename from rust/lithe-core/src/vcs/model.rs rename to rust/crates/core/src/vcs/model.rs diff --git a/rust/lithe-core/src/vcs/requests.rs b/rust/crates/core/src/vcs/requests.rs similarity index 100% rename from rust/lithe-core/src/vcs/requests.rs rename to rust/crates/core/src/vcs/requests.rs diff --git a/rust/lithe-core/src/vcs/roots.rs b/rust/crates/core/src/vcs/roots.rs similarity index 100% rename from rust/lithe-core/src/vcs/roots.rs rename to rust/crates/core/src/vcs/roots.rs diff --git a/rust/lithe-core/tests/core_log_waker.rs b/rust/crates/core/tests/core_log_waker.rs similarity index 100% rename from rust/lithe-core/tests/core_log_waker.rs rename to rust/crates/core/tests/core_log_waker.rs diff --git a/rust/lithe-core/tests/git_push.rs b/rust/crates/core/tests/git_push.rs similarity index 100% rename from rust/lithe-core/tests/git_push.rs rename to rust/crates/core/tests/git_push.rs diff --git a/rust/lithe-core/tests/git_watch_context.rs b/rust/crates/core/tests/git_watch_context.rs similarity index 100% rename from rust/lithe-core/tests/git_watch_context.rs rename to rust/crates/core/tests/git_watch_context.rs diff --git a/rust/lithe-git-host/Cargo.toml b/rust/crates/git-host/Cargo.toml similarity index 100% rename from rust/lithe-git-host/Cargo.toml rename to rust/crates/git-host/Cargo.toml diff --git a/rust/lithe-git-host/src/authentication.rs b/rust/crates/git-host/src/authentication.rs similarity index 94% rename from rust/lithe-git-host/src/authentication.rs rename to rust/crates/git-host/src/authentication.rs index 0ffa0dbc..3fc48fa4 100644 --- a/rust/lithe-git-host/src/authentication.rs +++ b/rust/crates/git-host/src/authentication.rs @@ -23,12 +23,17 @@ fn nonce() -> io::Result { Ok(bytes.iter().map(|byte| format!("{byte:02x}")).collect()) } +/// A credential prompt from Git or SSH that the host must show to the user. #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct Challenge { + /// Identifies the prompt when the host replies through [`respond`]. pub request_id: String, + /// The prompt text exactly as Git or SSH asked it. pub prompt: String, + /// Whether the answer is a secret and the input must be masked. pub secret: bool, + /// How many times this prompt has been asked in the session, starting at 1. pub attempt: usize, } #[derive(Deserialize, Serialize)] @@ -64,6 +69,7 @@ pub struct Session { helper: std::path::PathBuf, } impl Session { + /// Opens a loopback listener with a fresh token for one Git invocation. pub fn new() -> io::Result { let listener = TcpListener::bind((std::net::Ipv4Addr::LOCALHOST, 0))?; listener.set_nonblocking(true)?; @@ -78,6 +84,7 @@ impl Session { helper: executable, }) } + /// Points the command's Git and SSH askpass at this executable and session. pub fn configure(&self, command: &mut Command) -> io::Result<()> { command .env("GIT_ASKPASS", &self.helper) @@ -240,10 +247,12 @@ pub fn helper_main(prompt: &str) -> i32 { /// Owns an explicit retry decision after a failed process has already been reaped. pub struct Confirmation { + /// Identifies the decision when the host replies through [`respond`]. pub request_id: String, receiver: mpsc::Receiver, } impl Confirmation { + /// Registers a new decision that the host answers through [`respond`]. pub fn new() -> io::Result { let request_id = nonce()?; let (sender, receiver) = mpsc::sync_channel(1); diff --git a/rust/lithe-git-host/src/configuration.rs b/rust/crates/git-host/src/configuration.rs similarity index 100% rename from rust/lithe-git-host/src/configuration.rs rename to rust/crates/git-host/src/configuration.rs diff --git a/rust/lithe-git-host/src/failure_log.rs b/rust/crates/git-host/src/failure_log.rs similarity index 91% rename from rust/lithe-git-host/src/failure_log.rs rename to rust/crates/git-host/src/failure_log.rs index 55e41086..9b583642 100644 --- a/rust/lithe-git-host/src/failure_log.rs +++ b/rust/crates/git-host/src/failure_log.rs @@ -76,7 +76,7 @@ pub(crate) fn io(event: &str, stage: &'static str, result: std::io::Result pub(crate) fn cleanup(event: &str, stage: &'static str, result: std::io::Result<()>) { match result { Ok(()) => {} - // log-exempt: 预期的缺失:清理对象可能尚未创建或已被并发清理。 + // log-exempt: Expected absence: the cleanup target may not exist yet or may already have been removed concurrently. Err(error) if error.kind() == std::io::ErrorKind::NotFound => {} Err(error) => io::<()>(event, stage, Err(error)), } @@ -86,10 +86,10 @@ pub(crate) fn cleanup(event: &str, stage: &'static str, result: std::io::Result< pub(crate) fn kill(event: &str, stage: &'static str, result: std::io::Result<()>) { match result { Ok(()) => {} - // log-exempt: 预期的缺失:进程已经退出或已被回收,没有仍需终止的进程。 + // log-exempt: Expected absence: the process already exited or was reaped, so nothing is left to terminate. Err(error) if error.kind() == std::io::ErrorKind::InvalidInput => {} #[cfg(unix)] - // log-exempt: 预期的缺失:ESRCH 表示进程已经退出,没有仍需终止的进程。 + // log-exempt: Expected absence: ESRCH means the process already exited, so nothing is left to terminate. Err(error) if error.raw_os_error() == Some(libc::ESRCH) => {} Err(error) => io::<()>(event, stage, Err(error)), } diff --git a/rust/lithe-git-host/src/lib.rs b/rust/crates/git-host/src/lib.rs similarity index 96% rename from rust/lithe-git-host/src/lib.rs rename to rust/crates/git-host/src/lib.rs index ce6fbc29..021d5baf 100644 --- a/rust/lithe-git-host/src/lib.rs +++ b/rust/crates/git-host/src/lib.rs @@ -28,25 +28,36 @@ static INPUT_SEQUENCE: AtomicU64 = AtomicU64::new(0); /// Identifies an independently decoded process output stream. #[derive(Clone, Copy)] pub enum Stream { + /// The child's standard output. Stdout, + /// The child's standard error. Stderr, } /// Raw output remains intact for Core parsers; capture overflow is an error. pub struct Outcome { + /// Every byte the child wrote to standard output, up to the capture limit. pub stdout: Vec, + /// Every byte the child wrote to standard error, up to the capture limit. pub stderr: Vec, + /// The exit status, or `None` when the child was not observed to exit. pub status: Option, + /// Why the run did not complete normally, if it did not. pub failure: Option, } /// Native failures are translated to stable application errors by the caller. #[derive(Debug)] pub enum Failure { + /// Preparing the input file or spawning the child failed. Start(io::Error), + /// Reading the output pipes or polling the child failed. Io(io::Error), + /// The caller cancelled the run; the child was terminated. Cancelled, + /// The child wrote more than the capture limit to one stream. OutputLimit, + /// The child or a helper holding its pipes could not be terminated in time. Cleanup, } diff --git a/rust/lithe-git-host/tests/authentication.rs b/rust/crates/git-host/tests/authentication.rs similarity index 100% rename from rust/lithe-git-host/tests/authentication.rs rename to rust/crates/git-host/tests/authentication.rs diff --git a/rust/lithe-git-host/tests/process.rs b/rust/crates/git-host/tests/process.rs similarity index 100% rename from rust/lithe-git-host/tests/process.rs rename to rust/crates/git-host/tests/process.rs diff --git a/rust/lithe-ide-host/Cargo.toml b/rust/crates/ide-host/Cargo.toml similarity index 91% rename from rust/lithe-ide-host/Cargo.toml rename to rust/crates/ide-host/Cargo.toml index 826b452f..423b5ddf 100644 --- a/rust/lithe-ide-host/Cargo.toml +++ b/rust/crates/ide-host/Cargo.toml @@ -2,6 +2,7 @@ name = "lithe-ide-host" version = "0.1.0" edition = "2021" +description = "Local IDE capability broker and MCP bridge for Lithe hosts" license = "Apache-2.0" publish = false diff --git a/rust/lithe-ide-host/src/bin/lithe-mcp.rs b/rust/crates/ide-host/src/bin/lithe-mcp.rs similarity index 100% rename from rust/lithe-ide-host/src/bin/lithe-mcp.rs rename to rust/crates/ide-host/src/bin/lithe-mcp.rs diff --git a/rust/lithe-ide-host/src/catalog.rs b/rust/crates/ide-host/src/catalog.rs similarity index 97% rename from rust/lithe-ide-host/src/catalog.rs rename to rust/crates/ide-host/src/catalog.rs index 8b0df5d1..2f9126db 100644 --- a/rust/lithe-ide-host/src/catalog.rs +++ b/rust/crates/ide-host/src/catalog.rs @@ -10,7 +10,9 @@ use std::collections::{BTreeMap, BTreeSet}; #[derive(Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct ToolExposure { + /// The catalog tool name. pub name: String, + /// The arguments the host serves; absent keeps the full input schema. #[serde(default, skip_serializing_if = "Option::is_none")] pub arguments: Option>, } @@ -72,8 +74,10 @@ pub fn served_tools(exposure: Option<&[ToolExposure]>) -> Result, Str #[derive(Clone, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Permissions { + /// Allows tools that change project or build configuration. #[serde(default)] pub configure: bool, + /// Allows tools that start, restart or stop builds and run configurations. #[serde(default)] pub execute: bool, } @@ -246,7 +250,7 @@ mod tests { #[test] fn native_inventory_can_only_narrow_known_tools_and_their_argument_fields() { let fixture: Value = serde_json::from_str(include_str!( - "../../fixtures/ide-api/host-tool-exposure.json" + "../../../fixtures/ide-api/host-tool-exposure.json" )) .unwrap(); let permissions = Permissions { @@ -336,7 +340,7 @@ mod tests { #[test] fn shared_fixture_protects_the_plugin_and_mcp_contract() { let fixture: Value = - serde_json::from_str(include_str!("../../fixtures/ide-api/calls.json")).unwrap(); + serde_json::from_str(include_str!("../../../fixtures/ide-api/calls.json")).unwrap(); let permissions = Permissions { configure: true, execute: true, diff --git a/rust/lithe-ide-host/src/failure_log.rs b/rust/crates/ide-host/src/failure_log.rs similarity index 100% rename from rust/lithe-ide-host/src/failure_log.rs rename to rust/crates/ide-host/src/failure_log.rs diff --git a/rust/lithe-ide-host/src/lib.rs b/rust/crates/ide-host/src/lib.rs similarity index 97% rename from rust/lithe-ide-host/src/lib.rs rename to rust/crates/ide-host/src/lib.rs index f810cb8a..2a8deeaf 100644 --- a/rust/lithe-ide-host/src/lib.rs +++ b/rust/crates/ide-host/src/lib.rs @@ -36,7 +36,9 @@ const MAX_PENDING: usize = 16; #[derive(Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Call { + /// The catalog tool name, for example `lithe_project_inspect`. pub name: String, + /// The tool arguments, validated against the tool's input schema. pub arguments: Value, } @@ -58,7 +60,7 @@ fn prune_pending(pending: &mut BTreeMap) { .collect(); for id in expired { if let Some(p) = pending.remove(&id) { - // log-exempt: 用户取消:IDE 调用方已结束超时请求,放弃等待超时应答。 + // log-exempt: User cancellation: the IDE caller already ended the timed-out request and no longer waits for the timeout reply. let _ = p.reply.send(failure( "TIMEOUT", "The IDE request expired. Inspect operations before retrying a mutation.", @@ -91,7 +93,7 @@ impl Drop for Host { self.task.abort(); if let Ok(mut pending) = self.broker.pending.lock() { for (_, p) in std::mem::take(&mut *pending) { - // log-exempt: 用户取消:IDE 调用方随项目关闭而释放请求,放弃等待断连应答。 + // log-exempt: User cancellation: the IDE caller released the request when the project closed and no longer waits for the disconnect reply. let _ = p.reply.send(failure( "DISCONNECTED", "IDE access was disabled or the project was closed", @@ -99,7 +101,7 @@ impl Drop for Host { } } if let Err(error) = std::fs::remove_file(&self.connection) { - // log-exempt: 预期的缺失:连接文件可能已经被关闭流程删除。 + // log-exempt: Expected absence: the shutdown path may already have removed the connection file. if error.kind() != std::io::ErrorKind::NotFound { failure_log::failed( "app.ide.connection_cleanup_failed", @@ -135,7 +137,9 @@ fn runtime() -> Result<&'static tokio::runtime::Runtime, String> { #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Connection { + /// The loopback HTTP URL that accepts calls. pub endpoint: String, + /// The bearer token every call must present. pub token: String, /// The tools the helper lists; absent when the host declared no selection. #[serde(default, skip_serializing_if = "Option::is_none")] @@ -307,7 +311,7 @@ fn deliver(broker: &Broker, dispatcher: &RequestDispatcher, id: String) { if let Ok(mut pending) = broker.pending.lock() { if pending.get(&id).is_some_and(|p| !p.claimed) { if let Some(request) = pending.remove(&id) { - // log-exempt: 用户取消:IDE 调用方已结束该请求,放弃等待 dispatcher 失败应答。 + // log-exempt: User cancellation: the IDE caller already ended the request and no longer waits for the dispatcher failure reply. let _ = request.reply.send(failure( "DISPATCHER_UNAVAILABLE", "The project could not receive this request. Retry after the IDE responds.", @@ -688,7 +692,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn an_authenticated_client_cannot_dispatch_unadvertised_native_workflows_or_fields() { let exposure: Value = serde_json::from_str(include_str!( - "../../fixtures/ide-api/host-tool-exposure.json" + "../../../fixtures/ide-api/host-tool-exposure.json" )) .unwrap(); let mut advertised = exposure["macos"].clone(); diff --git a/rust/lithe-remote/Cargo.toml b/rust/crates/remote/Cargo.toml similarity index 100% rename from rust/lithe-remote/Cargo.toml rename to rust/crates/remote/Cargo.toml diff --git a/rust/lithe-remote/src/bin/lithe-remote-server.rs b/rust/crates/remote/src/bin/lithe-remote-server.rs similarity index 100% rename from rust/lithe-remote/src/bin/lithe-remote-server.rs rename to rust/crates/remote/src/bin/lithe-remote-server.rs diff --git a/rust/lithe-remote/src/client/api.rs b/rust/crates/remote/src/client/api.rs similarity index 100% rename from rust/lithe-remote/src/client/api.rs rename to rust/crates/remote/src/client/api.rs diff --git a/rust/lithe-remote/src/client/bootstrap.rs b/rust/crates/remote/src/client/bootstrap.rs similarity index 100% rename from rust/lithe-remote/src/client/bootstrap.rs rename to rust/crates/remote/src/client/bootstrap.rs diff --git a/rust/lithe-remote/src/client/command.rs b/rust/crates/remote/src/client/command.rs similarity index 97% rename from rust/lithe-remote/src/client/command.rs rename to rust/crates/remote/src/client/command.rs index c698c2c6..6beaee28 100644 --- a/rust/lithe-remote/src/client/command.rs +++ b/rust/crates/remote/src/client/command.rs @@ -155,7 +155,7 @@ fn capture(pipe: Option) -> Capture { } } } - // log-exempt: 用户取消:命令调用方已结束输出收集,放弃等待 capture 完成通知。 + // log-exempt: User cancellation: the command caller already stopped collecting output and no longer waits for the capture completion notification. let _ = finished_sender.send(()); }); Capture { bytes, finished } diff --git a/rust/lithe-remote/src/client/forward.rs b/rust/crates/remote/src/client/forward.rs similarity index 96% rename from rust/lithe-remote/src/client/forward.rs rename to rust/crates/remote/src/client/forward.rs index 72956185..9691cedc 100644 --- a/rust/lithe-remote/src/client/forward.rs +++ b/rust/crates/remote/src/client/forward.rs @@ -106,7 +106,7 @@ impl Drop for PortForward { // already dropped it; otherwise the next accept result observes stopping. match TcpStream::connect(self.local_address) { Ok(_) => {} - // log-exempt: 预期的缺失:ConnectionRefused 表示 listener 已关闭,拥有它的 acceptor 已经退出。 + // log-exempt: Expected absence: ConnectionRefused means the listener closed because its owning acceptor already exited. Err(error) if error.kind() == io::ErrorKind::ConnectionRefused => {} Err(error) => crate::failure_log::io::<()>( "remote.client.operation_failed", @@ -139,7 +139,7 @@ fn bridge( let tunnel = match session.open_tunnel(target) { Ok(tunnel) => tunnel, Err(error) => { - // log-exempt: 同一次失败已经记录过:隧道建立错误向上传到 bridge 边界记录,随后关闭本地连接不再重复记录。 + // log-exempt: Same failure already recorded: the tunnel setup error propagates to the bridge boundary and is recorded there, so closing the local connection afterwards is not recorded again. let _ = local.shutdown(Shutdown::Both); return Err(error); } diff --git a/rust/lithe-remote/src/client/launch.rs b/rust/crates/remote/src/client/launch.rs similarity index 100% rename from rust/lithe-remote/src/client/launch.rs rename to rust/crates/remote/src/client/launch.rs diff --git a/rust/lithe-remote/src/client/mod.rs b/rust/crates/remote/src/client/mod.rs similarity index 100% rename from rust/lithe-remote/src/client/mod.rs rename to rust/crates/remote/src/client/mod.rs diff --git a/rust/lithe-remote/src/client/session.rs b/rust/crates/remote/src/client/session.rs similarity index 98% rename from rust/lithe-remote/src/client/session.rs rename to rust/crates/remote/src/client/session.rs index 4591817d..76b69a97 100644 --- a/rust/lithe-remote/src/client/session.rs +++ b/rust/crates/remote/src/client/session.rs @@ -662,12 +662,12 @@ fn read_loop( } = context; let mut reader = BufReader::new(reader); if let Err(error) = skip_preamble(&mut reader, PREAMBLE_NOISE_LIMIT) { - // log-exempt: 用户取消:连接调用方已结束握手,放弃等待 preamble 失败应答。 + // log-exempt: User cancellation: the connecting caller already ended the handshake and no longer waits for the preamble failure reply. let _ = ready.send(Err(error)); close(&pending); return; } - // log-exempt: 用户取消:连接调用方已结束握手,放弃等待 ready 通知。 + // log-exempt: User cancellation: the connecting caller already ended the handshake and no longer waits for the ready notification. let _ = ready.send(Ok(())); let mut acknowledged = 0; while let Ok(Some(frame)) = read_frame(&mut reader) { @@ -679,7 +679,7 @@ fn read_loop( (_, Some(error)) => Err(ClientError::Remote(error)), (result, None) => Ok(result.unwrap_or(Value::Null)), }; - // log-exempt: 用户取消:远程请求调用方已超时或取消,放弃等待该 response。 + // log-exempt: User cancellation: the remote request caller timed out or cancelled and no longer waits for this response. let _ = waiter.send(reply); } } @@ -760,7 +760,7 @@ fn close(pending: &Mutex) { let mut pending = lock(pending); pending.closed = true; for (_, waiter) in pending.waiting.drain() { - // log-exempt: 用户取消:远程请求调用方已结束请求,放弃等待断连应答。 + // log-exempt: User cancellation: the remote request caller already ended the request and no longer waits for the disconnect reply. let _ = waiter.send(Err(ClientError::Disconnected { diagnostics: String::new(), })); diff --git a/rust/lithe-remote/src/client/transport.rs b/rust/crates/remote/src/client/transport.rs similarity index 100% rename from rust/lithe-remote/src/client/transport.rs rename to rust/crates/remote/src/client/transport.rs diff --git a/rust/lithe-remote/src/failure_log.rs b/rust/crates/remote/src/failure_log.rs similarity index 88% rename from rust/lithe-remote/src/failure_log.rs rename to rust/crates/remote/src/failure_log.rs index d0f80fe8..ea3d85d0 100644 --- a/rust/lithe-remote/src/failure_log.rs +++ b/rust/crates/remote/src/failure_log.rs @@ -65,7 +65,7 @@ impl Hook { fn teardown(&self, event: &str, stage: &'static str, result: std::io::Result) { match result { Ok(_) => {} - // log-exempt: 预期的缺失:对端已经断开,没有仍需关闭或传输的连接。 + // log-exempt: Expected absence: the peer already disconnected, so no connection is left to close or write to. Err(error) if disconnected_io(error.kind()) => {} Err(error) => self.failed(event, stage, &format!("{:?}", error.kind()), "io"), } @@ -116,12 +116,12 @@ pub(crate) fn client( ) { match result { Ok(_) => {} - // log-exempt: 预期的缺失:远程连接已经关闭或关闭请求超时,取消或关闭的目标不再可达。 + // log-exempt: Expected absence: the remote connection already closed or the close request timed out, so the cancel or close target is unreachable. Err( crate::client::session::ClientError::Disconnected { .. } | crate::client::session::ClientError::Timeout, ) => {} - // log-exempt: 预期的缺失:关闭阶段的 Transport 只保留字符串,无法区分已断开的连接与异常,目标可能已不存在。 + // log-exempt: Expected absence: Transport errors during shutdown keep only a string and cannot tell a dropped connection from a fault, so the target may already be gone. Err(crate::client::session::ClientError::Transport(_)) => {} Err(error) => failed( "remote.client.operation_failed", @@ -144,9 +144,9 @@ fn disconnected_io(kind: std::io::ErrorKind) -> bool { pub(crate) fn kill(event: &str, stage: &'static str, result: std::io::Result<()>) { match result { Ok(()) => {} - // log-exempt: 预期的缺失:进程已经退出或已被回收,没有仍需终止的进程。 + // log-exempt: Expected absence: the process already exited or was reaped, so nothing is left to terminate. Err(error) if error.kind() == std::io::ErrorKind::InvalidInput => {} - // log-exempt: 预期的缺失:系统报告进程不存在,没有仍需终止的进程。 + // log-exempt: Expected absence: the system reports that the process does not exist, so nothing is left to terminate. Err(error) if error.kind() == std::io::ErrorKind::NotFound => {} Err(error) => io::<()>(event, stage, Err(error)), } @@ -157,9 +157,9 @@ pub(crate) fn kill(event: &str, stage: &'static str, result: std::io::Result<()> pub(crate) fn bridge_category(error: &crate::client::session::ClientError) -> Option { use crate::client::session::ClientError; match error { - // log-exempt: 预期的缺失:远程连接已经关闭,没有仍需建立的转发连接。 + // log-exempt: Expected absence: the remote connection already closed, so no forwarded connection is left to open. ClientError::Disconnected { .. } => None, - // log-exempt: 预期的缺失:本地客户端已经断开,没有仍需桥接的连接。 + // log-exempt: Expected absence: the local client already disconnected, so no connection is left to bridge. ClientError::Spawn(error) if disconnected_io(error.kind()) => None, _ => Some(client_category(error)), } diff --git a/rust/lithe-remote/src/lib.rs b/rust/crates/remote/src/lib.rs similarity index 100% rename from rust/lithe-remote/src/lib.rs rename to rust/crates/remote/src/lib.rs diff --git a/rust/lithe-remote/src/protocol/frame.rs b/rust/crates/remote/src/protocol/frame.rs similarity index 100% rename from rust/lithe-remote/src/protocol/frame.rs rename to rust/crates/remote/src/protocol/frame.rs diff --git a/rust/lithe-remote/src/protocol/message.rs b/rust/crates/remote/src/protocol/message.rs similarity index 100% rename from rust/lithe-remote/src/protocol/message.rs rename to rust/crates/remote/src/protocol/message.rs diff --git a/rust/lithe-remote/src/protocol/methods.rs b/rust/crates/remote/src/protocol/methods.rs similarity index 100% rename from rust/lithe-remote/src/protocol/methods.rs rename to rust/crates/remote/src/protocol/methods.rs diff --git a/rust/lithe-remote/src/protocol/mod.rs b/rust/crates/remote/src/protocol/mod.rs similarity index 100% rename from rust/lithe-remote/src/protocol/mod.rs rename to rust/crates/remote/src/protocol/mod.rs diff --git a/rust/lithe-remote/src/server/connection.rs b/rust/crates/remote/src/server/connection.rs similarity index 100% rename from rust/lithe-remote/src/server/connection.rs rename to rust/crates/remote/src/server/connection.rs diff --git a/rust/lithe-remote/src/server/connection/tests.rs b/rust/crates/remote/src/server/connection/tests.rs similarity index 100% rename from rust/lithe-remote/src/server/connection/tests.rs rename to rust/crates/remote/src/server/connection/tests.rs diff --git a/rust/lithe-remote/src/server/daemon.rs b/rust/crates/remote/src/server/daemon.rs similarity index 100% rename from rust/lithe-remote/src/server/daemon.rs rename to rust/crates/remote/src/server/daemon.rs diff --git a/rust/lithe-remote/src/server/environment.rs b/rust/crates/remote/src/server/environment.rs similarity index 100% rename from rust/lithe-remote/src/server/environment.rs rename to rust/crates/remote/src/server/environment.rs diff --git a/rust/lithe-remote/src/server/fs.rs b/rust/crates/remote/src/server/fs.rs similarity index 100% rename from rust/lithe-remote/src/server/fs.rs rename to rust/crates/remote/src/server/fs.rs diff --git a/rust/lithe-remote/src/server/link.rs b/rust/crates/remote/src/server/link.rs similarity index 100% rename from rust/lithe-remote/src/server/link.rs rename to rust/crates/remote/src/server/link.rs diff --git a/rust/lithe-remote/src/server/mod.rs b/rust/crates/remote/src/server/mod.rs similarity index 100% rename from rust/lithe-remote/src/server/mod.rs rename to rust/crates/remote/src/server/mod.rs diff --git a/rust/lithe-remote/src/server/platform/linux.rs b/rust/crates/remote/src/server/platform/linux.rs similarity index 100% rename from rust/lithe-remote/src/server/platform/linux.rs rename to rust/crates/remote/src/server/platform/linux.rs diff --git a/rust/lithe-remote/src/server/platform/linux_watch.rs b/rust/crates/remote/src/server/platform/linux_watch.rs similarity index 100% rename from rust/lithe-remote/src/server/platform/linux_watch.rs rename to rust/crates/remote/src/server/platform/linux_watch.rs diff --git a/rust/lithe-remote/src/server/platform/macos.rs b/rust/crates/remote/src/server/platform/macos.rs similarity index 100% rename from rust/lithe-remote/src/server/platform/macos.rs rename to rust/crates/remote/src/server/platform/macos.rs diff --git a/rust/lithe-remote/src/server/platform/macos_watch.rs b/rust/crates/remote/src/server/platform/macos_watch.rs similarity index 100% rename from rust/lithe-remote/src/server/platform/macos_watch.rs rename to rust/crates/remote/src/server/platform/macos_watch.rs diff --git a/rust/lithe-remote/src/server/platform/mod.rs b/rust/crates/remote/src/server/platform/mod.rs similarity index 100% rename from rust/lithe-remote/src/server/platform/mod.rs rename to rust/crates/remote/src/server/platform/mod.rs diff --git a/rust/lithe-remote/src/server/platform/unix.rs b/rust/crates/remote/src/server/platform/unix.rs similarity index 100% rename from rust/lithe-remote/src/server/platform/unix.rs rename to rust/crates/remote/src/server/platform/unix.rs diff --git a/rust/lithe-remote/src/server/ports.rs b/rust/crates/remote/src/server/ports.rs similarity index 100% rename from rust/lithe-remote/src/server/ports.rs rename to rust/crates/remote/src/server/ports.rs diff --git a/rust/lithe-remote/src/server/process.rs b/rust/crates/remote/src/server/process.rs similarity index 100% rename from rust/lithe-remote/src/server/process.rs rename to rust/crates/remote/src/server/process.rs diff --git a/rust/lithe-remote/src/server/resources.rs b/rust/crates/remote/src/server/resources.rs similarity index 100% rename from rust/lithe-remote/src/server/resources.rs rename to rust/crates/remote/src/server/resources.rs diff --git a/rust/lithe-remote/src/server/run_directory.rs b/rust/crates/remote/src/server/run_directory.rs similarity index 100% rename from rust/lithe-remote/src/server/run_directory.rs rename to rust/crates/remote/src/server/run_directory.rs diff --git a/rust/lithe-remote/src/server/session.rs b/rust/crates/remote/src/server/session.rs similarity index 100% rename from rust/lithe-remote/src/server/session.rs rename to rust/crates/remote/src/server/session.rs diff --git a/rust/lithe-remote/src/server/spawner.rs b/rust/crates/remote/src/server/spawner.rs similarity index 100% rename from rust/lithe-remote/src/server/spawner.rs rename to rust/crates/remote/src/server/spawner.rs diff --git a/rust/lithe-remote/src/server/terminal.rs b/rust/crates/remote/src/server/terminal.rs similarity index 100% rename from rust/lithe-remote/src/server/terminal.rs rename to rust/crates/remote/src/server/terminal.rs diff --git a/rust/lithe-remote/src/server/tunnel.rs b/rust/crates/remote/src/server/tunnel.rs similarity index 100% rename from rust/lithe-remote/src/server/tunnel.rs rename to rust/crates/remote/src/server/tunnel.rs diff --git a/rust/lithe-remote/src/server/upload.rs b/rust/crates/remote/src/server/upload.rs similarity index 100% rename from rust/lithe-remote/src/server/upload.rs rename to rust/crates/remote/src/server/upload.rs diff --git a/rust/lithe-remote/src/server/upload/tests.rs b/rust/crates/remote/src/server/upload/tests.rs similarity index 100% rename from rust/lithe-remote/src/server/upload/tests.rs rename to rust/crates/remote/src/server/upload/tests.rs diff --git a/rust/lithe-remote/src/server/walk.rs b/rust/crates/remote/src/server/walk.rs similarity index 100% rename from rust/lithe-remote/src/server/walk.rs rename to rust/crates/remote/src/server/walk.rs diff --git a/rust/lithe-remote/src/server/watch.rs b/rust/crates/remote/src/server/watch.rs similarity index 100% rename from rust/lithe-remote/src/server/watch.rs rename to rust/crates/remote/src/server/watch.rs diff --git a/rust/lithe-remote/tests/persistence.rs b/rust/crates/remote/tests/persistence.rs similarity index 100% rename from rust/lithe-remote/tests/persistence.rs rename to rust/crates/remote/tests/persistence.rs diff --git a/rust/lithe-remote/tests/processes.rs b/rust/crates/remote/tests/processes.rs similarity index 100% rename from rust/lithe-remote/tests/processes.rs rename to rust/crates/remote/tests/processes.rs diff --git a/rust/lithe-remote/tests/run_directories.rs b/rust/crates/remote/tests/run_directories.rs similarity index 100% rename from rust/lithe-remote/tests/run_directories.rs rename to rust/crates/remote/tests/run_directories.rs diff --git a/rust/lithe-remote/tests/server.rs b/rust/crates/remote/tests/server.rs similarity index 100% rename from rust/lithe-remote/tests/server.rs rename to rust/crates/remote/tests/server.rs diff --git a/rust/lithe-remote/tests/support/mod.rs b/rust/crates/remote/tests/support/mod.rs similarity index 100% rename from rust/lithe-remote/tests/support/mod.rs rename to rust/crates/remote/tests/support/mod.rs diff --git a/rust/lithe-remote/tests/terminals.rs b/rust/crates/remote/tests/terminals.rs similarity index 100% rename from rust/lithe-remote/tests/terminals.rs rename to rust/crates/remote/tests/terminals.rs diff --git a/rust/lithe-remote/tests/tunnels.rs b/rust/crates/remote/tests/tunnels.rs similarity index 100% rename from rust/lithe-remote/tests/tunnels.rs rename to rust/crates/remote/tests/tunnels.rs diff --git a/rust/lithe-remote/tests/watch_and_walk.rs b/rust/crates/remote/tests/watch_and_walk.rs similarity index 100% rename from rust/lithe-remote/tests/watch_and_walk.rs rename to rust/crates/remote/tests/watch_and_walk.rs diff --git a/rust/fixtures/debug/v1-baseline.json b/rust/fixtures/debug/v1-baseline.json index 6bea59b6..2d1be66b 100644 --- a/rust/fixtures/debug/v1-baseline.json +++ b/rust/fixtures/debug/v1-baseline.json @@ -10,12 +10,12 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "initialize_launch_breakpoints_and_inspection_are_reduced_in_order" }, { "platform": "rust", - "path": "rust/lithe-core/src/tests/protocol.rs", + "path": "rust/crates/core/src/tests/protocol.rs", "test": "debug_create_and_destroy_commands_cross_the_json_boundary", "fixture": "rust/fixtures/debug/dap-session-v1.json" }, @@ -39,7 +39,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "initialize_launch_breakpoints_and_inspection_are_reduced_in_order" }, { @@ -62,13 +62,13 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "source_breakpoint_binding_preserves_requested_identity_and_rejects_stale_replies", "fixture": "rust/fixtures/debug/breakpoint-binding-v1.json" }, { "platform": "rust", - "path": "rust/lithe-core/src/tests/protocol.rs", + "path": "rust/crates/core/src/tests/protocol.rs", "test": "debug_breakpoint_relocation_matches_the_shared_contract_fixture", "fixture": "rust/fixtures/debug/breakpoint-relocation-v1.json" }, @@ -92,13 +92,13 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "variable_paging_is_forwarded_and_normalized_from_shared_fixture", "fixture": "rust/fixtures/debug/variable-paging-v1.json" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "variable_paging_arguments_reject_invalid_combinations" }, { @@ -131,7 +131,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "disconnect_policy_matches_shared_fixture", "fixture": "rust/fixtures/debug/disconnect-policy-v1.json" }, @@ -160,18 +160,18 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "run_in_terminal_request_is_normalized_completed_and_stale_safe", "fixture": "rust/fixtures/debug/run-in-terminal-v1.json" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "malformed_run_in_terminal_request_gets_an_explicit_failure_response" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "unknown_server_request_gets_an_explicit_failure_response" }, { @@ -194,18 +194,18 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "start_debugging_request_is_normalized_completed_and_stale_safe", "fixture": "rust/fixtures/debug/start-debugging-v1.json" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "start_debugging_failure_and_unsupported_hosts_answer_the_adapter" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "disconnect_fails_a_pending_start_debugging_request" }, { @@ -215,12 +215,12 @@ }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "child_sessions_stop_with_the_parent_and_leave_the_tree_when_destroyed" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "destroying_a_parent_destroys_its_whole_child_tree" }, { @@ -240,7 +240,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "node_source_mapped_locations_pass_through_unchanged", "fixture": "rust/fixtures/debug/node-source-map-v1.json" } @@ -253,18 +253,18 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "hot_replace_normalizes_success_empty_and_error_bodies", "fixture": "rust/fixtures/debug/hot-code-replace-v1.json" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "hot_replace_requires_the_declaration_and_preserves_paused_state" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "declared_hot_code_replace_sends_the_declared_request_and_reads_its_fields" }, { @@ -287,13 +287,13 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/tests/protocol.rs", + "path": "rust/crates/core/src/tests/protocol.rs", "test": "debug_stepping_filters_match_the_shared_contract_fixture", "fixture": "rust/fixtures/debug/stepping-filters-v1.json" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "stepping_filters_are_normalized_projected_and_mark_stack_frames" } ], @@ -306,12 +306,12 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "cancelled_operation_forwards_dap_cancel_and_ignores_late_response" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "stale_reference_fixture_matches_core_behavior", "fixture": "rust/fixtures/debug/stale-reference-v1.json" }, @@ -340,7 +340,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "initialize_launch_breakpoints_and_inspection_are_reduced_in_order" }, { @@ -373,27 +373,27 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "data_breakpoint_identity_and_verification_are_correlated" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "variable_mutation_is_capability_gated_and_correlated" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "advanced_execution_controls_are_capability_gated_and_correlated" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "smart_step_and_goto_targets_are_normalized_before_targeted_execution" }, { "platform": "rust", - "path": "rust/lithe-core/src/debug/engine.rs", + "path": "rust/crates/core/src/debug/engine.rs", "test": "exception_information_is_capability_gated_and_normalized", "fixture": "rust/fixtures/debug/exception-info-v1.json" }, @@ -417,7 +417,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/endpoint.rs", + "path": "rust/crates/core/src/debug/endpoint.rs", "test": "dap_endpoint_contract_fixtures_match_validation_and_consent_classification", "fixture": "rust/fixtures/debug/adapter-endpoints-v1.json" }, @@ -441,7 +441,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/transport_lifecycle.rs", + "path": "rust/crates/core/src/debug/transport_lifecycle.rs", "test": "lifecycle_fixture_scenarios_match_expected_steps", "fixture": "rust/fixtures/debug/transport-lifecycle-v1.json" }, @@ -489,7 +489,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/variable_paging.rs", + "path": "rust/crates/core/src/debug/variable_paging.rs", "test": "variable_page_plan_matches_the_shared_fixture", "fixture": "rust/fixtures/debug/variable-page-plan-v1.json" } @@ -503,7 +503,7 @@ "evidence": [ { "platform": "rust", - "path": "rust/lithe-core/src/debug/disassembly_paging.rs", + "path": "rust/crates/core/src/debug/disassembly_paging.rs", "test": "disassembly_paging_matches_the_shared_fixture", "fixture": "rust/fixtures/debug/disassembly-paging-v1.json" } diff --git a/rust/logging/README.md b/rust/logging/README.md index 2bc53e4d..70f778e1 100644 --- a/rust/logging/README.md +++ b/rust/logging/README.md @@ -39,7 +39,7 @@ | `error` | `any Error` | 展开为 ``、`_code`、`_domain`,字段名通常就是 `error`;消息脱敏并限长至 1 KiB,code 可以是整数或稳定 token | | `text` | `String` | 只用于无法结构化的上游诊断(stderr 行、LSP logMessage)和经 Core 集中格式化函数脱敏的外部进程 argv;脱敏、去除控制字符、限长至 1 KiB | -源码、编辑缓冲区、文件内容、提交说明正文、环境变量值、进程的 stdout 与 stdin、凭据、终端历史和协议正文没有对应类型,不得塞进 `text`、`error`、token、路径字段或消息模板。外部进程的 argv 只经过 `rust/lithe-core/src/git/command_trace.rs` 的 `format_arguments`,stderr 只保留脱敏后的末尾几行(第五节)。迁移旧日志时拆开拼接消息,只保留结构化的时间、计数、受控结果词和错误类别。`text` 的理由不能写成“方便调试”。 +源码、编辑缓冲区、文件内容、提交说明正文、环境变量值、进程的 stdout 与 stdin、凭据、终端历史和协议正文没有对应类型,不得塞进 `text`、`error`、token、路径字段或消息模板。外部进程的 argv 只经过 `rust/crates/core/src/git/command_trace.rs` 的 `format_arguments`,stderr 只保留脱敏后的末尾几行(第五节)。迁移旧日志时拆开拼接消息,只保留结构化的时间、计数、受控结果词和错误类别。`text` 的理由不能写成“方便调试”。 Swift 的事件值是**未经脱敏的内存输入**,不能自行序列化落盘。Core 先对 `error`、`text` 输入脱敏、删除控制字符、按 UTF-8 字符边界截断到 1024 字节,再由 `catalog::validate_fields(id, fields)` 校验磁盘键展开后的类型、必填、未知字段、长度和错误组件完整性;这一步校验形状,不代替隐私脱敏。macOS 的跨边界适配器连接 Core 的脱敏、格式化和写入路径,不得另写 Swift 格式化或隐私策略。 @@ -69,8 +69,8 @@ Swift 的事件值是**未经脱敏的内存输入**,不能自行序列化落 | `vcs.git.command.finished` / `.traced` / `.failed` | `vcs/git` | info / debug / warn | `command`、`arguments`、`source`,可选 `repository`、`remote`、`exit_code`、`stderr`,`duration`;finished 与 traced 可带 `cancelled`,failed 可带 `error` | - `app.action.performed` 由 `UserActionTrace` 在最外层用户入口记录,owner 为 `LitheModuleAPI`。`action` 是稳定的操作 id,`surface` 是 `UserActionSurface` 的取值。它的 op 绑定到 `UserActionContext.current`,桥接层据此给 Core 请求附上 `origin`。 -- Core 请求轨迹在 `rust/lithe-core/src/runtime/dispatcher.rs` 的请求分发处记录,实现在 `rust/lithe-core/src/diagnostics/request_trace.rs`。用户来源的成功或取消记 finished,后台或未知来源的成功或取消记 traced,失败记 failed。`request_trace::is_hot` 列出的按键、每帧、轮询和监听批次方法,以及全部 `diagnostics.*` 和 `core.ping`,不记录。 -- Git 进程轨迹在 `rust/lithe-core/src/git/command_trace.rs` 的执行点记录,本地与远程工作区都经过这里。可见命令指经 `execute_git` 执行、作为 invocation 返回给宿主并显示在 Git 控制台的命令;内部读取指 Core 经 `capture_git` 执行、自己解析输出的命令。来源为用户的可见命令,成功或取消记 finished;其余成功或取消记 traced,包括用户操作中的内部读取;失败记 failed。退出码表示“回答”的情形(`exit_is_answer`),以及来源不是用户的内部读取的非零退出,不算失败;后者由调用方判断含义,调用方返回错误时由请求轨迹记录失败。 +- Core 请求轨迹在 `rust/crates/core/src/runtime/dispatcher.rs` 的请求分发处记录,实现在 `rust/crates/core/src/diagnostics/request_trace.rs`。用户来源的成功或取消记 finished,后台或未知来源的成功或取消记 traced,失败记 failed。`request_trace::is_hot` 列出的按键、每帧、轮询和监听批次方法,以及全部 `diagnostics.*` 和 `core.ping`,不记录。 +- Git 进程轨迹在 `rust/crates/core/src/git/command_trace.rs` 的执行点记录,本地与远程工作区都经过这里。可见命令指经 `execute_git` 执行、作为 invocation 返回给宿主并显示在 Git 控制台的命令;内部读取指 Core 经 `capture_git` 执行、自己解析输出的命令。来源为用户的可见命令,成功或取消记 finished;其余成功或取消记 traced,包括用户操作中的内部读取;失败记 failed。退出码表示“回答”的情形(`exit_is_answer`),以及来源不是用户的内部读取的非零退出,不算失败;后者由调用方判断含义,调用方返回错误时由请求轨迹记录失败。 - `arguments` 由 `format_arguments` 生成:提交说明值换成 ``,`-c` 中凭据和个人身份键的值换成 ``,URL 用户信息和共享脱敏规则覆盖的内容被改写,超过 1 KiB 时在末尾截断并以 `…` 标记。 - `stderr` 只在失败或非零退出时出现:取进程最后 16 KiB 输出中最后 8 个非空行,逐行脱敏后用 ` | ` 连接,超过 1 KiB 时丢弃最早的内容并以 `…` 标记。 - Core 轨迹的失败固定为 WARN,因为 Core 不知道宿主会重试、降级还是放弃。宿主提示的事实都在同一 op 的 Core 失败轨迹里时,提示用 `LogRecordReference(channel:event:op:)` 引用它,宿主不再记录;宿主只为降级、放弃、重试耗尽、残留等 Core 不掌握的事实记录自己的终态。 @@ -89,7 +89,7 @@ Swift 的事件值是**未经脱敏的内存输入**,不能自行序列化落 - stderr 读取器限制每行 4 KiB、每秒 200 行,之后再走 `text` 的 1 KiB 脱敏规范化。与 v1 相比唯一的兼容变化是从任意 trim 的读取块改为逐行文本:保留行内空格,移除 LF 和末尾 CR,并应用已声明的长度上限和限流。 - 上游明确给出的严重度通过独立的目录事件保留:`window/logMessage` 和 `window/showMessage` 的 type 1/2/3/4 分别为 ERROR/WARN/INFO/DEBUG,未知类型为 DEBUG。未分类的 stderr 是 DEBUG 排障证据,流名称不表示警告;实际的进程或协议失败由 `*.session.failed` 记录 ERROR,正常关闭仍是生命周期状态。 - 插件自身使用独立协商的 `litheLogging` 0 和 `lithe/log`,由 Core 把四种受控事实映射到插件目录事件,不能再用 stderr 或任意自由消息代替。协议字段、op、限额和 fixture 以 [插件契约](../../shared/plugins/contract/v1/README.md#structured-plugin-diagnostics) 为准。 -- 声明式贡献没有插件进程,不能发 `lithe/log`。实际执行它的一方通过 `diagnostics.recordPluginOperation` 代记每次尝试的一条终态,事件和通道与 SDK 插件相同:`plugins.operation.finished` 或 `plugins.operation.failed`,写入 `plugins/{plugin}/host`。平台层只上报观察到的阶段和耗时,级别和 `host.*` 失败类别只由 Core 按阶段决定;取消、停止和过期结果不记录。宿主当前代记下表四种贡献,唯一来源是 `rust/lithe-core/src/diagnostics/plugin_operations.rs` 的 `CONTRIBUTIONS`;输入、阶段到类别的对应和 -32064 见 [Rust Core API](../contracts/rust-core-api.md#engine-logging-v2-handoff-pr3)。 +- 声明式贡献没有插件进程,不能发 `lithe/log`。实际执行它的一方通过 `diagnostics.recordPluginOperation` 代记每次尝试的一条终态,事件和通道与 SDK 插件相同:`plugins.operation.finished` 或 `plugins.operation.failed`,写入 `plugins/{plugin}/host`。平台层只上报观察到的阶段和耗时,级别和 `host.*` 失败类别只由 Core 按阶段决定;取消、停止和过期结果不记录。宿主当前代记下表四种贡献,唯一来源是 `rust/crates/core/src/diagnostics/plugin_operations.rs` 的 `CONTRIBUTIONS`;输入、阶段到类别的对应和 -32064 见 [Rust Core API](../contracts/rust-core-api.md#engine-logging-v2-handoff-pr3)。 | operation | 声明来源 | 记录方 | 可能的失败阶段 | | --- | --- | --- | --- | @@ -108,9 +108,9 @@ Swift 的事件值是**未经脱敏的内存输入**,不能自行序列化落 ## 八、辅助 crate -- `rust/lithe-git-host`、`rust/lithe-ide-host` 和 `rust/lithe-remote` 的客户端链接进 Core,各自通过 `failure_log` 模块交出失败事实,依赖方向保持不变。sink 未注入时只增加原子计数,不写 stderr。 +- `rust/crates/git-host`、`rust/crates/ide-host` 和 `rust/crates/remote` 的客户端链接进 Core,各自通过 `failure_log` 模块交出失败事实,依赖方向保持不变。sink 未注入时只增加原子计数,不写 stderr。 - Core 的 `diagnostics/helper_failures` 是唯一的安装处。JSON dispatcher、独立 ACP FFI open、直接 IDE dispatcher 和 AskPass 入口在调用辅助 crate 前都经过它的 `Once`。sink 只转换标量字段,之后走相同的目录校验、脱敏和 256 条 Core 队列。这些事件的 owner 都是 `lithe-core`,错误只保留固定摘要和类别。 -- 辅助 crate 的收尾只记录丢失数据、能力或清理结果的意外错误。已断开的连接、已退出的进程,以及远程关闭或取消时的 Disconnected、Timeout,在类型化辅助函数里豁免;ACP Cancel 的 InternalError 无法区分正常断连与序列化失败,按预期缺失豁免。转发 accept 与 bridge 失败可能逐连接发生,目录 rate 为 12;`rust/lithe-remote/src/client/forward.rs` 在发送侧让每一族失败在进程内每 5 秒最多记录一条,并发转发连接也共用这个限制,正常断连不占日志配额。强制终止后进程仍未退出的最终超时保留 WARN。 +- 辅助 crate 的收尾只记录丢失数据、能力或清理结果的意外错误。已断开的连接、已退出的进程,以及远程关闭或取消时的 Disconnected、Timeout,在类型化辅助函数里豁免;ACP Cancel 的 InternalError 无法区分正常断连与序列化失败,按预期缺失豁免。转发 accept 与 bridge 失败可能逐连接发生,目录 rate 为 12;`rust/crates/remote/src/client/forward.rs` 在发送侧让每一族失败在进程内每 5 秒最多记录一条,并发转发连接也共用这个限制,正常断连不占日志配额。强制终止后进程仍未退出的最终超时保留 WARN。 ## 九、目录遍历与清理事件 @@ -158,7 +158,7 @@ Rust 通过静态 `EVENTS`(按 ID 排序)和二分查找的 `event_by_id` ## 十二、用法门禁 -`scripts/logging/verify-log-usage.mjs` 扫描 `macos/Sources`、`rust/lithe-core/src`、`rust/lithe-git-host/src`、`rust/lithe-ide-host/src` 和 `rust/lithe-remote/src`。排除 `rust/lithe-remote/src/server/`、`rust/lithe-remote/src/bin/` 和 `rust/lithe-ide-host/src/bin/`:它们在远端主机或独立进程中运行,stderr 由宿主进程处理,以后单独迁移。 +`scripts/logging/verify-log-usage.mjs` 扫描 `macos/Sources`、`rust/crates/core/src`、`rust/crates/git-host/src`、`rust/crates/ide-host/src` 和 `rust/crates/remote/src`。排除 `rust/crates/remote/src/server/`、`rust/crates/remote/src/bin/` 和 `rust/crates/ide-host/src/bin/`:它们在远端主机或独立进程中运行,stderr 由宿主进程处理,以后单独迁移。 门禁只扫描生产代码:词法上遮蔽注释和字符串内容,排除 `Tests/`、`tests/`、`tests.rs`、文件名以 `_tests.rs` 结尾的 Rust 文件,以及明确标注 `#[cfg(test)]` 或 `#[cfg(all(test, …))]` 的项。它只检查列出的直接写法,不跨文件追踪别名或动态调用。规则分两类: diff --git a/scripts/rust-core/README.md b/scripts/rust-core/README.md index 66f68c3f..b5b11475 100644 --- a/scripts/rust-core/README.md +++ b/scripts/rust-core/README.md @@ -2,7 +2,10 @@ Run `scripts/rust-core/verify-rust-core-comments.sh` from any directory. It checks module documentation, English comments, unsafe API safety sections, exported -Rustdoc, and intra-doc links in `lithe-core`, `lithe-core-rules` and `lithe-ai`. +Rustdoc, and intra-doc links in every crate under `rust/crates/`. A crate in the +script's `missing_docs_pending` list keeps every check except `missing_docs`; each +entry names the issue that adds the missing documentation and is removed when +that crate passes. The small `comment-lexer` helper uses pinned `rustc_lexer` tokens to distinguish comments from ordinary, raw, and byte string literals. It does not parse source diff --git a/scripts/rust-core/verify-rust-core-comments.sh b/scripts/rust-core/verify-rust-core-comments.sh index 9ab5f96d..d5d8013d 100755 --- a/scripts/rust-core/verify-rust-core-comments.sh +++ b/scripts/rust-core/verify-rust-core-comments.sh @@ -6,10 +6,14 @@ ROOT_DIR="$(cd -- "$SCRIPT_DIR/../.." && pwd)" # Keep this helper, Rustdoc and subsequent checks in one native build-state # directory. A desktop worktree supplies its own existing Cargo target. export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT_DIR/.artifacts/rust-core-checks}" -# lithe-core-rules is part of Core and holds reusable editor/UI rules; lithe-ai holds the -# ai.* commands. -SOURCE_DIRS=("$ROOT_DIR/rust/lithe-core/src" "$ROOT_DIR/rust/lithe-core-rules/src" "$ROOT_DIR/rust/lithe-ai/src") +# Every crate under rust/crates follows the same comment rules, so a new crate is +# covered as soon as it joins the workspace. cd "$ROOT_DIR" +crate_manifests=(rust/crates/*/Cargo.toml) +SOURCE_DIRS=() +for manifest in "${crate_manifests[@]}"; do + SOURCE_DIRS+=("$ROOT_DIR/${manifest%Cargo.toml}src") +done rust_files=() production_files=() @@ -106,12 +110,27 @@ fi # Let Rust understand visibility instead of treating pub items in private # modules as exported APIs. This covers public functions, types, variants, and # fields without requiring documentation for every internal helper. -for manifest in rust/lithe-core/Cargo.toml rust/lithe-core-rules/Cargo.toml rust/lithe-ai/Cargo.toml; do +# +# Crates listed here still lack public documentation. They keep the link check +# but skip missing_docs until the linked issue lands; remove an entry once its +# crate passes, and never add a crate to make a new gap pass. +missing_docs_pending=( + # https://github.com/1lck/Lithe-IDEA/issues/1863 + rust/crates/remote/Cargo.toml +) +for manifest in "${crate_manifests[@]}"; do + lints=(-D rustdoc::broken_intra_doc_links) + pending=false + for entry in "${missing_docs_pending[@]}"; do + [[ "$entry" == "$manifest" ]] && pending=true + done + if [[ "$pending" == false ]]; then + lints+=(-D missing_docs) + fi cargo rustdoc --quiet \ --manifest-path "$manifest" \ --lib -- \ - -D missing_docs \ - -D rustdoc::broken_intra_doc_links + "${lints[@]}" done printf '%s\n' "Rust Core comment verification passed" diff --git a/shared/plugins/contract/v1/README.md b/shared/plugins/contract/v1/README.md index a1af66c2..7ac177af 100644 --- a/shared/plugins/contract/v1/README.md +++ b/shared/plugins/contract/v1/README.md @@ -37,8 +37,8 @@ This directory is the cross-platform source of truth: | `fixtures/marketplace/` | Marketplace index, availability, source URL, and install review golden cases | Validation and template expansion are implemented once in Rust Core -(`rust/lithe-core/src/plugins/`, with build systems in -`rust/lithe-core/src/build/`) and exposed through the +(`rust/crates/core/src/plugins/`, with build systems in +`rust/crates/core/src/build/`) and exposed through the `plugins.declarative.*` commands in [`rust/contracts/rust-core-api.md`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/contracts/rust-core-api.md). Hosts must not reimplement them. @@ -2659,7 +2659,7 @@ same plugin, for example from that plugin's own window, and another plugin can call only an [exported function](#cross-plugin-calls). Functions complement the typed domain protocols; they never replace them. The protocol is implemented in -Rust Core (`rust/lithe-core/src/lsp/interface/plugin_function.rs`, +Rust Core (`rust/crates/core/src/lsp/interface/plugin_function.rs`, `function_relay.rs`). A host starts every build provider process as a session of the plugin that owns it and invokes its functions from that plugin's web pages (the diff --git a/shared/plugins/contract/v1/toolchains/README.md b/shared/plugins/contract/v1/toolchains/README.md index 0540dd7a..92cec321 100644 --- a/shared/plugins/contract/v1/toolchains/README.md +++ b/shared/plugins/contract/v1/toolchains/README.md @@ -417,10 +417,10 @@ total time, and reports skipped work as diagnostics rather than a missing tool. Production-shape examples are [tool-definition.plugin.json](../fixtures/toolchains/tool-definition.plugin.json) and [toolchain-provider.plugin.json](../fixtures/toolchains/toolchain-provider.plugin.json). Core acceptance vectors are in -[toolchain_definitions.rs](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/tests/toolchain_definitions.rs), +[toolchain_definitions.rs](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/tests/toolchain_definitions.rs), with sibling pins/query/resolution suites. The pin document, query exchange and one error reply per stable code that those suites share are inline in -[toolchain_vectors.rs](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/tests/toolchain_vectors.rs). +[toolchain_vectors.rs](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/tests/toolchain_vectors.rs). Passing them is not native product verification. Contract changes land in the same pull request as the Core code that enforces them; there is no other copy to update. diff --git a/shared/plugins/reference/capabilities-and-versions.md b/shared/plugins/reference/capabilities-and-versions.md index ee24555f..0b6dab66 100644 --- a/shared/plugins/reference/capabilities-and-versions.md +++ b/shared/plugins/reference/capabilities-and-versions.md @@ -6,7 +6,7 @@ 本页把插件会碰到的所有版本号放在一起:`pluginAPIVersion`、清单格式、18 个能力、进程协议和文档格式。**它们现在的版本全部是 `0`。** 规范以 [`contract/v1/README.md`](../contract/v1/README.md) 的 [Versioning](../contract/v1/README.md#versioning)、[Capabilities](../contract/v1/README.md#capabilities)、[Host capabilities](../contract/v1/README.md#host-capabilities) 和 [Publishing](../contract/v1/README.md#publishing) 为准;本页与契约不一致时以契约为准,并请到 [Lithe-core-rust 的 Issues](https://github.com/Lithe-IDEA/Lithe-core-rust/issues) 反馈。 -Core 列以本仓库 `main` 上的 Core 源码为准([`capabilities.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/plugins/capabilities.rs) 的 `SUPPORTED_CAPABILITIES`,[`declarative.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/plugins/declarative.rs) 的 `SUPPORTED_PLUGIN_API_VERSIONS`);Lithe 桌面端列以桌面端的[声明与说明](https://github.com/1lck/Lithe-IDEA/blob/preview/desktop/internal/pluginhost/pluginhost.go)为准。Core 能校验不等于宿主能运行:桌面端声明了 12 个能力,另外 6 个没有声明,需要它们的插件不会被提供安装。 +Core 列以本仓库 `main` 上的 Core 源码为准([`capabilities.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/plugins/capabilities.rs) 的 `SUPPORTED_CAPABILITIES`,[`declarative.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/plugins/declarative.rs) 的 `SUPPORTED_PLUGIN_API_VERSIONS`);Lithe 桌面端列以桌面端的[声明与说明](https://github.com/1lck/Lithe-IDEA/blob/preview/desktop/internal/pluginhost/pluginhost.go)为准。Core 能校验不等于宿主能运行:桌面端声明了 12 个能力,另外 6 个没有声明,需要它们的插件不会被提供安装。 ### 四类版本号 @@ -109,7 +109,7 @@ Node.js SDK 0.5.0、Java SDK 0.5.0 和 Rust SDK 0.4.0 说的是版本 `0` 的协 This page puts every version number a plugin meets in one place: `pluginAPIVersion`, the manifest format, the 18 capabilities, the process protocols, and the document formats. **Every one of them is `0`.** The normative text is [Versioning](../contract/v1/README.md#versioning), [Capabilities](../contract/v1/README.md#capabilities), [Host capabilities](../contract/v1/README.md#host-capabilities), and [Publishing](../contract/v1/README.md#publishing) in [`contract/v1/README.md`](../contract/v1/README.md). Where this page disagrees with the contract, the contract wins; please report it in the [Lithe-core-rust issues](https://github.com/Lithe-IDEA/Lithe-core-rust/issues). -The Core column follows the Core source on this repository's `main` (`SUPPORTED_CAPABILITIES` in [`capabilities.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/plugins/capabilities.rs), `SUPPORTED_PLUGIN_API_VERSIONS` in [`declarative.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/plugins/declarative.rs)); the Lithe desktop column follows the desktop client's [declarations and notes](https://github.com/1lck/Lithe-IDEA/blob/preview/desktop/internal/pluginhost/pluginhost.go). Validating a capability is not running it: the desktop client declares 12 capabilities and does not declare the other 6, so a plugin that needs one of those is not offered for installation. +The Core column follows the Core source on this repository's `main` (`SUPPORTED_CAPABILITIES` in [`capabilities.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/plugins/capabilities.rs), `SUPPORTED_PLUGIN_API_VERSIONS` in [`declarative.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/plugins/declarative.rs)); the Lithe desktop column follows the desktop client's [declarations and notes](https://github.com/1lck/Lithe-IDEA/blob/preview/desktop/internal/pluginhost/pluginhost.go). Validating a capability is not running it: the desktop client declares 12 capabilities and does not declare the other 6, so a plugin that needs one of those is not offered for installation. ### Four kinds of version diff --git a/shared/plugins/reference/domains/toolchains.md b/shared/plugins/reference/domains/toolchains.md index e13ea89d..5e318d6f 100644 --- a/shared/plugins/reference/domains/toolchains.md +++ b/shared/plugins/reference/domains/toolchains.md @@ -147,7 +147,7 @@ | [`toolchains/toolchain-provider.plugin.json`](../../contract/v1/fixtures/toolchains/toolchain-provider.plugin.json) | 生产形态的版本管理器提供者(`mise`):覆盖多个工具,监视项目版本文件(`.tool-versions` 用兼容读取器),后端是包内可执行文件 | | [`run/tool-reference-launch.plugin.json`](../../contract/v1/fixtures/run/tool-reference-launch.plugin.json) | 清单顶层 `requiresTools` 列出插件自己定义的 `interpreter`,语言服务器的 `runtime` 启动按这个工具定义 ID 引用运行时 | -Core 的验收测试在主仓库的 [`toolchain_definitions.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/tests/toolchain_definitions.rs) 和同目录的 `toolchain_pins.rs`、`toolchain_queries.rs`、`toolchain_resolution.rs`。这三个测试共用的固定值文档、查询往返和每个稳定失败码的错误回复内联在 [`toolchain_vectors.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/tests/toolchain_vectors.rs) 里。 +Core 的验收测试在主仓库的 [`toolchain_definitions.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/tests/toolchain_definitions.rs) 和同目录的 `toolchain_pins.rs`、`toolchain_queries.rs`、`toolchain_resolution.rs`。这三个测试共用的固定值文档、查询往返和每个稳定失败码的错误回复内联在 [`toolchain_vectors.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/tests/toolchain_vectors.rs) 里。 ### 相关指南 @@ -301,7 +301,7 @@ When a plugin starts a process by tool-definition ID (a launch plan with `launch | [`toolchains/toolchain-provider.plugin.json`](../../contract/v1/fixtures/toolchains/toolchain-provider.plugin.json) | A production-shaped version-manager provider (`mise`): several tools, watched project version files (`.tool-versions` through the compatible reader), with a packaged backend | | [`run/tool-reference-launch.plugin.json`](../../contract/v1/fixtures/run/tool-reference-launch.plugin.json) | `requiresTools` lists the plugin's own `interpreter` definition, and a language server's `runtime` launch references the runtime by that tool-definition ID | -The Core acceptance tests are in [`toolchain_definitions.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/tests/toolchain_definitions.rs), with `toolchain_pins.rs`, `toolchain_queries.rs`, and `toolchain_resolution.rs` beside it. The fixture documents, query round trips, and the error reply for each stable failure code shared by these tests are inlined in [`toolchain_vectors.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/tests/toolchain_vectors.rs). +The Core acceptance tests are in [`toolchain_definitions.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/tests/toolchain_definitions.rs), with `toolchain_pins.rs`, `toolchain_queries.rs`, and `toolchain_resolution.rs` beside it. The fixture documents, query round trips, and the error reply for each stable failure code shared by these tests are inlined in [`toolchain_vectors.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/tests/toolchain_vectors.rs). ### Related guides diff --git a/shared/plugins/reference/protocol-changelog.md b/shared/plugins/reference/protocol-changelog.md index 1c44dd0a..07df8627 100644 --- a/shared/plugins/reference/protocol-changelog.md +++ b/shared/plugins/reference/protocol-changelog.md @@ -2,7 +2,7 @@ 本页记录插件协议和 API 的每次修改:哪天、哪个 PR、谁改的、改了什么。只有中文。 -- **收录范围**:Lithe-core-rust 仓库 `main` 分支上的 PR,只要它修改了下面三处中的任意一处:插件契约 `shared/plugins/contract/v1/`、Core 能力表 [`capabilities.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/plugins/capabilities.rs)、插件函数协议 [`plugin_function.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/lithe-core/src/lsp/interface/plugin_function.rs)。三处都没改的 PR 不收录。 +- **收录范围**:Lithe-core-rust 仓库 `main` 分支上的 PR,只要它修改了下面三处中的任意一处:插件契约 `shared/plugins/contract/v1/`、Core 能力表 [`capabilities.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/plugins/capabilities.rs)、插件函数协议 [`plugin_function.rs`](https://github.com/Lithe-IDEA/Lithe-core-rust/blob/main/rust/crates/core/src/lsp/interface/plugin_function.rs)。三处都没改的 PR 不收录。 - **日期**:PR 合入 `main` 的日期。 - **修改人**:PR 的作者(GitHub 账号)。 - **每一版的内容和宿主现状**:见[能力与协议版本对照](capabilities-and-versions.md)。字段和行为以 [`contract/v1/README.md`](../contract/v1/README.md) 为准。 @@ -143,7 +143,7 @@ ## 维护 -修改 `shared/plugins/contract/v1/`、`rust/lithe-core/src/plugins/capabilities.rs` 或 `rust/lithe-core/src/lsp/interface/plugin_function.rs` 的 Core PR,在**同一个 PR** 里更新本页: +修改 `shared/plugins/contract/v1/`、`rust/crates/core/src/plugins/capabilities.rs` 或 `rust/crates/core/src/lsp/interface/plugin_function.rs` 的 Core PR,在**同一个 PR** 里更新本页: 1. 把这个 PR 补到时间线最上面(按合入日期分组):PR、修改人、API 编号、协议 / 能力、改了什么。新增的版本号要加粗,并写进“按协议查首次出现”里对应的表:例如给 `buildProviders` 加版本 `1`,就在能力表里为它加一行,并在进程协议表里同步 `litheBuild`。一个 PR 只给一个能力加一个版本。 2. “API 编号”填这个 PR 涉及的全部 API-01–44 编号,取自 PR 描述里的“原计划编号”。PR 没写时按 [API 实施计划](https://github.com/1lck/Lithe-IDEA/blob/preview/docs/development/macos-plugin-api-plan.md) 判断,不要自编新号;不属于任何编号的写 —。 diff --git a/shared/plugins/scripts/sdk-e2e.mjs b/shared/plugins/scripts/sdk-e2e.mjs index cfd2d330..51019719 100644 --- a/shared/plugins/scripts/sdk-e2e.mjs +++ b/shared/plugins/scripts/sdk-e2e.mjs @@ -4,7 +4,7 @@ // node shared/plugins/scripts/sdk-e2e.mjs // // The scenario files are Cargo integration tests of lithe-core, declared in -// rust/lithe-core/Cargo.toml behind the `plugin-sdk-e2e` feature, so a plain +// rust/crates/core/Cargo.toml behind the `plugin-sdk-e2e` feature, so a plain // `cargo test` skips them. This script builds the sample backends and then // runs those tests, which exercise the Node.js, Java and Rust SDKs, the native // build workflows and shortcut import against Core at this working tree. diff --git a/shared/plugins/sdk/e2e/plugin_sdk/mod.rs b/shared/plugins/sdk/e2e/plugin_sdk/mod.rs index 959967c4..5585f9d3 100644 --- a/shared/plugins/sdk/e2e/plugin_sdk/mod.rs +++ b/shared/plugins/sdk/e2e/plugin_sdk/mod.rs @@ -10,7 +10,7 @@ //! registration, and state recovery across a restart. Both samples answer it //! identically, which keeps the SDKs' behaviour aligned. //! -//! `rust/lithe-core/Cargo.toml` declares these files as lithe-core +//! `rust/crates/core/Cargo.toml` declares these files as lithe-core //! integration tests behind the `plugin-sdk-e2e` feature, and //! `shared/plugins/scripts/sdk-e2e.mjs` builds the samples and runs them; //! `LITHE_PLUGIN_SDK_ROOT` names the `shared/plugins` directory that holds diff --git a/shared/plugins/sdk/java/plugin-sdk/src/main/java/io/github/litheidea/plugin/sdk/Protocol.java b/shared/plugins/sdk/java/plugin-sdk/src/main/java/io/github/litheidea/plugin/sdk/Protocol.java index 3d0aeb15..5daa8364 100644 --- a/shared/plugins/sdk/java/plugin-sdk/src/main/java/io/github/litheidea/plugin/sdk/Protocol.java +++ b/shared/plugins/sdk/java/plugin-sdk/src/main/java/io/github/litheidea/plugin/sdk/Protocol.java @@ -6,7 +6,7 @@ /** * Wire constants and validation shared with Lithe's Rust Core - * ({@code rust/lithe-core/src/lsp/interface/plugin_function.rs} in the Lithe + * ({@code rust/crates/core/src/lsp/interface/plugin_function.rs} in the Lithe * repository) and the Node.js * SDK. The SDK checks the same rules locally so a plugin author sees a mistake * when registering a handler instead of as a refused session at runtime. diff --git a/shared/plugins/sdk/node/src/protocol.mjs b/shared/plugins/sdk/node/src/protocol.mjs index df13e4da..5e0ca0ae 100644 --- a/shared/plugins/sdk/node/src/protocol.mjs +++ b/shared/plugins/sdk/node/src/protocol.mjs @@ -1,6 +1,6 @@ // Wire constants and validation shared with Lithe's Rust Core -// (rust/lithe-core/src/lsp/interface/plugin_function.rs and -// rust/lithe-core/src/vcs/ in the Lithe repository). The SDK checks the +// (rust/crates/core/src/lsp/interface/plugin_function.rs and +// rust/crates/core/src/vcs/ in the Lithe repository). The SDK checks the // same rules locally so a plugin author sees a mistake when registering a // handler instead of as a refused session at runtime. diff --git a/shared/plugins/sdk/rust/plugin-sdk/src/protocol.rs b/shared/plugins/sdk/rust/plugin-sdk/src/protocol.rs index 05c1b745..9f057b95 100644 --- a/shared/plugins/sdk/rust/plugin-sdk/src/protocol.rs +++ b/shared/plugins/sdk/rust/plugin-sdk/src/protocol.rs @@ -1,5 +1,5 @@ //! Wire constants and validation shared with Lithe's Rust Core -//! (`rust/lithe-core/src/lsp/interface/plugin_function.rs` in the Lithe +//! (`rust/crates/core/src/lsp/interface/plugin_function.rs` in the Lithe //! repository). The SDK checks the same rules locally so a plugin author sees //! a mistake when declaring a function instead of as a refused session.