Skip to content

feat(macos): 补齐提交文件操作、批量回滚确认与初始布局 - #1591

Merged
xiaoyumuxi merged 7 commits into
previewfrom
codex/commit-file-context-actions
Oct 30, 2026
Merged

xiaoyumuxi merged 7 commits into
previewfrom
codex/commit-file-context-actions

Conversation

@xiaoyumuxi

@xiaoyumuxi xiaoyumuxi commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

背景

补齐 Commit 面板缺少的批量回滚和文件上下文动作,并调整首次打开工作区时的侧栏、底部工具窗口尺寸。交互参考 IDEA Community 公开源码;复用 Lithe 既有 Git Core、VCS Provider 契约和原生共享控件,不新增独立 SVN 命令执行器。

功能改动

批量回滚与确认

  • Commit 和 Worktrees 复用现有回滚按钮,先打开可重新勾选文件的“回滚更改”确认窗口,确认后才修改文件。
  • 工具栏限定当前 ChangeList:优先纳入已暂存文件,其次使用高亮多选,均没有时纳入当前列表全部文件;右键按其上下文目标初始化。
  • 确认窗口的勾选独立于真实 Git 暂存区,支持分组三态选择;取消、关闭、空选择均不会回滚。
  • 回滚同时恢复所选文件的暂存区与工作区;新增文件默认保留本地副本,仅在明确勾选删除后移除。覆盖部分暂存、意向新增、重命名、删除和复制来源保护。
  • 工作树动作固定到对应根目录;忙状态、取消、工作区代次和请求身份检查隔离过期操作,首错停止并刷新状态。

文件右键菜单

  • 补齐“提交文件、回滚、显示差异、在新标签页显示差异、删除、添加到 VCS”。右键已选集合中的行作用于该集合,右键集合外的行只作用于被点击文件;行高亮不冒充提交勾选。
  • “提交文件”准备所选 ChangeList 的准确暂存范围、取消无关文件暂存,保留所选文件已部分暂存的内容,验证后聚焦提交消息;不会绕过用户确认直接提交,也不覆盖消息或 amend 状态。
  • 普通差异入口保留标签复用,“在新标签页显示差异”显式创建新标签。插件差异使用占位标签及标签级任务所有权,关闭标签或切换工作区后拒绝迟到结果。
  • 隐藏但保留的原生编辑器宿主不再接收输入、命中测试或无障碍焦点。

VCS 插件与删除安全

  • “添加到 VCS”对未版本化文件按真实所属 Provider 派发排序、去重的 .add 批次;Git 使用暂存入口,SVN 等插件使用自己的文件操作能力,能力不足时禁用。
  • 插件已跟踪文件通过 Provider .delete 删除并记录版本操作;Git 或未版本化文件使用 macOS 废纸篓。确认窗口区分两类后果,Provider 失败不会退回磁盘删除。
  • 删除使用不可变、单次消费的确认请求;同步待处理编辑器输入后重新校验,拒绝未保存内容、根外路径、根目录自身及危险的嵌套仓库/歧义根目标。
  • 校验符号链接父路径、目录后代和最新仓库发现;取消、替换、重复确认、工作区切换及状态/根发现过期均不能重放旧请求。只关闭成功删除的干净文档。

初始布局与配套维护

  • 左侧栏默认宽度由 320pt 调整为 360pt,“修订提交(上一次)”保持一行;底部工具窗口默认约占可用分隔区域的 28%。
  • 统一模型、视图及预览使用的布局默认值;保留原有最小尺寸、拖拽行为和已保存的工作区尺寸,不强制重置已有布局。
  • 补齐共享中英文词条并提交生成结果;更新回滚、上下文动作、差异标签和布局 Agent Notes,以及五项相关跨平台能力记录。
  • 不修改插件公开契约、不新增下载/缓存资源、不写入已安装程序包。

首轮功能验证(daf0b3ff5)

  • Swift 6.3.3 下 506 项不同的受影响 Swift 测试通过(主回归 467 项,布局回归 39 项),另有重叠的最终确认及资源宿主复测;无失败、超时或硬性能预算超限。
  • 真实临时 Git 仓库与 linked worktree 集成:批量恢复、未选文件不变、部分暂存、新增保留/删除、复制来源、重命名/删除及嵌套仓库保护。
  • Provider 测试替身:真实菜单回调、精确添加/删除批次、能力不足、嵌套/歧义根、取消、互斥和迟到结果隔离。
  • 带当前字体、图标和语言资源的临时原生宿主:中英文 × 深浅色的提交区域、回滚、废纸篓删除和 VCS 删除;核对 16 张截图及本地化无障碍值。临时宿主和相关进程均已清理。
  • ./.agents/skills/write-stable-tests/scripts/verify-test-stability.sh
  • node scripts/i18n/verify-app-language-localization.mjs
  • node scripts/i18n/generate-i18n.mjs --check
  • node --test --test-timeout=60000 scripts/i18n/test-i18n.mjs(35 项)
  • ./scripts/architecture/verify-service-boundaries.sh
  • ./scripts/architecture/verify-shared-contracts.sh
  • ./scripts/macos/verify/verify-runtime-bundle-immutability.sh
  • ./scripts/agent-notes/verify-agent-notes.sh
  • ./scripts/platform-feature-matrix/verify-platform-feature-matrix-change.sh origin/preview HEAD
  • ./scripts/platform-feature-matrix/verify-platform-feature-matrix.sh
  • git diff --check

逐项计时、HTML/JUnit 和复现命令已在本地验证报告中保留。最慢的新增原生回滚测试聚合四个语言/主题场景为 6.324s,未超过 15s 硬预算。提交前同步的最新 preview 仅包含 README/截图更新,51 个任务文件与已验证快照逐字节一致。

后续修复:删除残留与回滚延迟(36866d6b2)

根因与行为

  • 原生废纸篓只移走磁盘文件,不改变 Git 索引。已暂存新增文件会留下 AD 状态,所以单纯刷新仍会看到绿色行;本轮只对确认已缺失的所选新增项取消暂存,复制只处理目标。批次部分失败也清理已成功移走的新增项,保留未删除项、普通跟踪删除、源文件独立编辑及无关/部分暂存。
  • GitService 已把原生命令放在后台工作线程,并未发现 Git 子进程直接阻塞主线程。可见延迟来自等待顺序:命令后先解冻并等待项目树/项目服务/搜索与全仓库扫描,再做重复 Git 刷新;Core 的 discardAll 还会为每个所选文件扫描全库未跟踪状态。
  • 暂存、取消暂存、文件/区块丢弃、删除、提交文件准备和回滚统一先确认本次涉及仓库的真实状态,再释放监听。Commit、Worktrees 及相应 Diff 先更新;项目树和服务沿用 Workspace 持有、可取消的合并刷新任务,不再让无关仓库、Stash 或历史拖住操作。
  • 回滚普通跟踪文件直接用 discardAll 恢复 HEAD 的索引和磁盘,去掉多余取消暂存;只有新增文件先取消暂存。Core 只查询所选字面路径,复用 porcelain v2 解析器、按命令行预算分批,并保护特殊文件名、重命名源及“暂存删除 + 保留副本”同路径状态。
  • 增加每根请求身份、全局状态版本和工作区代次保护:较早全量/局部/目录读取不能恢复旧行;同根按实际命令完成顺序确认;一根被替代不跳过同批其他根;父/固定 checkout 模型保持各自展开状态及已加载历史/cursor。读取失败保留旧行和未确认勾选,并显示共享中英文错误。
  • 同步更新四篇所属 Agent Note、三项能力记录与生成语言资源。不新增公开 API、插件契约、依赖、下载或缓存目录。

本轮验证

  • Swift 6.3.3 + macOS 26.5 SDK:287 项测试 / 18 suites,包含真实临时 Git/linked worktree、删除部分失败、复制来源保护、有界控制的竞争写入/旧刷新/多根与目录展开回归。无失败、超时或硬预算超限。
  • 逐项隔离计时的 1,380 项 Core 测试通过;五项新增回滚集成每项 224–290ms,验证命令范围、磁盘与索引及未选文件不变,不以测试时间宣称产品延迟数值。
  • Rust-only 完整门禁:Core、Git/Agent/IDE Host、MCP、集成和文档测试;Core 注释、布局与针对性格式检查通过。
  • Swift bridge 门禁:C ABI/链接符号、46 个 LSP Provider、12 项本地 Git/HTTP/AskPass 集成、9 项额外 Swift 桥接测试通过。桥接探针使用本地 SDK 解析适配来固定 26.5,未修改仓库验证脚本。
  • verify-core.sh、稳定性静态检查、i18n 完整性/生成检查与 35 项测试、服务边界、共享契约、运行时程序包只读边界、Windows 源码边界、170 篇 Notes、213 项功能矩阵及 git diff --check 通过。
  • 提交后以精确 PR merge-base d3072abd45faaccc4b6a33f3507b5f8b5622afde 和 HEAD 运行平台能力变更门禁,并核对 origin/preview。

本轮没有重新执行完整工作台人工性能验收、真实 SVN 插件端到端或 Windows 原生测试;矩阵验证状态保持 pending,不沿用旧提交 CI 作为新提交验证。逐项 HTML/JUnit/JSON、命令及验证边界保存在本地 commit-refresh-validation 报告。

后续修复:已打开面板实时刷新与回滚按钮(222b512a6)

根因与行为

  • 外部普通文件事件原来只登记待刷新标记,Git 刷新排在项目树、搜索索引及项目服务重载之后。慢速项目导入会拖住已经打开的 Commit 面板,后续事件取消原任务时还可能丢掉最后一次刷新;不是 Git 子进程直接在主线程运行。
  • 同一批文件事件现在分别调度既有的 Git 与项目内容合并任务,各自持有取消和合并生命周期。写操作完成后的非等待式监听恢复也同时调度这两项,不因存在项目路径就跳过 Git;不新增轮询或第二个 watcher。
  • 恢复流程确认监听配置及快照后先读 Git,再准备项目服务。尚无快照的批次由重建负责本次读取,避免前后重复读同一批状态。
  • 在途读取用请求身份及工作区代次保护:取消期间登记的新请求仍会补读,旧工作区读取完成不能释放新读取;等待解冻的旧任务也不能取走新工作区尚待处理的文件批次。工作区切换、模块释放和重置会取消各自拥有的任务。
  • canRollbackChanges 不再仅因后台全量纯读取就禁用回滚。暂存待确认、提交及其他写操作的互斥条件保持不变;确认继续验证最新已知文件状态及请求身份,写入后的版本保护拒绝较早读取把已回滚行加回来。固定 checkout 模型复用同一规则。
  • 同步更新 Git 执行架构、回滚确认两篇所属 Note 和提交/工作树两项能力记录;不修改公开 API、插件契约、依赖、运行时资源或下载/缓存目录,本轮无新增界面文案。

