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
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ add_executable(search_test experiments/core/search_test.cpp)
target_link_libraries(search_test PRIVATE termforge_core)
termforge_warnings(search_test)

add_executable(buffer_state_test experiments/core/buffer_state_test.cpp)
target_link_libraries(buffer_state_test PRIVATE termforge_core)
termforge_warnings(buffer_state_test)

add_executable(paste_test experiments/shell/paste_test.cpp)
termforge_warnings(paste_test)
add_executable(clipboard_policy_test experiments/shell/clipboard_policy_test.cpp)
Expand Down Expand Up @@ -274,6 +278,7 @@ if(BUILD_TESTING)
add_test(NAME history_core COMMAND history_test)
add_test(NAME selection_core COMMAND selection_test)
add_test(NAME search_core COMMAND search_test)
add_test(NAME buffer_state_core COMMAND buffer_state_test)
add_test(NAME paste COMMAND paste_test)
add_test(NAME clipboard_policy COMMAND clipboard_policy_test)
add_test(NAME keyboard COMMAND keyboard_test)
Expand Down
1 change: 1 addition & 0 deletions docs/EVIDENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

| 配置 | 证据定位 |
|---|---|
| 自主 C++ 双缓冲存储与文档 epoch 基础 | [固定结果](../experiments/core/results/2026-10-29-buffer-state-r2/README.md)、[验证身份](../experiments/core/results/2026-10-29-buffer-state-r2/validation.json):拥有状态、共享 ID、隐藏帧 resize 回滚与跨缓冲句柄失效;Qt/candidate 关闭配置的完整 50 项及 12 条内部 skip 分列。未接 private CSI,不是原版模式、Qt 产品路线或完整 #27 验收 |
| Qt cmd 标签与退出前回收 | [固定结果](../experiments/shell/results/2026-10-28-qt-tabs/README.md)、[验证身份](../experiments/shell/results/2026-10-28-qt-tabs/validation.json):双 cmd 隔离、失败页、关闭与四个实际事件循环边界;Qt 1 项和其他 49 项诊断及内部跳过分列,旧中断轮不拼接 |
| Qt 正式入口的独立 hosted 构建 | [固定结果](../experiments/shell/results/2026-10-28-qt-cpp-ci/README.md)、[验证身份](../experiments/shell/results/2026-10-28-qt-cpp-ci/validation.json):固定 SDK、VS 2026 hosted 与真实 cmd 的 offscreen / OwnedJob 检查;原依赖换行和 generator 失败保留。没有原生上屏、完整部署哈希或产品包验收 |
| 自主 C++ + Qt Widgets + 固定微软 ConPTY 正式目标 | [ADR-0007](adr/0007-bundled-microsoft-conpty.md) / [ADR-0008](adr/0008-cpp-core-qt-widgets.md) 记录用户确认;新组合的实现与验证另行留证,不引用旧默认或 Alacritty 通过结果代替 |
Expand Down
2 changes: 2 additions & 0 deletions docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
|---|---|---|---|
| 自主 C++ / Qt / 固定微软 ConPTY | **实现中,未验收**:[显式 Qt 入口](../src/qt/README.md)提供固定 80×24 的 cmd 标签、基本 ASCII/16 色及各会话独立有界队列;双 cmd 输入、关闭和错误隔离及真实事件循环退出前回收有[限定验证](../experiments/shell/results/2026-10-28-qt-tabs/README.md)。Qt 1 项与其余 49 项既有/独立诊断分列 | 分屏、其他 shell、工作区恢复、动态 resize、历史/选择/Find、Unicode/IME、真实 DPI、应用兼容与性能仍需实现或迁移;应用/标签退出策略沿原型合同,完整 WindTerm 标签行为对照未完成;当前不是可发布开发包 | R2 |

