Skip to content

feat(core): 八组 Viva 宿主规则移进 Core(项目树、编辑分组、插件生命周期、工作树、Git 分组、代理排除、停止等待) - #30

Merged
xiaoyumuxi merged 7 commits into
refactor/core-split-logging-workspacefrom
feat/core-sink-viva-rules
Nov 14, 2026
Merged

xiaoyumuxi merged 7 commits into
refactor/core-split-logging-workspacefrom
feat/core-sink-viva-rules

Conversation

@xiaoyumuxi

@xiaoyumuxi xiaoyumuxi commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

关联 Issue

Refs 1lck/Lithe-IDEA#1800、1lck/Lithe-IDEA#1806、1lck/Lithe-IDEA#1814、1lck/Lithe-IDEA#1817、1lck/Lithe-IDEA#1829、1lck/Lithe-IDEA#1830、1lck/Lithe-IDEA#1842、1lck/Lithe-IDEA#1847(Lithe-IDEA 侧的“需要沉入内核”八张单)。这几张单在桌面端的跟进 PR 里关闭;本 PR 只负责 Core 这一侧。

本 PR 叠在 #28(refactor/core-split-logging-workspace)上,base 就是 #28 的分支,diff 里只有本 PR 新增的 7 个提交。#28 合入后,本 PR 会自动改到 main 为目标。

背景

Viva 桌面端(Go)里还留着八组本该由 Core 决定的规则:停止等待时间的上下限、代理排除项的写法、Git 改动文件按目录分组、工作树状态与新建对话框、插件启用与卸载步骤、编辑分组的拆分与拖放、项目树可见行与多选。宿主各写一份,将来换 UI 壳子时还得再写一份。这次把它们都移进 Core,宿主只负责 I/O 和绘制。

新增的规则都放在独立的小 crate 里,纯计算、不读磁盘,可以并行编译。crate 总数从 46 个增加到 50 个。

改动