本轮验证

  • Swift 6.3.3 + macOS 26.5 SDK:577 个不同测试函数 / 32 suites 全部通过(主回归 491 / 24,额外工作区回归 86 / 8,无重叠)。无失败、超时、停滞、未完成或 15 秒硬预算超限。
  • 在同一个已挂载的真实 ChangesSidebarView 中,以临时真实 Git、Rust Core 和 MacDirectoryWatcher 验证外部修改、新建、删除自动更新模型及原生无障碍行;暂存后阻塞 Stash 只读,原生回滚按钮仍启用,真实鼠标事件打开正确纳入集合,取消后真实索引保持不变。
  • 有界 gate 覆盖慢项目重载与写操作恢复期间独立 Git 刷新、连续文件批次、取消读取保留待处理请求、旧工作区不得释放新读取、旧解冻不得吞掉新文件批次;模块回归另验证回滚期间的旧读取不能恢复已消失的行。
  • 已检查逐项 HTML/JUnit 及合并模块健康报告。新增原生集成测试 2.818s,其他本轮改变的受控回归各 1ms;共有 12 项真实 Git/监听集成超过 1 秒预警,最慢 2.977s,无硬预算超限。测试时间包含夹具和 I/O,不是产品回滚延迟指标。
  • 最终稳定性静态检查、服务边界、共享契约、运行时程序包只读边界、共享 i18n 完整性/生成检查及 35 项 i18n 测试、171 篇 Notes、213 项能力矩阵及 diff 检查全部通过。
  • 提交后以精确 PR 基线 d3072abd45faaccc4b6a33f3507b5f8b5622afde → 222b512a68c158a84bdc3f755afc247b96e16e0c 运行能力变更门禁,并以更新后的 origin/preview 再次核对。9 个提交文件与验证快照逐项哈希一致。

本轮未重新运行此前 Core 全量测试,也不将此前 1,380 项结果算作本轮验证。完整工作台人工端到端、大型仓库实测延迟、真实 SVN 插件及 Windows 原生验证仍未执行,相关矩阵保持 pending。测试窗口/子面板、观察器和任务已清理,用户原工作区已暂存的 LICENSE 未触碰。两组 HTML/JUnit/JSON、原始日志、命令及门禁输出保存在本地 commit-live-refresh-validation 报告。

合并 preview 后的最终验证(953ce95fc)

合并与测试宿主修正

  • 在 7229d6d9b 合入 preview f3ee7114f,解决三份共享 i18n 源文件及工作台能力记录的冲突。按词条/键进行语义三方合并,保留双方独立改动、证据与追加的验证要求,再重新生成语言资源;核对 28,716 个 catalog 叶子,不以整份 ours/theirs 覆盖另一边。
  • 9 个实时刷新修复文件与已推送的 222b512a6 逐字节一致。最终提交 953ce95fc 只修正一个合入后的 LSP 原生挂载测试及所属 Note,不改变产品 LSP 行为,也不让设置根树订阅工作区通知。
  • 首轮合并回归为 719 个函数中 718 通过、1 个 LSP 参数化测试失败。相同二进制开启可选截图时通过、关闭时再次失败:命令行测试宿主没有持续的 AppKit 绘制轮次,模型通知不足以驱动 SwiftUI 新的 .task(id:),截图意外掩盖了这一测试调度缺口。
  • 测试使用 5 秒单调截止时间驱动非阻塞原生绘制并让出执行器,仍通过真实页面任务生成摘要;不手工加载、不放宽断言、不增加真实 sleep 或稳定性豁免。关闭可选截图后,完整回归及三次独立进程复测均通过。历史失败、编译异常及截图对照日志单独保留,不计入最终成功汇总。

最终结果

  • Swift 6.3.3 + macOS 26.5 SDK:732 个不同测试函数 / 45 个 suites 全部通过,覆盖原批量回滚、删除、Provider 菜单、初始布局,以及实时监听、工作区/设置/编辑器入口和上游分隔条变更的受影响范围。没有失败、跳过、超时、停滞、未完成或 15 秒硬预算超限。
  • 同一个已挂载 Commit 面板完成真实外部修改/新建/删除及后台只读时可回滚的原生交互回归;最终 2.878s。受控的旧读取、取消、跨工作区和慢项目重载回归通过;不把夹具/I/O 测试耗时当成产品延迟指标。
  • 最终完整回归中的 LSP 参数化挂载测试为 249ms;另有 30 项聚焦验证、三次各 5 项复测通过,均与主回归重叠,不叠加到 732。三次挂载测试分别为 349、365、388ms。
  • 已打开最终 HTML 并检查失败、模块健康和优化队列:12 项超过 1 秒预警,其中 11 项真实 Git/监听集成、1 项为 16 场景的编辑器 Diff 入口测试;最慢 2.878s,无硬预算超限。
  • 稳定性静态检查、服务边界、共享契约、发行资源只读边界、Rust Core 注释、Windows 源码边界全部通过。
  • 共享 i18n 完整性与生成一致性(中英文各 9,571/9,571)、35 项 i18n 测试、172 篇 active Notes、214 项能力矩阵及生成视图、27 项资源复用脚本测试通过。
  • 精确 PR 基线 d3072abd45faaccc4b6a33f3507b5f8b5622afde → 最终 HEAD,以及 origin/preview → 最终 HEAD 的能力变更门禁通过;diff/补丁检查及 61 个 PR 文件的提交内容哈希核对通过。

最终本地报告为 commit-live-refresh-merged-validation,包含 732 项独立总览、HTML/JUnit/JSON、原始日志、聚焦复测、历史诊断和门禁。未重跑此前的全量 1,380 项 Core 测试,不以其充当本轮结果;也不把合入 preview 的上游功能宣称为全产品验收通过。

验证边界与评审注意

  • 本次新增入口针对 macOS;没有宣称 Windows UI 同步完成,平台矩阵保留真实状态。
  • 真实 SVN 插件端到端流程和完整产品人工验收尚未执行;Provider 测试替身和原生组件测试不能替代它们。
  • 多文件回滚/删除不是跨文件事务;失败或取消前可能已完成前面的文件。已进行的一次原生废纸篓调用不能中途撤销,但取消后不会继续派发后续文件。
  • 已保存的布局优先,测试新默认尺寸需使用没有保存布局的工作区。
  • PR 已处于 ready 状态,保持不变。实时刷新修复 222b512a6 已推送;本轮将必要的 preview 冲突合并与测试宿主修正完成本地验证后集中推送,不为观察 CI 反复 push。最终提交的 GitHub 检查以其自身状态为准,旧提交上的成功结果不等同于新提交已通过。

@ghfind-review ghfind-review Bot added the review: medium ghfind author score; see https://ghfind.com label Oct 29, 2026
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review October 29, 2026 16:44
@lithe-code-review

lithe-code-review Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Lithe Review

结论: ⚠️ 有建议
范围: preview ← codex/commit-file-context-actions · head: daf0b3f

未发现需要阻塞合并的问题。发现两处 P2 目录删除边界问题。

Findings

  1. [P2] Git 删除检查应包含已发现的歧义根
    macos/Sources/Lithe/Models/AppModel/AppModel+GitOperations.swift:136

    • 实际影响:整目录移入废纸篓时,会连带移走已经被识别为归属不明的嵌套工作副本。
    • 触发条件:所选未跟踪目录包含 vcsProvidersFeature.ambiguous 中的目录,且该目录没有可被 Git 发现的仓库。
    • 复现步骤:让 Git 显示未跟踪目录摘要 folder/,Provider 根发现将 folder/nested 报告为两个非 Git Provider 的歧义根;对 folder/ 执行删除并确认。这里仅合并 Git 根和 Provider 的 roots,遗漏独立保存的 ambiguous;后续 deleteCommitFiles 也只重新发现 Git 仓库,因此仍会执行整目录 Trash。
    • 来源:本次引入的新删除入口。
  2. [P2] 插件目录删除前应重新发现仓库根
    macos/Sources/Lithe/Application/Features/VcsProvidersFeatureModel.swift:681

    • 实际影响:确认期间新出现的独立仓库可能随父目录一起移入废纸篓。
    • 触发条件:打开未版本化目录的删除确认后,目录内部新增仓库,而后台根发现尚未更新。
    • 复现步骤:在 SVN 工作副本中,对未版本化目录 folder 打开删除确认,然后在其已有子目录执行 Git 初始化,再确认删除。owns 将缓存的 allRootIDs 传给 planner.owners;实际实现调用的 vcs.ownerOf 只对传入路径列表计算归属,不读取磁盘。缓存列表未变时检查通过,随后 trash 将整个目录交给原生删除流程。
    • 来源:本次引入的新插件文件操作;异步归属计算没有提供新的根发现结果。

Scope Check

  • 未找到可验证的关联 Issue;按 PR 声明范围核对。
  • 已检查提交准备、批量回滚、文件菜单、差异标签、删除流程、布局默认值及配套测试、i18n 源和 Notes。
  • 复用了现有 Git Core、Provider 协议和共享控件,未发现新增并行领域实现。
  • 两项 Finding 均属于本次新增删除流程的职责范围。

Suggestions

  1. Git 删除保护应纳入 ambiguous 对应的实际目录,补充父目录包含歧义根时拒绝删除的回归测试。
  2. 插件目录操作前执行有界的最新根发现,用返回的普通根、歧义根和截断状态重新验证目标及其后代;补充确认期间新增嵌套仓库的测试。
  3. 请在 PR 描述或评论附上受影响界面的截图;已有提交区域和布局提供前后对比。当前上下文没有附图,视觉效果尚未验证。

Summary

主要流程具有请求身份、忙状态和迟到结果保护,测试覆盖了部分暂存、复制来源及取消路径。建议补齐上述目录删除保护。

Verification

  • 静态检查指定 base...head 的变更,并追踪至 RustVcsOperations、vcs.ownerOf、Git 仓库发现及 Trash 适配器;未读取生成字符串表正文。
  • 作者报告 506 项受影响 Swift 测试及 i18n、架构、资源只读等检查通过;本次未独立执行或复核这些结果。
  • 提供的 head 检查中,Swift、Rust 和 Windows 主体测试为 skipped,部分 i18n 仍 queued;平台 gate success 不代表这些测试已运行。
  • 本次未运行任何代码、测试或应用,未访问网络。真实 SVN 端到端、完整工作台验收及界面截图仍缺验证证据。

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator Author

@lithe review

@lithe-code-review

lithe-code-review Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Lithe Review

结论: ⚠️ 有建议
范围: preview ← codex/commit-file-context-actions · head: 953ce95

未发现需要阻塞合并的问题。当前 head 仍存在两项 P2 删除边界问题。

Findings

  1. [P2] Git 目录删除保护应包含 Provider 歧义根
    macos/Sources/Lithe/Models/AppModel/AppModel+GitOperations.swift:136

    • 实际影响:删除未跟踪目录时,会连带将已识别但归属不明的嵌套工作副本移入废纸篓。
    • 触发条件:所选目录包含 vcsProvidersFeature.ambiguous 中的非 Git 根。
    • 复现步骤:让 Git 显示未跟踪目录摘要 folder/,Provider 发现将 folder/nested 记录为两个非 Git Provider 的歧义根,再删除 folder/。这里仅合并 Git 根和 Provider 的 roots,遗漏独立保存的 ambiguous;后续 deleteCommitFiles 只重新发现 Git 仓库,因此不能补上此保护。
    • 来源:本次引入的新删除入口。
  2. [P2] 插件目录删除前应重新发现仓库根
    macos/Sources/Lithe/Application/Features/VcsProvidersFeatureModel.swift:681

    • 实际影响:确认期间新出现的独立仓库可能随父目录一起移入废纸篓。
    • 触发条件:打开插件未版本化目录的删除确认后,其内部新增仓库,相关事件尚未触发根发现。
    • 复现步骤:在 SVN 工作副本中,对未版本化目录 folder 打开删除确认,在其已有子目录初始化 Git 仓库,再于根发现更新前确认。owns 将缓存的 allRootIDs 交给 planner.owners;实际的 vcs.ownerOf 只根据传入列表计算归属,不扫描磁盘。缓存未变时检查通过,随后原生 Trash 移走整个目录。
    • 来源:本次引入的新插件删除流程。

Scope Check

  • 未找到可验证的关联 Issue;按 PR 声明范围核对。
  • 已检查提交准备、批量回滚、文件菜单、差异标签、删除保护、实时刷新、布局默认值及相关测试、i18n 源和 Notes。
  • 复用了既有 Git Core、Provider 协议和共享控件,未发现新增并行领域实现。
  • 两项 Finding 均由本次改动引入,属于新增目录删除流程的职责范围;其余平台及人工验收仍有验证缺口。

Suggestions

  1. 将 Provider 歧义根转换为实际目录并纳入 Git 删除保护,补充父目录包含歧义根时拒绝删除的回归测试。
  2. 插件递归删除前复用现有根发现能力,以最新普通根、歧义根及截断状态重新校验目标和后代;补充确认期间新增嵌套仓库的测试。
  3. 请在 PR 描述或评论附上受影响界面的截图,已有提交区域和布局提供前后对比。作者提到本地截图,但提供的上下文未附图,视觉效果尚未验证。

Summary

主要流程具备请求身份、取消和过期结果保护,测试覆盖部分暂存、复制来源及竞争刷新等关键场景。建议补齐上述两处目录删除保护;上轮指出的两项边界问题在当前 head 中仍然存在。

Verification

  • 核对完整的 61 文件清单,静态审查固定 f3ee7114...953ce95f 差异,并追踪至 Git 仓库发现、RustVcsOperations、vcs.ownerOf 和原生 Trash;未读取生成资源正文。
  • 作者报告最终 head 的 732 个不同 Swift 测试函数及稳定性、i18n、架构、程序包只读边界等检查通过;本次未独立复核运行结果。此前 1,380 项 Core 结果属于较早提交。
  • 提供的 head 检查中,Windows 前端、共享 i18n、Notes 和矩阵检查成功;Swift、Rust Core、Windows Rust、插件检查仍在运行,arm64 发布包检查排队,真实 Windows JDT 与 Rust 远程工作区测试跳过。
  • 本次未运行代码、测试或应用,未访问网络。真实 SVN 端到端、完整工作台人工验收、大型仓库延迟及界面截图仍缺验证证据。

- Git 未跟踪目录删除的资格检查纳入 Provider 的歧义根,嵌套但未选定 VCS 的工作副本不再随父目录移入废纸篓
- Git 与插件的未版本化目录废纸篓删除在执行前有界地重新发现 Provider 根;结果与缓存不一致、被截断或失败时拒绝并触发重新发现
- 补充歧义根与确认期间新增嵌套根的回归测试,更新提交文件操作 Agent Note
@xiaoyumuxi
xiaoyumuxi merged commit 90b5339 into preview Oct 30, 2026
12 of 15 checks passed
1lck added a commit that referenced this pull request Oct 30, 2026
* perf(lsp): stop copying open documents and draining events on the main actor

The engine copied the whole client state for every request, document
change, and server message while holding the session locks. That state
holds the full text of every open document, so a jdtls project import,
which publishes thousands of messages, kept completion and navigation
waiting behind the copies. Open document text is now shared (Arc<str>,
still a plain JSON string), and each server message is parsed once,
outside the state lock, instead of up to three times.

macOS drained Core's event queue on the main actor every 10 ms while
requests were pending, waiting on the same session lock. The drain now
runs off the main actor; a send waits for a drain already in flight, so
a drain still never returns a reply before its operation is registered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(jdt): key the workspace on build structure and tune the jdtls JVM

The JDT -data fingerprint no longer includes build-file mtime or size.
jdtls already detects pom and Gradle script edits itself
(MavenProjectImporter.needsMavenUpdate, GradleProjectImporter.
checkGradlePersistence), so switching to a fresh -data directory on every
edit only turned an incremental update into a full re-import. The Gradle
wrapper distribution stays part of the key because jdtls does not check it.

jdtls now launches with the GC and logging defaults vscode-java and the
upstream CI use (ParallelGC with GCTimeRatio=4 and
AdaptiveSizePolicyWeight=90, -Xlog:disable, DetectVMInstallationsJob
disabled). A plugin option with the same key replaces each default, and a
plugin collector choice replaces ParallelGC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(matrix): record the JDT workspace key and jdtls JVM defaults

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(run): keep detected run configurations in memory, not in the workspace

Identifying a project wrote .lithe/run/generated.json, toolchains/
requirements.json, project.json and .gitignore into the user's workspace, and
Run and Debug stayed unavailable until the user pressed "Identify project".

Core now owns the detected layer:
- runConfig.generate stores its result per workspace in process memory
  (execution/generated_layer.rs); inspect, resolve, user-configuration id
  checks and toolchain diagnostics read it from there.
- An optional cacheDirectory records the result in the application cache so a
  new session can list JDT's previous Java entry points before JDT answers.
  A .lithe/run/generated.json left by older versions is only read as that
  seed, never written.
- resolve picks the default configuration (framework service first, else the
  first detected entry other than Current File) when project.json names none.
- selectJava derives the project JDK minimum from pom.xml / .java-version /
  the Maven wrapper before any generation.

Hosts stop writing detection files and identify automatically:
- Windows removes run_write_generated; the run store identifies a project on
  load when inspect reports missing, without the entry-count notice.
- macOS removes MacRunConfigurationStore.writeGenerated, passes the cache
  directory, identifies after the workspace snapshot is applied, and drops the
  "regenerate broken generated.json" action.
- UI copy no longer mentions generated.json (shared i18n regenerated).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(run): restore detected entries alongside saved tasks after restart

* Merge pull request #1568 from 1lck/codex/macos-global-style

feat(macos): 补齐全局编辑器样式与 VS Code/IDEA 语法配色

* Merge pull request #1567 from 1lck/codex/issue-1564-global-search

fix(search): 修复搜索布局并支持文件名优先展示与滚动自动分页