自主 C++ 核心的 [#130 双缓冲存储基础](../experiments/core/results/2026-10-29-buffer-state-r2/README.md)已在独立模块边界实现拥有状态、交换激活、共享行 ID、双帧物理 resize 与文档 epoch 隔离,旧位置、选择、搜索及 viewport 不会在切换返回后复活。该基础尚未接入 private CSI;1049 的样式、重复进入清空及历史文档策略与完整 [#27](https://github.com/JavaZeroo/termforge/issues/27)另行验收,不表示产品已支持备用屏或 Qt 交互已迁移。

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

| 能力 | 当前状态与边界 | 目标差距 | 路标 |
Expand Down
319 changes: 319 additions & 0 deletions experiments/core/buffer_state_test.cpp

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion experiments/core/history_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@ struct ViewSnapshot {
int cursor_row = -1, cursor_column = 0;
};
class HistoryViewport {
uint64_t anchor_ = 0;
uint64_t anchor_ = 0, observed_epoch_ = 0;
bool following_ = true;
void sync_epoch(const Screen& screen) {
if (observed_epoch_ == screen.buffer_epoch()) return;
observed_epoch_ = screen.buffer_epoch();
anchor_ = 0;
following_ = true;
}
public:
// A viewport is owned by exactly one session. Never share it across Screens.
ViewportState reconcile(const Screen& screen) {
sync_epoch(screen);
const size_t maximum = screen.history.size();
const size_t top = following_ ? maximum : (std::min)(screen.lower_bound_line(anchor_), maximum);
anchor_ = screen.retained_line(top).id;
return {top, screen.retained_size(), static_cast<size_t>(screen.height()), maximum, anchor_, following_};
}
ViewportState scroll_to(const Screen& screen, size_t top) {
sync_epoch(screen);
top = (std::min)(top, screen.history.size());
following_ = top == screen.history.size();
anchor_ = screen.retained_line(top).id;
Expand Down
40 changes: 40 additions & 0 deletions experiments/core/results/2026-10-29-buffer-state-r2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 自主 C++ 双缓冲存储与文档世代基础(#130)

本记录只验证 [#130](https://github.com/JavaZeroo/termforge/issues/130) 的独立工程基础:两个缓冲拥有各自状态,交换激活并隔离旧读者。**未接入 private CSI,也不验收 1049、完整 #27 或 R2。**

运行源码固定为 `63589fa21b68c3029501772b7bb415e66aa99e97`,已合入 main 基点 `337812bc27b10a8f4dee5e4e35ded21c90f4a151`。后续能力矩阵和本证据整理是文档提交,不改变该运行身份。字段、命令、源码/EXE 及原始本地记录哈希见 [validation.json](validation.json)。

## 实现与断言边界

- `Parser::screen` 保留原对象和主屏接口;另一帧私有拥有文本、光标、样式、pending-wrap、combining attachment、历史与丢弃计数。激活只交换状态,不复制保留历史;共享行 ID 分配器不随帧恢复。
- 主屏保持原历史容量,备用存储历史上限为零;两帧共享尺寸。物理行 resize 先准备两帧,再提交;隐藏帧分配 ID 耗尽时,两帧内容、几何和分配器均不半更新。零历史是工程界限,不代表原版文档浏览合同。
- `TextPosition` 带单调切换 epoch;selection、search 和 history viewport 检查世代。旧句柄不会因主屏返回且行 ID/version 保留而复活;非零 epoch 下新建的 alt/main 选择、查询及 viewport 仍可使用。未切换的默认 epoch 为零,现有三字段位置初始化及 JSON schema 保持兼容。
- [独立公开边界测试](../../buffer_state_test.cpp)使用自写字面内容验证两帧往返、光标/样式/wrap/附件、隔离历史、宽字裁剪、软硬行元数据、增长 ID、resize 回滚与旧句柄失效;没有通过测试内部调用次数代替可见内容断言。

原版样式继承、重复进入清空、保存/恢复协议策略及历史文档呈现均不在本项选择。存储激活的幂等性不能用来宣称原版 1049 重复进入也幂等。

## 固定配置与完整回归

Windows 11 `10.0.26200`、x64 Release,Visual Studio 2022 / MSVC `19.42.34433.0`,Python `3.12.10`。`TERMFORGE_BUILD_QT_SHELL=OFF`,`TERMFORGE_BUILD_CANDIDATE_ADAPTER=OFF`;既有 Windows 诊断使用系统 ConPTY。**本轮不构建 Qt/固定 ConPTY 产品组合,也不构建 Alacritty 参考。**

完整 configure 和 build 均退出 **0**;完整 CTest **50/50、退出 0**,耗时 **355.09 秒**。这是测试耗时,不是终端性能指标。运行前已观察固定提交及干净源码,完成后采集精选源码、45 个 EXE 和完整日志身份;没有单独的运行前冻结 manifest,也不声称可复现构建证明。

主体命令为:

```powershell
cmake -S . -B build/core-buffer-state -G 'Visual Studio 17 2022' -A x64 -DTERMFORGE_BUILD_QT_SHELL=OFF -DTERMFORGE_BUILD_CANDIDATE_ADAPTER=OFF -DPython3_EXECUTABLE=<Python-3.12.10路径>
cmake --build build/core-buffer-state --config Release
ctest --test-dir build/core-buffer-state -C Release --output-on-failure --output-junit <工作树>/local/buffer-state-r2/13-main-all-ctest.xml
```

仅测试进程的 PATH 前置 Git `usr/bin`,并设置 `PYTHONUTF8=1`、`TERMFORGE_REQUIRE_SYSTEM_CLIPBOARD=0`。路径占位符替代私人绝对路径。原始 configure/build/CTest/JUnit、退出码文件及完整 `LastTest.log` 保存在本地;JSON 公开其实际字节数与哈希,不发布原件。

CTest 注册级没有 skip,但 Python 框架内部有 **12 条 skip**,逐条名称及原因在 JSON:4 个可选参考整类、7 个需要 disposable hosted VM 的实际系统剪贴板 UI 场景,以及1个 opt-in 原版失败注入。成功 JUnit 输出被 CTest 截短,内部 skip 以完整 `LastTest.log` 为准。`paste_system` 注册及其中的系统 API 检查实际通过,不能替代上述跳过的 UI 场景或完整剪贴板验收,也不转为 Qt 能力。

## 分次失败与审查

7 条实际运行红分别覆盖 writing context、备用历史界限、隐藏 resize、旧 position、selection、search 和 viewport;每条的失败日志及当时源码/测试/EXE 身份记录均保留,脱敏哈希见 JSON。接口编译失败、选择测试夹具参数错误、早期只构建部分 target 导致缺 `receive.exe` 的回归准备失败另列,不计为算法运行红;最终整轮已完整构建该 target。

双轴审查无未解决阻断;原字段交换清单的重复已用私有同一 helper 消除,复审确认没有引入 copy 或改变 `noexcept` 边界。没有独立审查报告附件,因此不补造报告哈希。远端 hosted 检查属于 PR 的独立运行,不并入本地 50 项计数。

本公开记录仅含合成断言、脱敏配置、计数及身份哈希;不包含 WindTerm 私有材料、资源、会话、原始抓取或私人路径。它不证明原版一致性、完整备用屏、GUI/TUI 组合、IME/真实 DPI、全平台完整产品、可分发包或性能达标。
Loading