Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ tools/owned_vm_request.cs text eol=lf
tools/run_vm_request_queue.ps1 text eol=lf
tools/fixtures/vm_request_*.ps1 text eol=lf
third_party/conpty/LICENSE text eol=lf
third_party/qt/LICENSES/LGPL-3.0-only.txt text eol=lf
third_party/msvc_runtime/NOTICE.txt text eol=lf
experiments/core/fixtures/*.bin binary
24 changes: 23 additions & 1 deletion .github/workflows/qt-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
with:
python-version: '3.12'
- name: Verify preparation failure contracts
run: python -m unittest tools.test_prepare_qt_build tools.test_prepare_msvc_runtime tools.test_msvc_runtime -v
run: python -m unittest tools.test_prepare_qt_build tools.test_prepare_msvc_runtime tools.test_msvc_runtime tools.test_stage_qt_product -v
- name: Prepare manifest-pinned Qt qtbase, Microsoft ConPTY and CRT
run: python -m tools.prepare_qt_build
- name: Preserve path-free dependency preparation identity
Expand All @@ -43,6 +43,28 @@ jobs:
"-DTERMFORGE_MSVC_RUNTIME_DIR=$dependencyRoot/crt"
- name: Build Qt product and independent smoke
run: cmake --build build/qt-cpp --config Release --target termforge_qt_shell qt_cpp_shell_smoke qt_cpp_resize_smoke qt_unicode_input_test qt_unicode_render_test qt_eight_session_test qt_terminal_modes_test qt_hidden_retention_test qt_history_navigation_test qt_selection_migration_test qt_find_test qt_scrollbar_size_test qt_clipboard_system_test --parallel 2
- name: Stage the frozen Qt product and verify every file identity
run: |
python -m tools.stage_qt_product stage `
--bin-dir build/qt-cpp/qt-bin/Release `
--dependencies local/qt-build-deps `
--dependency-summary local/qt-build-preparation.json `
--out local/qt-product-staging `
--summary local/qt-product-staging.json
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
python -m tools.stage_qt_product verify --staging local/qt-product-staging
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Preserve path-free product staging identities
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: qt-cpp-product-staging
retention-days: 14
if-no-files-found: warn
path: |
local/qt-product-staging.json
local/qt-product-staging/product-manifest.json
local/qt-product-staging/THIRD-PARTY-NOTICES.txt
- name: Record complete path-free runtime manifests
run: |
python tools/msvc_runtime.py manifest --directory build/qt-cpp/qt-bin/Release --executable termforge_qt_shell.exe
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -683,8 +683,14 @@ if(TERMFORGE_BUILD_QT_SHELL)
"$<TARGET_FILE_DIR:${target}>/assets/fonts"
VERBATIM)
add_dependencies(${target} ${target}_font_bundle)
# The system D3D compiler and Microsoft DXC redistributables are not part
# of the fixed, pinned product set: the Widgets raster entry does not link
# them, and windeployqt would otherwise copy them from the developer's
# Windows SDK/system directories. Product staging verifies the remaining
# files against the pinned SDK; see tools/stage_qt_product.py.
add_custom_command(TARGET ${target} POST_BUILD
COMMAND "${qt_deploy_tool}" --release --no-translations --no-compiler-runtime
--no-system-d3d-compiler --no-system-dxc-compiler
"$<TARGET_FILE:${target}>"
VERBATIM)
endfunction()
Expand Down
2 changes: 1 addition & 1 deletion assets/fonts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
| `RobotoMono-Regular.ttf` | [fonts/ttf/RobotoMono-Regular.ttf](https://raw.githubusercontent.com/googlefonts/RobotoMono/895ec691990d041dd727c7b5afa3ce56525d98e6/fonts/ttf/RobotoMono-Regular.ttf) | 125748 | `af0bff7599c3df3831755c16e39b3c496df74b8c8d8a1161b14dc8461be17cb4` |
| `OFL.txt` | [OFL.txt](https://raw.githubusercontent.com/googlefonts/RobotoMono/895ec691990d041dd727c7b5afa3ce56525d98e6/OFL.txt) | 4395 | `50ab8dd54680d3473f649c9db86fece88434d097c7834475c1c72d2f8c429215` |

版权所有者与许可见随附 [OFL.txt](OFL.txt)。该文件授权字体随软件分发,要求保留版权声明及完整许可,字体本身继续适用 SIL Open Font License 1.1。TermForge 的 MIT 许可不覆盖此字体。字体和许可均按上游原始字节保存,没有子集化、转换或改名。
版权所有者与许可见随附 [OFL.txt](OFL.txt)。该文件授权字体随软件分发,要求保留版权声明及完整许可,字体本身继续适用 SIL Open Font License 1.1。TermForge 的 MIT 许可不覆盖此字体。字体和许可均按上游原始字节保存,没有子集化、转换或改名。机器可读的身份、上游固定提交与许可映射见 [manifest.json](manifest.json);构建和产品 staging 以该文件校验字体与许可的原始字节,本文不作为许可依据。

构建不访问网络。Windows `termforge_shell` 的构建步骤把本目录的字体、许可与本文复制到可执行文件旁的 `assets/fonts/`;分发可执行文件时须一并保留该目录。`WorkspaceFont` 从可执行文件目录解析路径,以 [`AddFontResourceExW(..., FR_PRIVATE, ...)`](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-addfontresourceexw)仅对本进程加载,释放 HFONT 后卸载。字体不存在、加载失败或 [`GetTextFaceW`](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-gettextfacew) 返回的实际 face 不是 `Roboto Mono` 时明确失败,不静默替换。

Expand Down
36 changes: 36 additions & 0 deletions assets/fonts/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"schema": "termforge-font-resource-v1",
"name": "Roboto Mono",
"style": "Regular (static)",
"scope": "Workspace UI font for the C++/Qt entry, loaded privately per process. It is not the terminal grid font and not a claim of WindTerm font parity.",
"upstream": {
"repository": "https://github.com/googlefonts/RobotoMono",
"fixed_commit": "895ec691990d041dd727c7b5afa3ce56525d98e6",
"acquired": "2026-10-23",
"note": "The unmodified static Regular font and the same-commit license are kept as the upstream original bytes. No subsetting, conversion or renaming is applied."
},
"license": {
"spdx": "OFL-1.1",
"bundled_path": "OFL.txt",
"upstream_url": "https://raw.githubusercontent.com/googlefonts/RobotoMono/895ec691990d041dd727c7b5afa3ce56525d98e6/OFL.txt"
},
"files": {
"RobotoMono-Regular.ttf": {
"bytes": 125748,
"sha256": "af0bff7599c3df3831755c16e39b3c496df74b8c8d8a1161b14dc8461be17cb4",
"upstream_path": "fonts/ttf/RobotoMono-Regular.ttf"
},
"OFL.txt": {
"bytes": 4395,
"sha256": "50ab8dd54680d3473f649c9db86fece88434d097c7834475c1c72d2f8c429215",
"upstream_path": "OFL.txt"
}
},
"deployment": {
"source_directory": "assets/fonts",
"staged_directory": "assets/fonts",
"additional_documentation": "README.md",
"required": true,
"note": "Product staging requires the pinned font and license, verifies the build copy is byte-identical to this source tree, and also carries README.md as provenance documentation."
}
}
4 changes: 2 additions & 2 deletions docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

`DA1` 当前只在 strict/replay 路径回复 `ESC[?6c`;recovery 产品路径保持静默。`?1004`/`?9001` 与单参数 `CSI 1t/2t/3t` 接受后忽略,不代表焦点上报、Win32 输入模式或窗口操作已实现。`?2004`、鼠标模式、DA2 和 OSC 10/11 仍缺;详见 [#28](https://github.com/JavaZeroo/termforge/issues/28)。

Qt 构建显式准备并部署[固定微软 CRT 14.51.36247.0](../third_party/msvc_runtime/README.md),不安装到 System32。隔离 Windows 的[限定加载与 cmd 验证](../experiments/shell/results/2026-10-29-qt-crt-deploy/README.md)保留原包失败、原 52 文件不变且仅追加 CRT/原许可后的成功,以及新源码包的独立验证;它不解除完整产品打包、Qt/第三方分发审计、实际 DPI/IME 或物理呈现的验收缺口。
Qt 构建显式准备并部署[固定微软 CRT 14.51.36247.0](../third_party/msvc_runtime/README.md),不安装到 System32。隔离 Windows 的[限定加载与 cmd 验证](../experiments/shell/results/2026-10-29-qt-crt-deploy/README.md)保留原包失败、原 52 文件不变且仅追加 CRT/原许可后的成功,以及新源码包的独立验证;它不解除完整产品打包、Qt/第三方分发审计、实际 DPI/IME 或物理呈现的验收缺口。正式入口现有 [`packaging/qt-product/manifest.json`](../packaging/qt-product/manifest.json) 冻结的工程 staging:只接收固定依赖准备摘要和逐文件字节都匹配的构建目录,输出路径无关的逐文件 SHA-256 与许可索引,并拒绝测试夹具或未固定来源;它仍不是 R2 包,干净 Windows 运行、96/144 DPI、完整 Qt 第三方许可清单与最终验收未完成。

官方参考的基础文字行为已按 [R1-01 合同](research/windterm-r1-text-contract.md)完成两组各两轮的自动取证;这为独立实现提供行为依据,产品能力仍按下表分别验收。

Expand Down Expand Up @@ -92,7 +92,7 @@ Qt 构建显式准备并部署[固定微软 CRT 14.51.36247.0](../third_party/ms
| 八会话文字工作流 | **限定验收**:[R1 固定源码整体验收](../experiments/shell/results/2026-10-24-r1-system-workflow/validation.json)覆盖同次 8 会话/拒绝第 9 个、后台有限洪流、历史/Find/实际选择与 CF 复制/确认粘贴/真实拼音、切换缩放、淘汰、取消关闭和重复回收;实际字节、目标隔离、动作与 Job/desktop 回收有独立审计 | 限定 Windows 固定拼音、本地 cmd 与有界负载;这是固定 R1 配置的组合验收,不能替代 R2 候选/新后端组合。实际呈现、常用 TUI、长期稳定及 UI/性能等价仍未验收 | R1 |
| 活体资源与滚动端点 | **限定测量**:普通启动默认关闭;[R1 组合审计](../experiments/shell/results/2026-10-24-r1-system-workflow/validation.json)绑定实际接收、state 与同 revision 的 WM_PAINT/BitBlt/GdiFlush 提交,保留跨时钟校准与阶段资源,可离线重算 | launcher-tree 不等于 UI 归因;观察进程成本不等于增量采样成本,短命进程及退出 CPU 可能漏采。短驻留不证明长期无泄漏,`presented_done=null`,不构成性能通过 | R1;扩展 R4 / R5 |
| 自动正确性与构建 | **限定验收**:Windows shell/ConPTY/呈现及 Windows/Linux 核心 CI、差分/恢复/队列/生命周期场景 | 产品打包、干净机器使用、依赖升级、长期回归和更广平台矩阵;#40 的 CI 纯夹具超时、窄窗口选择 #73、四 shell 原事件 #80、hosted 准备 #81 和[复制夹具 OpenClipboard 5 #85](https://github.com/JavaZeroo/termforge/issues/85) 等原失败已按各责任项记录修正或用户接受的未复现收口;当前开放的是 #44/#80/#99,由 #38 汇总;#72 保存判据与 #80 同步条件的限定修正不代替其他配置或未知根因验收 | R2 / R4 |
| Windows 产品交付 | **实现中,未验收**:首个 [v0.1.0-alpha.1 预发布](releases/v0.1.0-alpha.1.md)提供 Windows x64、静态 MSVC 运行库、附资源许可和构建身份的免安装 ZIP;未签名,已验环境限 Windows 11 本机与 Server 2025 CI,布局仍写入 LOCALAPPDATA | 这是旧 Win32 路线的 R1 体验包,尚非正式 Qt 路线的 R2 基础开发包;干净机器与更广平台矩阵、签名/安装、配置升级及持续运行仍待完成。Windows 10 未验收,Server 2022 句柄基线已按 ADR-0009 改记录制,不代表产品在该平台验收 | R2 / R3 |
| Windows 产品交付 | **实现中,未验收**:首个 [v0.1.0-alpha.1 预发布](releases/v0.1.0-alpha.1.md)提供 Windows x64、静态 MSVC 运行库、附资源许可和构建身份的免安装 ZIP;正式 Qt 路线已有可复现的工程 staging/清单入口(见上),但没有正式 Qt 产品包。两者均未签名,已验环境限 Windows 11 本机与 Server 2025 CI,布局仍写入 LOCALAPPDATA | 旧 Win32 体验包不是正式 Qt 路线的 R2 基础开发包;staging 也不等于产品包或验收。干净机器与更广平台矩阵、Qt 第三方分发审计、签名/安装、配置升级及持续运行仍待完成。Windows 10 未验收,Server 2022 句柄基线已按 ADR-0009 改记录制,不代表产品在该平台验收 | R2 / R3 |
| Linux/macOS 与其他架构 | **未实现**客户端;Linux 核心 CI 已有。[官方平台范围台账](../research/windterm-2.7.0-platform-scope.md)已固定 2.7.0 的 Windows x86/x64、macOS x64、Linux x64 资产及声明下限;这不是 TermForge 支持或实测结论 | 最终需真实 Linux/macOS 客户端;平台调查可提前进行,整合及完整验收排在 Windows 11 x64 完整版本之后。其他系统版本、最低版本和架构由用户后续明确;旧系统及 ARM 等保持调查记录,不自动承诺或排除,也不能由核心 CI 推断产品支持 | 持续调查;R5 全平台出口 |
| 吞吐、响应、内存与稳定性 | **实现中,未验收**:已有机制实验、连续 CPU 区间校准与合成回归;候选字素改动的受限诊断中 project/interactive 吞吐中位数约下降 16%/9%,由 [#54](https://github.com/JavaZeroo/termforge/issues/54) 跟踪。[冻结批次执行器](../experiments/measure/R54-COST.md#冻结批次执行器windows)核对构建来源、原始输出、停止规则与逐轮配对统计;[独立 hosted 构建与实测](../experiments/measure/results/2026-10-27-r54-hosted/README.md)已验证来源和失败保留,但首批因环境护栏停止,尚无完整成本批次;[共享宿主CPU诊断](../experiments/measure/results/2026-10-27-r54-cpu-boundary/README.md)及[新hosted六位置](../experiments/measure/results/2026-10-27-r54-cpu-hosted/README.md)分别记录完整子进程/执行器分量;后者仍有3.333%–5.263%未归属余额,不改原护栏或判成本通过 | 旧诊断的共享宿主、allocator 包装与缺少真实呈现/输入时延端点使其不构成正式预算;新的不完整批次也不作吞吐结论。仍需同负载/同正确性、无插桩对照、观测开销和长期/多会话公平性;可靠原版基线后提出逐项预算及允许波动范围,**由用户明确确认**。与 WindTerm 的实际差距**待取证** | 当前优先;贯穿 R1–R5 |
| 大历史与动态内存压缩 | **未实现**产品能力;WindTerm 压缩属于官方性能声明,内部机制尚未证实 | 1/10/100 万行等明确规模下的内存/滚动/搜索/淘汰实验;根据瓶颈决定独立存储/压缩实现 | R4 |
Expand Down
114 changes: 114 additions & 0 deletions packaging/qt-product/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"schema": "termforge-qt-product-staging-contract-v1",
"scope": "Frozen Windows x64 C++/Qt/ConPTY product staging inputs for the termforge_qt_shell entry. This is an engineering candidate: not a released package, not an accepted R2 deliverable and not a redistribution clearance.",
"entry_executable": "termforge_qt_shell.exe",
"platform": "windows-x64",
"configuration": "Release",
"staging_entry": "python -m tools.stage_qt_product stage",
"build": {
"cmake_options": [
"-DTERMFORGE_BUILD_QT_SHELL=ON",
"-DTERMFORGE_BUILD_CANDIDATE_ADAPTER=OFF"
],
"windeployqt_flags": [
"--release",
"--no-translations",
"--no-compiler-runtime",
"--no-system-d3d-compiler",
"--no-system-dxc-compiler"
],
"note": "The Qt SDK, fixed ConPTY pair and fixed CRT are prepared by tools.prepare_qt_build. BUILD_TESTING only adds separate test output directories; no test executable belongs to this product staging."
},
"qt_deployed": {
"libraries": [
"Qt6Core.dll",
"Qt6Gui.dll",
"Qt6Network.dll",
"Qt6Widgets.dll"
],
"plugins": [
"generic/qtuiotouchplugin.dll",
"imageformats/qgif.dll",
"imageformats/qico.dll",
"imageformats/qjpeg.dll",
"networkinformation/qnetworklistmanager.dll",
"platforms/qwindows.dll",
"styles/qmodernwindowsstyle.dll",
"tls/qcertonlybackend.dll",
"tls/qschannelbackend.dll"
],
"source_layout": "Libraries must be byte-identical to <prepared-qt>/bin/<name>; plugins must be byte-identical to <prepared-qt>/plugins/<relative path>."
},
"os_provided": [
{
"name": "icuuc.dll",
"provider": "Microsoft Windows 11 System32 ICU common forwarder",
"deployment": "excluded_not_bundled",
"reason": "Qt6Core imports icuuc.dll, and windeployqt copies the developer machine's System32 forwarder into the build directory. The staged product must not redistribute or pin that OS component; the Windows 11 target supplies it at run time.",
"verification": "Staging requires the build copy to be byte-identical to the running system's System32 copy before excluding it. A copy from another source fails explicitly instead of being silently dropped."
}
],
"excluded_system_redistributables": [
{
"name": "D3Dcompiler_47.dll",
"reason": "windeployqt --no-system-d3d-compiler; the Windows system D3D compiler is not pinned or redistributed in this package."
},
{
"name": "dxcompiler.dll",
"reason": "windeployqt --no-system-dxc-compiler; the Microsoft DXC out-of-band redistributable is not pinned, and the Widgets raster entry does not link it."
},
{
"name": "dxil.dll",
"reason": "windeployqt --no-system-dxc-compiler; the Microsoft DXC out-of-band redistributable is not pinned, and the Widgets raster entry does not link it."
}
],
"license_evidence": {
"termforge": {
"spdx": "MIT",
"files": [
"LICENSE"
]
},
"qt": {
"license_manifest": "third_party/qt/manifest.json",
"bundled_texts": [
"licenses/LGPL-3.0-only.txt"
],
"status": "third_party_component_inventory_pending"
},
"conpty": {
"license_manifest": "third_party/conpty/manifest.json",
"files": [
"conpty-backend/LICENSE",
"conpty-backend/manifest.json"
],
"status": "bundled"
},
"msvc_runtime": {
"license_manifest": "third_party/msvc_runtime/manifest.json",
"files": [
"LICENSE-MICROSOFT-VC-REDIST.docx",
"NOTICE.txt"
],
"status": "bundled"
},
"font": {
"license_manifest": "assets/fonts/manifest.json",
"files": [
"assets/fonts/OFL.txt"
],
"status": "bundled"
}
},
"test_fixture_policy": "Staging admits only this contract and the pinned dependency manifests. Test executables (qt_*_test, qt_cpp_* smoke, shell_*_client), debug/link/log artifacts and any other unlisted file are rejected rather than copied.",
"ignored_build_artifacts": {
"runtime-manifest.json": "Derived inventory written into the same directory by tools/msvc_runtime.py manifest; it is evidence output, never part of the product staging."
},
"claims": {
"r2_acceptance": false,
"clean_machine_run": "not_performed",
"single_screen_96_144_dpi": "not_verified_in_this_slice",
"full_third_party_license_inventory": "pending",
"performance_equivalence": false
}
}
Loading