Conversation
The startup load path rewrites a changed config.toml with tomli_w.dump, which reserializes the whole document and silently drops the user's comments and layout. The repository already ships a comment-preserving patcher used by three other import paths; this wires it into the migration write: - Extract atomic_replace_bytes so the crash-durability contract (same-dir temp, fsync, 0600, replace) stays in one place; atomic_write_config serializes and calls it. - Carry the pre-migration payload on ConfigMigrationResult so the write path can patch from the exact validated bytes to the new payload. - backup_and_write_migrated_config now patches first; on LosslessTomlPatchError it falls back to the previous whole-file rewrite and records which rewrite ran in the structured warning. Tests: the full startup migration path keeps all three comment forms (byte-equal to the patcher output); moved-on disk bytes exercise the fallback with rewrite=full-reserialize in the structured log.
Contributor
Author
|
CI 结果说明(供参考):本 PR 的 20 pass / 3 fail / 13 skip 中,两处红都已在改动外定性——
本改动自身:本地 CI 同款两相——并行相 31983 passed(38 条失败与 |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
Scope boundary:
src/opensquilla/gateway/config_migration.py(单文件)+ 两个测试文件。启动期配置迁移的落盘从"整档重排"改为"先走仓库自带的保注释 patcher":atomic_replace_bytes(target, data):把atomic_write_config里字节落地那一步(同目录临时文件、fsync、0600、os.replace)抽出来共用——崩溃可持久化契约仍只有一份;atomic_write_config改为tomli_w.dumps成字节后调它(字节与旧tomli_w.dump逐字节等价,已实测)。ConfigMigrationResult增original字段(load 时校验过的迁移前 payload;全仓构造点仅一处);三个门控点与全部调用签名零改动(gateway/config.py0 改动)。backup_and_write_migrated_config:先patch_import_config(盘上字节, original, payload)保注释改写;patcher 抛LosslessTomlPatchError时回落全量重排,并在结构化日志记rewrite: "comment-preserving" | "full-reserialize"(回落时另带lossless_error)。Non-goals: 不改配置值的迁移语义;不改调用侧;不动 onboarding 的合并路径(
onboarding/config_store.py:975那条是合并、不是迁移);不给 patcher 增加新的表达能力。Branch
Base branch: main
Target exception: N/A
Issue
Linked issue: Fixes #1872
If None, reason: N/A
Release Note
Release note: 启动期配置迁移不再整档重排
config.toml——只改写真正变化的行,用户的注释与排版保留;仅当无法无损改写时才回落到旧的整档重写(备份照旧,日志注明)。Tests
Ruff:
uv run ruff check src tests— All checks passedPytest: 新增两条,另跑 CI 同款两相全量——并行相(
-n 8 --dist loadfile):31983 passed / 728 skipped / 38 failed(31983 = 基线 31981 + 新增 2;38 条失败集合与4494195b9基线上同机跑出的清单逐条一致,全部为本机环境类或上游自带红,见下方 details);串行相(ci_serial):313 passed / 5 skipped / 0 failed。新增覆盖:a) 完整启动迁移路径保注释(三种注释形态存活 + 落盘字节 == patcher 输出);b) 盘上字节被外部改动时回落全量重排(结构化日志rewrite=full-reserialize+lossless_error)。Build:
npm --prefix opensquilla-webui run build— 通过(Web UI artifact verified: 156 files,已按仓库流程 stage 给打包);uv build --wheel— 成功(opensquilla-0.5.6-py3-none-any.whl)Regression tests: added
Notes: 为什么这里回落而不是像三处既有 patcher 调用方那样 fail-closed——这条路径在启动加载链上,"补丁打不上"的替代行为是"整档被重排"(本次改动前的既有行为),而不是"半迁移的导入";两者代价不对称,所以保留可用性并显式记录。该理由已写进函数 docstring。
The default test path remains offline, deterministic, credential-free, and safe for forks.
本机全量的环境类失败说明(38 条与 4494195 基线上同机跑出的集合逐条一致,零条与本次改动相关)
WinError 1314(无符号链接特权,未开开发者模式);4 条 Git-Bash → 原生 Python 的/tmp路径互操作;2 条 PATH 缺python3;1 条gh不在 PATH(github技能requires: bins: ["gh"]);1 条本机 ANSI 代码页(GBK)进入子进程输出编码嗅探;1 条本机系统代理注册表项进入 httpx 默认挂载——明细与机制见 docs: add Turn, Tier, and Budget entries to the glossary #1879 的同名 details 块。test_ci/test_workflows.py::test_release_jobs_share_one_rerun_stable_verified_webui_artifact(fix(release): validate existing Draft upgrades without rebuilding #1871 新增 upload 步缺overwrite: true),已另开 [Bug]: 4494195b9 上 test_release_jobs_share_one_rerun_stable_verified_webui_artifact 必红:#1871 新增两个 upload 步缺 overwrite: true([skip ci] 未跑 CI) #1880。PYTHONUTF8=1(GBK 区域默认编码会让tests/contracts/test_page_context_contract.py收集期抛错;UTF-8 环境不触发)。Maintainer Live Check
Maintainer live check: no
Surface: N/A
Maintainer-only note: contributors are not expected to provide secrets or run credentialed live checks. Maintainers may run
Live Release E2Efor provider, browser, gateway, channel, or release smoke coverage.Safety
Secrets, local-only artifacts, private prompts/transcripts, channel identifiers, AI session artifacts, non-public fixtures, and tests/_private/ contents must not be committed.
Third-Party Origin
Third-party origin: none
Details if non-none: N/A
Documentation Changes