Commit Graph
100 Commits
Author SHA1 Message Date
luo jiyinandfanlusky acc25f40e6 fix(installer): 在最终数据目录保存云候选选择 (#972)
* fix(installer): 在最终数据目录保存云候选选择

安装器在数据目录确定后检查已有配置。升级迁移遇到配置冲突时停止,避免覆盖目标配置。

首次安装以 UTF-8 写入云候选选择,并在写入失败时报告错误。

增加安装时序检查和 Windows 安装测试矩阵。

Refs #931

* test(installer): 用 Inno 探针验证云候选配置写回

主安装器与探针共用云候选配置函数。

Windows CI 执行五个隔离的首次安装和升级场景。

Refs #931

* test(installer): 接受 Inno 配置文件的 CRLF 行尾

测试按完整的 cloud_candidates 行检查结果。失败时打印实际字段值。

Refs #931

* fix(installer): check config migration conflict before stopping IME

* test(installer): clear expected conflict exit code

* test(installer): narrow source check to migration order

* fix(installer): 云候选写回失败不再中断安装,迁移可重试

- 写回「不启用云候选」失败时只记日志并提示,挪到必需的安装后步骤之后
- 两处 config.toml 内容相同时视为上次迁移的残留,允许重试
- config.toml 没搬过去时中止安装,避免新目录装上出厂配置
- 数据目录页就检查配置冲突
- ShouldSkipPage 不再写全局状态
- 探针复用生产的迁移判断与顺序,补齐改目录首次安装、重试和迁移失败场景

---------

Co-authored-by: fanlusky <1730976608@qq.com>
2026-10-15 23:00:34 +08:00
小莫 93933602ff fix(installer): avoid certificate store in SignPath test mode (#923) 2026-10-13 21:19:05 +09:00
小莫 d0d87efb53 feat(installer): add SignPath test signing workflow
Adds a manual test_signing dispatch that uses GitHub-hosted runners, test-signing policy, signer verification, and run-summary request links without publishing a release.
2026-10-13 11:43:05 +00:00
Lu Fan(SonnyCalcr) 19543ead61 fix(server,installer): 升级不再改掉老用户设置和效果档模型,SimplySign 打包前构建词库 (#852)
* fix(server): 升级不再把只给新装用户的出厂默认值推给老用户

* fix(installer): 升级时把 0.9.x 随包的效果档模型挪到 models\neural-desktop,不再删掉

* fix(installer): SimplySign 完整包打包前从同级 msime-dictionary 构建词库并备好模型
2026-10-12 00:27:59 +08:00
luo jiyin 5a5d5dee80 fix(ci): fall back to MSVC when sccache is unavailable (#832)
* fix(ci): fall back to MSVC when sccache is unavailable

* test(ci): build with MSVC after simulated sccache setup failure
2026-10-11 20:39:51 +09:00
luo jiyinandfanlusky 66e0a6dc76 fix(server): 保留候选文本中的逗号和私用字符 (#766)
* fix(server): 保留候选文本中的逗号和私用字符

* fix(server): render candidate frame from one snapshot

* fix(server): use captured preedit for sticky card key

* fix(server): dedup candidate frames by item-aware signature

Candidate text now keeps raw commas, so the comma-joined candidate_string
could make ["a,b","c"] and ["a","b,c"] share one frame signature and drop
a real page change as a duplicate repaint. Length-prefix each item instead.

Also serialize the WebView candidate items with the replace error handler
so an invalid UTF-8 translation gloss cannot throw on the UI thread, and
let CandidateWindowContent own its preedit and page snapshot rather than
referencing caller locals.

---------

Co-authored-by: fanlusky <1730976608@qq.com>
2026-10-11 02:08:25 +08:00
luo jiyinandfanlusky 13861f8bad ci: cache Engine compilation with sccache (#770)
* ci: cache Engine compilation with sccache

* ci: verify Engine cache across commits

* ci: harden Engine sccache setup

- Fall back to plain cl.exe when the sccache server is unreachable
- Only report sccache stats when sccache was actually installed
- Also launch C compiles through sccache, matching the Server job
- Note why the Engine job must stay on Ninja Multi-Config

---------

Co-authored-by: fanlusky <1730976608@qq.com>
2026-10-11 01:11:26 +08:00
小莫andfanlusky ad78409e3c ci(release): run the SignPath path on GitHub-hosted runners (#709)
* ci(release): run the SignPath path on GitHub-hosted runners

SignPath's open-source plan accepts a signing request only when every job leading up to it ran on a GitHub-hosted runner, and tsf, server and package all ran on the self-hosted release machine. With WINDOWS_SIGNING_PROVIDER=signpath they now run on windows-2025, restoring vcpkg binaries and (for the Server) sccache the way ci.yml does; the certificate path keeps the self-hosted runner unchanged.

The org secret holding the SignPath API token is SIGNPATH_TOKEN, so the workflow and detect-release-signing.ps1 read that name instead of SIGNPATH_API_TOKEN.

AGENTS.md lists what SignPath needs configured, and the code signing policy records the accepted application and the hosted-runner rule.

* fix(ci): let the SignPath action read the run's artifacts

* fix(installer): drop authenticode-sign attributes SignPath Foundation rejects

* fix(ci): fail the hosted SignPath release before signatures are spent

- Probe ISCC with WizardStyle=modern dynamic and run that probe at the start of the hosted package job, so an image ISCC older than 6.6 fails before the payload signing request instead of after it.
- Verify the TSF vcpkg root before installing into it or saving its archives under the -complete key.
- Check the Server job's C:\vcpkg override against the vcpkg the hosted image puts on PATH.
- Code signing policy: drop the stale "once approved" wording and state that the hosted-runner rule applies to SignPath-signed releases.

* docs: list only the configured SignPath approver

---------

Co-authored-by: fanlusky <1730976608@qq.com>
2026-10-08 23:16:34 +08:00
fanlusky 1ae1f1eddb revert(server): 撤回 #576 的 skin.toml 统一规则
This reverts commit c5b0c24c48.

#576 未经评审即被合入 develop,先撤回,待评审意见处理后重新提交。
2026-10-03 18:11:23 +08:00
小莫 c5b0c24c48 feat(server): read skin.toml with the rules every platform shares (#576)
* feat(server): 外部皮肤接受跨平台客户端的 base 与装饰规则,社区皮肤可在 Windows 加载

社区皮肤库按跨平台客户端(msime 的 client-core)的规则校验,base 写的是全局主题 system / shuishan / light / paper / night / ink,而 Windows 只认六个内置皮肤 ID,所以社区里绝大多数皮肤在 Windows 上整包加载失败。

- base 为 system 时按 fluent 加载,配色原样保留。
- base 为五个内置全局主题时按 fluent 加载,并照 theme::resolve 换算配色:主题固定明暗,只取包里那一种明暗的配色,深浅两种模式都画它;读不懂的颜色当作没写,没写的按主题补齐,右键菜单和悬浮工具栏一并补上。包没声明那一种明暗时不生效,与客户端一致。
- 装饰规则与客户端对齐:空表或两个尺寸都为 0 表示无装饰;有尺寸而无 image 时用图片类型的 preview,都没有就不画。
- 复制 msime-cloud 的 client_dialect.json 作测试夹具,新测试要求客户端接受的每个包在 Windows 上都能加载;scripts/sync-client-dialect.py 负责同步,每周的 Skin client dialect 工作流比对上游。

* feat(server): 皮肤清单与跨平台客户端统一为同一套规则

同一个皮肤包现在在每个平台上要么都能加载,要么都被拒绝。规则以 msime client-core 的 load() 为准,共享用例表 client_dialect.json 改为从 msime 同步,测试要求每一条用例的接受与否都与客户端一致。

- 保留 ID 加上全局主题 ID(system、shuishan、light、paper、night、ink、custom)。
- 收紧到客户端的规则:skin.toml 最大 64 KiB;schema_version 必须是整数 1;author、description 写了不能为空;preview 写了必须指向包内已有的文件;toolbar_stylesheet 写了必须是包根目录里已有的 .css 文件;[license] 的各键有长度限制;[candidate] 与其中的 dark、light 必须是表;装饰图与背景图须是图片扩展名。
- 仓库自带的 7 个皮肤、示例皮肤和 msime-skins 里的 4 个皮肤在新规则下都能加载。
2026-10-03 17:39:49 +09:00
小莫 8814cd41e7 ci(release): add a SignPath signing path, off by default (#589)
The release job can now sign through SignPath instead of the certificate in the repository secrets. It only does so when the WINDOWS_SIGNING_PROVIDER repository variable is set to signpath, which nothing sets yet, so every release keeps taking the existing certificate path until a maintainer switches it.

On the SignPath path, scripts/ci/signpath-files.ps1 stages only the project's own binaries (the seven Server executables and both TSF DLLs) as the signing request's artifact, because SignPath Foundation does not allow signing the third-party DLLs vcpkg builds for the Server. The signed files are checked for a valid Authenticode signature before they replace the originals, and staging fails if a MetasequoiaIme* binary is missing from the list. The installer goes through a second request after it is compiled. installer/signpath/ holds the reviewed copies of the two artifact configurations to paste into SignPath.

detect-release-signing.ps1 fails the release when the provider is signpath but a SignPath setting is missing, or when the provider value is unknown, instead of falling back to the certificate or to an unsigned build.
2026-10-03 03:45:09 +09:00
dependabot[bot] 96306ef273 chore(deps): bump the actions group with 2 updates
Bumps the actions group with 2 updates: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.9 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-01 21:21:50 +00:00
fanlusky ae36403230 feat(installer): 随包安装 skins 下的外部皮肤,覆盖前把改过的同名皮肤备份为 .bak 2026-09-30 23:58:11 +08:00
fanlusky 218542fa35 chore: 将皮肤样例与皮肤合集接入本仓 CI 与文档
移除样例仓库自带的 .github(子目录里的 workflow 不会运行)和误提交的 __pycache__,改由根 CI 的 Skins 任务同时校验 examples/skin-examples 与 skins/。manifest 测试与 schema 说明对齐 Server 皮肤目录的实际规则:base 必填,author 可选。
2026-09-29 19:41:21 +08:00
Jia Sui 0b11322dfd fix(installer): 覆盖安装清空输入统计库——保留与迁移两份名单补上 stats.db
完整包升级走 CleanAppDataExceptUserFiles,它按 IsPreservedAppDataItem 白名单清空数据目录,
不在名单里的项一律删。名单只有 msime_user.db*、config.toml、config.base.toml、skins 和标记
文件,0.8.0 才落地的 stats.db(输入统计,ffcd1aee)从不在其中,于是每次覆盖安装都被
DeleteFile 删掉;Store::Open 固定 SQLITE_OPEN_CREATE,文件一没就立刻重建空库,用户看到的是
统计数字被清零而不是报错。换数据目录安装是同一条缝:MigrateUserDataDir 的 robocopy 清单同样
没有它,文件留在旧目录,随后随 TryDeleteTree(OldDir) 一起没了。

本次把 stats.db 及其三个 sidecar 同时补进覆盖安装保留名单和换数据目录迁移名单,并加一个
静态反解这两份清单的测试互相交叉校验。

- msime_setup.iss:新增 IsUserStatisticsDatabase(stats.db / -wal / -shm / -journal)并接入
  IsPreservedAppDataItem;MigrateUserDataDir 的 robocopy 清单追加同样四个文件名。sidecar 必须
  一起带:安装器先 StopImeProcesses 强杀 Server,WAL 里可能还有尚未 checkpoint 的写入,
  只搬主库会丢掉最后一批数据。卸载路径不动,卸载语义本就是删光用户数据。
- installer/tests/preserve-user-data.ps1(新增):从 iss 源码反解保留名单与迁移名单,断言必需
  名单逐项在两边、两份名单互为子集、Server 侧 stats_pipe.cpp 的库名也在两边,并设规模下限
  防解析器自身失效造成的假绿。注册进 ci.yml 的 packaging job。
2026-09-28 09:13:09 +08:00
fanlusky 4b30659fca ci: 单独构建并运行引擎自己的测试
Server 任务以 BUILD_TESTING=OFF 把引擎当库引入(避免 EXCLUDE_FROM_ALL 下的测试
找不到可执行文件),于是引擎的 23 组测试从来没在 CI 里跑过,只在开发机上跑。
server/tests 覆盖不到的行为——比如用户日志的连接管理、关闭它时要放开数据目录里
所有缓存句柄——只有这些测试能发现;#491 的一个回归就是这样在本地才测出来的。

新增 Engine 任务:按 engine/vcpkg.json 单独配置引擎、构建、再用
scripts/ci/test-engine.ps1 在与 Server 相同的锁定词库上跑 ctest。数据目录与
LOCALAPPDATA 都隔离到临时目录,布局与 test-server.ps1 一致。同步更新
server/CMakeLists.txt 里「引擎测试经 server/tests 覆盖」的旧说法。

本地按同样命令(不设 BOOST_ROOT,只靠 vcpkg 清单)配置、构建并运行:23/23 通过。
2026-09-27 16:54:20 +08:00
fanlusky 9dfa69c7e5 build(installer): 打包神经整句模型并在发布流程中下载
Prepare-PackageFiles 断言并拷贝两个模型与授权声明;release workflow 在收集产物前
运行 fetch-neural-model.ps1。
2026-09-24 14:03:43 +08:00
Evan c8a71ef141 fix(release): notify MSIME-Web after every release, not just the repair path (#451)
The step that dispatches to MSIME-Web was gated on `github.event_name == 'workflow_dispatch'`. This workflow's own header documents workflow_dispatch as the repair path and a push to main as the normal one, so the notification only fired on the branch that almost never runs. MSIME-Web has received zero repository_dispatch events; its most recent twenty sync runs are all `schedule`.

That left the site waiting on a cron GitHub delivers about seven times a day instead of the forty-eight the schedule asks for, with measured gaps of two to five hours. Windows 0.8.0 published on 2026-09-20 and msime.app still offered 0.7.1 a day later.

The enclosing job already runs only when a release is being published, so the step needs no event condition at all.
2026-09-21 14:46:57 +09:00
fanlusky d30d2946e4 feat(installer): 打包时生成并安装词格语言模型 sc.lm
sc.lm 此前只能手工投放,重装即失效,发布包里也没有它。这里把它变成一个被钉住、
可复现、自动参与打包的产品输入。

它不走词库那条路:词库 release 由本仓库之外的构建器产出,资产集合和摘要在产品锁
里逐一钉死,加一项要对方先发新版。改为独立钉住上游语料,与 libime 自己的做法一致。

- language-model/lock.json 钉住上游 URL、语料摘要、转换参数和产物摘要。转换是
  确定性的(已在 MSVC 14.44 与 14.50 两套工具链上验证产物摘要一致),所以产物
  摘要可以像下载摘要一样钉死。
- scripts/build-language-model.ps1 下载、校验、转换、再校验,写临时文件后改名,
  中途失败不会留下摘要对不上的 sc.lm。幂等,摘要对得上直接返回。
- 它只 configure engine/ngram 一个目录,不拉 vcpkg 和 SQLite:转换工具只依赖
  kenlm 自己,而打包机上未必装得起引擎的全部依赖。
- Invoke-LocalTest.ps1 打完整包前自动调用它,轻量包本就不带数据文件,不调。
- 打包脚本只断言文件存在,摘要由构建脚本负责,与词库交给 product_lock.py 校验
  的分工一致。缺模型让打包失败而不是跳过:引擎对缺模型是静默降级的,运行期不会
  暴露,打包是唯一拦得住的地方,package-files.ps1 为此加了反向用例。

模型是 LGPL-2.1-or-later 的第三方数据,声明随之安装为 libime-lm-NOTICE.md。
安装脚本无需改动,它已按通配收集资源目录。产物与语料不进仓库,只进锁与声明。
2026-09-19 10:08:39 +08:00
fanlusky 9bc1c925b2 fix(installer): 正式签名覆盖包内全部 EXE/DLL
此前只有 MetasequoiaImeServer.exe 拿到真实签名——它是唯一一个技术上必须签的,
uiAccess=true 没有可信 Authenticode 签名就会被 Windows 忽略。其余随包分发的
二进制全部未签名:设置页、表情面板、手写面板、键盘面板、看门狗、词库回放,
以及 libcurl/sqlite3/zlib/WebView2Loader 四个 DLL 和两个架构的 TSF DLL。

Microsoft Defender 会按信誉拦下这些未签名的可执行文件,用户看到的现象是输入法
装完了、某个面板却打不开。

package-simplysign.ps1 和 release workflow 现在都签 server_exe\ 与 tsf_dll\ 下的
全部 EXE/DLL,共 13 个文件,加上外层安装包。

所有文件在一次 signtool sign 调用里签完,而不是逐个调用:SimplySign 可能对每次
调用弹一次 PIN,逐个签会把本地打包变成十几次手机确认。签名配额按文件计,合并
调用不会多花配额;证书每月 3000 次,每次发布十几个仍然远在额度之内。
2026-09-17 23:10:54 +08:00
fanlusky 3b6b65020d perf(installer): 本地打包默认不含 PDB,另开带符号入口
本地跑 test-light.ps1 等很久,慢的大头不是编译而是 Inno Setup 在压 PDB:
包里 PDB 约 140 MB,而真正的 EXE/DLL 只有约 20 MB,msime_setup.iss 又是
Compression=lzma2 + SolidCompression=yes,整整一遍压下来轻量包要 58.7 秒。

Prepare-PackageFiles.ps1 新增 -IncludeSymbols,不带它就把 server_exe\ 和
tsf_dll\ 里的 PDB 全部剔除。校验逻辑没有放松:仍然要求 Release 构建产出同名
PDB,缺符号照样打包失败,只是「符号是否随包安装」变成了显式选择。
msime_setup.iss 的两条 *.pdb 加上 skipifsourcedoesntexist,同一份脚本在带
符号和不带符号两种暂存下都能编译。

正式发布行为不变:release.yml 的打包步骤显式传 -IncludeSymbols,发布的安装包
依旧携带与二进制匹配的符号。

test.ps1 和 test-light.ps1 原本是两份几乎逐行相同的拷贝,现在一起收进
Invoke-LocalTest.ps1,三个入口都是它的薄包装:

  test.ps1          含词库,不含 PDB
  test-light.ps1    不含词库,不含 PDB
  test-symbols.ps1  含 PDB,默认轻量,加 -Full 走完整包

轻量包 Inno Setup 耗时 58.7s -> 9.2s,安装包体积 33.4 MB -> 7.7 MB。
2026-09-13 03:56:58 +08:00
dependabot[bot] fecad35baa chore(deps): bump the actions group with 3 updates
Bumps the actions group with 3 updates: [pnpm/action-setup](https://github.com/pnpm/action-setup), [actions/setup-go](https://github.com/actions/setup-go) and [actions/dependency-review-action](https://github.com/actions/dependency-review-action).


Updates `pnpm/action-setup` from 6.0.10 to 6.1.0
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/0977fd99725f1db4007ccb2928dbb4e90d06cc86...ea17c68df8912ef543352723c149a84f56e3d413)

Updates `actions/setup-go` from 6.5.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/924ae3a1cded613372ab5595356fb5720e22ba16...b7ad1dad31e06c5925ef5d2fc7ad053ef454303e)

Updates `actions/dependency-review-action` from 4.9.0 to 5.0.0
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/2031cfc080254a8a887f58cffee85186f0e49e48...a1d282b36b6f3519aa1f3fc636f609c47dddb294)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: actions/setup-go
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/dependency-review-action
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-11 20:01:39 +00:00
fanlusky a7779d2b05 refactor(engine): 将 engine 从 submodule 内嵌为仓内一等组件
`vendor/MetasequoiaImeEngine` submodule 改为 `engine/` 目录,导入的是
product-lock.json 原本钉住的提交 c810d201,逐文件核对过 blob,因此这是一次
搬迁而不是引擎升级。引擎自己的嵌套 submodule(googlepinyinime-rev、utfcpp、
miniaudio)按各自 gitlink 一并展开,来源与提交见 engine/UPSTREAM.md。

Windows 专门化裁掉了不属于本产品的部分:whisper.cpp 与本地推理 provider、
macOS 示例宿主、整个 dictionary/ 建库流水线、上游 CI 与 release-please 配置。
词库仍按 product-lock.json 在构建时取发布产物。

引擎不再进 product-lock.json:没有 gitlink 就没有可比对的东西,锁里写一个上游
commit 等于宣称这棵树仍等于上游,而第一个 Windows 专门化改动落地时这句话就假了。
verify-contracts / verify-checkout 随之移除,verify-published 保留。

CI 与工具链:引擎源码并入根 scripts/format.sh(删掉引擎自己的那份,避免两套排除
列表分叉);引擎 voice.yml 里的 silero_vad.onnx 摘要校验移到本仓 lock job;
engine-bump-triage 工作流与其测试删除;gitsubmodule 的 dependabot 频率由 daily
改为 monthly。

README、README.en、AGENTS.md、CONTRIBUTING、docs/product-release.md 及各子目录
文档同步说明新的位置与边界。
2026-09-12 03:40:48 +08:00
fanlusky 73ec6fe9c9 perf(ci): cache the Server MSVC build with sccache
The Server job's Build step dominates the pipeline (~6m37s of a ~9.5m job;
the dictionary/integration test is only ~43s). sccache caches individual
MSVC compiles across runs so an incremental change rebuilds only what it
touched instead of the whole server + engine tree.

sccache only caches an MSVC compile whose debug info is embedded in the
object, so switch the Server build's Release debug info from /Zi to /Z7.
The linker's /DEBUG still emits the beside-the-executable PDB the release
job validates, so the symbol layout is unchanged.

Its compiler-launcher hook is honoured only by the Ninja and Makefile
generators, so configure the Server build with Ninja Multi-Config (keeping
the --config Release / bin/Release layout the later steps depend on) and
add an MSVC-environment step, since Ninja does not locate cl.exe on its own.
2026-09-11 03:46:30 +08:00
fanlusky d7e7b3f0d9 fix(ci): stop the self-hosted jobs racing on the global git config
The three self-hosted release jobs are separate runner instances on one
machine, so they share C:\Users\runner\.gitconfig and all reach "Trust the
runner workspace" in the same second. Two win the config lock and the third
dies with "could not lock config file ...: File exists", taking Build TSF x64
down before it compiles anything and skipping the installer job.

Retry the write, and re-read safe.directory before each attempt so a peer
instance having already trusted this path counts as success.
2026-09-09 03:00:23 +08:00
fanlusky 28689361ad fix(ci): unblock packaging on the self-hosted runners
Two independent failures kept the v0.6.5 installer from being built after
the pipe probe was fixed.

The package job died in "Verify the release commit is on main" with git
exiting 128 on dubious ownership: runner instance 2 leaves _work owned by
SYSTEM while the job runs as `runner`. actions/checkout is unaffected, so
the first plain git call is what fails, and only jobs scheduled onto that
instance see it. Mark the workspace as safe in the three self-hosted jobs.

Neither vcpkg manifest carried a builtin-baseline, so vcpkg resolved ports
against the registry at HEAD and every build depended on a live fetch of
microsoft/vcpkg. When that fetch degraded, the ports simply vanished:

    Fetching registry information from https://github.com/microsoft/vcpkg (HEAD)...
    fmt does not exist
    utfcpp does not exist

Build TSF x64 failed this way twice and passed twice on the same runner,
which is what an unpinned registry looks like. Pin both manifests to
04a9d8e5, the commit vcpkg-lock.json already records as resolved.
2026-09-09 02:18:57 +08:00
Evan 2fb4560d99 fix(release): use beta tags for automatic builds (#252)
* fix(release): separate ci snapshots from stable tags

* fix(release): use beta tags for automatic builds
2026-09-07 17:56:34 +09:00
Evan 0025e79b45 chore(ci): run CodeQL only on nightly schedule
Run CodeQL daily at 00:00 Asia/Tokyo and remove all other workflow triggers.
2026-09-07 17:55:09 +09:00
Evanandgithub-actions[bot] d1ac5273e4 fix(ci): guard the release vcpkg selection (#247)
* chore(main): release 0.6.1

* release (#245)

* fix(installer): test server before embedding uiAccess manifest (#243)

* fix(ci): align release matrix with selected vcpkg (#244)

* fix(ci): guard the release vcpkg selection

* fix(ci): report the release runner in vcpkg errors

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-07 16:38:19 +09:00
Evan fbd6b390f1 fix(ci): align release matrix with selected vcpkg (#244) 2026-09-07 16:03:23 +09:00
Evan f62e8e5fc8 fix(installer): test server before embedding uiAccess manifest (#243) 2026-09-07 15:37:08 +09:00
Evan Hu 818069f9c3 fix(server): make release probes non-interactive 2026-09-07 13:28:25 +09:00
Neptrue_Lin 4b95c90fde Merge pull request #228 from AaGMix/feat/installer-pdb
feat(installer): include release PDB symbols
2026-09-07 09:46:06 +08:00
Evan ad48153c8e Merge pull request #230 from metasequoiaime/fix/release-vcpkg-lock
fix(server): embed uiAccess manifest before signing
2026-09-07 07:53:08 +09:00
Evan Hu 84de68fd1b fix(server): embed uiAccess manifest before signing 2026-09-07 07:42:14 +09:00
AaGMix e9a2c91214 feat(installer): include release PDB symbols 2026-09-07 02:10:38 +08:00
Evan Hu 2ff0509e67 feat(contracts): verify shared product lock primitives 2026-09-07 02:53:50 +09:00
Evan Hu 5b50503252 fix(ci): avoid duplicate CodeQL scans on pushes 2026-09-07 00:59:42 +09:00
Evan Hu 0973d3d4ef fix(ci): defer next release PR after publish 2026-09-07 00:52:01 +09:00
Evan Hu 7dc68ff498 fix(installer): sign releases from runner certificate store 2026-09-07 00:32:22 +09:00
Evan Hu 5b5960e5a0 fix(ci): correct isolated vcpkg command syntax 2026-09-07 00:05:17 +09:00
Evan Hu 5c85d297cd fix(ci): isolate release vcpkg installations 2026-09-07 00:03:40 +09:00
Evan Hu b827bbee3c fix(ci): serialize release builds sharing vcpkg 2026-09-07 00:02:19 +09:00
Evan Hu 8fa00f5576 chore(ci): 把工作流同步到 main
release.yml 是从 main 运行的,branch-guard 也按 PR 的 base 分支加载工作流定义。两者只合进 develop 时都不生效:main 上的 release-please 仍会把版本 PR 开到默认分支 develop,而提到 main 的 PR 根本不会触发拦截。
2026-09-06 22:51:28 +09:00
Evan 39c94b092d Merge pull request #196 from metasequoiaime/fix/ci-sanitizer-format
fix(ci): separate automatic and manual release locks
2026-09-06 18:39:52 +09:00
Evan Hu 276625fe31 fix(ci): separate automatic and manual release locks 2026-09-06 18:30:33 +09:00
Evan Hu 88720a80df fix(ci): 修复引擎 bump 自动合并的守卫,并补回 Issue 模板的脱敏警告
engine-bump-triage.yml 里 `&& steps.lock.outputs.locked == 'yes'` 被写进了 HEAD 这个环境变量的值,而不是步骤的 if:。它在那个位置根本不是条件:不论契约锁校验通过与否,自动合并都会执行;步骤随后发出的评论还会把 commit 后面跟上字面量 `&& steps.lock.outputs.locked == 'yes'` 一起打印出来。因为没有任何东西失败,这个问题没有暴露过。

(实际风险有限:Product inputs 是必需检查,未审的 bump 不会真的被放行。但这条守卫本身写了等于没写。)

补 tests/test_engine_bump_triage.py 三个断言:自动合并的条件必须同时包含判定和锁;任何步骤的 env 值里都不许再出现条件片段;评论用的 BASE/HEAD 必须只是 range 输出本身。第二条是通用的,同类错误以后写在别的步骤上也会被抓到。

同时补回本仓 bug_report.yml 相对组织模板丢掉的两项:日志字段的「不要粘贴真实输入内容、用户词库、API Key 或任何凭据」加粗警告,以及「这不是安全漏洞」的必选确认项。全组织的 Issue 流量几乎都在这个仓库,恰恰是最需要这两条的地方——输入法的日志天然贴近用户真实输入。
2026-09-06 18:15:51 +09:00
Evan Hu 1c25466511 test(ci): 给解析不可信输入的宿主无关代码加 ASan / UBSan
MSIME-Linux 的 ci.yml 注释里已经写下了这个结论:「前端层才是解析不可信输入的那层……Windows 前端上次审计修的就是一批 race 和空指针,现有的 Debug 构建一个都抓不到。」Linux 仓照这个结论补了 sanitizer job,Windows 仓一条都没有。

给整个 Server 上 sanitizer 意味着要在 Windows runner 上做一份带 sanitizer 的 Boost、curl、sqlite 和 WebView2,代价很高。这里换一个能立刻落地的做法:把宿主无关的解析与策略代码单独建成一个不依赖任何包管理器的小目标,在 Linux runner 上用 ASan + UBSan 跑,几秒钟完成,每个 PR 都跑。

覆盖面确实小于全量 sanitize 构建,但它是真的在跑。目标从皮肤 CSS 策略起步,后续凡是能与 Windows 头文件解耦的、读取用户没写过的数据的逻辑(词库文件、IPC 负载、配置解析)都可以加进这个列表。

该目标同时以 -Wall -Wextra -Wpedantic -Werror 编译,与 Linux、Apple 两仓的标准一致。本机已用 ASan+UBSan 构建并运行通过。
2026-09-06 18:11:37 +09:00
Evan Hu 1ec7bdd690 fix(settings): 检查更新时消费 update.json 的校验值与签名状态
update.json 一直发布四个关于安装包的字段(installerName / installerUrl / installerSha256 / signed),而设置页的 UpdateManifest 类型只声明了 version 和 releaseUrl,另外两个字段发布出来却没有任何人消费。结果是:在安装包未签名的当下,SHA256 是用户唯一的完整性防线,服务端早已算好,却要用户自己去官网翻。

现在发现新版本的对话框会显示:signed 为 false 时给出明确警告(SmartScreen 会拦截、uiAccess 失效导致候选窗无法浮在提权程序之上),以及 Get-FileHash 命令和应得到的摘要,可选中复制。

「不做后台自动检查」是 PRIVACY.md 明示的隐私设计,没有改动——改的只是用户按下检查更新之后看到什么。

校验与展示逻辑抽到 update-manifest.ts:validateManifest 收紧了 releaseUrl 的判断(此前 startsWith 前缀匹配会放过 …/releases.attacker.example 这类同前缀域名),并对三个可选字段做格式校验——安装包名会进入一段让用户粘贴的命令,限制成发布流水线实际产出的形状;格式不对的可选字段按缺失处理,不让整次更新检查失败,老版本 manifest 仍然可用。

接入 vitest,11 个用例覆盖版本解析与排序(0.10.0 > 0.9.0、0.3 == 0.3.0)、manifest 校验的拒绝路径、以及签名/未签名/未声明三种状态下的展示。CI 在 build 之前加一步 pnpm test。
2026-09-06 18:08:34 +09:00
Evan Hu a4d583bf2d ci: sign uiAccess server and installer 2026-09-06 17:04:08 +09:00