* feat(editor): 类方法跳转默认开启并新增 Java 关键字跳过查询设置 (#1561)

* feat(macos):完善类方法跳转与悬停导航交互

* fix(macos): 稳定慢查询期间的 Command 悬停光标

* fix(editor): present Java files after initial import folding

* fix(editor): delay Command hover hints and cancel pending hints on leave

* fix(editor): show Command navigation feedback before semantic lookup

* fix(editor): exclude non-code tokens from Command navigation

* fix(editor): color Java comment delimiters as comments

* feat(macos): preserve navigation toggle implementation for integration

* fix(macos): unify welcome actions and clone remote panels

* feat(java-support): own optional class and method navigation lifecycle

* fix(navigation): sync plugin opt-out across projects and preserve other providers

* fix(i18n): preserve catalog ordering after preview merge

* test: align Java generator host capabilities and pin Git fixture branch

* fix(remote): resolve daemon startup before attaching concurrent clients

* fix(windows): provide the optional Java requirements snapshot

* feat(editor): 类方法跳转默认开启并新增 Java 关键字跳过查询设置

- 撤销插件级 classMethodNavigation / editorNavigation 开关(设置、策略表、校验和契约 fixture)。F12、Command 点击、悬停提示和 implementation 回退对所有语言默认生效,由宿主统一实现。
- 新增宿主设置“Java 关键字不查询定义”(设置 → 编辑器,默认开启):关键字位置不再发送定义查询,避免语言服务器对 static、switch 等关键字等待约 7 秒。
- Java 库类跳转优先读取本地 -sources.jar(~/.m2、~/.gradle 缓存),找不到时回退到 JDT LS 反编译。
- 删除已废弃的开关截图,新增关键字设置截图。

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

* fix(matrix): 移除已删除的 editor-navigation fixture 证据路径

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

* fix(navigation): 仅对 jar 内库类异步查找 sources jar

非 jar 的虚拟文档保持同步请求语言服务器,避免选择器接受目标后的源码请求被推迟;
合并 preview 并修复 Java 实现选择器相关回归测试。

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

* fix(navigation): 撤回 sources jar 快速路径并保留 this/super 构造器跳转

- 撤回本地 sources jar 快速路径:文本与 JDT 返回的坐标不一定对应,且 jar 文件名无法确认依赖身份,统一回到语言服务器虚拟文档。
- Java 关键字过滤不再包含 this 和 super,它们对应构造器调用,仍会发送定义查询。

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

* test(macos): align rollback symlink assertion with document errors

* test(git): 为子模块测试的 git submodule add 放宽超时

Windows runner 上 git submodule add 克隆子模块超过辅助函数写死的 10 秒,
进程被取消,导致 watch_context_resolves_a_submodule_git_directory_outside_its_workspace
失败。该测试的时间预算已在 test-stability-windows.ps1 中放宽到 30 秒,
这里把命令超时与预算保持一致,其余 git 命令仍使用 10 秒。

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: lick <2188718831@qq.com>

* fix(run): 只将已确认的 Java 应用识别为 Spring 服务 (#1593)

* fix(run): require confirmed Java entries for Spring services

* docs(run): align launch boundary with confirmed Spring entries

* test(run): require confirmed services in persistence fixtures

* fix: 连续输入时刷新两端 LSP 补全候选 (#1592)

* fix(lsp): preserve completion refresh context across editor hosts

* fix(completion): type trigger mapping and adapter expectations

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* 统一 Java 启动准备并补齐保存到构建的同步 (#1594)

* Unify Java launch preparation and notify language servers after saves

* fix(windows): refresh buffers before launch save notifications

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): 启动反馈、Blame 闪烁、导入进度与全局 Maven 设置 (#1600)

* fix(windows): startup feedback, blame flicker, import progress and global Maven settings

- Agent host subprocesses (environment probe, subscription quota, MCP probe)
  start with CREATE_NO_WINDOW so the Agent panel no longer flashes consoles.
- Windows are created with the last applied theme background, stored in the
  app local data directory, instead of WebView2's white until first paint.
- Inline Git blame refreshes only for file or history changes, keeps the
  previous annotation while reloading, ignores index-only rewrites, and is
  off by default for new installs.
- The status bar shows Java import percentage, current module and download,
  then language-server background tasks; navigation during import reports
  the import progress and slow requests show a pending notice.
- The Maven settings page edits <localRepository> of the user's own
  ~/.m2/settings.xml without a project, with revision-checked writes.
- New "Import Java projects on open" setting: automatic, ask or manual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): honour the import policy in run discovery and translate Maven settings errors

- Automatic run-configuration generation on project load no longer starts
  the Java import when the user chose to be asked or to import manually; an
  explicit generate still starts it.
- The Maven user-settings host returns error codes that the settings page
  maps to translated messages; OS errors are shown inside a translated frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(windows): drive the Maven user settings draft through the injected picker

Typing relied on React's input-event plugin seeing this file's DOM, which
fails when another test file loaded react-dom first in the same process.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): serialize window background writes and keep linked settings.xml

- Windows applying a theme at the same moment shared one temporary file;
  writes now take turns under a process-wide lock.
- Saving the user Maven settings writes through a symlinked settings.xml
  instead of replacing the link with a regular file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): keep the shared navigation notice until the last slow request settles

Each navigation dismissed the shared "Finding…" notice when it finished,
hiding it while an earlier slow request still waited. The notice now counts
the requests showing it and closes after the last one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): drop background tasks when a language server process restarts

A recovered process never ends the previous process's work, so its tasks
would stay in the status bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(macos): 补齐提交文件操作、批量回滚确认与初始布局 (#1591)

* feat(macos): complete commit file actions and rollback confirmation

* fix(git): publish file mutations before workspace recovery

* fix(macos): refresh open commit panels independently of project reloads

* test(macos): drive native rendering while awaiting LSP snapshot updates

* fix(macos): 目录删除前避开 Provider 歧义根并重新发现仓库根

- Git 未跟踪目录删除的资格检查纳入 Provider 的歧义根,嵌套但未选定 VCS 的工作副本不再随父目录移入废纸篓
- Git 与插件的未版本化目录废纸篓删除在执行前有界地重新发现 Provider 根;结果与缓存不一致、被截断或失败时拒绝并触发重新发现
- 补充歧义根与确认期间新增嵌套根的回归测试,更新提交文件操作 Agent Note

* feat(macos): 设置页新增网络代理,支持跟随系统/不走代理/自定义服务器 (#1571)

* feat(macos): 设置页新增网络代理,支持跟随系统/不走代理/自定义服务器

新增「外观与行为 › 网络」设置页,管理 Lithe 自身 HTTP 流量的代理策略:

- 三档模式:跟随系统(默认,即现状行为)、不走代理(显式禁用)、自定义代理服务器
- 自定义档完整字段:代理类型(HTTP/SOCKS5)、服务器地址、端口、
  可选用户名与密码(密码存 Keychain,经 SecureStore 端口读写,
  不入偏好存储)、逗号分隔的排除列表(kCFNetworkProxiesExceptionsList)
- 测试连接:经端口 NetworkProxyChecking 由 MacNetworkProxyTester 执行,
  HEAD github.com、10 秒有界超时,成功显示耗时或失败显示原因
- 统一接入点 MacNetworkSessionProvider:按 NetworkProxyPreferences
  快照缓存会话,配置变化时旧会话 finishTasksAndInvalidate;提供 applyPolicy
  供自带超时的稳定版回滚下载复用同一策略;自定义未填完整时按跟随系统处理
- 四个 URLSession 出口接入:插件市场传输与下载、GitHub 传输、AI HTTPS 传输、
  MacStableRollback;三个传输的 session 参数改为按请求解析的 sessionProvider,
  设置变化对新请求生效,无需重建服务
- 明确不接管并在设置页说明:Sparkle 更新(框架无会话注入 API,
  SPUDownloader 写死 defaultSessionConfiguration,天然跟随系统代理)、
  AI 明文 HTTP 的 NWConnection 分支、终端 git/Agent 子进程、JVM 依赖下载
- 新增 NetworkProxySettingsTests(16 例)与 MacNetworkSessionProviderTests;
  更新 SettingsSidebarLayoutTests;词条进 shared/i18n 真源并重新生成;
  功能矩阵新增 network-proxy-settings(macOS implemented/pending,
  Windows platform-specific)

* feat(macos): 网络代理自定义配置增加重置按钮

与保存成对:放弃未保存的草稿,把类型/地址/端口/用户名/排除列表
恢复为当前已保存生效的值;密码框不从 Keychain 回显,重置一并清空;
之前的测试连接结果随旧草稿一并清除。复用现有 native.reset 词条。

* chore(matrix): 网络代理设置 macOS 实机验收通过,转 verified

* refactor(network): 代理策略下沉 Rust 内核并修复评审缺陷

按维护者方向把双端可复用的代理逻辑下沉 Rust 内核,Swift 只保留
前端绑定与平台映射:

- 新增确定性命令 network.proxyPolicy(rust/lithe-core/src/network/):
  归一化(trim、排除列表清洗、密码保形)+ 校验(未填完整的 custom
  归一为 system),共享 fixture proxy-policy-v1.json 预钉跨平台契约,
  契约文档补索引与 Network proxy 小节
- Swift 侧新增 RustCoreBridge+NetworkProxy 桥接;MacNetworkSessionProvider
  改持 policyResolver(组合根注入桥接,测试注入静态计划),CFNetwork
  字典映射保留为平台专属部分,以 Rust 返回的 plan 为唯一事实来源

修复评审 4 项缺陷:
- P1 初始化同步:updateNetworkProxyPreferences 移到 init 真正末尾
  (原先误落在 restoreDefaults),重启后快照恢复已存策略;补重建设置
  对象后检查快照的回归测试
- P1 凭据隔离:凭据仅绑定到其所属代理(质询主机/端口需与配置一致),
  系统/直连会话不挂凭据 delegate,杜绝凭据发给其他系统代理
- P2 测试连接使用有效密码:草稿为空时回退已保存密码
- P2 Keychain 写失败保留密码草稿与重试入口

复用现有 native.reset 词条的重置按钮行为不变;Swift 侧归一化去重,
归 Rust 权威。

* fix(network): 隔离代理凭据并修复会话与连接测试生命周期

将密码与代理身份同存 Keychain,由 Rust 归一化策略拒绝跨端点复用;旧版无身份密码需重新输入。以覆盖响应消费的会话租约避免设置切换时提前失效,并让稳定版回滚复用完整认证会话工厂。连接测试增加资源总超时、取消和过期结果隔离。补共享 fixture、回归测试、中英提示与决策笔记。验证:Swift 85 项、Rust 1373 单元及 32 集成测试、i18n 35 项及相关静态门禁通过;真实代理产品验收保持 pending。

---------

Co-authored-by: Yao Jingxi <23722032@bjtu.edu.cn>

* feat(icons): add common project file glyphs and bot Agent icon (#1606)

- macOS/Windows: dedicated icons for .gitignore/.gitattributes, go.mod/go.sum,
  Makefile, package.json, lock files, README and LICENSE (#1584)
- Windows icon generator accepts lithe: sources for original icons; PowerShell
  icon moves under it so regeneration keeps it
- Agent tool-window entry uses the Lucide bot glyph on both platforms

* feat(plugins): macOS 公共宿主 API、纯命令与后端生命周期补全 (#1595)

* docs(plugins): 按 preview e8c4e9f 刷新 macOS 插件 API 计划

#1517(原生 Provider 工作流)和 #1515(远程工作区适配)都已合并,
计划里"在途/未合并"的说法已过时。本次只改文档,不改运行时代码、
schema、SDK 和功能矩阵状态。

基线与现状
- 盘点基线:Lithe 更新为 preview e8c4e9f;#1517 记为已合并;新增 #1515
  (阶段性实现,范围与缺口见 API-40);记录插件文档仓库 main 仍是
  be779d2000e3,且其契约锁落后主仓库 4 个触及 plugins/v1 的提交
- 能力版本:对照 PluginTypes.swift 与 capabilities.rs,补上
  buildProviders 1–6、buildModelInputs 1、debugAdapters 1/2;
  Core 与 Mac 唯一差异是 serverProcess(Core 1/2,Mac 1)
- API-29、API-31、API-35、M4、DOC-12、5.1 SDK 行:去掉对 #1517 在途的依赖,
  改为已合并后的文档、SDK 对齐与端到端验收

新增条目(编号接续 API-39,不改动既有编号)
- API-40 工作区 authority(M0):远程工作区仍是本机空占位根,backend:1 与
  Web bridge 不识别远程绑定;未实现的 authority 必须明确拒绝。API-05、
  API-35 同步指向它
- API-41 激活事件与启动预算(M0/M1):现有 activationEvents 只与已声明的
  Provider/窗口命令一一对应;应用没有工作区信任概念,M0 需决定
- API-42 内置 Git 只读快照(M3):Git 不在统一 VCS 层,API-31 只覆盖插件 VCS
- API-43 documents.onWillSave(M3):保存路径没有保存前钩子
- API-44 Agent 侧贡献(后续):Skills/Hooks/MCP 是用户管理的原生配置,
  没有插件来源
- 同步 2.1 现状表、4.1/4.2 评审清单、阶段表 M0/M1/M3c/M4/后续、
  DOC-02/04/07/13 以及新增 DOC-18/19、来源索引 S20–S22

公共扩展契约提案(proposed Note)
- 修正"内置 Git 与插件 VCS 共用同一统一模型",与 2026-10-22 评审一致:
  Git 暂不接入统一层
- #1517 改为已合并,补 #1515 的范围;新增 authority/激活/保存前事件/
  Agent 侧贡献一节,说明本 Note 不预设答案

* 插件后端 2 与函数协议 3:工作区上下文、能力发现与宿主错误码

- requires.backend 新增版本 2:可由 onWorkspaceOpen 或插件命令启动,不再必须有网页;后端可以是插件唯一内容;backend 1 语义不变
- 新权限 workspace.metadata(仅 backend 2)授予 workspace 宿主服务;拒绝 onStartupFinished 等常驻启动事件
- 插件函数协议新增版本 3:lithe/host/getCapabilities 由 Core 直接回答,subscriptions/dispose,workspace/listContexts、getContext、getFolders
- 宿主方法改为表驱动(HOST_METHODS),后续文件、编辑器、窗口服务按行接入
- lsp.functionRequest 可携带 context,仅 v3 后端收到 params.context
- lsp.hostResponse.error 可带 code,按白名单映射为 contextExpired、authorityUnsupported、versionConflict、limitExceeded、cancelled、timeout 等
- 后端可用 $/cancelRequest 取消自己的宿主请求,Core 立即回复 cancelled 并发出 hostRequestCancelled 事件
- 同步契约 README、manifest schema、正反例 fixture 与 Rust 单元测试

* feat(macos): 插件后端 backend 2 的工作区上下文、激活事件与宿主服务分发

- hostCapabilities 提供 backend [1, 2]
- 新增 PluginWorkspaceContexts:每窗口一个上下文,contextID 加 generation,本地/远程 authority,rootID 与状态目录摘要
- 新增 PluginHostServiceDispatcher 与 PluginHostServiceHandling 扩展点,统一错误码、授权与上下文核验、订阅回收与宿主请求取消;凭据与 workspace 服务接入
- MacPluginBackendSessions 支持 onWorkspaceOpen 与 onCommand 激活(串行、不阻塞),调用携带工作区上下文
- RustCoreBridge 传递 lsp.functionRequest.context 与 hostResponse.error.code,会话处理 hostRequestCancelled
- 新增界面文案词条并重新生成;新增 Agent Note 记录设计、第 4 节回答与威胁模型,写明工作区信任暂不引入

* test(macos): 补上上下文测试缺少的 throws 声明

* feat(macos): 为插件 API-09/10 提供宿主内部文档与编辑器服务

实现 macos-plugin-api-plan 中 API-09(documents.list/getSnapshot、
editor.getActive/getSelections)和 API-10(editor.applyEdits/
replaceSelections/insertText)的 Mac 宿主内部服务,暂不对插件公开,
等 M0 分发层接入。

- EditorDocumentService:调用方必须显式传入窗口与工作区范围和文档 ID,
  不回退到当前活动窗口;读取的是含未保存修改的内存缓冲区。
- 新增 EditorDocument.contentVersion 作为版本来源:每次文本变化单调
  递增,不受保存/冲突决策改写,没有 WebView 时也存在,WebView 重载
  后不归零。
- 坐标:行、列都从 1 开始,列按 UTF-16 码元计数;CR/LF/CRLF 各算
  一次换行。只在 LSP 适配边界换算成从 0 开始。
- EditorTextEditPlanner 先校验整批编辑(越界、反向、拆开代理对、
  重叠),全部通过才下发;插入的换行沿用文档首个换行符。
- Monaco 适配:同步比对桥接 revision;JS 端再核对 revision 和未确认
  输入,有 IME 组字、只读、冻结或关闭中时拒绝;用前后两个 undo stop
  加 pushEditOperations 作为一个撤销步骤应用;编辑消息带 origin,
  用来回报这一批产生的精确版本。
- SourceText.apply 支持按批次指定 EOL。
- 补充 Swift 单测(emoji、组合字符、CRLF、中文、多选区、版本冲突、
  只读、越界、重叠)和 bun 单测。

* feat(macos): 新增插件工作区文件访问的宿主内部服务(API-06/07/08)

尚未暴露为插件公共 API,也未改动 shared/contracts、capabilities.rs 和 hostCapabilities;
M0 分发层负责授权并把插件请求映射为显式根和调用方身份。

- Core/Ports/PluginWorkspaceFileAccess.swift:服务协议与值类型。每次调用显式携带
  工作区根(root ID、目录、authority、generation、可见性规则)和调用方身份,不回退到活动窗口;
  资源 ID 为 root ID + 以 / 分隔的 NFC 相对路径,结果中不出现系统绝对路径;
  错误分类、集中的预算常量及每个取值的依据。
- MacWorkspaceSecurePath:路径词法校验(拒绝绝对路径、空段、.、..、NUL、超长段和超长路径),
  逐段 NFC 规范化;从根描述符逐段 openat(O_NOFOLLOW) 解析,末段用 fstatat(AT_SYMLINK_NOFOLLOW)
  或 O_NOFOLLOW|O_NONBLOCK 打开,防止 .. 越界、任意段的符号链接以及检查后换成链接的 TOCTOU;
  注释写明能防和不能防的范围(硬链接、持有描述符期间被移出的目录、挂载点)。
- MacPluginWorkspaceFileService:
  - readDirectory 用不透明游标分页(游标绑定根、generation 和目录,记录最后一个排序键),
    单页上限和单目录扫描上限;排序与项目树一致(目录优先、自然文件名序),
    隐藏规则、符号链接和嵌套 linked worktree 的省略也与项目树一致。
  - stat 报告链接本身。readFile 有字节上限、编辑器同款编码探测、二进制结果、截断标记,
    未截断时附带 SHA-256 身份。
  - findFiles/findText 复用现有搜索 owner(Search Everywhere 文件提供者和项目文本搜索),
    支持取消、偏移游标分页和截断标记,结果标明只来自磁盘、不含未保存缓冲区。
  - 拒绝非本地 authority,以及被标为本地的远程占位根(unsupportedAuthority);
    旧的或已关闭的 generation 返回 staleWorkspace。
  - 阻塞工作在宿主队列上执行;按调用方限制并发;任务取消时立即返回 cancelled。
- MacPluginWorkspaceWatchHub:复用 DirectoryWatcherFactory/DirectoryChangeSource,
  同一根 generation 的订阅共享一个变更源并做引用计数;订阅归属调用方和工作区,
  在 dispose、releaseResources、closeWorkspace 或新 generation 取代时释放;
  高频事件按订阅合并,超出待处理上限或源报告丢失时折叠为“需要重新扫描”;
  旧 generation 的迟到事件按键丢弃,不会到达新订阅;dispose 返回后不再投递。
- MacWorkspaceSnapshotBuilder.isNestedLinkedWorktree 改为 internal 以复用。
- PluginWorkspaceFileServiceTests 覆盖:越界与路径校验、根外符号链接、
  链接互换竞态(含中途换链接)、分页游标与篡改、超大目录、隐藏规则、二进制文件、
  超限截断、NFC 名称、watcher 释放/合并/溢出/旧 generation、远程 authority 拒绝、
  搜索分页与不可用、取消与并发预算。

* feat(macos): 增加插件宿主的编辑器打开、HTML 预览、外部浏览器和窗口消息内部服务

实现 docs/development/macos-plugin-api-plan.md 中 API-15、API-16 和 API-17
最小部分的宿主内部服务。只提供 Swift 协议和实现,不对插件公开,不修改插件契约、
Rust capabilities 和 PluginTypes 的 hostCapabilities,授权与调用分发留给 M0。

作用域与资源
- 每次调用显式携带插件、窗口、工作区和工作区代际,不回退到当前活动窗口。
- PluginHostScopeGate 在窗口缺失、远程工作区、工作区或代际变化时拒绝,并在每个
  等待点之后再次校验,窗口关闭或工作区替换后不再放光标、不再启动浏览器。
- 资源使用“根 ID + 工作区相对路径”,在符号链接解析后按带尾部斜杠的前缀比较,
  拒绝路径逃逸、兄弟目录前缀、控制字符和超长路径。

editor.open / reveal
- 复用 documentFeature.openFileAsync 和文档 owner:已打开的文档只激活不重载,
  未保存缓冲区保持原样;没打开才从磁盘加载一次。
- activation 为 select 时调用 selectEditorTab,等同点击标签,把后台标签切成前台
  标签,编辑器切片读选区、改文本前需先走这条路径;background 不改前台标签、
  不放光标。结果中 isActive 表示标签在前台,windowIsForeground 表示窗口在前台。
- 后台窗口只在自己的窗口内工作,不提升窗口、不激活应用。
- range 只落到起点光标并在结果里明示;可替换预览标签暂不支持,明确拒绝。
- reveal 要求文件已打开,否则返回 documentNotOpen。

preview.openHTML
- 仅接受 .html/.htm,走 editor.open 的 select 路径,内嵌预览使用当前缓冲区。
- 仅预览模式是标签视图的 @State,暂不支持,明确拒绝。

browser.openExternal
- 网址只允许 http/https,必须有主机名,禁止用户信息、空白和控制字符,限长
  4096 字节;其它 scheme 一律拒绝,不追加内容、不执行脚本。
- 本地文件只接工作区内的 .html/.htm,让系统浏览器读磁盘;打开前先让编辑器交出
  未报告的输入,缓冲区脏或编辑器未确认都按“有未保存修改”处理。调用方可选择
  openSavedFile 并在结果里明示,或 requireSaved 返回 unsavedChanges。
- PlatformUI 新增 openWebURLInBrowser;MacHTMLBrowserOpener 新增 openWeb,
  自身再次校验协议和主机,只向 Launch Services 查询处理浏览器。

window.showInformation / Warning / Error
- 每个窗口一个 PluginHostMessageFeatureModel,WorkbenchView 左下角用
  PluginHostMessageStack 原样显示插件文字和按钮,不走会翻译文案的宿主通知栈。
- 最多同时显示 3 条,其余排队;返回用户选择的按钮序号或关闭、窗口关闭、
  工作区替换、调用取消等结束原因,每条消息恰好结束一次。
- 限额:同一插件每窗口 10 秒 5 条、同时 3 条,每窗口共 10 条;文字 2000 字符,
  按钮 3 个、每个 40 字符。超频返回 rateLimited 并向用户提示一次,队列满返回
  messageQueueFull;限频时间由调用方注入。
- 宿主自己的 20 条文案补齐 shared/i18n 中英词条并重新生成。

HTML 预览与 plugin bridge 隔离
- 核对结论:预览使用全新的 WKWebViewConfiguration,唯一脚本处理器是应用内容世界里
  的 litheScrollbarFrame;lithe 消息处理器和 lithe-plugin 协议只在
  MacPluginWebPage,项目页面和外部浏览器都拿不到 bridge,无需改代码。
- 新增 HTMLPreviewBridgeIsolationTests 作为回归测试。

测试与文档
- 新增 PluginHostEditorServiceTests、PluginHostBrowserServiceTests、
  PluginHostMessageServiceTests(含限频器与编辑器同步等待)、
  HTMLPreviewBridgeIsolationTests,并扩展 HTMLBrowserOpenerTests;测试使用假窗口、
  注入时钟和有界等待,不依赖 sleep。
- 新增 Agent Note 2026-10-30-plugin-host-open-preview-services.md,记录决策、
  前台标签与前台窗口的区别、未保存语义、bridge 隔离证据、运行期不写发行包、
  已知限制和被否方案。

本次未在本机编译或运行 Swift 测试。

* fix(macos): isolate editor flush request to the main actor

* feat(plugins): give each host error its own JSON-RPC code from protocol 3

Record the backend workspace context and host services in the platform
feature matrix, and require one-to-one error codes in develop-lithe.

* fix(macos): make the editor flush callback sendable

* feat(core): add host notifications, failure details and finer host error codes

* feat(macos): push host notifications to plugin backends and tighten workspace contexts

- Push lithe/host/workspace/didChangeContexts to running backends granted
  workspace on every context open, change, or close.
- Deliver lithe/host/commands/didRun to a backend 2 plugin when its command
  runs: at once when ready, after the start when starting, and only on its
  own onCommand:<id> when stopped.
- Send subscription events with a per-subscription sequence through
  lithe/host/subscriptions/notify; notifications to one backend stay in
  order and are cancelled with the session.
- Start onWorkspaceOpen backends on enable or register when a workspace is
  already open.
- Grant a backend only the host services this host has handlers for, so
  getCapabilities lists nothing that fails for want of one.
- Switching a window to another workspace closes its context and opens one
  with a new contextID; generation counts changes of the same workspace.
- Make rootID an HMAC keyed per plugin with a host secret kept in
  Application Support/Lithe/PluginHost/root-id.key (0600, created once).
- listContexts no longer returns or creates stateDirectory; getContext does.
- Add notFound, readOnly, unsupportedOption, preconditionFailed, busy and
  rateLimited host error codes and structured failure details.
- Fix the dispose error message, document the protocol 3 notifications,
  details, error-code range, and context semantics in the contract, the
  Rust Core API, the Agent Note, and the feature matrix.

* feat(plugins): extend protocol 3 additively instead of new versions

- From protocol 3, new host services, methods, notifications, options,
  result fields and failure codes are added within the version and found
  with getCapabilities; only a change an existing backend would misread
  needs a new protocol version.
- Core answers a field a host method does not define with
  plugin.host.unsupportedOption (-32018) and details { option } for a
  version 3 session, before the host sees the request; version 2 keeps
  plugin.host.invalidParams.
- Document the extension rule and the backend's duties (call only listed
  methods, ignore unknown fields and notifications, treat unknown numbers
  as host failures) in the contract README, the outcomes table, the Agent
  Notes, and the feature matrix; add fixture and engine tests.

* feat(plugins): connect public host APIs and harden backend lifecycle

* fix(plugins): preserve older backends when host notifications are unsupported

* test(macos): stabilize Agent popup clicks and record API-01–44 completion

- Agent selector/activity tests: fix the hosting view size only where the
  layout needs it, display windows before synthesized clicks, and compute
  click points from LitheDropdownMetrics in flipped and unflipped documents.
- macOS plugin API plan: add the per-API completion table for PR #1595 and
  a summary of the public host methods with their permissions.

* fix(macos): restore settings window sessions after relaunch (#1599) (#1601)

* perf(windows): 修复文档漂移并大幅降低大文件打字成本 (#1605)

* fix(lsp): replay document changes in the order they happened

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(editor): stop TextMate tokenizing once the rule state converges

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): register the folder drop listener once

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(windows): rebuild Spring and MyBatis indexes on the autosave pause

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(windows): answer Java definitions from syntax while importing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(windows): measure frontend interactions against budgets

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(windows): cover recoloring far below a multi-line edit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(macos): cover CR positions through the source change path

sourcePositionAt no longer exists because positions now come from the
piece tree. Assert the same CR line counting on SourceText changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): start a fired autosave only once

The task stays queued until its write settles, so a blur during the claim
ran the same closure again. Both runs shared an operation id and could both
write, turning the second into a false conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(java): resolve syntax member references from their scope

The whole-tree search returned the first same-named member, so a jump could
land in a nested type. A lookup now stays on the named type, and a reference
walks outward from where it is used, answering nothing when an inherited
name or a local could change the binding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(windows): count the work typing leaves behind

Per-key metrics now share one window, and the final autosave and index
rebuild are reported separately once the host goes quiet. The new Windows
document sync, syntax navigation and perf statistics tests join CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* perf/fix(windows): 文件树交互与图标、文件菜单设置入口、Git 推送弹窗、工作区扫描提速 (#1586)

* fix(windows): 文件树单击仅选中、双击打开,并支持 Delete 键删除(始终二次确认)

- 单击文件只选中并高亮,不再打开或新建预览页签;双击或 Enter 才打开,与单击目录行为一致
- 选中后按 Delete 弹出删除确认框,多选时一次确认并逐项删除;
  即使“删除前确认”设置关闭也始终确认,工作区根目录与带修饰键的 Delete 不触发
- 补充选择与 Delete 键的组件测试,并更新跨平台功能矩阵说明

* fix(windows): Git Log 文件列表选中行跟随 Diff 预览的上一/下一文件导航

- Commit files 列表监听预览标签页当前显示的文件并同步选中行;
  仅当预览属于当前所选提交或范围时才同步,避免过期预览改变选中
- 同步选中时自动展开被折叠的父目录,并仅在纵向滚动到可见位置,不改变横向滚动
- 抽出 commitFilePreviewHash 与 selectedCommitFilePath,发布预览与观察预览共用同一标识
- 补充选中跟随与折叠目录自动展开的组件测试,并更新跨平台功能矩阵说明

* fix(windows): 推送弹窗按钮对齐 IDEA 样式并修复强制推送下拉被弹窗遮挡

- 推送按钮组改为 IDEA 默认选项按钮样式:实心主色底、白字,1px 分隔线上下内缩;
  ButtonGroup 新增 primary 变体,禁用时整组一起变淡
- 下拉箭头悬停和菜单展开时不变色;Button 带 tooltip 会被包一层 span,
  分组的直接子元素选择器无法命中,箭头改为自带样式
- DropdownMenu 定位层从 z-50 提到 z-10070,与 context-menu、popover、select 一致;
  此前弹窗(z-9999)会盖住强制推送菜单
- DropdownMenuContent 支持透传 anchor,强制推送菜单锚定整个按钮组,宽度与按钮组一致

* feat(windows): 文件菜单新增设置入口

针对 #1560 的第 1 点:点击左上角“文件”后,菜单里找不到设置入口。

- 文件菜单在“关闭标签页”上方新增“设置”项,齿轮图标加文字,上下以分隔线隔开,
  显示 Ctrl+, 快捷键提示;点击走已有的 menu_open_settings 事件,打开设置对话框
- 新增共享词条 menu.settings(设置 / Settings),重新生成 Windows i18n 资源
- 补充菜单源码断言测试:设置项位于“关闭标签页”和“退出”之前
- 新增功能矩阵条目 windows-file-menu-settings(Windows 已实现、待验证,macOS 不适用)

未覆盖:#1560 的第 2 点(菜单只有“退出”、没有“重启”)尚未实现,
因此只引用 issue,不关闭。

Refs #1560

* feat(file-tree): 补齐 Windows IDEA 图标主题并新增 jsonl/wbmp/Office/i18n 图标

- Windows IDEA Icons 主题补齐 macOS 已识别的类型:Kotlin、Rust、Go、Python、
  Ruby、Scala、PHP 图标(取自 IDEA,明暗各一份),以及 .m/.hh/.hxx/.mm/.fish/
  .svelte/.pom/.ini/.cfg/.conf/.env/.db/.sqlite/.markdown/.adoc/.tsv/.tiff/.icns、
  .class/.jar/.so/.dylib/.dll/.pdf 等扩展名,和 .classpath/.project/
  .gitattributes/.dockerignore/compose 文件等文件名
- .kts 改用 Kotlin 图标,.gradle.kts 仍用 Gradle 图标,与 macOS 一致
- 两端新增:.jsonl/.jsonlines/.ndjson/.ldjson 用 JSON 图标,.wbmp 用图片图标,
  .doc/.docx/.ppt/.pptx 用 IDEA Native 类型的 custom 图标,.strings 用 i18n 图标
- macOS LitheIconKind 新增 .i18n、.document,补充 custom/i18n 资源与 NOTICE 来源说明
- 新增 macOS FileTypeIconKindTests,并在 Windows 主题清单测试中覆盖新映射与资源
- 更新功能矩阵 file-explorer 的证据与验证说明

未覆盖:.env.*、dockerfile.* 这类前缀文件名在 Windows 主题里无法表达;
macOS 侧未在本机编译验证(当前环境为 Windows),验证状态保持 pending。

* perf(windows): 去掉项目文件树行的 hover 高亮

滚动时指针会连续扫过大量文件行,每行 hover 都会重绘整行覆盖的 ::before 伪元素,
造成滚动卡顿。

- file-explorer-tree.css 新增规则,在 .file-explorer-shell 内让行的 hover 背景保持透明;
  选中、焦点样式和缩进线不变
- Git 状态面板与提交文件树共用同一套样式,不在 .file-explorer-shell 内,hover 保持不变
- file-explorer-surface.test.ts 增加样式断言,防止该规则被误删

* perf(core): 工作区扫描默认跳过 Python 环境和字节码,Windows 快照只取文件清单

Python 项目里虚拟环境和 __pycache__ 占了绝大多数文件(一个典型项目约 3.2 万个文件中
约 2.7 万个),而打开项目时 Windows 会连续请求多次整库快照,每次都重复扫描并序列化
这些路径。

- Rust Core 内置隐藏名单增加 .venv、venv、__pycache__ 目录和 *.pyc 文件:这些目录整个
  不再被读取,也不进搜索索引、文件监听和 Git 仓库发现
- macOS FileVisibilityRules 同步增加同样四项,保持设置页显示的内置规则与实际规则一致
- Windows 的 fffListFiles 和 Lombok 导航请求 workspace.snapshot 时带 includeTree: false,
  不再让 Core 构造并序列化没人使用的整棵目录树(macOS 已在 #1245 这样做)
- 新增 Rust 测试覆盖快照、只要文件清单、目录列举和监听事件,并保留名字相近的目录可见;
  新增 Windows 测试断言快照请求只取文件清单
- 更新契约文档、lazy-project-tree 笔记,新增 Agent Note,补充功能矩阵 workspace-files

未覆盖:Windows 文件树仍按前端设置读磁盘目录,.venv 在 Windows 文件树里仍可见;
名字不同的虚拟环境不会被识别。macOS 侧未在本机编译验证(当前环境为 Windows),
验证状态保持 pending。

* fix(tests): 图标资源断言脱离应用 bundle,file-search 测试接入 Windows CI

- FileTypeIconKindTests 不再经 ideaImage 依赖 Bundle.main(单元测试宿主
  没有应用资源包,返回 nil 导致 Swift tests 失败):新增
  LitheIcons.ideaAssetPath(for:) 只读访问器解析目录映射,测试从源码
  Resources/IDEAIcons 断言明暗 SVG 存在,与 IDEAIconRasterizationTests
  的源码路径先例一致
- GitCommitTreeStyleTests 的 Localizable.strings 断言从 .plainText 更新
  为 .i18n,同步本 PR 的 .strings 图标映射变更
- ci-windows.yml 为 file-search-api.test.ts 新增独立计时步骤(该套件装
  进程级 Tauri 边界 mock,需与其他套件隔离执行);接入后暴露 mock 缺少
  isTauri/transformCallback 导出,按 tauri-core.test.ts 的 ...nativeCore
  展开模式修正

* fix(tests): 图标清单断言跟随 upstream #1606 新增的 AgentIcon

合并 upstream/preview 后,CI 的 "Test Agent panel and capability gate"
批次失败:application icon mappings > exports the complete icon inventory
断言 216 个图标导出,但 #1606 在 icons.tsx 新增了 AgentIcon(bot 图标),
导出数变为 217,且该 PR 合并时 CI 被取消未暴露此问题。

将断言更新为 217,本地完整重跑该批次 242 个测试全部通过。

* feat(windows): 行内 Git Blame 对齐 IDEA annotate(行号注释、Git Log 定位、右键菜单) (#1602)

* feat(windows): 行内 Git Blame 对齐 IDEA 行号注释

- 行号列渲染注释:作者与绝对日期浮在行号左侧,同一提交块只在首行显示,
  行号列随之加宽到 26ch 并在关闭后恢复
- 右键行号栏 Annotate with Git Blame / Hide Git Blame 按文件开关,
  删除全局 enableInlineGitBlame 设置(原行尾 widget 一并移除)
- 点注释用 openCommitDiffBuffer 打开该行提交的单文件 diff 并定位命中行
- 修正 core-result-adapter 的 total_lines:Core 每行一条记录,
  旧值让每条记录覆盖整文件,导致任意行显示别的提交
- 新增 git.blame.* 共享词条并移除旧设置词条

* fix(windows): Git Blame 注释按 IDEA 每行标注并右对齐

- 每行都显示作者与日期,不再按提交块合并(空行会被读成缺失归属)
- 标签右对齐紧贴行号,去掉贴最左 + 大段空隙的排版
- Annotate/Hide 入口只在行号区右键菜单出现,内容区菜单不再显示禁用项
- 图标改为作者语义的用户图标

* fix(windows): Git Blame 日期补零为 08/08/2026

月份与日期改为两位,避免注释列在个位数日期上抖动;月份顺序仍跟随应用语言
(中文界面为 2026/08/08)。

* fix(windows): Git Blame 标注改 yyyy/M/d + 日期在前,行号右键精简为行级菜单

- 日期改为不补零的 yyyy/M/d(与 macOS 一致),标签顺序改为「日期, 作者」
- 行号区右键改用独立精简菜单(Annotate/Hide Git Blame + Show Line History),
  不再弹出完整编辑器菜单;内容区菜单保留行历史、不再出现 Annotate
- 新增 gutter-context-menu 构建器与单测

* feat(windows): 行号 gutter 菜单对齐 IDEA annotate 菜单并扩大命中范围

- 菜单项按 IDEA 分组:Annotate/Close Annotations、Show Diff、Copy Revision Number,
  分隔线后是 Show Line History;提交相关项只在已注释且该行有提交时出现
- 关闭注释改名为 Close Annotations / 关闭注释,新增 showDiff/copyRevision/revisionCopied 词条
- 右键命中范围从行号列扩大到整个 gutter(行号、变更标记列、字形边距)
- gutter-context-menu 单测覆盖分组顺序与可见性条件

* fix(windows): Git Blame 注释去掉日期与作者之间的逗号

标签改为「yyyy/M/d 作者」,两者之间只留一个空格;行号列仍整体右对齐。

* fix(windows): Git Blame 注释标签改为左对齐,行号保持右对齐

标签贴注释列左侧、超长省略号截断,行号仍贴列右边缘(与 macOS 布局一致)。

* fix(windows): Git Blame 日期与作者间留两个空格,注释列宽按最长标签自适应

- 标签改为「yyyy/M/d  作者」(两个空格),去掉逗号感
- 行号列宽不再固定 26 字符:取最长标签宽度(中文按双宽)+ 4 个行号格,
  夹在 12–26 之间,短名字不再白占一列
- 新增 gitBlameColumnChars 与中日韩双宽计算的单测

* feat(windows): 注释点击定位到 Git Log,内容菜单新增 Git 子菜单

- 点注释改为打开 Git Log 并选中该行提交(新增 git-log-reveal store 传递请求,
  日志按页向前加载直到命中,最多 20 页)
- 行号右键菜单移除 Show Line History,只保留注释与提交动作
- 内容区右键新增 Git 子菜单:Annotate/Close Annotations、Show Diff、
  Copy Revision Number、Show Line History
- 补充 reveal store、gutter 菜单与编辑器 Git 子菜单单测

* fix(windows): 只读 diff 视图内 Ctrl+C/Ctrl+X 交回 Monaco 原生复制

只读 diff(提交预览、工作树差异、独立 diff 面)里的选中文字此前无法复制:
编辑器 keymap 在捕获阶段拦下 Ctrl+C 并执行源编辑器的 editor.copy,
复制的是源编辑器模型(通常为空),原生复制被 preventDefault 掉。

- diff 面根节点标记 data-readonly-diff
- keymap 在命中该区域时不再拦截 copy/cut,交给 Monaco 原生处理
- 新增 shouldDeferClipboardToReadOnlyDiff 与单测(含粘贴/带 Shift 不受影响)

* chore(windows): review 收尾——常量移出 import 区,补齐矩阵证据与验收项

* docs(matrix): Windows Git Blame 记为实现并已验证

2026-10-30 维护者在 Windows 实机确认:行号右键精简菜单、每行 yyyy/M/d  作者 注释
与自适应列宽、点注释跳转 Git Log、Show Diff 两侧复制、未跟踪与只读预览不出现入口。

* fix(windows): Git Blame 注释列补一格余量,避免最长标签被省略号截断

Monaco 的行号列宽按 cells × maxDigitWidth 四舍五入,而标签宽度受 CSS 的
calc(100% - 4ch) 限制;余量为 0 时最长标签会超出不到 1px 而被省略号截断
(截图里 2026/10/29 的日期被截成 chenb…)。

- 列宽改为标签格数 + 行号格数(按行号位数取 max(4, 位数))+ 1 格余量
- gitBlameColumnChars 改为接收条目 Map,以便按最后一行判断行号位数
- 补 5 位行号与余量的单测

* fix(windows): Git Log 定位请求在翻页无进展时结束,不再挂起

评审观察项 1:当 hasMore 为真但分页游标为空(一次失败的翻页会留下这种状态)时,
loadMore() 静默返回、effect 不会重跑,待处理的定位请求会一直挂着,可能在之后
一次刷新时突然跳到旧提交。

- useGitLogController 的 load()/loadMore() 改为返回"本页是否新增提交";
  refresh() 维持 Promise<void>
- 定位 effect 在 loadMore 解析为 false 时清空请求
- 补 integration 测试:分页返回是否推进 + 耗尽后返回 false

* fix(windows): locate-current-file ignores active paths spelled differently from the tree (#1578)

* fix(windows): match locate-current-file against the tree's path spelling

Add toRootedPath, which respells a path inside the workspace root with the root's own prefix and separator, and use it when revealing the active file in the project tree.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Add tests for toRootedPath function

Added tests for the toRootedPath function to ensure it correctly respells paths with the specified root prefix and separator.

* fix(windows): reveal the active file using the tree's path spelling

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(windows): locate resolves a forward-slash path against a backslash tree

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs(matrix): record Windows locate-current-file path handling

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: lick <2188718831@qq.com>

* perf(windows): 优化文件打开与编辑器交互性能 (#1607)

* perf(windows): 优化文件打开性能与编辑器生命周期

- 复用 Monaco 编辑器表面与模型,保留隐藏标签布局并按可见性调度语言服务
- 缓存主题定义、静态编辑器样式和输入配置,减少全窗口样式与布局计算
- 仅为未保存编辑发送 Spring、MyBatis 索引覆盖,合并扫描并跳过无 XML 映射的工作区
- 稳定文件树、快捷键和拖放回调,减少布局测量、重绘与原生监听注册
- 文件读取使用原始二进制响应,合并前端日志 IPC 并保留上游异步文件操作
- 优化标签菜单渲染,新增最近最少使用关闭策略,默认标签上限调整为 20
- 修复模型复用后的浮层位置解析,同步国际化、能力矩阵与回归测试

* fix(windows): 合并标签上限实现并修复编辑器复用的泄漏与状态问题

- 标签上限只保留 selectBuffersOverTabLimit 一份逻辑:store 不再保存设置副本,
  改为读取真实设置和关闭策略;标签栏不再关闭终端和 Agent 标签;0 表示不限制
- 默认上限定为 30,并按测量结果说明理由;已保存的配置不变
- Monaco addCommand 的处理函数不再捕获创建 effect 作用域,修复每个销毁的
  编辑器被留在内存里的泄漏(leaks 场景回到与 preview 相同)
- 卸载时先做模型清理再销毁编辑器,保证视口状态能保存
- 文件切换时关闭行号和行历史菜单;文本未就绪时不挂 Vim;模型绑定后补设诊断
- 新增 fileOpen 性能场景和预算,新测试接入 Windows CI,补功能矩阵和 Agent Note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: zhengfuping <fuping.zheng@onmicro.com.cn>
Co-authored-by: lick <2188718831@qq.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): 在 Quick Open 中搜索 Spring 接口路由 (#1475) (#1522)

* fix(windows): 在 Quick Open 中搜索 Spring 接口路由 (#1475)

- 默认 Quick Open 合并 Spring 接口与文件结果,复用现有 spring.index,不新增注解解析器
- 支持按路由精确/前缀/包含、控制器、处理函数和 HTTP 方法组合搜索
- 接口结果参与统一键盘导航,回车打开控制器注解行;@/# 模式不混入接口
- 校验 Spring 索引与当前工作区根一致,补充 i18n、能力矩阵、Agent Note 和回归测试

* test(windows): 同步 Quick Open 接口搜索文案断言

* fix(windows): 补齐 Spring 路由搜索边界 (#1475)

- 多 HTTP 方法分别与路由组合匹配,避免仅单个方法可命中

- Quick Open 在索引非 ready 状态隐藏旧接口结果

- 补充多方法查询和刷新失败回归测试并同步 Agent Note

* fix(workspace): avoid main-thread linear lookups on external file batches (#1598)

External file-change refreshes checked project membership with a linear
scan over the whole inventory, standardizing URLs on every comparison.
On large workspaces this kept the main thread busy after each batch.

- Keep standardized file paths and ancestor directory paths in sets,
  rebuilt only when the project inventory changes.
- Deduplicate changed URLs with a set instead of repeated contains checks.
- Record external-change history in one actor call per batch, pruning
  expired snapshots only until the first snapshot is written.
- Add regression tests for a 4000-file edit batch, batched history
  recording with skipped files, and cancelled batches.

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>

* fix(run): 读取登录 shell 环境并按项目 Java 版本精确挑选 JDK (#1612)

* fix(run): 读取登录 shell 环境并按项目 Java 版本精确挑选 JDK

从 Finder 启动的 Lithe 只继承 launchd 的最小 PATH,mise/SDKMAN/asdf/fnm/Homebrew
安装的 Maven、JDK、Node 都找不到;自动选 JDK 时 JAVA_HOME 只要不低于项目版本就胜出,
Java 8 项目会跑在 JDK 21 上。做法参考 OpenIDEA(Apache-2.0),出处见 NOTICE。

- macOS:启动时读取 $SHELL -ilc 的环境;只把 PATH 缓存到 Caches,热启动用缓存并后台刷新;
  其余变量只在内存中补齐缺失键,经 MacRuntimeLocator、MacManagedProcess 与 JDT 发现生效。
- Core:select_java_candidates 改为同主版本优先、其次最旧的更新版本,来源优先级只在同版本内比较;
  更新共享 fixture 与契约文档。
- 发现:macOS 增加 mise/asdf/~/.jdks JDK 与 SDKMAN/mise/asdf Maven,跳过 shims;
  Windows 增加 mise/asdf/Scoop/Semeru/OpenJDK JDK 与 mise/asdf/SDKMAN/Scoop Maven。
- 新增 NOTICE、Agent Note、功能矩阵条目与测试。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(run): end the login shell's process group on timeout and log read outcomes

- Read the login shell through MacManagedProcess so a timeout or shell exit
  also ends jobs the rc file left running; keep stdout as raw bytes and
  discard stderr so one non-UTF-8 greeting cannot void the read.
- Record each startup/refresh read (shell name, source, duration, variable
  count; never values) in the application log, buffering the startup record
  until the log writer attaches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(macos): 更新下载断点续传,失败提示区分原因 (#1609)

* fix(macos): 更新下载断点续传、区分失败原因,本地历史限制 100MB

- Sparkle 下载经本机回环转发 UpdateDownloadRelay:Range + If-Range 续传,断点存 Caches,
  跨会话保留;206 时自行核对 ETag/Last-Modified,防止 GitHub CDN 无视 If-Range 拼出坏包
- 下载失败区分超时、无法连接、服务器错误,并提示已下载数据会保留、重试可继续
- 启动时清理已完成或废弃的回退暂存目录
- 本地历史每个项目上限 100MB(基线最多 50MB),基线跳过生成目录与嵌套仓库,
  保存时清理旧版本遗留的基线,超限按基线→编辑→标签由旧到新淘汰
- 新增 scripts/release/sparkle/test-sparkle-relay-e2e.sh:本地服务器 + 真实 Sparkle 五场景端到端

* chore: 本地历史上限拆到 #1610,本 PR 只保留更新下载改动

---------

Co-authored-by: lick <2188718831@qq.com>

* fix(core): 本地历史每个项目限制 100MB,基线跳过生成目录 (#1610)

- 每个项目上限 100MB(按 4KB 分配块计,占用量进程内缓存),其中项目基线最多 50MB
- 基线跳过 node_modules、.venv、target、.claude、.uv-cache 等生成目录和嵌套 Git 仓库
- 保存时清理过期条目和旧版本遗留的排除目录基线;超限按基线→编辑→标签由旧到新淘汰

Co-authored-by: lick <2188718831@qq.com>

* feat(macos): 设置中可配置正式版更新源 (#1611)

* fix(macos): 更新下载断点续传、区分失败原因,本地历史限制 100MB

- Sparkle 下载经本机回环转发 UpdateDownloadRelay:Range + If-Range 续传,断点存 Caches,
  跨会话保留;206 时自行核对 ETag/Last-Modified,防止 GitHub CDN 无视 If-Range 拼出坏包
- 下载失败区分超时、无法连接、服务器错误,并提示已下载数据会保留、重试可继续
- 启动时清理已完成或废弃的回退暂存目录
- 本地历史每个项目上限 100MB(基线最多 50MB),基线跳过生成目录与嵌套仓库,
  保存时清理旧版本遗留的基线,超限按基线→编辑→标签由旧到新淘汰
- 新增 scripts/release/sparkle/test-sparkle-relay-e2e.sh:本地服务器 + 真实 Sparkle 五场景端到端

* chore: 本地历史上限拆到 #1610,本 PR 只保留更新下载改动

* feat(macos): 设置中可配置正式版更新源

- 外观与行为 > 更新新增「更新源」,默认是仓库最新 Release 下载目录
- 镜像需平铺提供同名 appcast-<arch>.xml 与更新包,Sparkle 仍校验签名
- 输入先测试连接(读取清单并 HEAD 最新归档),成功后才能应用;可恢复默认
- 下载失败与连接测试的提示带出镜像主机名
- AutoBuild 安装或选择 AutoBuild 渠道时禁用,始终用官方源

---------

Co-authored-by: lick <2188718831@qq.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: arkleselect <166632698+arkleselect@users.noreply.github.com>
Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
Co-authored-by: 大德 <zher52@aliyun.com>
Co-authored-by: lincoco <77844710+lin-coco@users.noreply.github.com>
Co-authored-by: 若水 <frankw.wang@qq.com>
Co-authored-by: waani <kuun993@163.com>
Co-authored-by: AACS111 <103710223+AACS111@users.noreply.github.com>
Co-authored-by: zhengfuping <fuping.zheng@onmicro.com.cn>
Co-authored-by: puppyben1 <136492871+puppyben1@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: medium ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant