Skip to content

feat(build): 构建检测跳过工作区的忽略路径,默认跳过所有以 . 开头的目录 - #35

Merged
xiaoyumuxi merged 2 commits into
mainfrom
feat/build-ignored-paths
Nov 14, 2026
Merged

xiaoyumuxi merged 2 commits into
mainfrom
feat/build-ignored-paths

Conversation

@xiaoyumuxi

Copy link
Copy Markdown
Contributor

关联

  • 用户反馈:希望在构建选项里加一个忽略路径的配置,默认忽略所有以 . 开头的目录里的目标。feat(execution): 构建检测和运行项发现跳过被 Git 忽略的目录 #33 已经让检测跳过被 Git 忽略的目录,但没写进 .gitignore 的点目录(工具状态、缓存、代理工作树副本等)仍会被当成构建根目录。
  • 合入后,桌面端另开 PR:在 Build 选项弹窗里编辑这份列表,并把 scripts/desktop/build-desktop-core.sh 的 PINNED_CORE_REVISION 升到合并提交。

这个 PR 做什么

1. 忽略路径的语义(lithe_execution::IgnoredPaths)

规则 行为
语法 .gitignore 语法,相对工作区根,一条一个规则;只对目录生效(扫描在列出目录之前剪枝,所以 *.txt 这类文件规则不起作用)
匹配 和单个忽略文件一样,最后一条匹配的规则说了算;中间带 / 的规则锚定在工作区根,其它规则匹配任意深度的目录名(.* 是所有以 . 开头的目录)
和 Git 的关系 先于 Git 规则判断:命中忽略就跳过,命中 ! 就保留(即使 Git 忽略了它),都没命中再交给 Git 规则
不变的部分 共享扫描策略排除的缓存和构建输出(target、node_modules、.git 等)照样跳过;工作区根本身从不参与匹配
作用范围 只作用于 build.detect。自动运行项发现、指纹扫描和 Node 清单发现都不变

新增 scan_run_workspace_ignoring 和 detectors::scan_ignoring;原来的 scan 改为传一个空的 IgnoredPaths,行为不变。

2. 存储与分层(build crate 新增 ignored_paths 模块)

  • 团队文档 .lithe/build/options.json 和本机构建选项的 document 新增可选字段 ignoredPaths: [pattern]。
  • 本机列表整份替换团队列表;两处都没有时用 Core 的默认值 [".*"]。[] 是明确的“不额外忽略”。
  • build.resolveStoredOptions 的 storage 新增 ignoredPaths: { patterns, source },source 是 local、team 或 default;合并后的 document 也带上生效的 ignoredPaths。
  • 新增宿主命令 build.editIgnoredPaths { document, local, patterns }(不需要清单):数组替换本机列表,null 删除本机列表、回到团队或默认值。patterns 必须给出,避免漏传被当成重置。返回 edit: { local, ignoredPaths },只读团队文档,不做 I/O。
  • build.detect 新增可选请求字段 ignoredPaths:省略或 null 用默认值,宿主传 storage.ignoredPaths.patterns。

3. 校验与错误码

  • 新增 plugin.build.invalidIgnoredPath(一码一义),field 为 ignoredPaths[<序号>],指向第一条不被接受的规则,宿主可以据此标出行号。
  • 不被接受的规则包括:空字符串、首尾有空白、注释(# 开头)、单独的 !、含控制字符、ignore crate 解析不了的 glob(如 [z-a])、超过 1024 字节、第 257 条起。全部能解析但合起来编译失败时,field 是 ignoredPaths。
  • build.editIgnoredPaths 和 build.detect 返回这个错误码。文档里已经存了不可用的列表时,整份文档仍报 plugin.build.invalidOptionsDocument,和其它坏值一致,不会悄悄回退到默认值。

4. 文档

  • rust/contracts/build-project-options-v1.schema.json 新增 ignoredPaths(本机 schema 通过 $ref 复用)。
  • rust/contracts/rust-core-api.md:命令列表、扫描策略段落、Build 命令表(build.detect、build.projectOptions、build.resolveStoredOptions,以及新增的 build.editIgnoredPaths 行)。
  • 契约 README 的 detection 一行、构建系统参考页中英两张表:说明检测还会跳过忽略路径,默认是所有以 . 开头的目录,用户可以用 ! 放回。
  • 协议更新记录 2026-11-14 加一行(API 编号 —,pluginAPIVersion 0 内的补充)。build.editIgnoredPaths 是宿主调用 Core 的命令,不是插件可调用的宿主方法,所以不涉及 API 总表和能力版本。

5. 顺带修复:remote 启动锁测试偶发失败(单独提交 4edfec7)

跑全量测试时,server::daemon::identity_tests::startup_lock_is_exclusive_bounded_and_released_on_drop 失败了一次,单独运行时通过。原因:同一测试二进制里的其它测试会启动子进程,fork 出的子进程在 exec 之前持有锁文件描述符的副本,也就持有 flock。测试释放锁后立刻用当前时刻做期限重新加锁,正好碰上这段窗口就会 TimedOut。现在释放后的重新加锁最多等 5 秒(走生产代码已有的有界轮询),独占和超时两条断言不变。

测试

测试 覆盖
workspace_scan::tests::ignored_paths_decide_before_git_and_the_last_matching_pattern_wins [".*"] 剪掉所有点目录;!.config、!generated 覆盖默认值和 Git 规则,/tools 只锚定根下的 tools;空列表与普通扫描一致
workspace_scan::tests::an_ignored_path_list_names_the_first_entry_that_is_not_a_pattern 合法列表(含 \#literal、a/**/b);空、首尾空白、注释、单独 !、! spaced、换行、[z-a] 各自报出正确序号
tests::build_systems::detection_skips_the_ignored_paths_and_by_default_every_dot_directory 经分发器跑 build.detect:省略和 null 时跳过 .cache、.config;[] 时点目录重新出现;! 放回 Git 忽略的 generated;坏规则返回 plugin.build.invalidIgnoredPath 和 ignoredPaths[1]
tests::build_project_options::ignored_paths_resolve_by_layer_and_local_edits_replace_or_remove_the_list default / team / local 三种来源;编辑替换、[]、null 删除后回到团队值;五类坏输入的字段序号(含超长和第 257 条);缺少 patterns 字段被拒绝;文档里存了坏列表时报 invalidOptionsDocument

验证

命令(在 rust/) 结果
cargo test --workspace --no-fail-fast 通过(lithe-core 单测 782);修复前 remote 锁测试在全量运行中失败一次,修复后 lithe-remote 33 个单测通过
cargo clippy --workspace --all-targets -- -D warnings 无告警
cargo fmt --all -- --check 通过
scripts/rust-core/verify-rust-core-comments.sh(仓库根) 通过
node shared/plugins/scripts/verify-docs.mjs(仓库根) 通过

没有改插件后端协议,没有跑 sdk-e2e.mjs。只在 macOS 上运行;Windows 上的路径匹配靠 ignore crate 处理,没有实机验证。

- 同一测试二进制里的其它测试会启动子进程。fork 出的子进程在 exec 之前持有锁文件描述符的副本,因此也持有锁,释放后立即用当前时刻做期限重新加锁会偶发 TimedOut。
- 释放后的重新加锁改为最多等待 5 秒;独占和超时两条断言不变。
- 构建选项新增 ignoredPaths:.gitignore 语法,相对工作区根,只对目录生效,最后一条匹配的规则说了算。它可以写在团队文档 .lithe/build/options.json 或本机构建选项里,本机的整份替换团队的;两处都没有时用 Core 的默认值 [".*"],即所有名字以 . 开头的目录(如 .claude/worktrees)。
- 这些规则先于 Git 规则判断,所以 !pattern 能放回被 Git 忽略的目录;共享扫描策略排除的缓存和构建输出仍然跳过。只作用于 build.detect,自动运行项发现、指纹扫描和 Node 清单发现不变。
- lithe-execution 新增 IgnoredPaths 和 scan_run_workspace_ignoring / scan_ignoring;build.detect 新增可选 ignoredPaths 请求字段,省略或为 null 时用默认值,[] 表示不额外忽略。
- build.resolveStoredOptions 返回 ignoredPaths: { patterns, source },source 为 local、team 或 default。
- 新增宿主命令 build.editIgnoredPaths { document, local, patterns }:替换本机列表,null 删除本机列表,回到团队或默认值;patterns 字段必须给出。
- 新增错误码 plugin.build.invalidIgnoredPath,字段为 ignoredPaths[<序号>],指向第一条不被接受的规则:空、首尾有空白、注释、单独的 !、控制字符、无法解析的 glob、超过 1024 字节,或第 257 条起。文档里存了不可用的列表时,整份文档仍报 plugin.build.invalidOptionsDocument。
- 同步更新 build-project-options-v1 schema、rust-core-api.md、契约 README 的 detection 说明、构建系统参考页(中英)和协议更新记录。
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review November 14, 2026 05:41
@xiaoyumuxi
xiaoyumuxi merged commit d19e9ef into main Nov 14, 2026
5 checks passed
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