Add bundled bus fonts and shared font favorites

This commit is contained in:
2026-10-12 15:00:40 +08:00
parent c9dd03c23b
commit 4be74a34f9
181 changed files with 2078575 additions and 76 deletions
@@ -0,0 +1,32 @@
# 公交窄体双字号优化验收
两款独立字格:类似公交窄体(推荐16px)8×16,类似公交窄体(推荐32px)16×32。每款6884码位,含6763个GB2312汉字。32px中文骨架来源GNU Unifont18.0.01,16px来源Fusion Pixel Font;官方材料、许可、锁定wheel、字模与修订理由随源码保存。正常构建离线完成,不读取Downloads附件。
## 证据
- glyphs-16、glyphs-32:全码位像素图册、audit.json和公交文字样张。全库无空字(空格除外)、灰阶和越格;重复仅ASCII空格/全角空格。
- comparison:旧16、优化16、旧16直接放大、新32的四路比较,以及六类代表字。旧款仅作历史对照,没有登记为第三款可选字体。
- 网页站名对比、网页包围字对比、网页密集字对比、字体选择器截图:实际后端文字层预览及选择器,不以浏览器原生字体代替帧。
- visual-review.json:14页小字、27页大字及分类图的视觉复核记录和局限。
## 本机验证
字体/目录/模板/动图/图层/API定向回归89项通过;新增32→64px整数放大后,放大专项4项通过。Node字体选择器和场景模型24项通过。在含中文及空格的隔离目录新建venv,使用随交付wheel离线安装并重建,两款TTF及manifest字节一致,全字库像素校验通过。
## 已验证经验
Unifont BDF 的BITMAP行尾空格须先去除;单纯cmap覆盖检查不能发现空字。共享像素轮廓边需要抵消,避免FreeType灰阶接缝。字体版本使用缩略图辅助stamp及URL参数,不能修改作品修订号。板端完整测试多份字体占用使/run tmpfs不足,生产未切换;改用任务专属/var/tmp保存测试产物后重测。稳定要求与经验已补入测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md。
## 边界
分类规则生成与独立网格改绘分别记录,不把全部字形声称为逐字手工设计。16px复杂汉字仍需要简化;32px的硼、牖、鼬等少见密集字仍较拥挤,需要结合词语辨识。没有真实用户辨识率实验。主要站名和分类字的结构细节优于旧款直接放大;不能据此推断所有字同等易读。
本轮不修改Android、不导出OTA/IMG、不推进VERSION,不启动摄像头或实屏测试图案。
## 部署
板端候选90项中89项通过,1项Node跨语言测试在板端跳过(本机已通过)。候选通过后保护运行目录,备份替换文件与登记字体,切换真实systemd服务。部署记录见deployment-result.json:446个其他持久文件摘要不变,变化仅为两款新增字体和摘要一致的旧字体删除。现有设备作品没有引用被更新字体,受影响缩略图数量为0;缩略图重建和不改修订的路径由候选测试验证。
设备验证见device-verification.json与device-frames:15组最终帧与本机逐像素一致;旧摘要别名与优化16px相同。真实systemd服务重启后两款仍可选,持久数据摘要不变。22个部署代码/字体/登记/来源校验文件与本机摘要一致,旧程序资源不再存在。rollback.tar.gz为历史回滚备份,未登记为可选字体。更新前完整持久文件摘要保存在本项目被忽略的受保护本机材料中,不进入公开日志。
cleanup-and-hashes.json登记已清理的板端目录:/run/matrix-screen-controller/bus-fonts-v2-20261012、/var/tmp/qms-bus-fonts-v2-tests-20261012,以及/var/tmp/qms-bus-fonts-v2-rollback.tar.gz。未清理其他设备材料。此前被策略拒绝的本机临时清理未重试或换方法绕过;本轮受保护基线和调试材料继续留在项目本机测试环境.local中。
@@ -0,0 +1,78 @@
88a028196ffc4c43478b554d38dfd720e242f137740f186a2822b470ca333a1a cleanup-and-hashes.json
78cba5da3949fb038adb35ca349620f35bf69319cd5849691f2c6f730766fe00 comparison/class-dense.png
ed8e0b27faf0dc469112f9680eee67b36bf75f58d6f6673a72981849c446430b comparison/class-diagonal.png
4e03858f4030113de2e97c819182cc14694013f256d0b6489600acdb62441158 comparison/class-enclosure.png
68cfa34f74392b66104abe5444ec8130ee02106d139f7ba348949f5d880ca6b5 comparison/class-latin.png
8e99f94d0a2702bdbdf21c9e091ccb182efcfe2726eb8e8036d2b8dca8a25410 comparison/class-left_right.png
ed1041e5592156b0145ba558fdb80835f1d988de01a629065311a7b692695e56 comparison/class-stacked.png
f057b3e3d7d51beac5631ceb94cefd477b559536476d2ebd33ff00a20372e837 comparison/four-way.png
ae4b88a5536ce7dd9883b9954e4066bcea2f29687d9abfd430fa1c28384daaf7 deployment-result.json
cf4065a36fed4367cc030226b8185b8f5e232f2160f55143fb43ca087ec75ce5 device-frames/16-0O1Il5S8B.png
5e3ae43e4a4a3499fd9d4b1207b708c367c21f864c3fb8851e3ed4fa472e79e2 device-frames/16-人入大文.png
61afaa65a9c1bd59c0dcc9f250e698a17f97dc0074fda4fd375e6f1a5d147cf2 device-frames/16-口日目田.png
6df42db997f9505d5b3cae5d3cb758afb9c3b97548e70de942d0ff8cd92e8030 device-frames/16-站铁路湖.png
2280286d9c8e932fabe1338e93345fc5f694d81c00982a03b6c87d300f44bf44 device-frames/16-高花草重.png
75614aed2e0c3150fed451c9a34886343b34f5ae0bbdd34e8a3f138660e0fd85 device-frames/16-高铁北站21路.png
af9e5da1a383e7e9996de6502889bc6f73dbca519cb12ad8dda05a9d941a9a66 device-frames/16-鹤警藏赢.png
787a5098a408365b70f4eb4eaf3a4e6ea2ca4298ecfa51501e011d52b2d74eb5 device-frames/32-0O1I.png
f2504e21687c6bba6b4b8a4699fb5d59d69d2bcca89cf8ef0a1347089f519854 device-frames/32-l5S8B.png
f2fbaa613eb13cab5d095ab9492926db2b4b6aa97478ba4e50a59c38f2dbd716 device-frames/32-人入大文.png
d1072001ba2772457e89b031cb3bdd4be31287e62b3a6be01099c096905cc96c device-frames/32-口日目田.png
74093b55f7bfb0ccff693f6cde2f714893832e5d7ff94674b377b506a365adc7 device-frames/32-站铁路湖.png
0cf5c1d45a1f6fff029b3fac98a57db83f05e8d7580627aad32cfb7771de1e58 device-frames/32-高花草重.png
16d8736d84a66fd03ee155ac33654219ae2e1855d4daa03342bd1fe04c580af9 device-frames/32-高铁北站.png
757e0812f199ba3d9a6a2446fcdfa1a06b0f08d426fe8a705626e5f227f58f17 device-frames/32-鹤警藏赢.png
f923d1785788181ad8cdf75e50b5d043420bab9dcfa0dc7256821d1cac345e3a device-verification.json
348dd8c9aee0266420e3585275d35d6d1c4f9a3648caaa0362ebcb7be488c43b glyphs-16/audit.json
2c232f44355d72e242423118d46213418050605b85ef9df67acc59cb1f901750 glyphs-16/comparison.png
67196a50f2687afe57233ed49996dc7ed4353cb1d4f1341af31a5b5dfa3694ea glyphs-16/glyphs-01.png
70731b53a11fe1e1faf81fa19ede7680473e017932a1dccc9b1b19d6dd545c55 glyphs-16/glyphs-02.png
ece1b9e90e3bf28273eb9651aa15e45a2f04dac620b6ed85c2ca6baa45620047 glyphs-16/glyphs-03.png
9bc2ac1601d58cbb1abb588397709be752b4c0297be5a962c807e94654e87bfd glyphs-16/glyphs-04.png
2e678c7bbf004c62f60b4277ad0a042b28d57eec0c6493178422ade060b91ecb glyphs-16/glyphs-05.png
4749e48a82df7bbf922214740c84f52d62633a0e405b0012a6988fa62442738a glyphs-16/glyphs-06.png
ebfeb09c57bef917f6c30f0fe397b7a99e10f117e4ee203e814f80bc5819b6ba glyphs-16/glyphs-07.png
efd54aefba31d33039bb9b2f3c6fc3c86218f9954f2ca7f9176f39887cdb2b10 glyphs-16/glyphs-08.png
7a2961bfacd46ace736f8b7c80c9f909390129c4ef3b9085b8ca1651ea17cab6 glyphs-16/glyphs-09.png
68c8ab5f21a074922eb018205796f99ec46492306d831c14b1c8092bfa403225 glyphs-16/glyphs-10.png
300cd2062b68d4449fa299aedecee9c61c43f11b3ca6b306ef46416060cd3eec glyphs-16/glyphs-11.png
d6f3395494dad5d8b5c29a6c799763ae9f105c686306770bf13fb08e6f31c4d6 glyphs-16/glyphs-12.png
3c2f146c8d86af6fc43e91613e9ce46b9ef61d9a26c5a5c39aaa09ad7cc9ae19 glyphs-16/glyphs-13.png
a2ee91bc201e7d4f90adb738abbb1fa898e02ec0e901e24e7c7457a39a5fb390 glyphs-16/glyphs-14.png
21be522fb032972a90432aaaf744541f53c66666f5312f7fe8eaf2415a204662 glyphs-32/audit.json
9f74440751e4b38a0362c515ffbec100ba660c9c7ff881d23ed485fd0bd604ed glyphs-32/comparison.png
777c0f5c89e3646bbe1a65aa6125926688d89c6973ecfe17c3a4c07e457af124 glyphs-32/glyphs-01.png
b9e708ef7f2fc9cb11b5f515510171afc4a24a38ac7edb86004cb04e377e7cd7 glyphs-32/glyphs-02.png
fa27bac94e0610868cb5cb97e74142e78824349160bcd581d60b9733341668e6 glyphs-32/glyphs-03.png
768485669bb9d580e47740b41b9b0b94bdefe55e70c745b413aa70561459aa1e glyphs-32/glyphs-04.png
286a4343832e1d342c358ebcc1acae2de6876ee99ca7f1bdf5361a98f7f115c7 glyphs-32/glyphs-05.png
2bcef2e11d1d09d65248e0eaeee1dc5f7038764198bfb95b23d6df8bf00b5a87 glyphs-32/glyphs-06.png
99839241053a32cc3627c45b107d0c8dbece838586a26972862800458cfaf024 glyphs-32/glyphs-07.png
0e34aa1bab395b6f75bfce6950bda03d5f1f0ac62bd800c7cce21ec1b099c0df glyphs-32/glyphs-08.png
a58af2596da4a2fe3be0904abd003a057885a83070c4084aab7ef6661af8fcaa glyphs-32/glyphs-09.png
67b721a6cb876733d4341a029673e0f916006edc039e2bd2252246e329cd0327 glyphs-32/glyphs-10.png
7dba664403211533678220b05946554a2942030d679101c213a523544c0ce0e0 glyphs-32/glyphs-11.png
946667d85424c31d2fb6b18b5ef7bd59deceefabd4896e96b96663db2176aed2 glyphs-32/glyphs-12.png
84150181e523c3831c13bd75e2913913b44c7f11cfe3ba2fcf714bebe97830e8 glyphs-32/glyphs-13.png
5eea7f55e2e986e3994f8e25df2200d800b3d232e1c038ad408089d09d9be5e9 glyphs-32/glyphs-14.png
5ef624f7f9c3a7b8121f12ca2329d16d4bec61de23197915f78058d70bc0c488 glyphs-32/glyphs-15.png
05a589e15269798a81f11626c7c7d5d05a5980afa3e79e94a4e38edba8b0942b glyphs-32/glyphs-16.png
51a0cbc98c147cd0c0eaa0eb851ff24a7771d066df304ed9898a54093c2f1863 glyphs-32/glyphs-17.png
c3dba0870b405f6bcfd887e2a35a51c07c7eca8ee57accdd4f6f36fff1d87d80 glyphs-32/glyphs-18.png
cae7953dcd6b115ff2cbbad6f8f43d8a1eb41b290c67a92c7fdc8a5857b64058 glyphs-32/glyphs-19.png
d718821127f635f1108f8cd792277eb80a17efcec8b2a5255005bd2b9da7ee44 glyphs-32/glyphs-20.png
02e3dd420c9226ee4a599a670b8fc0e6af12799b449b7cd10b55d5464d9a5c20 glyphs-32/glyphs-21.png
18307bb08ce66800491dc753dbf2e8a365ac78c5caea8c051514f6bda30ef439 glyphs-32/glyphs-22.png
fc418d2e43383d05c8594ec713b7fa37d2435373f09525b6b63dff03d3131435 glyphs-32/glyphs-23.png
967185f45c6e0311ac2ebe657b65e8943652fd0b37c208773270ac58a0b8269c glyphs-32/glyphs-24.png
1dc5cfb53a93ef324210f8c046e726c3c98c993ab3ee6fe905e83686498e2596 glyphs-32/glyphs-25.png
93245747ed06e16df5ee374eb09c12dc1a9e0fb68d813860af18a895df1a9970 glyphs-32/glyphs-26.png
c7fb0a5a4fefb78677c41152b3c31761f8cd479f90c62d7cb1bdbcb7cf4c357e glyphs-32/glyphs-27.png
3a9fb309a872a65252fab71127d5a1bbee8e0723442d2716bfe99c82ca4f31ee README.md
0919ae2b0b7df6ba3f57f926a28cc518bf08dd8c848bb71bf9d7251208eaa166 rollback.tar.gz
135eb953e755af5841d977f7eb692bfccb8f719fa69d8371b81071e5c747abad test-results.json
613922e85b3a53b593d640c7312859511dbf83050fdd6de7dc723be6f27726b5 visual-review.json
3558b3c2a81d83e30d75719f6f6b40317e0482f20608ed2908bda7a1388abbd0 字体选择器.jpg
c0871027be3f1264b8c3895a3467ea2e380c5a66fdded53c9a3af92176a7c87c 网页包围字对比.jpg
3a310e017c2c9b308c9f6534a04475ecde883f5b3a19c5aa4a6eb873a5081b34 网页密集字对比.jpg
96522056ba2b20a7b25f3b75780c6aee6558d86dff2c1244969ac0bd7b211588 网页站名对比.jpg
@@ -0,0 +1,10 @@
{
"deployed_file_hashes_verified": 22,
"protected_baseline_equal_to_deployment_result": true,
"service_active": true,
"cleaned": [
"/run/matrix-screen-controller/bus-fonts-v2-20261012",
"/var/tmp/qms-bus-fonts-v2-tests-20261012",
"/var/tmp/qms-bus-fonts-v2-rollback.tar.gz"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@@ -0,0 +1,51 @@
{
"result": "deployed",
"unchanged_persistent_files": 446,
"changed_allowed": [
"fonts/aba652e330975ff3db2f41a2795a2d0478806ed83c52197acdbee85291cf5111.font",
"fonts/b1d4035f2fa9dfd839f1b573b994cbec245f041c4a0a62ee9ef1a7c7b1bfa126.font",
"fonts/d38bf29d6408a6f731865a1ca760a80b5156ebf6ab96d5ad8d649df28163564c.font"
],
"affected_thumbnails": [],
"old_font_removed": true,
"runtime_survived_stop": true,
"manifest": {
"version": 2,
"fonts": [
{
"id": "builtin:walnut-bus-8x16",
"file": "SimilarBus8x16.ttf",
"sha256": "aba652e330975ff3db2f41a2795a2d0478806ed83c52197acdbee85291cf5111",
"label": "类似公交窄体(推荐16px)",
"family": "类似公交窄体(推荐16px)",
"style": "Regular",
"glyph_count": 6884,
"recommended_size": 16,
"cell": [
8,
16
]
},
{
"id": "builtin:walnut-bus-16x32",
"file": "SimilarBus16x32.ttf",
"sha256": "b1d4035f2fa9dfd839f1b573b994cbec245f041c4a0a62ee9ef1a7c7b1bfa126",
"label": "类似公交窄体(推荐32px)",
"family": "类似公交窄体(推荐32px)",
"style": "Regular",
"glyph_count": 6884,
"recommended_size": 32,
"cell": [
16,
32
]
}
],
"obsolete": [
"d38bf29d6408a6f731865a1ca760a80b5156ebf6ab96d5ad8d649df28163564c"
],
"aliases": {
"user:d38bf29d6408a6f731865a1ca760a80b5156ebf6ab96d5ad8d649df28163564c:0": "builtin:walnut-bus-8x16"
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

@@ -0,0 +1,9 @@
{
"restart_persistent_unchanged": true,
"old_alias_pixel_match": true,
"font_labels": [
"类似公交窄体(推荐16px)",
"类似公交窄体(推荐32px)"
],
"local_device_pixel_equal": 15
}
@@ -0,0 +1,174 @@
{
"glyph_count": 6884,
"grey": [],
"blank": [],
"right_edge_lit": [],
"duplicates": [
[
"0020",
"3000"
]
],
"densest_32": [
{
"codepoint": "86D0",
"lit_pixels": 67,
"density": 0.5234375
},
{
"codepoint": "7792",
"lit_pixels": 67,
"density": 0.5234375
},
{
"codepoint": "916E",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "817C",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "811A",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "7784",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "64D0",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "571C",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "5704",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "9E4F",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "9B4D",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "9190",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "8774",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "80F4",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "7F71",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "570A",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "5708",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "5703",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "9CD3",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "961A",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "8DDA",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "89D0",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "89CF",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "8334",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "77B0",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "77A9",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "56EB",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "56E4",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "9F83",
"lit_pixels": 63,
"density": 0.4921875
},
{
"codepoint": "9CB4",
"lit_pixels": 63,
"density": 0.4921875
},
{
"codepoint": "9603",
"lit_pixels": 63,
"density": 0.4921875
},
{
"codepoint": "9522",
"lit_pixels": 63,
"density": 0.4921875
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

@@ -0,0 +1,174 @@
{
"glyph_count": 6884,
"grey": [],
"blank": [],
"right_edge_lit": [],
"duplicates": [
[
"0020",
"3000"
]
],
"densest_32": [
{
"codepoint": "787C",
"lit_pixels": 318,
"density": 0.62109375
},
{
"codepoint": "7256",
"lit_pixels": 316,
"density": 0.6171875
},
{
"codepoint": "9F2C",
"lit_pixels": 312,
"density": 0.609375
},
{
"codepoint": "917E",
"lit_pixels": 312,
"density": 0.609375
},
{
"codepoint": "68DA",
"lit_pixels": 306,
"density": 0.59765625
},
{
"codepoint": "6175",
"lit_pixels": 306,
"density": 0.59765625
},
{
"codepoint": "5220",
"lit_pixels": 304,
"density": 0.59375
},
{
"codepoint": "955B",
"lit_pixels": 302,
"density": 0.58984375
},
{
"codepoint": "9EFC",
"lit_pixels": 300,
"density": 0.5859375
},
{
"codepoint": "918B",
"lit_pixels": 298,
"density": 0.58203125
},
{
"codepoint": "89CF",
"lit_pixels": 298,
"density": 0.58203125
},
{
"codepoint": "812F",
"lit_pixels": 298,
"density": 0.58203125
},
{
"codepoint": "580B",
"lit_pixels": 298,
"density": 0.58203125
},
{
"codepoint": "570A",
"lit_pixels": 296,
"density": 0.578125
},
{
"codepoint": "9CA1",
"lit_pixels": 294,
"density": 0.57421875
},
{
"codepoint": "8E66",
"lit_pixels": 294,
"density": 0.57421875
},
{
"codepoint": "537F",
"lit_pixels": 294,
"density": 0.57421875
},
{
"codepoint": "9E42",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "916C",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "81CC",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "8169",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "7EF7",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "77B0",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "73CA",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "5889",
"lit_pixels": 292,
"density": 0.5703125
},
{
"codepoint": "9163",
"lit_pixels": 290,
"density": 0.56640625
},
{
"codepoint": "84AF",
"lit_pixels": 290,
"density": 0.56640625
},
{
"codepoint": "6930",
"lit_pixels": 290,
"density": 0.56640625
},
{
"codepoint": "9EDC",
"lit_pixels": 288,
"density": 0.5625
},
{
"codepoint": "9CAB",
"lit_pixels": 288,
"density": 0.5625
},
{
"codepoint": "97B4",
"lit_pixels": 288,
"density": 0.5625
},
{
"codepoint": "90E6",
"lit_pixels": 288,
"density": 0.5625
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0919ae2b0b7df6ba3f57f926a28cc518bf08dd8c848bb71bf9d7251208eaa166
size 3373825
@@ -0,0 +1,26 @@
{
"local_python": {
"passed": 89,
"additional_integer_scaling_passed": 4
},
"local_node": {
"passed": 24
},
"candidate_board": {
"passed": 89,
"skipped": 1,
"skip_reason": "Node仅用于本机跨语言一致性,本机已通过"
},
"offline_isolated_build": {
"fonts_and_manifest_identical": true,
"both_full_pixel_audits_passed": true
},
"first_board_attempt": {
"production_unchanged": true,
"cause": "run tmpfs exhausted by test font copies",
"passed": 59,
"failed": 29,
"skipped": 1
},
"resolved": "task test data moved to var/tmp and full candidate regression passed"
}
@@ -0,0 +1,20 @@
{
"reviewed_sheets": {
"16px": 14,
"32px": 27
},
"classification_sheets": 6,
"small_revisions": 73,
"large_revisions": 120,
"boundary": {
"16px": [
"复杂汉字压缩仍会降低辨识度;优先32px"
],
"32px": [
"硼 U+787C",
"牖 U+7256",
"鼬 U+9F2C"
],
"note": "密度较高的少见字仍需结合实际词语辨识;没有重复汉字轮廓,但这不等于所有字在单字条件下同等易读。"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

@@ -0,0 +1,35 @@
# 公交窄体首版验收
已制作、集成并部署“核桃公交窄体(推荐16px)”。字格 8×16,6763 个 GB2312 汉字、95 个可打印 ASCII、26 个标点/符号,共 6884 个码位。完整字模、42 项逐字修订、离线构建脚本、锁文件、wheel、上游许可和校验信息保存在 `核桃派软件源代码/font_sources/walnut-bus-8x16/`。字体本体为 `核桃派软件源代码/app/fonts/bundled/WalnutBus8x16.ttf`,摘要见 manifest 与 summary。
## 实际验证
- 本机 Python 相关套件 68 项及补充的新字体模板/裁切/回退测试 1 项通过;Node 字体选择器、场景、图层 24 项通过。
- 全部 6884 个字符在 16px 下与字模逐像素一致,alpha 只有 0/255;非空字符无空白、无越格,最后一列保留间隔。32/48/64px 的重点字与整数倍最近邻放大一致。
- 14 页最终字形图册分批查看;重复字形只有空格/全角空格。密度最高 32 字记录在 audit 中;复杂字简化边界保留,不以覆盖检查代替辨识率实验。
- 带中文和空格的隔离副本从新建字体 venv、本地锁定 wheel 重建,TTF 字节一致,完整校样再次通过。
- 网页实际搜索、选择、16px 设置及三行最终合成预览已检查,见 `网页最终预览.jpg`。截图来自本机 mock 页面,“未连接”状态仅指本机 mock 的设备网络信息,不代表部署失败。
- 核桃派隔离候选中累计 68 项 Python 测试通过。1 项 Node 跨语言比较因板端没有 Node 跳过,同项已在本机通过,没有为本次字体任务增加板端 Node 依赖。
- 部署前后 446 个原有持久文件摘要一致,只新增 1 个字体文件。真实 stop/start 的运行目录保留检查通过;后续真实 restart 后 447 个持久文件摘要一致,字体目录仍可用。
- 设备实际 `/api/preview/text-layer` 返回的五组 PNG 在重启前后字节一致,解码后与本机预览逐像素一致。`device-*.png` 是设备原始透明预览;`设备渲染样张.png` 是关闭平滑的放大排版,不是摄像头画面。
- H618 真实驱动仍可用,读取状态时最后错误、OE 错误及 safeoff 错误均为空。驱动参数和扫描实现未改;不据启动时刷新率采样值声称实屏视觉验收或刷新性能验收通过。
正式 VERSION 保持原值,没有导出 OTA/IMG、没有修改或发布 App。功能更新时间为 `2026-10-12T11:09+08:00`。未启动摄像头、未切换实屏测试图案,也没有物理接线或断电操作。
## 已修复的测试准备问题
首次 SFTP 直传任务运行目录失败:父目录仅 root 可访问,子目录 chown 无法绕过父目录权限。改用具名 `/var/tmp/` 暂存后由 sudo 转入任务目录,立即删除上传文件,没有放宽生产目录权限。
隔离候选首次遗漏 VERSION 导致测试无法收集,补齐后有 66 项通过、1 项 Node 比较跳过;另一个测试因遗漏 systemd 文件失败。补齐原生产 systemd 文件后定向重测该项通过。均未在失败状态下切换生产服务。记录中的旧部署路径来自板端历史 `.pyc` 的 traceback,不是对旧工作区的构建依赖。
可重复经验已更新到 `测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md` 的 TEST-BUS-FONT 条目。接缝合并、bearing、构建锁定和复杂字边界也记录在字体源目录 README。
## 回滚与清理
`rollback.tar.gz` 保存部署前被替换的程序文件,`deployed-files.json` 登记本轮程序文件;回滚时停服务、恢复 backup 中的旧文件,再移除登记的新增程序文件,然后启动并等待健康检查。持久字体、用户配置和用户资源不删除;保留运行目录,不修改 systemd unit。该备份不含设备凭据。
远端本轮候选、测试数据、程序备份和日志在归档拉回后清理,具体路径和结果见 `cleanup.json`。本机持续使用的字体构建环境保留在项目专用 `.local/font-build/`。临时网页与 mock 服务已关闭。本机 10 个具名任务目录及 7 个一次性辅助脚本的批量清理被安全策略拒绝,工具仅返回 blocked by policy,没有提供进一步原因;未换手段重试。本机这些文件仍在,已无用途,可由用户按 `cleanup.json` 的完整仓库相对路径手动删除;不得删除其中未列出的材料、持续环境或用户数据。
## 保留边界
8 列汉字不是标准印刷字形,罕用密集字(如鹤、警、藏、赢、鬻及密度榜中的字符)仍依赖简化和上下文;尚未做真实用户逐字辨识率测试。非 16px 整数倍字号不保证二值边缘。网页最终帧作为本轮视觉依据,不记录为物理实屏观察通过。
@@ -0,0 +1,174 @@
{
"glyph_count": 6884,
"grey": [],
"blank": [],
"right_edge_lit": [],
"duplicates": [
[
"0020",
"3000"
]
],
"densest_32": [
{
"codepoint": "9190",
"lit_pixels": 69,
"density": 0.5390625
},
{
"codepoint": "571C",
"lit_pixels": 69,
"density": 0.5390625
},
{
"codepoint": "9CB4",
"lit_pixels": 68,
"density": 0.53125
},
{
"codepoint": "91B4",
"lit_pixels": 67,
"density": 0.5234375
},
{
"codepoint": "86D0",
"lit_pixels": 67,
"density": 0.5234375
},
{
"codepoint": "7792",
"lit_pixels": 67,
"density": 0.5234375
},
{
"codepoint": "5708",
"lit_pixels": 67,
"density": 0.5234375
},
{
"codepoint": "916E",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "817C",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "811A",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "7784",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "64D0",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "5704",
"lit_pixels": 66,
"density": 0.515625
},
{
"codepoint": "9E4F",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "9B4D",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "8774",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "80F4",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "7F71",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "570A",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "5703",
"lit_pixels": 65,
"density": 0.5078125
},
{
"codepoint": "9CD3",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "961A",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "8DDA",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "89D0",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "89CF",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "8334",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "77B0",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "77A9",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "56EB",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "56E4",
"lit_pixels": 64,
"density": 0.5
},
{
"codepoint": "9F83",
"lit_pixels": 63,
"density": 0.4921875
},
{
"codepoint": "9603",
"lit_pixels": 63,
"density": 0.4921875
}
]
}
@@ -0,0 +1,31 @@
{
"removed": [
"/run/matrix-screen-controller/bus-font-20261012",
"/var/tmp/qms-bus-font-upload-20261012.tar"
],
"shared_runtime_preserved": true,
"service_active": true,
"font_available": true,
"local_unused_manual_cleanup": [
"测试相关资料/如何测试/本机测试环境/.local/work/公交 字体隔离",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-deploy",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-extra-pytest",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-font-proof-final",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-font-proof-v1",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-font-proof-v2",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-font-proof-v3",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-parity-data",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-pytest",
"测试相关资料/如何测试/本机测试环境/.local/work/bus-web",
"测试相关资料/如何测试/本机测试环境/.local/work/archive_bus_font.py",
"测试相关资料/如何测试/本机测试环境/.local/work/bus_remote.py",
"测试相关资料/如何测试/本机测试环境/.local/work/cleanup_bus_remote.py",
"测试相关资料/如何测试/本机测试环境/.local/work/deploy_bus_font.py",
"测试相关资料/如何测试/本机测试环境/.local/work/isolate_bus_font.py",
"测试相关资料/如何测试/本机测试环境/.local/work/refine_bus_font.py",
"测试相关资料/如何测试/本机测试环境/.local/work/verify_bus_device.py"
],
"local_cleanup_rejected": "blocked by policy; no further reason provided",
"font_build_environment_retained": true,
"mock_server_stopped": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@@ -0,0 +1,31 @@
{
"restorable_files": [
"FEATURE_UPDATED_AT",
"app/fonts/store.py",
"tests/test_fonts.py"
],
"added_program_files": [
"app/fonts/bundled/LICENSES/boutique-bitmap-7x7/OFL.txt",
"app/fonts/bundled/LICENSES/galmuri/LICENSE.txt",
"app/fonts/bundled/LICENSES/misaki/misaki.txt",
"app/fonts/bundled/LICENSES/miseki-bitmap/LICENSE.txt",
"app/fonts/bundled/OFL.txt",
"app/fonts/bundled/WalnutBus8x16.ttf",
"app/fonts/bundled/manifest.json",
"font_sources/walnut-bus-8x16/README.md",
"font_sources/walnut-bus-8x16/glyphs.json",
"font_sources/walnut-bus-8x16/requirements-build.lock.txt",
"font_sources/walnut-bus-8x16/revisions.json",
"font_sources/walnut-bus-8x16/upstream/LICENSES/boutique-bitmap-7x7/OFL.txt",
"font_sources/walnut-bus-8x16/upstream/LICENSES/galmuri/LICENSE.txt",
"font_sources/walnut-bus-8x16/upstream/LICENSES/misaki/misaki.txt",
"font_sources/walnut-bus-8x16/upstream/LICENSES/miseki-bitmap/LICENSE.txt",
"font_sources/walnut-bus-8x16/upstream/OFL.txt",
"font_sources/walnut-bus-8x16/upstream/fusion-8px-bdf.zip",
"font_sources/walnut-bus-8x16/upstream/fusion-pixel-8px-monospaced-zh_hans.bdf",
"font_sources/walnut-bus-8x16/upstream/source.json",
"scripts/build_bus_font.py",
"scripts/proof_bus_font.py",
"tests/test_bus_font.py"
]
}
@@ -0,0 +1,235 @@
8d99e3cb8c63490e019dd3d567ba874dd75c250dc9b94fb0fb6097717568970d /run/[private]-screen-controller/bus-font-20261012/payload.tar
==================================== ERRORS ====================================
___________________ ERROR collecting tests/test_bus_font.py ____________________
app/ota/versioning.py:36: in read_software_version
return SoftwareVersion.parse(path.read_text(encoding="utf-8"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1059: in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1045: in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E FileNotFoundError: [Errno 2] No such file or directory: '/run/[private]-screen-controller/bus-font-20261012/candidate/VERSION'
The above exception was the direct cause of the following exception:
tests/test_bus_font.py:16: in <module>
from app.main import create_app
app/main.py:2106: in <module>
app = create_app(ui_copy_editor_build_enabled=UI_COPY_EDITOR_BUILD_ENABLED)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/main.py:449: in create_app
software_version = read_software_version(code_root)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/ota/versioning.py:38: in read_software_version
raise RuntimeError(f"software VERSION file is unreadable: {path}") from exc
E RuntimeError: software VERSION file is unreadable: /run/[private]-screen-controller/bus-font-20261012/candidate/VERSION
_____________________ ERROR collecting tests/test_fonts.py _____________________
app/ota/versioning.py:36: in read_software_version
return SoftwareVersion.parse(path.read_text(encoding="utf-8"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1059: in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1045: in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E FileNotFoundError: [Errno 2] No such file or directory: '/run/[private]-screen-controller/bus-font-20261012/candidate/VERSION'
The above exception was the direct cause of the following exception:
tests/test_fonts.py:12: in <module>
from app.main import create_app
app/main.py:2106: in <module>
app = create_app(ui_copy_editor_build_enabled=UI_COPY_EDITOR_BUILD_ENABLED)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/main.py:449: in create_app
software_version = read_software_version(code_root)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/ota/versioning.py:38: in read_software_version
raise RuntimeError(f"software VERSION file is unreadable: {path}") from exc
E RuntimeError: software VERSION file is unreadable: /run/[private]-screen-controller/bus-font-20261012/candidate/VERSION
_________________ ERROR collecting tests/test_scene_layers.py __________________
app/ota/versioning.py:36: in read_software_version
return SoftwareVersion.parse(path.read_text(encoding="utf-8"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1059: in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1045: in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E FileNotFoundError: [Errno 2] No such file or directory: '/run/[private]-screen-controller/bus-font-20261012/candidate/VERSION'
The above exception was the direct cause of the following exception:
/usr/lib/python3.11/importlib/__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1206: in _gcd_import
???
<frozen importlib._bootstrap>:1178: in _find_and_load
???
<frozen importlib._bootstrap>:1149: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:690: in _load_unlocked
???
/opt/[private]-screen-controller/.venv/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
exec(co, module.__dict__)
/opt/[private]-screen-controller.stage.animation-20261010-094a526b/tests/test_scene_layers.py:11: in <module>
???
app/main.py:2106: in <module>
app = create_app(ui_copy_editor_build_enabled=UI_COPY_EDITOR_BUILD_ENABLED)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/main.py:449: in create_app
software_version = read_software_version(code_root)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/ota/versioning.py:38: in read_software_version
raise RuntimeError(f"software VERSION file is unreadable: {path}") from exc
E RuntimeError: software VERSION file is unreadable: /run/[private]-screen-controller/bus-font-20261012/candidate/VERSION
___________________ ERROR collecting tests/test_templates.py ___________________
app/ota/versioning.py:36: in read_software_version
return SoftwareVersion.parse(path.read_text(encoding="utf-8"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1059: in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1045: in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E FileNotFoundError: [Errno 2] No such file or directory: '/run/[private]-screen-controller/bus-font-20261012/candidate/VERSION'
The above exception was the direct cause of the following exception:
/usr/lib/python3.11/importlib/__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1206: in _gcd_import
???
<frozen importlib._bootstrap>:1178: in _find_and_load
???
<frozen importlib._bootstrap>:1149: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:690: in _load_unlocked
???
/opt/[private]-screen-controller/.venv/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
exec(co, module.__dict__)
/opt/[private]-screen-controller.stage.animation-20261010-094a526b/tests/test_templates.py:10: in <module>
???
app/main.py:2106: in <module>
app = create_app(ui_copy_editor_build_enabled=UI_COPY_EDITOR_BUILD_ENABLED)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/main.py:449: in create_app
software_version = read_software_version(code_root)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/ota/versioning.py:38: in read_software_version
raise RuntimeError(f"software VERSION file is unreadable: {path}") from exc
E RuntimeError: software VERSION file is unreadable: /run/[private]-screen-controller/bus-font-20261012/candidate/VERSION
______________________ ERROR collecting tests/test_api.py ______________________
app/ota/versioning.py:36: in read_software_version
return SoftwareVersion.parse(path.read_text(encoding="utf-8"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1059: in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1045: in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E FileNotFoundError: [Errno 2] No such file or directory: '/run/[private]-screen-controller/bus-font-20261012/candidate/VERSION'
The above exception was the direct cause of the following exception:
/usr/lib/python3.11/importlib/__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1206: in _gcd_import
???
<frozen importlib._bootstrap>:1178: in _find_and_load
???
<frozen importlib._bootstrap>:1149: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:690: in _load_unlocked
???
/opt/[private]-screen-controller/.venv/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
exec(co, module.__dict__)
/opt/[private]-screen-controller.stage.animation-20261010-094a526b/tests/test_api.py:11: in <module>
???
app/main.py:2106: in <module>
app = create_app(ui_copy_editor_build_enabled=UI_COPY_EDITOR_BUILD_ENABLED)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/main.py:449: in create_app
software_version = read_software_version(code_root)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/ota/versioning.py:38: in read_software_version
raise RuntimeError(f"software VERSION file is unreadable: {path}") from exc
E RuntimeError: software VERSION file is unreadable: /run/[private]-screen-controller/bus-font-20261012/candidate/VERSION
=========================== short test summary info ============================
ERROR tests/test_bus_font.py - RuntimeError: software VERSION file is unreada...
ERROR tests/test_fonts.py - RuntimeError: software VERSION file is unreadable...
ERROR tests/test_scene_layers.py - RuntimeError: software VERSION file is unr...
ERROR tests/test_templates.py - RuntimeError: software VERSION file is unread...
ERROR tests/test_api.py - RuntimeError: software VERSION file is unreadable: ...
!!!!!!!!!!!!!!!!!!! Interrupted: 5 errors during collection !!!!!!!!!!!!!!!!!!!!
5 errors in 8.77s
8d99e3cb8c63490e019dd3d567ba874dd75c250dc9b94fb0fb6097717568970d /run/[private]-screen-controller/bus-font-20261012/payload.tar
.....................s........................................F..... [100%]
=================================== FAILURES ===================================
____ test_systemd_preserves_runtime_marker_across_service_stop_and_restart _____
/opt/[private]-screen-controller.stage.animation-20261010-094a526b/tests/test_api.py:1144: in test_systemd_preserves_runtime_marker_across_service_stop_and_restart
???
/usr/lib/python3.11/pathlib.py:1059: in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.11/pathlib.py:1045: in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E FileNotFoundError: [Errno 2] No such file or directory: '/run/[private]-screen-controller/bus-font-20261012/candidate/systemd/[private]-screen-controller.service'
=========================== short test summary info ============================
FAILED tests/test_api.py::test_systemd_preserves_runtime_marker_across_service_stop_and_restart
1 failed, 66 passed, 1 skipped, 165 warnings in 239.70s (0:03:59)
8d99e3cb8c63490e019dd3d567ba874dd75c250dc9b94fb0fb6097717568970d /run/[private]-screen-controller/bus-font-20261012/payload.tar
. [100%]
1 passed, 67 deselected, 4 warnings in 7.18s
{"result": "deployed", "preserved_files": 446, "added_fonts": 1, "runtime_survived_stop": true, "manifest": {"id": "builtin:walnut-bus-8x16", "file": "WalnutBus8x16.ttf", "sha256": "d38bf29d6408a6f731865a1ca760a80b5156ebf6ab96d5ad8d649df28163564c", "label": "核桃公交窄体(推荐16px)", "family": "核桃公交窄体", "style": "Regular", "glyph_count": 6884, "recommended_size": 16, "cell": [8, 16]}, "status_keys": ["frp", "mobile", "network", "ok", "power", "resources", "screen", "service", "state", "system", "ui"]}
{
"result": "deployed",
"preserved_files": 446,
"added_fonts": 1,
"runtime_survived_stop": true,
"manifest": {
"id": "builtin:walnut-bus-8x16",
"file": "WalnutBus8x16.ttf",
"sha256": "d38bf29d6408a6f731865a1ca760a80b5156ebf6ab96d5ad8d649df28163564c",
"label": "核桃公交窄体(推荐16px)",
"family": "核桃公交窄体",
"style": "Regular",
"glyph_count": 6884,
"recommended_size": 16,
"cell": [
8,
16
]
},
"status_keys": [
"frp",
"mobile",
"network",
"ok",
"power",
"resources",
"screen",
"service",
"state",
"system",
"ui"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Some files were not shown because too many files have changed in this diff Show More