按提交列出:

  • d0b05d1 processLifecycle.resolve 返回 gracefulStopRule([Feature] 停止等待时间的默认值与上下限由 Core 公开,桌面端不再三次探测推导 1lck/Lithe-IDEA#1830)
    • 返回停止等待时间的 { defaultSeconds, minSeconds, maxSeconds },与 resolve 共用同一组常量。
    • 设置页不再用三个越界值探测推导上下限。
    • fixture:rust/fixtures/process-lifecycle/*。
  • 964c7e6 Core 解析代理排除项([Feature] 代理排除列表的写法解释与匹配下沉到 Core,netproxy 不再自行实现 1lck/Lithe-IDEA#1829)
    • network.proxyPolicy 新增 exclusionRules,按 host、suffix、ip、cidr、local 五种规则解析。
    • 新增 invalidExclusions:哪种写法都不是的条目。
    • 契约写明网络栈要做的比较:地址只在同一地址族内比较,忽略 IPv6 zone。
    • 新 fixture rust/fixtures/network/proxy-bypass-v1.json 固定哪些主机直连。
  • e760c23 新命令 git.changedFileGroups([Feature] 将 Viva Git Log 提交改动文件的文件夹分组下沉到 Core 1lck/Lithe-IDEA#1814)
    • 提交、stash、shelf 的改动文件按最后一个 / 之前的目录分组,顶层目录是 ""。
    • 目录按段比较,文件按项目树的自然顺序排序(lithe_core_rules::file_names),所以 v0.1.4 排在 v0.1.12 前面。
    • 返回请求里 paths 的下标,宿主继续用自己的文件记录。
    • 新 fixture rust/fixtures/git/changed-file-groups-v1.json。
  • 110a209 工作树状态、可用操作和新建预览([Feature] 将 Viva 工作树操作的可用性、状态和新建建议路径下沉到 Core 1lck/Lithe-IDEA#1817)
    • git.worktrees 给每个工作树返回状态(missing、locked、modified、current、available)、允许的写操作和被禁止的原因。
    • 新增 countChanges:一次列出里统计每个检出的本地改动数。
    • 新命令 git.worktreeCreationPreview:给出新建对话框的可选项、占用的引用、清理后的分支名、建议目录和是否可以创建。
    • fixture:rust/fixtures/git/worktree-*.json 和 worktrees-v1.json。
  • 612986a 新命令 plugins.installed.lifecycle,新 crate lithe-plugin-lifecycle([Feature] Viva 插件生命周期规则(启用选择、卸载清理与停止顺序)仍在 Go 平台层,应迁入 Rust Core 1lck/Lithe-IDEA#1842)
    • 输入已安装版本、用户的启用选择和动作(确认安装、启用、禁用、卸载)。
    • 返回每个插件的启用状态,以及宿主要按顺序执行的步骤:记录或清除选择、停止程序、逐个删除版本和它的批准记录、删除状态目录。
    • 规则:没有选择就是禁用;确认安装只在还没有选择时启用;禁用先记录再停止;卸载先停止再清理。
    • 对未安装的插件执行动作时返回 plugin.lifecycle.notInstalled(新错误码,没有和别的情况共用)。
    • fixture:rust/fixtures/plugins/installed-lifecycle.json。
    • 这是宿主内部命令,不属于插件契约,没有改 shared/plugins/contract/v1/、能力版本或插件函数协议。
  • e09a931 新命令 editor.groupLayout.reduce / editor.groupLayout.dropTargets,新 crate lithe-editor-layout([Feature] 将编辑分组的共享状态转换迁入 Rust Core 1lck/Lithe-IDEA#1806)
    • 分组状态和分栏树一起归约。支持 editor.workbenchState.reduce 的全部动作,另加 openTab、dropTab、removeEmptyGroups;分组离开状态时,它的叶子自动从树里移除。
    • 落点过期返回 stale,规则拒绝返回 refused,两种情况都原样返回状态和树。
    • dropTargets 在拖动开始时给出每个分组接受的落点:标签条、主体边缘分栏、主体中间追加,以及空编辑区。
    • 分栏比例、像素和拖动过程留在宿主。新分栏和新分组的编号由宿主给出。
    • fixture:rust/fixtures/editor/group-layout-v1.json。
  • 5efe90b 新命令 workspace.rowSelection.reduce 和 workspace.projectTree.rows,新 crate lithe-row-selection、lithe-project-tree([Feature] 将 Viva 项目树可见行和导航规则下沉到 Rust Core 1lck/Lithe-IDEA#1800)
    • rowSelection.reduce:路径行的多选。
      • 普通点击清掉标记;Cmd/Ctrl 点击切换标记并设为锚点;Shift 点击从锚点标到点击行。
      • 根节点永远不会被标记。点到已经消失的行返回 stale。
      • targets 给出批量操作的对象,去掉已标记文件夹里面的路径。
      • 项目树和变更列表共用这一套。
    • projectTree.rows:宿主按先序发送已加载的节点,Core 返回:
      • 可见行;
      • 修正后的选择(节点消失或被折叠时移到最近的可见上级);
      • 视口顶端行的新行号;
      • targets。
    • projectTree.rows 只在树的形状变化时调用,不是每帧调用。
    • fixture:rust/fixtures/workspace/project-tree-rows-v1.json、row-selection-v1.json。

每条新命令都在 rust/contracts/rust-core-api.md 的命令表里登记了,写明来自哪个 crate。

不在本 PR 范围内

验证

在本 PR head 5efe90b 上运行:

命令 平台 结果
cargo fmt --all -- --check(rust/) macOS 通过
./scripts/rust-core/verify-rust-core-comments.sh macOS 通过
cargo clippy --locked --workspace --all-targets -- -D warnings macOS(aarch64-apple-darwin) 通过
cargo clippy --locked --workspace --all-targets --target x86_64-pc-windows-msvc -- -D warnings 在 macOS 上交叉检查 Windows target 通过
cargo test --locked --workspace macOS 全部通过,没有失败或忽略
node shared/plugins/scripts/verify-docs.mjs macOS 通过
node shared/plugins/scripts/sdk-e2e.mjs macOS Node、Java、Rust 三个 SDK 的示例后端全部通过
桌面端 desktop-go.sh vet / test,指向本分支 macOS 通过(54 个包 ok),见 1lck/Lithe-IDEA#1888

未能执行的检查:没有在 Windows 实机上运行 cargo test,只做了 Windows target 的 clippy 交叉检查。

…Rule

设置页读取 gracefulStopRule { defaultSeconds, minSeconds, maxSeconds },不再用三个越界值探测推导(Lithe-IDEA #1830)。规则与 resolve 共用同一组常量。
network.proxyPolicy now returns exclusionRules, the exclusion entries as
host, suffix, ip, cidr and local rules, and invalidExclusions, the entries
with none of the forms. The contract states the exact comparison a network
stack applies, addresses compared within their family and an IPv6 zone
ignored, and rust/fixtures/network/proxy-bypass-v1.json pins which hosts
go direct, so hosts no longer parse the entries themselves.
…tural order

The changed-file lists of a commit, a stash and a shelf grouped their files
in the desktop client with path.Dir and a byte comparison. Core now owns the
grouping: a file belongs to the folder before its last slash, the top being
"", folders sort segment by segment and files by name in the project tree's
natural order (lithe_core_rules::file_names), a folder right before its
subfolders. The response carries indices into the request's paths so hosts
keep their own file records. Shared fixture rust/fixtures/git/changed-file-groups-v1.json.

Refs Lithe-IDEA/Lithe-IDEA#1814
git.worktrees now gives each worktree its state (missing, locked, modified,
current, available) and the writes it allows with the reason a write is
blocked; countChanges counts the local changes of every checkout in the same
listing. git.worktreeCreationPreview derives the dialog's choices, held
reference, cleaned branch name, suggested destination and readiness, so the
desktop no longer keeps its own copy of these rules (Lithe-IDEA#1817).
新 crate lithe-plugin-lifecycle:输入已安装版本、用户的启用选择和动作(确认安装、启用、
禁用、卸载),返回每个已安装插件的启用状态和宿主按顺序执行的步骤(记录/清除选择、停止
程序、逐个删除版本并清除其批准记录、删除状态目录)。没有选择即禁用;确认安装只在没有
选择时启用;禁用先记录再停止;卸载先停止,再删除全部版本、清除选择和状态。对未安装插件
的动作返回 plugin.lifecycle.notInstalled。契约写入 rust-core-api.md,共享用例在
rust/fixtures/plugins/installed-lifecycle.json。

Refs 1lck/Lithe-IDEA#1842
新增纯规则 crate lithe-editor-layout,公开两条命令:

- editor.groupLayout.reduce:在分组状态和分栏树上一起执行一次转换。
  支持 editor.workbenchState.reduce 的全部动作,以及 openTab、dropTab、
  removeEmptyGroups;分组离开状态时,叶子自动从树中移除。
  拖放落点过期返回 stale,规则拒绝返回 refused,两种情况都按原样返回状态和树。
- editor.groupLayout.dropTargets:拖动开始时给出每个分组可接受的落点
  (标签条、主体边缘分栏、主体中间追加),以及空编辑区是否可接受。

分栏比例、像素和拖动过程留在宿主;Core 只接收树的形状。新分栏使用宿主
提供的编号,新分组使用宿主提供的 ID。契约、fixture 和测试同步补齐。

Refs 1lck/Lithe-IDEA#1806
新增两个纯规则 crate,公开两条命令:

- workspace.rowSelection.reduce(lithe-row-selection):路径行的多选。
  普通点击选中并清掉标记和锚点;Cmd/Ctrl 点击切换标记并设为锚点;Shift
  点击从锚点(没有锚点时从选中行)标记到点击行,保留其他标记;clear 结束
  批量操作。根节点永远不会被标记。点击已经消失的行返回 stale。targets 给出
  批量操作的对象:去掉已标记文件夹里面的路径。项目树和变更列表共用。
- workspace.projectTree.rows(lithe-project-tree):宿主按先序发送已加载
  节点(深度、是否展开)、选择和视口顶行路径;Core 返回可见行、修复后的选择
  (节点消失或被折叠时移到最近的可见上级)、顶行的新行号和 targets。不读
  磁盘,只在树形变化时调用,不在每帧调用。

契约、fixture 和测试同步补齐。

Refs 1lck/Lithe-IDEA#1800
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review November 14, 2026 03:01
@xiaoyumuxi
xiaoyumuxi merged commit dfab9c5 into refactor/core-split-logging-workspace Nov 14, 2026
5 checks passed
@xiaoyumuxi

Copy link
Copy Markdown
Contributor Author

本 PR 在 #28 合入 main 之后才合入,合进的是 #28 原来的分支,没有进 main。同样的代码已从 main 重新提交为 #31。

xiaoyumuxi added a commit that referenced this pull request Nov 14, 2026
…#30) (#31)

* feat(process): processLifecycle.resolve 返回停止等待时间的默认值与上下限 gracefulStopRule

设置页读取 gracefulStopRule { defaultSeconds, minSeconds, maxSeconds },不再用三个越界值探测推导(Lithe-IDEA #1830)。规则与 resolve 共用同一组常量。

* feat(network): read proxy exclusion entries in Core

network.proxyPolicy now returns exclusionRules, the exclusion entries as
host, suffix, ip, cidr and local rules, and invalidExclusions, the entries
with none of the forms. The contract states the exact comparison a network
stack applies, addresses compared within their family and an IPv6 zone
ignored, and rust/fixtures/network/proxy-bypass-v1.json pins which hosts
go direct, so hosts no longer parse the entries themselves.

* feat(git): git.changedFileGroups groups changed files by folder in natural order

The changed-file lists of a commit, a stash and a shelf grouped their files
in the desktop client with path.Dir and a byte comparison. Core now owns the
grouping: a file belongs to the folder before its last slash, the top being
"", folders sort segment by segment and files by name in the project tree's
natural order (lithe_core_rules::file_names), a folder right before its
subfolders. The response carries indices into the request's paths so hosts
keep their own file records. Shared fixture rust/fixtures/git/changed-file-groups-v1.json.

Refs Lithe-IDEA/Lithe-IDEA#1814

* feat(git): worktree states, allowed writes and creation preview in Core

git.worktrees now gives each worktree its state (missing, locked, modified,
current, available) and the writes it allows with the reason a write is
blocked; countChanges counts the local changes of every checkout in the same
listing. git.worktreeCreationPreview derives the dialog's choices, held
reference, cleaned branch name, suggested destination and readiness, so the
desktop no longer keeps its own copy of these rules (Lithe-IDEA#1817).

* feat(core): 新增 plugins.installed.lifecycle,插件启用与卸载规则由 Core 持有

新 crate lithe-plugin-lifecycle:输入已安装版本、用户的启用选择和动作(确认安装、启用、
禁用、卸载),返回每个已安装插件的启用状态和宿主按顺序执行的步骤(记录/清除选择、停止
程序、逐个删除版本并清除其批准记录、删除状态目录)。没有选择即禁用;确认安装只在没有
选择时启用;禁用先记录再停止;卸载先停止,再删除全部版本、清除选择和状态。对未安装插件
的动作返回 plugin.lifecycle.notInstalled。契约写入 rust-core-api.md,共享用例在
rust/fixtures/plugins/installed-lifecycle.json。

Refs 1lck/Lithe-IDEA#1842

* feat(editor-layout): 编辑分组与分栏树的状态转换下沉到 Core

新增纯规则 crate lithe-editor-layout,公开两条命令:

- editor.groupLayout.reduce:在分组状态和分栏树上一起执行一次转换。
  支持 editor.workbenchState.reduce 的全部动作,以及 openTab、dropTab、
  removeEmptyGroups;分组离开状态时,叶子自动从树中移除。
  拖放落点过期返回 stale,规则拒绝返回 refused,两种情况都按原样返回状态和树。
- editor.groupLayout.dropTargets:拖动开始时给出每个分组可接受的落点
  (标签条、主体边缘分栏、主体中间追加),以及空编辑区是否可接受。

分栏比例、像素和拖动过程留在宿主;Core 只接收树的形状。新分栏使用宿主
提供的编号,新分组使用宿主提供的 ID。契约、fixture 和测试同步补齐。

Refs 1lck/Lithe-IDEA#1806

* feat(project-tree): 项目树可见行与多选规则下沉到 Core

新增两个纯规则 crate,公开两条命令:

- workspace.rowSelection.reduce(lithe-row-selection):路径行的多选。
  普通点击选中并清掉标记和锚点;Cmd/Ctrl 点击切换标记并设为锚点;Shift
  点击从锚点(没有锚点时从选中行)标记到点击行,保留其他标记;clear 结束
  批量操作。根节点永远不会被标记。点击已经消失的行返回 stale。targets 给出
  批量操作的对象:去掉已标记文件夹里面的路径。项目树和变更列表共用。
- workspace.projectTree.rows(lithe-project-tree):宿主按先序发送已加载
  节点(深度、是否展开)、选择和视口顶行路径;Core 返回可见行、修复后的选择
  (节点消失或被折叠时移到最近的可见上级)、顶行的新行号和 targets。不读
  磁盘,只在树形变化时调用,不在每帧调用。

契约、fixture 和测试同步补齐。

Refs 1lck/Lithe-IDEA#1800
@xiaoyumuxi
xiaoyumuxi deleted the feat/core-sink-viva-rules branch November 14, 2026 04:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant