From 40bee8e504410ed167bee600a1a5597417204809 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Thu, 29 Oct 2026 01:00:21 +0800 Subject: [PATCH 1/6] feat(core): implement bounded WindTerm 1049 subset (#135) --- CMakeLists.txt | 5 + experiments/core/alternate_mode_test.cpp | 215 +++++++++++++++++++++++ experiments/core/screen.hpp | 7 + experiments/core/terminal.hpp | 29 ++- 4 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 experiments/core/alternate_mode_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ce9dae4d..cc98dc72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,10 @@ 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(alternate_mode_test experiments/core/alternate_mode_test.cpp) +target_link_libraries(alternate_mode_test PRIVATE termforge_core) +termforge_warnings(alternate_mode_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) @@ -279,6 +283,7 @@ if(BUILD_TESTING) 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 alternate_mode_core COMMAND alternate_mode_test) add_test(NAME paste COMMAND paste_test) add_test(NAME clipboard_policy COMMAND clipboard_policy_test) add_test(NAME keyboard COMMAND keyboard_test) diff --git a/experiments/core/alternate_mode_test.cpp b/experiments/core/alternate_mode_test.cpp new file mode 100644 index 00000000..2094c859 --- /dev/null +++ b/experiments/core/alternate_mode_test.cpp @@ -0,0 +1,215 @@ +#include "terminal.hpp" +#include "text_selection.hpp" +#include "text_search.hpp" +#include "history_view.hpp" +#include +#include +#include + +using namespace termforge; + +static void check(bool condition, const char* message) { + if (!condition) throw std::runtime_error(message); +} +static std::string text(const Line& line) { + std::string result; + for (const auto& cell : line) result += cell.text; + return result; +} +static void enter_and_restore(ParseMode mode) { + Parser parser(4, 12, 2, mode); + auto* stable = &parser.screen; + parser.feed("\x1b[31;44mMAIN\x1b[?1049h"); + check(&parser.screen == stable && parser.screen.active_buffer() == ScreenBuffer::alternate, + "1049 entry did not activate the same Screen's alternate frame"); + check(parser.screen.row == 0 && parser.screen.column == 0 && + parser.screen.style.fg == -1 && parser.screen.style.bg == -1, + "1049 entry did not home the cursor with default writing colours"); + check(text(parser.screen.lines[0]) == " ", "alternate entry retained primary text"); + parser.feed("ALT\x1b[?1049l"); + check(parser.screen.active_buffer() == ScreenBuffer::primary && + text(parser.screen.lines[0]) == "MAIN " && + parser.screen.row == 0 && parser.screen.column == 4, + "1049 exit did not restore primary text and cursor"); + check(parser.screen.style.fg == 1 && parser.screen.style.bg == 4, + "1049 exit did not restore primary writing colours"); + parser.finish(); +} +static void repeated_entry_and_exit(ParseMode mode) { + Parser parser(3, 10, 2, mode); + parser.feed("\x1b[31;44mMAIN\x1b[?1049hALT\x1b[32;45m\x1b[3;4HZ\x1b[?1049h"); + check(parser.screen.row == 0 && parser.screen.column == 0 && + parser.screen.style.fg == -1 && parser.screen.style.bg == -1, + "repeated 1049 entry did not home with default writing colours"); + check(text(parser.screen.lines[0]) == " " && text(parser.screen.lines[2]) == " ", + "repeated 1049 entry retained old alternate text"); + parser.feed("NEW\x1b[?1049l!\x1b[?1049l?"); + check(text(parser.screen.lines[0]) == "MAIN!? " && parser.screen.column == 6, + "repeated entry overwrote primary state or repeated exit rewound it"); + check(parser.screen.style.fg == 1 && parser.screen.style.bg == 4, + "alternate colour writes changed saved primary colours"); + parser.feed("\x1b[?1049h"); + check(text(parser.screen.lines[0]) == " " && parser.screen.column == 0, + "1049 re-entry retained text from the earlier alternate visit"); + parser.feed("\x1b[?1049l"); + check(text(parser.screen.lines[0]) == "MAIN!? " && parser.screen.column == 6, + "later primary writes were not preserved across re-entry"); + parser.finish(); +} +static void pending_wrap_roundtrip(ParseMode mode) { + Parser parser(25, 91, 2, mode); + parser.feed("\x1b[3;91HW\x1b[?1049hALT\x1b[?1049lX"); + check(parser.screen.row == 3 && parser.screen.column == 1 && + text(parser.screen.lines[2]) == std::string(90, ' ') + "W" && + text(parser.screen.lines[3]) == "X" + std::string(90, ' '), + "return lost the primary pending wrap before the next printable byte"); + check(parser.screen.lines[2].ending == LineEnding::soft_wrap && + parser.screen.lines[2].next_id == parser.screen.lines[3].id, + "restored pending wrap did not preserve the real continuation"); + parser.finish(); +} +static void observed_colour_trace(ParseMode mode, size_t split, bool bytewise) { + const std::string input = + "\x1b[0m\x1b[2J\x1b[H\x1b[2;3HD0 H H\x1b[4;3H\x1b[31;44mM0 H H" + "\x1b[?1049hA0 H\x1b[31;44m A0S1 H\x1b[0m A0D0 H" + "\x1b[4;5H\x1b[32;45mA1 H H" + "\x1b[?1049hA2 H\x1b[0m A2D0 H\x1b[31;44m A2S1 H\x1b[32;45m A2S2 H" + "\x1b[?1049l M1 H\x1b[31;44m M1S1 H\x1b[32;45m M1S2 H\x1b[0m M1D0 H"; + Parser parser(25, 91, 2, mode); + if (bytewise) for (const auto byte : input) parser.feed(std::string_view(&byte, 1)); + else { + parser.feed(std::string_view(input).substr(0, split)); + parser.feed(std::string_view(input).substr(split)); + } + parser.finish(); + const auto& screen = parser.screen; + check(screen.active_buffer() == ScreenBuffer::primary && screen.row == 3 && screen.column == 34, + "five-stage trace ended in the wrong primary cursor state"); + check(text(screen.lines[1]) == " D0 H H" + std::string(83, ' ') && + text(screen.lines[3]) == " M0 H H M1 H M1S1 H M1S2 H M1D0 H" + std::string(57, ' '), + "five-stage trace did not preserve the literal primary text"); + check(screen.lines[3][12].text == "H" && screen.lines[3][12].style.fg == 1 && + screen.lines[3][12].style.bg == 4 && screen.lines[3][33].style.fg == -1 && + screen.lines[3][33].style.bg == -1, + "return output did not use restored main colours and the explicit default control"); +} +static void history_and_resize(ParseMode mode) { + Parser parser(2, 8, 3, mode); + parser.feed("A\r\nB\r\nC\r\nD\x1b[?1049hX\r\nY\r\nZ\r\nT"); + check(parser.screen.history.empty(), "alternate output entered retained history"); + parser.screen.resize(3, 6); + parser.feed("\x1b[?1049l"); + const auto& screen = parser.screen; + check(screen.height() == 3 && screen.width() == 6 && screen.history.size() == 2 && + text(screen.history[0]) == "A " && text(screen.history[1]) == "B " && + text(screen.lines[0]) == "C " && text(screen.lines[1]) == "D " && + screen.row == 1 && screen.column == 1, + "1049 output or resize changed the saved primary history and writing position"); + parser.finish(); +} +static void readers_follow_protocol_transitions(ParseMode mode) { + Parser parser(2, 8, 2, mode); + parser.feed("ONE\r\nTWO\r\nMAIN"); + const TextDocument document(parser.screen); + const auto old_position = *document.position(2, 0); + TextSelection selection; + check(selection.set(document, {old_position, *document.position(2, 4)}), "selection setup failed"); + TextSearch search; + const auto generation = search.start(document, "MAIN"); + for (int step = 0; step < 20 && search.status() == SearchStatus::running; ++step) + search.step(document, generation, 64); + check(search.match(document, 0).has_value(), "search setup failed"); + HistoryViewport viewport; + viewport.scroll_to(parser.screen, 0); + parser.feed("\x1b[?1049hALT"); + check(!document.valid(old_position) && !search.match(document, 0) && + selection.copy(document, 1024).status == SelectionCopyStatus::invalidated, + "a main text reader crossed into alternate output"); + check(selection.set(document, {*document.position(0, 0), *document.position(0, 3)}) && + selection.copy(document, 1024).text == "ALT", "fresh alternate selection failed"); + const auto old_alternate = *document.position(0, 0); + parser.feed("\x1b[?1049hNEW"); + check(!document.valid(old_alternate) && + selection.copy(document, 1024).status == SelectionCopyStatus::invalidated, + "repeated 1049 entry revived an erased alternate reader"); + parser.feed("\x1b[?1049l"); + check(!document.valid(old_position) && !search.match(document, 0), + "return revived an old primary reader"); + check(viewport.snapshot(parser.screen).viewport.following, + "a prior historical viewport survived a protocol buffer roundtrip"); + check(selection.set(document, {*document.position(2, 0), *document.position(2, 4)}) && + selection.copy(document, 1024).text == "MAIN", "fresh returned primary selection failed"); + parser.finish(); +} +static void recovery_keeps_private_sequences_separate() { + const std::vector ignored{ + "\x1b[?31m", "\x1b[?1049;25h", "\x1b[?1049;h", "\x1b[0?1049h", + "\x1b[??1049h", "\x1b[?1049 h", "\x1b[?1049:1h", "\x1b[?25l", + std::string("\x1b[?") + std::string(33, '0') + "1049h"}; + for (const auto& sequence : ignored) { + Parser parser(2, 8, 1, ParseMode::recovery); + parser.feed(sequence + "\x1b[31mR"); + parser.finish(); + check(parser.screen.active_buffer() == ScreenBuffer::primary && + text(parser.screen.lines[0]) == "R " && parser.screen.lines[0][0].style.fg == 1 && + parser.diagnostics().ignored_sequences == 1 && parser.diagnostics().max_sequence_bytes <= 33, + "an unsupported private sequence mutated a buffer or contaminated the next CSI"); + } + for (const auto cancellation : {char(0x18), char(0x1a), char(0x1b)}) { + Parser parser(2, 8, 1, ParseMode::recovery); + parser.feed(std::string("\x1b[?1049") + cancellation + "\x1b[31mR"); + parser.finish(); + check(parser.screen.active_buffer() == ScreenBuffer::primary && + text(parser.screen.lines[0]) == "R " && parser.screen.lines[0][0].style.fg == 1, + "cancellation or ESC resynchronization retained the private prefix"); + } + Parser truncated(2, 8, 1, ParseMode::recovery); + truncated.feed("\x1b[?1049"); truncated.finish(); truncated.feed("\x1b[31mR"); truncated.finish(); + check(truncated.screen.active_buffer() == ScreenBuffer::primary && truncated.screen.lines[0][0].style.fg == 1, + "truncated private input contaminated the next normal CSI"); +} +static void identical_repeated_text_is_a_new_document(ParseMode mode) { + Parser parser(2, 8, 2, mode); + parser.feed("\x1b[?1049hALT"); + const TextDocument document(parser.screen); + TextSelection selection; + check(selection.set(document, {*document.position(0, 0), *document.position(0, 3)}), + "alternate selection setup failed"); + parser.feed("\x1b[?1049hALT"); + check(selection.copy(document, 1024).status == SelectionCopyStatus::invalidated, + "identical text after repeated 1049 entry revived a prior alternate selection"); + parser.finish(); +} +static void strict_rejects_unsupported_private_modes_atomically() { + for (const auto* input : {"\x1b[?31m", "\x1b[?1049;25h", "\x1b[?1049;1049h", "\x1b[?25l"}) { + Parser parser(2, 8, 1); + parser.feed("\x1b[31;44mMAIN"); + bool rejected = false; + try { parser.feed(input); } + catch (const InputError&) { rejected = true; } + check(rejected && parser.screen.active_buffer() == ScreenBuffer::primary && + text(parser.screen.lines[0]) == "MAIN " && + parser.screen.style.fg == 1 && parser.screen.style.bg == 4, + "strict private dispatch accepted an unsupported command or partially applied its modes"); + } +} +int main() { + try { + for (const auto mode : {ParseMode::strict, ParseMode::recovery}) { + enter_and_restore(mode); + repeated_entry_and_exit(mode); + pending_wrap_roundtrip(mode); + history_and_resize(mode); + readers_follow_protocol_transitions(mode); + identical_repeated_text_is_a_new_document(mode); + // The fixed five sources contain 208 bytes, excluding DSR queries. + for (size_t split = 0; split <= 208; ++split) observed_colour_trace(mode, split, false); + observed_colour_trace(mode, 0, true); + } + recovery_keeps_private_sequences_separate(); + strict_rejects_unsupported_private_modes_atomically(); + std::cout << "alternate mode checks passed\n"; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; return 1; + } +} diff --git a/experiments/core/screen.hpp b/experiments/core/screen.hpp index 26dd2d83..cedebb2f 100644 --- a/experiments/core/screen.hpp +++ b/experiments/core/screen.hpp @@ -169,6 +169,13 @@ class Screen { int width() const { return columns_; } ScreenBuffer active_buffer() const { return active_buffer_; } uint64_t buffer_epoch() const { return buffer_epoch_; } + // An in-place logical reset must invalidate old readers even if the next + // writes reproduce identical text using the same physical row storage. + void invalidate_buffer_readers() { + if (buffer_epoch_ == (std::numeric_limits::max)()) + throw std::overflow_error("buffer epoch exhausted"); + ++buffer_epoch_; + } // The configured limit belongs to primary history; the independent // alternate storage budget is zero. This does not define a document view. size_t active_history_limit() const { return active_buffer_ == ScreenBuffer::primary ? history_limit : 0; } diff --git a/experiments/core/terminal.hpp b/experiments/core/terminal.hpp index 17dfe8b8..228ca86b 100644 --- a/experiments/core/terminal.hpp +++ b/experiments/core/terminal.hpp @@ -18,13 +18,28 @@ class Parser { State state = State::ground; const ParseMode mode; RecoveryDiagnostics stats; - bool osc = false; + bool osc = false, private_csi = false; std::vector params; size_t sequence_bytes = 0; uint32_t scalar = 0, minimum = 0; int remaining = 0; std::string encoded; void dispatch(unsigned char final) { + if (private_csi) { + if (params.size() != 1 || params[0] != 1049 || (final != 'h' && final != 'l')) + throw InputError("unsupported private CSI command"); + if (final == 'h') { + // Re-entry clears only the active alternate frame; the saved + // primary writing state must survive until a real return. + if (screen.active_buffer() == ScreenBuffer::alternate) screen.invalidate_buffer_readers(); + screen.activate_buffer(ScreenBuffer::alternate); + // Colour reset leaves other attributes owned by this frame. + screen.style.fg = screen.style.bg = -1; + screen.erase_display(2); + screen.move(0, 0); + } else screen.activate_buffer(ScreenBuffer::primary); + return; + } if (final == 'm') { screen.sgr(params); return; } if (params.size() > ((final == 'H' || final == 'f') ? 2u : 1u)) throw InputError("too many CSI parameters"); @@ -57,17 +72,18 @@ class Parser { } if (state == State::escape) { if (c != '[') throw std::runtime_error("unsupported escape"); - state = State::csi; params.assign(1, 0); sequence_bytes = 0; continue; + state = State::csi; params.assign(1, 0); sequence_bytes = 0; private_csi = false; continue; } if (state == State::csi) { if (++sequence_bytes > 32) throw std::runtime_error("CSI exceeds limit"); + if (c == '?' && sequence_bytes == 1) { private_csi = true; continue; } if (c >= '0' && c <= '9') { if (params.back() > 9999) throw std::runtime_error("CSI parameter exceeds limit"); params.back() = params.back() * 10 + c - '0'; } else if (c == ';') { if (params.size() == 16) throw std::runtime_error("too many CSI parameters"); params.push_back(0); - } else { dispatch(c); state = State::ground; } + } else { dispatch(c); state = State::ground; private_csi = false; } continue; } if (c >= 0x80) { @@ -92,7 +108,7 @@ class Parser { if (value != (std::numeric_limits::max)()) ++value; } void reset_sequence() { - state = State::ground; params.clear(); sequence_bytes = 0; + state = State::ground; params.clear(); sequence_bytes = 0; private_csi = false; } void reset_utf8() { remaining = 0; encoded.clear(); scalar = minimum = 0; } void replacement() { screen.put(0xFFFD, "\xEF\xBF\xBD"); } @@ -119,7 +135,7 @@ class Parser { } void ignore_sequence(State ignored) { if (state != State::escape_ignore && state != State::csi_ignore) count(stats.ignored_sequences); - state = ignored; params.clear(); + state = ignored; params.clear(); private_csi = false; } void feed_recovering(unsigned char c) { if (remaining) { @@ -171,7 +187,8 @@ class Parser { reset_sequence(); return; } if (state == State::csi_ignore) return; - if (c >= '0' && c <= '9') { + if (c == '?' && sequence_bytes == 1) private_csi = true; + else if (c >= '0' && c <= '9') { if (params.back() > 9999) ignore_sequence(State::csi_ignore); else params.back() = params.back() * 10 + c - '0'; } else if (c == ';') { From c1be53ebdbc8f4094749924d821699eb5368eba0 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Thu, 29 Oct 2026 01:14:57 +0800 Subject: [PATCH 2/6] test(core): distinguish supported 1049 from unknown private modes --- experiments/core/test_core.py | 6 +++++- experiments/core/test_recovery.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/experiments/core/test_core.py b/experiments/core/test_core.py index ca0a2faf..88113fe9 100644 --- a/experiments/core/test_core.py +++ b/experiments/core/test_core.py @@ -75,7 +75,7 @@ def test_json_escaping(self): self.expect(b'"\\', ['"\\ '], 0, 2) def test_unsupported_and_truncated_fail(self): - for data in [b"\x1b", b"\x1b[12;", b"\x1b[38;5;1m", b"\x1b[?1049h", b"\x1b]title\x07", + for data in [b"\x1b", b"\x1b[12;", b"\x1b[38;5;1m", b"\x1b[?9999h", b"\x1b]title\x07", b"\0", b"\x1b[999999999A", b"\x1b[1;2;3H", b"\x1b[" + b"0" * 33 + b"A"]: for chunk in (1, 65536): @@ -83,6 +83,10 @@ def test_unsupported_and_truncated_fail(self): self.assertEqual(result.returncode, 2, data) self.assertEqual(result.stdout, "") + def test_alternate_screen_roundtrip_and_repeated_entry(self): + self.expect(b"MAIN\x1b[?1049hALT\x1b[?1049hNEW\x1b[?1049l!", + ["MAIN! ", " "], 0, 5) + def test_dimensions_guard(self): self.assertEqual(self.replay(b"X", rows=0).returncode, 2) self.assertEqual(self.replay(b"X", columns=501).returncode, 2) diff --git a/experiments/core/test_recovery.py b/experiments/core/test_recovery.py index 5d2b2d28..516cea65 100644 --- a/experiments/core/test_recovery.py +++ b/experiments/core/test_recovery.py @@ -135,7 +135,11 @@ def test_both_real_more_captures_keep_their_complete_bytes_and_expected_ech_resu self.assertFalse(value["screen"]["wrap_pending"]) def test_unknown_csi_consumes_private_and_intermediate(self): - self.expect(b"A\x1b[?1049h\x1b[1 q\x1b[6nZ", "AZ", stats={"ignored_sequences": 3}) + self.expect(b"A\x1b[?9999h\x1b[1 q\x1b[6nZ", "AZ", stats={"ignored_sequences": 3}) + + def test_known_alternate_mode_is_not_counted_as_ignored(self): + self.expect(b"A\x1b[?1049hALT\x1b[?1049hNEW\x1b[?1049lZ", "AZ", + stats={"ignored_sequences": 0}) def test_invalid_parameter_does_not_apply_prefix(self): self.expect(b"A\x1b[2;3;4H\x1b[3J\x1b[3KZ", "AZ", stats={"ignored_sequences": 3}) From c9f2eacff4540c2623552a72eaa5bab4fa6262c9 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Thu, 29 Oct 2026 01:37:41 +0800 Subject: [PATCH 3/6] docs: record bounded C++ 1049 validation and remaining gaps (#135) --- docs/EVIDENCE.md | 1 + docs/FEATURES.md | 2 +- experiments/core/README.md | 5 +- .../results/2026-10-29-cpp-1049/README.md | 37 + .../2026-10-29-cpp-1049/validation.json | 841 ++++++++++++++++++ 5 files changed, 883 insertions(+), 3 deletions(-) create mode 100644 experiments/core/results/2026-10-29-cpp-1049/README.md create mode 100644 experiments/core/results/2026-10-29-cpp-1049/validation.json diff --git a/docs/EVIDENCE.md b/docs/EVIDENCE.md index 030eb596..f6cfb9b8 100644 --- a/docs/EVIDENCE.md +++ b/docs/EVIDENCE.md @@ -8,6 +8,7 @@ | 配置 | 证据定位 | |---|---| +| 自主 C++ 限定 1049 协议 | [固定结果](../experiments/core/results/2026-10-29-cpp-1049/README.md)、[验证身份](../experiments/core/results/2026-10-29-cpp-1049/validation.json):文字/光标/颜色及 pending-wrap、重复进入与读者失效;55项中Qt1项分列,13条内部skip及旧负例判据失败保留。未验收非颜色属性/全网格背景、其他模式、真实TUI/IME/DPI、呈现或性能 | | 自主 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 失败保留。没有原生上屏、完整部署哈希或产品包验收 | diff --git a/docs/FEATURES.md b/docs/FEATURES.md index ce6fa6b1..26a81187 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -25,7 +25,7 @@ |---|---|---|---| | 自主 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 交互已迁移。 +自主 C++ 核心已有 [#130 双缓冲存储基础](../experiments/core/results/2026-10-29-buffer-state-r2/README.md),并接入 [#135 限定 1049 协议](../experiments/core/results/2026-10-29-cpp-1049/README.md):strict/recovery 识别 `?1049h/l`,重复进入归首格、清旧备用文本和复位写入颜色,返回恢复主屏文字/光标/颜色及 pending-wrap。共享行 ID、双帧物理 resize 与逻辑 epoch 防止旧位置、选择、搜索及 viewport 复活,包括清屏后重写相同文字。原版完整网格/背景、非颜色属性及其他模式仍未知;本地55项中 Qt1项与其余54项诊断分列,13条内部跳过保留,不表示完整 [#27](https://github.com/JavaZeroo/termforge/issues/27)、真实 TUI/Qt 交互或系统剪贴板已验收。 官方参考的基础文字行为已按 [R1-01 合同](research/windterm-r1-text-contract.md)完成两组各两轮的自动取证;这为独立实现提供行为依据,产品能力仍按下表分别验收。 diff --git a/experiments/core/README.md b/experiments/core/README.md index db1ba28b..b2288b29 100644 --- a/experiments/core/README.md +++ b/experiments/core/README.md @@ -1,6 +1,6 @@ # 最小终端状态回放与有界恢复 -本说明描述**默认自研 C++17 核心**:把分块字节流变成可检查的屏幕、光标和有界历史状态,供离线回放、接收实验和[本地 shell 工作区](../shell/README.md)使用,不依赖 WindTerm、Qt 或私有实现。显式候选构建的 Term/Processor 能力与 [C ABI / C++ 拥有值适配](CANDIDATE.md)另列,不受下表的自研支持范围约束;产品核心路线见 [ADR-0003](../../docs/adr/0003-core-reference-and-reuse.md)。 +本说明描述**默认自研 C++17 核心**:把分块字节流变成可检查的屏幕、光标和有界历史状态,供离线回放、接收实验和[本地 shell 工作区](../shell/README.md)使用,不依赖 WindTerm、Qt 或私有实现。显式候选构建的 Term/Processor 能力与 [C ABI / C++ 拥有值适配](CANDIDATE.md)另列,不受下表的自研支持范围约束;已确认的产品核心路线见 [ADR-0008](../../docs/adr/0008-cpp-core-qt-widgets.md)。 解析器提供默认 `strict` 和显式 `ParseMode::recovery` 两种模式。replay/receive、trace 默认值和共同子集差分使用严格模式,本地 shell 选择恢复模式;测试 trace 可用第七个参数 `--recovery` 比较恢复行为,或 `--resize=RxC` 在输入结束点 resize 并追加检查点。[恢复策略](RECOVERY.md)定义未知控制序列、非法 UTF-8、超长输入、取消及 EOF 的有界处理;下表未支持输入的失败规则适用于严格模式。 @@ -21,12 +21,13 @@ | `CSI n X` | 擦除当前位置起 n 格;省略或 0 为 1,裁剪到本行右边界,不移动光标,清除待换行;[来源与 More 回归](../../docs/research/more-capture-ech.md) | | UTF-8 | 跨块解码 1–4 字节;严格拒绝过长编码、代理区、越界、孤立续字节及截断输入 | | `CSI m` | 0 重置、1/22 粗体开关;30–37/40–47 和 90–97/100–107 前景/背景色;39/49 恢复默认色 | +| `CSI ?1049h/l` | [限定文字/光标/颜色合同](results/2026-10-29-cpp-1049/README.md):进入/重复进入归首格、清旧备用文本及复位前景/背景,退出恢复主屏与 pending-wrap;重复进入的逻辑世代使旧读者失效。原版完整网格背景、非颜色属性及其他模式未知 | 状态 JSON 使用 0 起始 `row/column`,每行保留尾部空格,记录 `wrap_pending`、完整可见行、保留的历史行和已淘汰行数。滚动按物理行保存历史,默认 24×80、最多 100 行历史;没有逻辑行重排。搜索由独立只读投影模块执行,解析器不持有查询。清除显示不是清除历史。 解析器在 `feed` 调用之间保留 ESC/CSI 和 UTF-8 状态。SGR 参数最多 16 个,其他命令按语义限制为 1 或 2 个;数值最多 99,999、CSI 参数到终止字符最多 32 字节。尺寸限制为 1–200 行、1–500 列,历史容量 0–10,000;容量为零时只累计淘汰数。 -**明确未支持:** 完整字素簇和文字整形、ZWJ/变体选择符/旗帜/肤色修饰序列、256 色/真彩色及其他 SGR 属性、OSC/DCS 的功能、备用屏幕、滚动区域、插入删除、逻辑行 reflow、模式切换、回复查询及其他控制字节。严格模式下,未支持输入、非法参数或 EOF 时截断的序列使运行失败;不静默忽略,也不输出成功快照。严格模式不支持控制序列内部的 C0 中断/取消;错误后不得继续复用该解析器对象。Recovery 可消费这些未实现功能,但不会执行它们。 +**明确未支持:** 完整字素簇和文字整形、ZWJ/变体选择符/旗帜/肤色修饰序列、256 色/真彩色及其他 SGR 属性、OSC/DCS 的功能、完整备用屏关联模式、滚动区域、插入删除、逻辑行 reflow、1049 以外的模式切换、回复查询及其他控制字节。严格模式下,未支持输入、非法参数或 EOF 时截断的序列使运行失败;不静默忽略,也不输出成功快照。严格模式不支持控制序列内部的 C0 中断/取消;错误后不得继续复用该解析器对象。Recovery 可消费这些未实现功能,但不会执行它们。 ## 字符宽度与单元格契约 diff --git a/experiments/core/results/2026-10-29-cpp-1049/README.md b/experiments/core/results/2026-10-29-cpp-1049/README.md new file mode 100644 index 00000000..14f88bb4 --- /dev/null +++ b/experiments/core/results/2026-10-29-cpp-1049/README.md @@ -0,0 +1,37 @@ +# 自主 C++ 的 1049 文字、光标与颜色子集(#135) + +本项把 `CSI ?1049h/l` 接入自主 C++ Parser,复用 [#130 的双帧存储](../2026-10-29-buffer-state-r2/README.md)。首次及重复进入备用屏归首格、清除旧备用文本并复位写入前景/背景颜色;退出恢复主屏文字、光标、颜色与 pending-wrap,重复退出不回退后续主屏写入。未知 private 模式及多模式列表不会部分执行。 + +依据是原版 [#118 文字/光标](../../../../docs/research/windterm-alternate-reference-2026-10-28.md)、[#123 pending-wrap](../../../../docs/research/windterm-alternate-style-reference-2026-10-28.md)及 [raw-capture-v1 的局部 H/space 输出](../../../../docs/research/windterm-raster-raw-reference-2026-10-29.md)。不把颜色正控的输出匹配写成读取了内部 pen。完整物理备用帧的文字擦除是本实现方法;原版全部网格/背景、bold 等非颜色属性、47/1047/1048、margin/origin/wrap 模式族及其组合仍未验收。其他属性保留每帧拥有状态,不能据工程默认值推断原版。 + +## 固定源码与公开接口 + +运行实现为 `40bee8e504410ed167bee600a1a5597417204809`;`c1be53ebdbc8f4094749924d821699eb5368eba0`只更新旧负例并增加正向 CLI 测试;将 main `5f7373fc79eb152d8e4574b1d2b0dfbdd7068f77` 合入后,最终完整验证源码为 **`575bd282b7f61fc4c47da0cad7739b0c46d8c1f2`**。本报告为后续文档整理,不改变运行身份。[validation.json](validation.json)保存实际源、EXE、日志和输入清单 SHA。 + +Parser 负责模式协议,Screen 负责帧状态和读者身份;`Parser::screen` 地址、JSON 和候选 C ABI 保持原边界。直接存储激活同帧仍幂等;协议重复进入另更新逻辑 epoch,防止清屏后重写相同文字时旧选区复活。激活交换容器,不复制整份历史;备用输出不污染主屏历史,物理 resize 沿原策略同时维护隐藏帧。 + +[公开边界测试](../../alternate_mode_test.cpp)覆盖 strict/recovery、首次/重复进入及退出、原版同一 `91×25` 网格的 208B 五阶段源(不含 DSR 查询)的全部分割点和逐字节输入、无中间 DSR 的末列 W→切屏→返回 X、历史/resize 与旧/新文档读者。预期为独立字面文本、位置、颜色和状态,未以同实现快照互比代替 oracle。strict 未知序列继续 fail-fast;recovery 的取消、截断、ESC 重同步和参数/长度上限仍回归。 + +## 真实红绿与旧判据更新 + +三个实际运行反例依次为:原 Parser 拒绝 private CSI;重复进入未归首格/清旧文本;重复进入后写回相同 `ALT` 使原选区被文本协调逻辑接受。前两者由协议接线/复位解决,第三者由逻辑 epoch 失效解决。固定边界、原失败日志与当时精选源码/EXE 身份保留;第一次 green 的 EXE 未在下一次构建前单独取哈希,JSON 如实为 null,不补造历史身份。 + +首次完整源码 `40bee8e` 为 **52/54,exit8,298.93s**:`core` 与 `recovery` 的旧负例仍把新支持的 `?1049h` 当未知。随后将未知模式样本改为仍不支持的 `?9999h`,保留原拒绝/吞序列检查并增加两条独立正向 CLI 往返测试;相关 2/2 通过。没有为这些负例失败修改生产 C++,也没有增大期限或跳过检查。两次完整运行之间 **101 个 runtime 文件逐字节相同**;新增 raw 工具回归使最终注册数为55,不把两次运行拼接为一次。 + +## 最终完整验证 + +Windows 11 x64 build26200,VS2022 / MSVC19.42.34433.0,Release,Python3.12.10,Qt6.10.3;Qt 开启、candidate adapter 关闭。Qt 使用随包固定微软 ConPTY1.25.260930003,其余既有 Windows 诊断各自使用 system backend。固定 Qt SDK 的 4,358 文件树 SHA 为 `a35ab6fe76b62e4d9bd6d3c6b0d476c63583070cea5c9118ef5bb02042ffe266`。 + +```powershell +cmake -S . -B build/qt-1049 -G 'Visual Studio 17 2022' -A x64 -DTERMFORGE_BUILD_QT_SHELL=ON -DTERMFORGE_BUILD_CANDIDATE_ADAPTER=OFF -DCMAKE_PREFIX_PATH=<固定QtSDK> -DTERMFORGE_CONPTY_BACKEND_DIR=<固定ConPTY> -DPython3_EXECUTABLE= +cmake --build build/qt-1049 --config Release --parallel 2 +ctest --test-dir build/qt-1049 -C Release --verbose --output-junit <工作树>/local/cpp-1049-r2/14-reviewed-ctest.xml +``` + +仅测试进程 PATH 前置 Git `usr/bin`,`PYTHONUTF8=1`、`TERMFORGE_REQUIRE_SYSTEM_CLIPBOARD=0`;Qt 对应 CTest 单独使用 offscreen。configure/build 均 exit0,最终 **55/55、exit0、289.74s**。时间仅为测试耗时,不是性能结果。Qt 为1项,其余54项为自研核心、既有或独立诊断,不能写成55项 Qt 产品能力。 + +运行前后 **7,196 文件**一致:源码2,737、Qt产品runtime25、smoke runtime27、既有诊断runtime49、SDK4,358。完整 manifest/raw 日志本地保留,公开只列精选身份及清单哈希。Qt smoke 1.47s,原有限 cmd 标签、错误隔离和真实事件循环退出前回收通过,outer Job `active0/total26/terminated0`;它没有新增 TUI/备用屏 GUI 验收,`presented_done=null`。 + +CTest 注册级无 skip,框架内部有 **13 条 skip**,逐条列在 JSON:4项可选参考整类、7项需要 disposable hosted VM 的真实剪贴板 UI、1项 opt-in 原版失败注入,以及本次 `paste_system` 私有 station 的系统 API 以 **OpenClipboard error5** 跳过。该 API 未通过,不能用完整55项计数或旧独立成功覆盖;没有为取绿重跑。完整 LastTest 原字节 SHA 保留;只从其中 ASCII skip 行生成脱敏字段,私有证据路径不公开。 + +Spec 0 项发现,Standards 0 项硬违规/0 项需单列 smell;完整测试及文档随后补齐交付证据。原版数据与本项目单元/CLI/Qt测试各自保留身份。本项不验收完整模式、真实 TUI/IME/不同 DPI、实际 presented、干净机器运行库分发、性能预算或 R2。 diff --git a/experiments/core/results/2026-10-29-cpp-1049/validation.json b/experiments/core/results/2026-10-29-cpp-1049/validation.json new file mode 100644 index 00000000..d4fffb0a --- /dev/null +++ b/experiments/core/results/2026-10-29-cpp-1049/validation.json @@ -0,0 +1,841 @@ +{ + "schema": "termforge-cpp-1049-local-validation-v1", + "issue": 135, + "scope": "Independent C++ 1049 text/cursor/colour subset; finite original observations and engineering reader invalidation", + "runtime_implementation_commit": "40bee8e504410ed167bee600a1a5597417204809", + "test_contract_commit": "c1be53ebdbc8f4094749924d821699eb5368eba0", + "validated_source_commit": "575bd282b7f61fc4c47da0cad7739b0c46d8c1f2", + "integrated_main_base": "5f7373fc79eb152d8e4574b1d2b0dfbdd7068f77", + "configuration": { + "platform": "Windows 11 x64, build 26200", + "generator": "Visual Studio 17 2022", + "compiler": "MSVC 19.42.34433.0", + "configuration": "Release", + "python": "3.12.10", + "qt_shell": true, + "candidate_adapter": false, + "qt_version": "6.10.3", + "qt_sdk_tree_sha256": "a35ab6fe76b62e4d9bd6d3c6b0d476c63583070cea5c9118ef5bb02042ffe266", + "qt_backend": "fixed Microsoft ConPTY, package 1.25.260930003", + "remaining_windows_diagnostics_backend": "system ConPTY, separate from the Qt product entry" + }, + "test_environment": { + "PATH_prepend": "/usr/bin", + "PYTHONUTF8": "1", + "TERMFORGE_REQUIRE_SYSTEM_CLIPBOARD": "0", + "qt_test_platform": "offscreen; only that CTest entry" + }, + "commands": [ + "cmake -S . -B build/qt-1049 -G \"Visual Studio 17 2022\" -A x64 -DTERMFORGE_BUILD_QT_SHELL=ON -DTERMFORGE_BUILD_CANDIDATE_ADAPTER=OFF -DCMAKE_PREFIX_PATH= -DTERMFORGE_CONPTY_BACKEND_DIR= -DPython3_EXECUTABLE=", + "cmake --build build/qt-1049 --config Release --parallel 2", + "ctest --test-dir build/qt-1049 -C Release --verbose --output-junit /local/cpp-1049-r2/14-reviewed-ctest.xml" + ], + "final_result": { + "configure_exit_code": 0, + "build_exit_code": 0, + "ctest_exit_code": 0, + "ctest_registered": 55, + "ctest_passed": 55, + "ctest_skipped": 0, + "test_elapsed_seconds": 289.74, + "elapsed_is_performance_measurement": false, + "qt_ctest_entries": 1, + "other_core_or_existing_diagnostic_entries": 54, + "internal_skips": [ + { + "test": "setUpClass (test_candidate_compare.CandidateComparisonTests)", + "reason": "optional Alacritty binary is not built; core-candidate workflow runs these checks" + }, + { + "test": "setUpClass (test_capability_matrix.CapabilityMatrixTests)", + "reason": "optional Alacritty binary is not built; core-candidate workflow runs these checks" + }, + { + "test": "setUpClass (test_fuzz_matrix.FuzzMatrixTests)", + "reason": "optional Alacritty binary is not built; core-candidate workflow runs these checks" + }, + { + "test": "setUpClass (test_real_app_matrix.RealApplicationMatrixTests)", + "reason": "optional real application capture dependencies are not built" + }, + { + "test": "test_actual_system_copy_paste_and_shortcuts_twice (experiments.shell.test_actions.ActionWindowTest.test_actual_system_copy_paste_and_shortcuts_twice)", + "reason": "actual system Copy/Paste requires a disposable hosted VM" + }, + { + "test": "test_suspended_target_is_reclaimed_if_job_assignment_fails (test_ui_r1.EvidenceBoundaryTests.test_suspended_target_is_reclaimed_if_job_assignment_fails)", + "reason": "opt-in pinned reference failure injection" + }, + { + "test": "test_mouse_selection_to_real_system_clipboard (experiments.shell.test_shell.ShellTests.test_mouse_selection_to_real_system_clipboard)", + "reason": "system copy UI gate requires a disposable hosted VM" + }, + { + "test": "test_system_clipboard_product_read_errors_cancel_and_close (experiments.shell.test_shell.ShellTests.test_system_clipboard_product_read_errors_cancel_and_close)", + "reason": "product clipboard read gate requires a disposable hosted VM" + }, + { + "test": "test_system_clipboard_shortcut_to_window_confirmation_and_receiver (experiments.shell.test_shell.ShellTests.test_system_clipboard_shortcut_to_window_confirmation_and_receiver)", + "reason": "real system clipboard UI gate requires a disposable hosted VM" + }, + { + "test": "test_owned_clipboard_contention_preserves_write_and_read_failures (experiments.shell.test_selection_bytes.SelectionBytesWindowTest.test_owned_clipboard_contention_preserves_write_and_read_failures)", + "reason": "system CF requires a disposable hosted VM" + }, + { + "test": "test_real_system_copy_shortcuts_for_styled_fixture_twice (experiments.shell.test_selection_bytes.SelectionBytesWindowTest.test_real_system_copy_shortcuts_for_styled_fixture_twice)", + "reason": "system CF requires a disposable hosted VM" + }, + { + "test": "test_real_system_copy_and_edit_context_twice (experiments.shell.test_selection_context.SelectionContextWindowTest.test_real_system_copy_and_edit_context_twice)", + "reason": "real CF/EDIT Copy requires a disposable hosted VM" + }, + { + "test": "test_real_system_clipboard (experiments.shell.test_paste.PasteTests.test_real_system_clipboard)", + "reason": "Private window station OpenClipboard denied (5); system API gate remains unverified." + } + ], + "internal_skips_source": "Complete LastTest.log, not truncated JUnit output", + "system_clipboard_api_passed": false, + "system_clipboard_limitation": "Private window station OpenClipboard denied (5); skipped, not repaired or accepted" + }, + "qt_supervisor": { + "schema": "termforge-qt-cpp-supervisor-v1", + "status": "passed", + "timed_out": false, + "exit_code": 0, + "job_after": { + "active": 0, + "total": 26, + "terminated": 0 + }, + "sample": { + "schema": "termforge-qt-cpp-smoke-v1", + "qt": "6.10.3", + "core": "cpp", + "backend": "fixed-microsoft-conpty", + "arithmetic": 750, + "child_exit": 37, + "cleanup_verified": true, + "image_changed": true, + "startup_error_visible": true, + "manual_close_reclaimed": true, + "tabs": { + "arithmetic": [ + 750, + 427 + ], + "survivor_after_close": 778, + "survivor_after_startup_failure": 147, + "natural_exit": 41, + "input_isolation": true, + "answer_ink_visible": true, + "independent_close": true, + "startup_error_visible": true, + "window_close_reclaimed": true, + "all_exited_status": 41, + "failed_only_kept_visible": true + }, + "app_exec": { + "window_close": true, + "last_tab_close": true, + "failed_only_close": true, + "completed_tab_close": true, + "cleanup_before_quit": true, + "manual_status": 0 + }, + "presented_done": null + } + }, + "fixed_inputs": { + "source_worktree_clean_before_test": true, + "counts": { + "source": 2737, + "product_runtime": 25, + "smoke_runtime": 27, + "legacy_diagnostic_runtime": 49, + "qt_sdk": 4358 + }, + "files_checked_after": 7196, + "changed_files_after": [], + "manifest": { + "bytes": 1570859, + "sha256": "cec180a0641469cfa91252b314f263320c886248d695a00689b727805573fe0e" + }, + "verification": { + "bytes": 186, + "sha256": "7130dd8e49b00af793b73f6b190f53a579bacdac3374c93d1566789a5c19b093" + }, + "selected_files": [ + { + "scope": "source", + "path": "CMakeLists.txt", + "bytes": 24445, + "sha256": "b38962ca303444fa982b9420374d3aae5dd2651cee27bd63ccc1cd78e6650a77" + }, + { + "scope": "source", + "path": "experiments/core/alternate_mode_test.cpp", + "bytes": 11614, + "sha256": "1b68d19fb4c64942d96e5d44ccda14e5937a7d2c418e6d9cffc135b94b3498ad" + }, + { + "scope": "source", + "path": "experiments/core/screen.hpp", + "bytes": 17242, + "sha256": "04c19f09ebc0c468efbef8dd4c9da8f4bcd44e94000a87c56239756c0df1b474" + }, + { + "scope": "source", + "path": "experiments/core/terminal.hpp", + "bytes": 12270, + "sha256": "ed3c030611a6df38df26057a8c2834f2808cd05306e73aead79927b1f76fe5ca" + }, + { + "scope": "source", + "path": "experiments/core/test_core.py", + "bytes": 4834, + "sha256": "f912732afadc939db9c52d0c9876a2c1626168fac0317091d7b93ed577a7a549" + }, + { + "scope": "source", + "path": "experiments/core/test_recovery.py", + "bytes": 15717, + "sha256": "a6b4f13199fd538c3de1240f29c58ba6f8756ca26a12efccaead936a45c03298" + }, + { + "scope": "source", + "path": "third_party/conpty/manifest.json", + "bytes": 1467, + "sha256": "e75e522a3355c0a66c6d60cafa02413a83d8757262747f650b77c959c09ed439" + }, + { + "scope": "source", + "path": "third_party/qt/manifest.json", + "bytes": 5806, + "sha256": "2796294f254f7fe0370be99d2de8f7745734c7352ac2648b1f8d9a8fab5ad2cd" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/assets/fonts/OFL.txt", + "bytes": 4395, + "sha256": "50ab8dd54680d3473f649c9db86fece88434d097c7834475c1c72d2f8c429215" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/assets/fonts/README.md", + "bytes": 3091, + "sha256": "760a714ad011733e0b93f3c25298190ff5fa493a9e40ad38d347922a355d538f" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/assets/fonts/RobotoMono-Regular.ttf", + "bytes": 125748, + "sha256": "af0bff7599c3df3831755c16e39b3c496df74b8c8d8a1161b14dc8461be17cb4" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/conpty-backend/conpty.dll", + "bytes": 119608, + "sha256": "feeef341d891643c62d30b6b07800bc70f0bc148f44cb8c3bee84aa557ae805a" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/conpty-backend/LICENSE", + "bytes": 1095, + "sha256": "ad0cf28f3381ca9bb0bf101d127402d44c17bfa0991e1a00bff7ae6679e9dada" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/conpty-backend/manifest.json", + "bytes": 1467, + "sha256": "e75e522a3355c0a66c6d60cafa02413a83d8757262747f650b77c959c09ed439" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/conpty-backend/OpenConsole.exe", + "bytes": 1089376, + "sha256": "3d66b23d0a71bb8eed2b77edc8b9df9bf54ce6c8fb74c863a30e760997f80586" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/D3Dcompiler_47.dll", + "bytes": 4669440, + "sha256": "0f89c19165fd83a05e39bea601a06007e6a8814d55e2adf913902926231f843e" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/dxcompiler.dll", + "bytes": 14019128, + "sha256": "2bc16dc5ec85315f89e2f10a482d46dde94a65d6b2d7077f4c49c77e10222acc" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/dxil.dll", + "bytes": 1502760, + "sha256": "0e90c12c1c6aa1e09d025322a815f9dd80da7d1e331f1df585c7fcbbf44b40d3" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/generic/qtuiotouchplugin.dll", + "bytes": 102712, + "sha256": "69498d05870aa583c31159f9350e3d8a598b895f6525de7b6fa382395ad27b9d" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/icuuc.dll", + "bytes": 36864, + "sha256": "59d134ddc15ae0594f0a328979f8201662fc82634ddb7c537b156e7cf871f5eb" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/imageformats/qgif.dll", + "bytes": 47928, + "sha256": "ded464ef782f41862f391bc5b21c54d58f6aee670fc9f10a2d909ae5b0ba09a7" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/imageformats/qico.dll", + "bytes": 45880, + "sha256": "0c2abdf95d778bfed9863b8be817dc6cffe2dacdd1a85b2117b4b4ccb1a08e66" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/imageformats/qjpeg.dll", + "bytes": 577848, + "sha256": "cd965015cce4638361d7bc01193d92a041a227d46d0759ec25d2a1a8608a6b40" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/networkinformation/qnetworklistmanager.dll", + "bytes": 70968, + "sha256": "4bc26d5b613c507634fd10f07fe031fcbd4f02157d23b9eb1407de4dd6da8278" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/platforms/qwindows.dll", + "bytes": 997688, + "sha256": "cafd5bfdef3d89d176ee26725c8d4759fd6cb007645b645a4cbf6386364a3f36" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/Qt6Core.dll", + "bytes": 10250040, + "sha256": "b712b4754588e89f855dc0aa087d6304b2fd21b0e0639d1cdeb9cb969bd5fb72" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/Qt6Gui.dll", + "bytes": 9514296, + "sha256": "03ba47a2025036a04f5548bce242788ac21edf551e78d5b42e1b87beb799904f" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/Qt6Network.dll", + "bytes": 1773880, + "sha256": "203f8ddf83c015ce56752ebe7a1986472be7dbb95c20e13ac8e1d741d9ac93d1" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/Qt6Widgets.dll", + "bytes": 6577464, + "sha256": "61ddd0316a731b8dbabaf2924cd0d47b756461e37329b4f535902cf450416127" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/styles/qmodernwindowsstyle.dll", + "bytes": 221496, + "sha256": "c279e7a97b21fcd7acdfde88cacb8baa119f563282e09c241acb3edee2bc9bbf" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/termforge_qt_shell.exe", + "bytes": 148480, + "sha256": "63c9c42186263b32d6bc2d0897ab9bd52fa063816da44ca7fd419afa7022a9ad" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/tls/qcertonlybackend.dll", + "bytes": 103224, + "sha256": "99d00b37bb2835c539366e4018a58e0ddad21e1c648a3f44f56335a0c1d34765" + }, + { + "scope": "product_runtime", + "path": "build/qt-1049/qt-bin/Release/tls/qschannelbackend.dll", + "bytes": 262968, + "sha256": "b7035c3689b93f55b48112c3e85cf4b8550fefde3f7a044df2784c29330e6940" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/assets/fonts/OFL.txt", + "bytes": 4395, + "sha256": "50ab8dd54680d3473f649c9db86fece88434d097c7834475c1c72d2f8c429215" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/assets/fonts/README.md", + "bytes": 3091, + "sha256": "760a714ad011733e0b93f3c25298190ff5fa493a9e40ad38d347922a355d538f" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/assets/fonts/RobotoMono-Regular.ttf", + "bytes": 125748, + "sha256": "af0bff7599c3df3831755c16e39b3c496df74b8c8d8a1161b14dc8461be17cb4" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/conpty-backend/conpty.dll", + "bytes": 119608, + "sha256": "feeef341d891643c62d30b6b07800bc70f0bc148f44cb8c3bee84aa557ae805a" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/conpty-backend/LICENSE", + "bytes": 1095, + "sha256": "ad0cf28f3381ca9bb0bf101d127402d44c17bfa0991e1a00bff7ae6679e9dada" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/conpty-backend/manifest.json", + "bytes": 1467, + "sha256": "e75e522a3355c0a66c6d60cafa02413a83d8757262747f650b77c959c09ed439" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/conpty-backend/OpenConsole.exe", + "bytes": 1089376, + "sha256": "3d66b23d0a71bb8eed2b77edc8b9df9bf54ce6c8fb74c863a30e760997f80586" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/D3Dcompiler_47.dll", + "bytes": 4669440, + "sha256": "0f89c19165fd83a05e39bea601a06007e6a8814d55e2adf913902926231f843e" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/dxcompiler.dll", + "bytes": 14019128, + "sha256": "2bc16dc5ec85315f89e2f10a482d46dde94a65d6b2d7077f4c49c77e10222acc" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/dxil.dll", + "bytes": 1502760, + "sha256": "0e90c12c1c6aa1e09d025322a815f9dd80da7d1e331f1df585c7fcbbf44b40d3" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/generic/qtuiotouchplugin.dll", + "bytes": 102712, + "sha256": "69498d05870aa583c31159f9350e3d8a598b895f6525de7b6fa382395ad27b9d" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/icuuc.dll", + "bytes": 36864, + "sha256": "59d134ddc15ae0594f0a328979f8201662fc82634ddb7c537b156e7cf871f5eb" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/imageformats/qgif.dll", + "bytes": 47928, + "sha256": "ded464ef782f41862f391bc5b21c54d58f6aee670fc9f10a2d909ae5b0ba09a7" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/imageformats/qico.dll", + "bytes": 45880, + "sha256": "0c2abdf95d778bfed9863b8be817dc6cffe2dacdd1a85b2117b4b4ccb1a08e66" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/imageformats/qjpeg.dll", + "bytes": 577848, + "sha256": "cd965015cce4638361d7bc01193d92a041a227d46d0759ec25d2a1a8608a6b40" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/networkinformation/qnetworklistmanager.dll", + "bytes": 70968, + "sha256": "4bc26d5b613c507634fd10f07fe031fcbd4f02157d23b9eb1407de4dd6da8278" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/platforms/qoffscreen.dll", + "bytes": 113976, + "sha256": "a35f87f597b91121cfc0ef39dcb0a5e7ad2876850fbfaf6377edf80eaa067bfd" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/platforms/qwindows.dll", + "bytes": 997688, + "sha256": "cafd5bfdef3d89d176ee26725c8d4759fd6cb007645b645a4cbf6386364a3f36" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/Qt6Core.dll", + "bytes": 10250040, + "sha256": "b712b4754588e89f855dc0aa087d6304b2fd21b0e0639d1cdeb9cb969bd5fb72" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/Qt6Gui.dll", + "bytes": 9514296, + "sha256": "03ba47a2025036a04f5548bce242788ac21edf551e78d5b42e1b87beb799904f" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/Qt6Network.dll", + "bytes": 1773880, + "sha256": "203f8ddf83c015ce56752ebe7a1986472be7dbb95c20e13ac8e1d741d9ac93d1" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/Qt6Test.dll", + "bytes": 380216, + "sha256": "9d0473552b332aa378c60da05af97d741fcce06b0fc4dd68e36d885015eb5187" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/Qt6Widgets.dll", + "bytes": 6577464, + "sha256": "61ddd0316a731b8dbabaf2924cd0d47b756461e37329b4f535902cf450416127" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/qt_cpp_shell_smoke.exe", + "bytes": 204800, + "sha256": "ee1e60ff8235ae3ce3fd702d083e3d4f6d85ef5fc2582364944a07c3bd3fa2f8" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/styles/qmodernwindowsstyle.dll", + "bytes": 221496, + "sha256": "c279e7a97b21fcd7acdfde88cacb8baa119f563282e09c241acb3edee2bc9bbf" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/tls/qcertonlybackend.dll", + "bytes": 103224, + "sha256": "99d00b37bb2835c539366e4018a58e0ddad21e1c648a3f44f56335a0c1d34765" + }, + { + "scope": "smoke_runtime", + "path": "build/qt-1049/qt-smoke-bin/Release/tls/qschannelbackend.dll", + "bytes": 262968, + "sha256": "b7035c3689b93f55b48112c3e85cf4b8550fefde3f7a044df2784c29330e6940" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/alternate_mode_test.exe", + "bytes": 121344, + "sha256": "8712b7e42a0085ebd050aeae25f7eaf50707291272b24758991133619e331530" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/buffer_state_test.exe", + "bytes": 132608, + "sha256": "c8c926184328f8cdb48c91e38e4a214660a79453c8338b60eeb1c0f1987fd288" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/history_test.exe", + "bytes": 118272, + "sha256": "407b55bece4877de846cb11605598ff3c411dd1839899a283983f1a107b5a320" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/replay.exe", + "bytes": 78848, + "sha256": "4e18684aa75b2e25853857e1c29848c3d53626e6be37f33c554a112eb88092aa" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/resize_test.exe", + "bytes": 105472, + "sha256": "35bc2bc20e5ec31040a1ac67f520833bb193cd2b66bffffb314b06d70cf632c5" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/search_test.exe", + "bytes": 148992, + "sha256": "403f51fb06371fe77f6c2357da4eedf86f59f7c73fdb71eacb718bc35322451d" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/selection_test.exe", + "bytes": 122368, + "sha256": "70e47db26964a51f5623904894d785e486051b5142be55af7b1891f3a1a563eb" + }, + { + "scope": "legacy_diagnostic_runtime", + "path": "build/qt-1049/bin/Release/terminal_trace.exe", + "bytes": 84992, + "sha256": "3f8bda9d6b1443d02265089ed560941ab8c226cd0bd2900cbadea3812a55d081" + } + ] + }, + "red_green_cases": [ + { + "case": "Unsupported private CSI", + "red_exit_code": 1, + "red_log": { + "bytes": 25, + "sha256": "fc4971332820f79b79e94fe734813499a86478b957c7d8502197a8426c8b3663" + }, + "red_source_base": "4f34146ab81f5b156537b080df2156f484793cc4", + "red_worktree_clean": false, + "red_selected_files": [ + { + "path": "CMakeLists.txt", + "sha256": "b91cbc73b2ed218f6e47d4258ef48e6643aae0639998054673878980eb13e541" + }, + { + "path": "experiments/core/alternate_mode_test.cpp", + "sha256": "89143144279dc1339e22ac4c252a43eebf5740d1c2507628fd6000fa5b7a0021" + }, + { + "path": "experiments/core/terminal.hpp", + "sha256": "e5ca6b065b38b98ba4bb32f579e4f0e8e126a7872de147ff37c2c68aac414358" + }, + { + "path": "experiments/core/screen.hpp", + "sha256": "534068ce7fc2d9b5436c87b84626d9cf5b9e9bf2811a9a789c03c77925786ccc" + }, + { + "path": "build/qt-1049/bin/Release/alternate_mode_test.exe", + "sha256": "d951179b8b45cd98cde6cb189b5a42bfc4f36fd4ebc4b77c6f9660b7d58e3a1b" + } + ], + "red_identity_record": { + "bytes": 950, + "sha256": "2526f468e4d4c499aa5e74b2af33c38d1f4dc698a0d5eeed3dd7ecf417fa04ed" + }, + "green_exit_code": 0, + "green_log": { + "bytes": 30, + "sha256": "9f320ce704edec8d720956840787392bd35766b436d07984360986836cffca2a" + }, + "green_identity_record": null, + "green_identity_limit": "First green executable was not separately hashed before the next build" + }, + { + "case": "Repeated entry did not home", + "red_exit_code": 1, + "red_log": { + "bytes": 63, + "sha256": "8bea610b69abf2cc3594396998392bcf52a5b326ad7e262fb55acd978eb068f9" + }, + "red_source_base": "4f34146ab81f5b156537b080df2156f484793cc4", + "red_worktree_clean": false, + "red_selected_files": [ + { + "bytes": 24334, + "sha256": "b91cbc73b2ed218f6e47d4258ef48e6643aae0639998054673878980eb13e541", + "path": "CMakeLists.txt" + }, + { + "bytes": 3121, + "sha256": "01045f38d1f8d10d93b5d05c0eaf4033babfc501d7e39675bf304ff68d4b8177", + "path": "experiments/core/alternate_mode_test.cpp" + }, + { + "bytes": 11857, + "sha256": "5a59ec953e4503aa6a15c8532dca2fc312dda4a848abbbbdf250e9e315335227", + "path": "experiments/core/terminal.hpp" + }, + { + "bytes": 16884, + "sha256": "534068ce7fc2d9b5436c87b84626d9cf5b9e9bf2811a9a789c03c77925786ccc", + "path": "experiments/core/screen.hpp" + }, + { + "bytes": 62976, + "sha256": "3837d5b4e89343df4f3f095de73167bd47043280affd3fc80204344544875224", + "path": "build/qt-1049/bin/Release/alternate_mode_test.exe" + } + ], + "red_identity_record": { + "bytes": 1100, + "sha256": "e2e0216fea934af9a4a1ef2b41c313e3286067bf8db0da21dd33b46e5c51dc0d" + }, + "green_exit_code": 0, + "green_log": { + "bytes": 30, + "sha256": "9f320ce704edec8d720956840787392bd35766b436d07984360986836cffca2a" + }, + "green_identity_record": { + "bytes": 1100, + "sha256": "7023c4d3ba9470b17b38e9487777c9be5c7e4ec964d613ad581254fa075de862" + }, + "green_identity_limit": null + }, + { + "case": "Identical text revived a prior selection", + "red_exit_code": 1, + "red_log": { + "bytes": 78, + "sha256": "0a4564f03a1a7c2398c691f705f0d98079f5b3d5bfb4dbb41112b561b4c5773c" + }, + "red_source_base": "4f34146ab81f5b156537b080df2156f484793cc4", + "red_worktree_clean": false, + "red_selected_files": [ + { + "bytes": 24334, + "path": "CMakeLists.txt", + "sha256": "b91cbc73b2ed218f6e47d4258ef48e6643aae0639998054673878980eb13e541" + }, + { + "bytes": 10807, + "path": "experiments/core/alternate_mode_test.cpp", + "sha256": "e96b45c59b8c507d084670482a9c764f9d6e22d9058df9ec52a4a1858954c64a" + }, + { + "bytes": 12086, + "path": "experiments/core/terminal.hpp", + "sha256": "37ff1e44e7b0633ff9d39582f7ea7ac47caa6d4330a633ec4f9eae803696e37f" + }, + { + "bytes": 16884, + "path": "experiments/core/screen.hpp", + "sha256": "534068ce7fc2d9b5436c87b84626d9cf5b9e9bf2811a9a789c03c77925786ccc" + }, + { + "bytes": 115712, + "path": "build/qt-1049/bin/Release/alternate_mode_test.exe", + "sha256": "0bce8a542b6420ac3bb245f20e7f5b2f31f43956a82b17187c25f3fd66f9722f" + } + ], + "red_identity_record": { + "bytes": 1102, + "sha256": "21dc97a10a43076fa10307b76c7f308f1d45577dab97d6318b406d24b0b92eac" + }, + "green_exit_code": 0, + "green_log": { + "bytes": 30, + "sha256": "9f320ce704edec8d720956840787392bd35766b436d07984360986836cffca2a" + }, + "green_identity_record": { + "bytes": 1136, + "sha256": "304f67f36aa7b916ffc3d930656db32430a0832a0d71b23799e91c69b333aa34" + }, + "green_identity_limit": null + } + ], + "first_full_run": { + "source_commit": "40bee8e504410ed167bee600a1a5597417204809", + "ctest_registered": 54, + "ctest_passed": 52, + "failed_entries": [ + "core", + "recovery" + ], + "ctest_exit_code": 8, + "test_elapsed_seconds": 298.93, + "cause": "Two old negative fixtures still classified newly supported ?1049h as unknown or unsupported", + "followup": "Retained unknown-mode rejection with ?9999h and added separate strict/recovery positive CLI roundtrips", + "product_runtime_changed_for_fixture_fix": false, + "frozen_files_verified": 7183, + "runtime_files_compared_with_final": 101, + "runtime_files_changed": [], + "raw_records": { + "11-final-ctest.log": { + "bytes": 169100, + "sha256": "adfc8351e64f632bb4a976e47411ceaff62800b652e2b7f3ac147d31010d8648" + }, + "11-final-ctest.xml": { + "bytes": 81229, + "sha256": "d1c84ff9a18a7247861942788369de9e855558d3e792a315b86303e45d57bbd3" + }, + "11-final-exit.json": { + "bytes": 140, + "sha256": "537fc8ee38c845b682a03e250f72b54b626499e67e01c70b8c6b2b01d40d9b5f" + }, + "LastTest.log": { + "bytes": 171545, + "sha256": "d2bdd95f318e95ee757f9f06418be55daba9a31809a7742ef23fe451a7108fd3" + }, + "frozen-inputs.json": { + "bytes": 1568159, + "sha256": "2e4f471c569fae35972458d4292cebe4de7664a5161eece3c73a993dd57c78a8" + }, + "frozen-after.json": { + "bytes": 186, + "sha256": "b19078a62eb2a8c38fe7974652906904c41fd7c623541df81c7e62df256e368e" + } + } + }, + "review": { + "fixed_base": "4f34146ab81f5b156537b080df2156f484793cc4", + "implementation_head": "40bee8e504410ed167bee600a1a5597417204809", + "spec_findings": 0, + "standards_hard_findings": 0, + "standards_smells": 0, + "test_only_followup": "Two unknown-mode fixture substitutions and separate positive CLI tests; production C++ unchanged", + "published_report_hash": null + }, + "raw_records": { + "configure.log": { + "bytes": 1225, + "sha256": "b8eec16a172441f15ba632918f0f5976b622df7e378202d85013fb584e42b91d" + }, + "10-full-build.log": { + "bytes": 15965, + "sha256": "02633f5515285b559b654531d47eeac5f7e6f9d753eeb983827a3d6dc39df9af" + }, + "10-full-build.exit": { + "bytes": 3, + "sha256": "13bf7b3039c63bf5a50491fa3cfd8eb4e699d1ba1436315aef9cbe5711530354" + }, + "13-reviewed-build.log": { + "bytes": 14181, + "sha256": "a3aff2b826b606cefd0ed2da06cbf1c92e0e990c053db6d6701d3883de151098" + }, + "13-reviewed-build.exit": { + "bytes": 3, + "sha256": "13bf7b3039c63bf5a50491fa3cfd8eb4e699d1ba1436315aef9cbe5711530354" + }, + "14-reviewed-ctest.log": { + "bytes": 139430, + "sha256": "d116bc59e09db169a16f1457f9c4fca57d4715dd0aa08c9d94b66d9f1e046138" + }, + "14-reviewed-ctest.xml": { + "bytes": 46165, + "sha256": "40f1eca34c467309fed620ca1243463a38457cb56daecea4daff1e259ac44bb7" + }, + "14-reviewed-exit.json": { + "bytes": 140, + "sha256": "66014eeb506453a81833982d3d8e1b45d570ac2e4a5abb4aac474f139824f628" + }, + "frozen-inputs.json": { + "bytes": 1570859, + "sha256": "cec180a0641469cfa91252b314f263320c886248d695a00689b727805573fe0e" + }, + "frozen-after.json": { + "bytes": 186, + "sha256": "7130dd8e49b00af793b73f6b190f53a579bacdac3374c93d1566789a5c19b093" + }, + "12-core-recovery-contract.log": { + "bytes": 414, + "sha256": "e61aafc8c53dbef649384f773a49e33e8762cd25745ad0b034d877fb7fac0b0f" + } + }, + "last_test_log": { + "bytes": 144171, + "sha256": "a57f0898edfb3d670aa90864693953d7aa1b786454bbb11e67416ab5d33d3d92" + }, + "limitations": [ + "Original reference is finite Telnet terminal text/cursor/H-space output, not local-shell parity.", + "Only writing foreground/background colours reset on entry; other attributes remain frame-owned and original bold behavior is unknown.", + "Full alternate physical-text erasure is an engineering method, not proof of original full-grid background behavior.", + "47/1047/1048, margins/origin/wrap families, keyboard replies, full TUI/IME/DPI and GUI text interactions remain incomplete.", + "Qt 1 smoke and the other54 diagnostic entries do not combine into full product acceptance.", + "The private-station system clipboard test skipped with error5; all13 internal skips remain gaps.", + "No presented endpoint, clean-machine CRT deployment, performance tolerance or R2 completion is claimed." + ], + "windterm_parity": false, + "r2_complete": false, + "performance_gate": "not_evaluated" +} From 1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Thu, 29 Oct 2026 02:08:57 +0800 Subject: [PATCH 4/6] fix(diagnostics): pin complete 1049 reference difference traces (#135) --- .../candidate-known-differences.json | 82 +++++++++++++++- experiments/differential/capability_matrix.py | 2 +- experiments/differential/compare_candidate.py | 71 ++++++++++++-- .../test_candidate_reference_contract.py | 96 +++++++++++++++++++ .../differential/test_capability_matrix.py | 25 ++++- 5 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 experiments/differential/test_candidate_reference_contract.py diff --git a/experiments/differential/candidate-known-differences.json b/experiments/differential/candidate-known-differences.json index 0967ef42..98c7bb94 100644 --- a/experiments/differential/candidate-known-differences.json +++ b/experiments/differential/candidate-known-differences.json @@ -1 +1,81 @@ -{} +{ + "alternate_screen": { + "basis": "Bounded WindTerm2.7.0 #118 first1049 entry homes; the Alacritty reference retains the primary cursor. This is a reference comparison difference, not approval of an original behavior deviation.", + "semantic_acceptance": false, + "projection_hash_encoding": "SHA256 of UTF-8 JSON of the complete ordered common-projection record array; sort_keys=True, ensure_ascii=False, compact separators", + "plans": { + "byte": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "8229315bee9585fa620254e0e294e51ac0bd81511abd114a225774a5ca19686b", + "canonical_candidate_trace_sha256": "f01576eb7ca499c8d3d72789b0cdf2411ba9479134cd6d85666f35e50c8c38b0", + "core_checkpoints": 25, + "candidate_checkpoints": 25 + }, + "seed:42": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 14, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "3dd867db0c75e2ce79f5200865b7365093efe5bc82c83642331775f003b5aaf2", + "canonical_candidate_trace_sha256": "429c29f1b622626efb40eccf768a483e176ced7884e9e9d2dc731aa234f96244", + "core_checkpoints": 6, + "candidate_checkpoints": 6 + }, + "seed:20261022": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "7fbc6a28fcfc045551ce577daf233df09b33d9eb15a2e87dc271c964cba765d8", + "canonical_candidate_trace_sha256": "c8d2626cae1eec2dd14ebfa89ce68c013125cfb77fe2bcadaf940eace57c6c24", + "core_checkpoints": 4, + "candidate_checkpoints": 4 + }, + "seed:8675309": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 13, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "63be2fb28cef585a2c6c7e0f0ae3c8de5225dc9cd1e3385a9b26997096f42667", + "canonical_candidate_trace_sha256": "95572ad54172efd387646f2c9745cdca7f42920626a5b380129a65abb0c5c187", + "core_checkpoints": 4, + "candidate_checkpoints": 4 + } + } + } +} diff --git a/experiments/differential/capability_matrix.py b/experiments/differential/capability_matrix.py index 47e95824..25770eb6 100644 --- a/experiments/differential/capability_matrix.py +++ b/experiments/differential/capability_matrix.py @@ -19,7 +19,7 @@ def data(self): CAPABILITIES = ( - dict(name="alternate_screen", supported=False, + dict(name="alternate_screen", supported=True, case=Case("alternate_screen", "A\r\nB\x1b[?1049hALT\x1b[?1049lZ")), dict(name="scroll_region", supported=False, case=Case("scroll_region", "A\r\nB\r\nC\r\nD\x1b[2;3r\x1b[3;1H\nX\x1b[r\x1b[1;1H")), diff --git a/experiments/differential/compare_candidate.py b/experiments/differential/compare_candidate.py index d9a55c05..09f9f283 100644 --- a/experiments/differential/compare_candidate.py +++ b/experiments/differential/compare_candidate.py @@ -2,6 +2,7 @@ from __future__ import annotations import argparse +import hashlib import json from pathlib import Path import platform @@ -13,7 +14,52 @@ from experiments.candidates.alacritty.run import trace_binary as candidate_trace_binary, vendor_sources +def reference_status(case, plan, difference, core, candidate, known): + """Adjudicate only one complete ordered projection, never a prefix/final shortcut.""" + signature = dict(input_sha256=hashlib.sha256(case.data).hexdigest(), + rows=case.rows, columns=case.columns, history=case.history, + first_difference={key: value for key, value in difference.items() if key != "checkpoint"}, + final_core_sha256=state_sha(core[-1]["screen"]), + final_candidate_sha256=state_sha(candidate[-1]["screen"]), + canonical_core_trace_sha256=state_sha(core), + canonical_candidate_trace_sha256=state_sha(candidate), + core_checkpoints=len(core), candidate_checkpoints=len(candidate)) + expected = known.get(case.name, {}).get("plans", {}).get(plan) + return "reference_difference" if expected == signature else "difference" + + def common_projection(records): + def validate_style(style): + if (not isinstance(style, dict) or not {"fg", "bg", "bold"}.issubset(style) + or type(style["fg"]) is not int or type(style["bg"]) is not int + or type(style["bold"]) is not bool): + raise ValueError("missing or invalid style projection fields") + + # Missing fields must fail even when both malformed traces would compare equal. + for record in records: + if not isinstance(record, dict) or type(record.get("offset")) is not int or record["offset"] < 0: + raise ValueError("invalid checkpoint offset") + screen = record.get("screen") + required = {"row", "column", "wrap_pending", "cells", "history", "current_style"} + if not isinstance(screen, dict) or not required.issubset(screen): + raise ValueError("missing screen projection fields") + validate_style(screen["current_style"]) + for group in ("cells", "history"): + if not isinstance(screen[group], list) or any(not isinstance(row, list) for row in screen[group]): + raise ValueError("invalid projected row collection") + for row in screen[group]: + for cell in row: + if (not isinstance(cell, dict) or not {"text", "width", "style"}.issubset(cell) + or not isinstance(cell["text"], str) or type(cell["width"]) is not int + or cell["width"] < 0): + raise ValueError("missing or invalid cell projection fields") + validate_style(cell["style"]) + cells = screen["cells"] + if (not cells or not cells[0] or any(len(row) != len(cells[0]) for row in cells) + or type(screen["row"]) is not int or not 0 <= screen["row"] < len(cells) + or type(screen["column"]) is not int or not 0 <= screen["column"] < len(cells[0]) + or type(screen["wrap_pending"]) is not bool): + raise ValueError("invalid screen geometry or cursor projection") canonicalize_core(records) result = [] for record in records: @@ -27,6 +73,20 @@ def common_projection(records): return result +def validate_checkpoints(records, sizes, arguments, input_length=None): + """Require every requested feed checkpoint, including an explicit resize tail.""" + offsets = [0] + for size in sizes: + if type(size) is not int or size <= 0: + raise ValueError("invalid requested chunk size") + offsets.append(offsets[-1] + size) + if any(argument.startswith("--resize=") for argument in arguments): + offsets.append(offsets[-1]) + if (input_length is not None and offsets[-1] != input_length + or [record["offset"] for record in records] != offsets): + raise ValueError("missing or unexpected ordered checkpoint") + + def execute(binary, prefix, case, sizes, output, arguments=()): command = [str(binary), str(output / "input.bin"), str(case.rows), str(case.columns), str(case.history), str(output / "chunks.txt"), *arguments] @@ -43,8 +103,7 @@ def execute(binary, prefix, case, sizes, output, arguments=()): if returncode == 0: try: records = common_projection([json.loads(line) for line in stdout.decode("utf-8").splitlines()]) - if not records or records[-1]["offset"] != len(case.data): - raise ValueError("missing final checkpoint") + validate_checkpoints(records, sizes, arguments, len(case.data)) except (ValueError, KeyError, TypeError) as exc: error = str(exc) return records, returncode, error @@ -63,15 +122,9 @@ def run_case(core_binary, candidate_binary, case, plan, output, core_arguments=( difference = compare_traces(core, candidate) status = "execution_failure" if core_code != 0 or candidate_code != 0 or core_error or candidate_error else "match" if difference: - signature = dict(input_sha256=sha(output / "input.bin"), rows=case.rows, columns=case.columns, - history=case.history, - first_difference={key: value for key, value in difference.items() if key != "checkpoint"}, - final_core_sha256=state_sha(core[-1]["screen"]), - final_candidate_sha256=state_sha(candidate[-1]["screen"])) known_path = Path(__file__).with_name("candidate-known-differences.json") known = json.loads(known_path.read_text(encoding="utf-8")) if known_path.exists() else {} - expected = known.get(case.name, {}).get("plans", {}).get(plan) - status = "reference_difference" if expected == signature else "difference" + status = reference_status(case, plan, difference, core, candidate, known) report = dict(case=case.name, plan=plan, input_sha256=sha(output / "input.bin"), bytes=len(case.data), rows=case.rows, columns=case.columns, history=case.history, chunk_sizes=sizes, checkpoints=len(core), status=status, diff --git a/experiments/differential/test_candidate_reference_contract.py b/experiments/differential/test_candidate_reference_contract.py new file mode 100644 index 00000000..c102b883 --- /dev/null +++ b/experiments/differential/test_candidate_reference_contract.py @@ -0,0 +1,96 @@ +"""Trace-data/CLI contract: known Alacritty differences cannot mask later drift.""" +import copy +import json +import unittest + +from cases import Case +import compare_candidate as comparison + +CASE=Case('alternate_screen','A\r\nB\x1b[?1049hALT\x1b[?1049lZ') +FINAL='624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067' +BYTE={ + 'input_sha256':'6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76', + 'rows':3,'columns':12,'history':3, + 'first_difference':{'offset':12,'path':'.screen.row','expected':0,'actual':1}, + 'final_core_sha256':FINAL,'final_candidate_sha256':FINAL, + 'canonical_core_trace_sha256':'8229315bee9585fa620254e0e294e51ac0bd81511abd114a225774a5ca19686b', + 'canonical_candidate_trace_sha256':'f01576eb7ca499c8d3d72789b0cdf2411ba9479134cd6d85666f35e50c8c38b0', + 'core_checkpoints':25,'candidate_checkpoints':25} + + +def literal_trace(candidate=False): + """Independent literal cursor/text states for the unchanged 24-byte input.""" + def screen(row,column,lines): + style={'fg':-1,'bg':-1,'bold':False} + cells=[[{'text':char if char!=' ' else '', 'width':1 if char!=' ' else 0,'style':dict(style)} + for char in line.ljust(12)] for line in lines] + return {'row':row,'column':column,'wrap_pending':False,'cells':cells,'history':[],'current_style':dict(style)} + states=[(0,0,['','','']),(0,1,['A','','']),(0,0,['A','','']),(1,0,['A','',''])] + states += [(1,1,['A','B',''])]*8 + states += ([(1,1,['','','']),(1,2,['',' A','']),(1,3,['',' AL','']),(1,4,['',' ALT',''])] if candidate else + [(0,0,['','','']),(0,1,['A','','']),(0,2,['AL','','']),(0,3,['ALT','',''])]) + states += [states[-1]]*7 + states += [(1,1,['A','B','']),(1,2,['A','BZ',''])] + return [{'offset':offset,'screen':screen(*state)} for offset,state in enumerate(states)] + + +class CandidateReferenceContract(unittest.TestCase): + def test_legacy_first_and_final_only_entry_must_not_authorize_a_trace(self): + core,candidate=literal_trace(),literal_trace(True) + difference=comparison.compare_traces(core,candidate) + legacy={key:value for key,value in BYTE.items() if not key.startswith('canonical_') and not key.endswith('checkpoints')} + known={'alternate_screen':{'plans':{'byte':legacy}}} + self.assertEqual(comparison.reference_status(CASE,'byte',difference,core,candidate,known),'difference') + + def test_complete_literal_signature_matches_and_later_checkpoint_drift_rejects(self): + core,candidate=literal_trace(),literal_trace(True) + self.assertEqual(len(core),25) + self.assertEqual(comparison.state_sha(core),BYTE['canonical_core_trace_sha256']) + self.assertEqual(comparison.state_sha(candidate),BYTE['canonical_candidate_trace_sha256']) + difference=comparison.compare_traces(core,candidate) + self.assertEqual(difference,{'checkpoint':12,**BYTE['first_difference']}) + known={'alternate_screen':{'plans':{'byte':BYTE}}} + self.assertEqual(comparison.reference_status(CASE,'byte',difference,core,candidate,known),'reference_difference') + for target in ('core','candidate'): + left,right=copy.deepcopy(core),copy.deepcopy(candidate) + (left if target=='core' else right)[13]['screen']['current_style']['fg']=1 + self.assertEqual(comparison.compare_traces(left,right),difference) + self.assertEqual(left[-1],core[-1]);self.assertEqual(right[-1],candidate[-1]) + self.assertEqual(comparison.reference_status(CASE,'byte',difference,left,right,known),'difference') + + def test_missing_signature_fields_truncation_and_unlisted_plan_stay_differences(self): + core,candidate=literal_trace(),literal_trace(True) + difference=comparison.compare_traces(core,candidate) + for field in BYTE: + expected=dict(BYTE);expected.pop(field) + self.assertEqual(comparison.reference_status(CASE,'byte',difference,core,candidate,{'alternate_screen':{'plans':{'byte':expected}}}),'difference',field) + known={'alternate_screen':{'plans':{'byte':BYTE}}} + self.assertEqual(comparison.reference_status(CASE,'seed:99',difference,core,candidate,known),'difference') + shortened=copy.deepcopy(candidate);shortened.pop(14) + self.assertEqual(comparison.reference_status(CASE,'byte',difference,core,shortened,known),'difference') + + def test_missing_projection_fields_cannot_become_a_match(self): + for field in ('offset','row','current_style','cell_style'): + records=literal_trace() + if field=='offset':records[14].pop('offset') + elif field=='cell_style':records[14]['screen']['cells'][0][0].pop('style') + else:records[14]['screen'].pop(field) + with self.subTest(field=field),self.assertRaises(ValueError):comparison.common_projection(records) + + def test_complete_checkpoint_schedule_is_required_including_initial_and_resize(self): + core=literal_trace() + comparison.validate_checkpoints(core,[1]*24,()) + for malformed in (core[1:],core[:14]+core[15:],core[:-1],core+[copy.deepcopy(core[-1])]): + with self.assertRaises(ValueError):comparison.validate_checkpoints(malformed,[1]*24,()) + comparison.validate_checkpoints(core+[copy.deepcopy(core[-1])],[1]*24,('--resize=2x6',)) + with self.assertRaises(ValueError):comparison.validate_checkpoints(core,[1]*24,(),input_length=25) + + def test_registry_is_closed_to_the_reviewed_four_plans(self): + path=comparison.Path(comparison.__file__).with_name('candidate-known-differences.json') + known=json.loads(path.read_text(encoding='utf-8')) + self.assertEqual(set(known['alternate_screen']['plans']),{'byte','seed:42','seed:20261022','seed:8675309'}) + self.assertEqual(known['alternate_screen']['plans']['byte'],BYTE) + self.assertFalse(known['alternate_screen']['semantic_acceptance']) + + +if __name__=='__main__':unittest.main() diff --git a/experiments/differential/test_capability_matrix.py b/experiments/differential/test_capability_matrix.py index cfc12ae3..3717d23f 100644 --- a/experiments/differential/test_capability_matrix.py +++ b/experiments/differential/test_capability_matrix.py @@ -1,7 +1,10 @@ """Extended native-candidate capabilities and explicit unsupported-core gates.""" import os +import json from pathlib import Path import tempfile +import subprocess +import sys import unittest import capability_matrix @@ -28,11 +31,12 @@ def records(self, name): def test_extended_matrix_preserves_execution_and_support_boundaries(self): self.assertTrue(self.summary["execution_passed"], self.summary["counts"]) self.assertEqual(self.summary["runs"], 25) - self.assertEqual(self.summary["counts"], {"core_unsupported": 15, "match": 5, "resize_difference": 5}) + self.assertEqual(self.summary["counts"], {"core_unsupported": 10, "match": 6, + "reference_difference": 4, "resize_difference": 5}) self.assertFalse(self.summary["semantic_acceptance"]) self.assertTrue(self.summary["resize_covered"]) self.assertFalse(self.summary["real_application_covered"]) - for name in ("alternate_screen", "scroll_region", "cursor_query"): + for name in ("scroll_region", "cursor_query"): for record in self.records(name): self.assertEqual(record["status"], "core_unsupported") self.assertFalse(record["expected_core_support"]) @@ -42,6 +46,10 @@ def test_extended_matrix_preserves_execution_and_support_boundaries(self): def test_alternate_query_and_region_have_real_candidate_results(self): for record in self.records("alternate_screen"): + self.assertTrue(record["expected_core_support"]) + self.assertEqual(record["status"], "match" if record["plan"] == "whole" else "reference_difference") + self.assertFalse(record.get("core_fragmentation_difference")) + self.assertFalse(record.get("candidate_fragmentation_difference")) self.assertEqual(record["candidate_final_rows"], ["A", "BZ", ""]) for record in self.records("cursor_query"): self.assertEqual(record["replies"], ["\x1b[1;2R"]) @@ -58,6 +66,19 @@ def test_recovery_matches_and_preserves_fragmentation(self): folder = self.artifacts / "suite" / "recovery_stream" / record["plan"].replace(":", "-") self.assertIn(b"\xff", (folder / "input.bin").read_bytes()) + def test_public_cli_keeps_reviewed_and_unlisted_plan_boundaries(self): + for plan,expected_code,expected_counts in ((None,0,{"match":1,"reference_difference":4}), + ("seed:99",1,{"difference":1})): + output=self.artifacts/("cli-fixed" if plan is None else "cli-unlisted") + command=[sys.executable,str(Path(capability_matrix.__file__).resolve()),"--trace",str(self.core), + "--candidate",str(self.candidate),"--out",str(output),"--case","alternate_screen"] + if plan is not None:command.extend(["--plan",plan]) + completed=subprocess.run(command,capture_output=True,text=True,timeout=20) + self.assertEqual(completed.returncode,expected_code,completed.stderr) + summary=json.loads((output/"summary.json").read_text(encoding="utf-8")) + self.assertEqual(summary["counts"],expected_counts) + self.assertFalse(summary["semantic_acceptance"]) + def test_resize_records_actual_dimensions_and_reflow_difference(self): for record in self.records("resize_stream"): self.assertEqual(record["status"], "resize_difference") From b487a6b10bd3c577235a752641bfd316ea1233d0 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Thu, 29 Oct 2026 02:21:17 +0800 Subject: [PATCH 5/6] docs(ci): preserve 1049 reference evidence and run strict gates (#135) --- .github/workflows/core-candidate.yml | 2 +- experiments/differential/README.md | 4 + experiments/differential/decisions.md | 8 + .../2026-10-29-1049-reference/README.md | 45 + .../capability-summary.json | 1693 +++++++++++++++++ .../hosted-observations.json | 623 ++++++ .../source-checkpoint-3156.py | 196 ++ .../2026-10-29-1049-reference/validation.json | 177 ++ 8 files changed, 2747 insertions(+), 1 deletion(-) create mode 100644 experiments/differential/results/2026-10-29-1049-reference/README.md create mode 100644 experiments/differential/results/2026-10-29-1049-reference/capability-summary.json create mode 100644 experiments/differential/results/2026-10-29-1049-reference/hosted-observations.json create mode 100644 experiments/differential/results/2026-10-29-1049-reference/source-checkpoint-3156.py create mode 100644 experiments/differential/results/2026-10-29-1049-reference/validation.json diff --git a/.github/workflows/core-candidate.yml b/.github/workflows/core-candidate.yml index 0b8d962c..9f56ba18 100644 --- a/.github/workflows/core-candidate.yml +++ b/.github/workflows/core-candidate.yml @@ -101,7 +101,7 @@ jobs: - name: Compare common native traces run: python experiments/differential/compare_candidate.py --out build/test-artifacts/candidate-common - name: Test common comparison and failure gates - run: python -m unittest discover -s experiments/differential -p test_candidate_compare.py -v + run: python -m unittest discover -s experiments/differential -p 'test_candidate*.py' -v - name: Compare extended capability traces run: python experiments/differential/capability_matrix.py --trace "${{ env.TERMFORGE_TRACE }}" --candidate "${{ env.TERMFORGE_ALACRITTY_TRACE }}" --out build/test-artifacts/candidate-capabilities-cli - name: Test extended capabilities and unsupported gates diff --git a/experiments/differential/README.md b/experiments/differential/README.md index e7b8abca..77c3af77 100644 --- a/experiments/differential/README.md +++ b/experiments/differential/README.md @@ -82,6 +82,10 @@ python -m unittest discover -s experiments/differential -p test_candidate_compar 自动断言包括备用屏恢复后的 `A/BZ` 主屏、滚动区结果 `B/D/X`、真实回复 `ESC[1;2R`、Recovery 的 `ABC U+FFFD D` 及双方分块不变性;[原始批次摘要](results/2026-10-25-capabilities-v2/summary.json)保留具体分类。未构建候选时主回归明确跳过可选项,candidate workflow 强制执行。 +自主核心接入限定 `1049h/l` 后,[当前参考诊断](results/2026-10-29-1049-reference/README.md)将该固定 `alternate_screen` 输入标为支持;这不表示全部备用屏模式通过。原输入/五种分块未变,whole 为 match,其余四计划保留为 `reference_difference`:原版 #118 观察支持进入归首格,自研保留该方向,Alacritty 参考在本例继承主光标。25 次分类为 10 core_unsupported、4 reference_difference、6 match、5 resize_difference,semantic_acceptance 仍为 false。 + +这些四项台账除输入/尺寸/首差异/最终状态外,还精确固定双方**完整有序共同投影数组 SHA 和检查点数**。投影仍只作已有 NFC/空白表示统一,不隐藏光标、样式或历史差异。缺失字段、缺少任一初始/feed/显式 resize 检查点、未列计划或后续中间状态漂移均不能沿已知签名放行;即使首差异及双方最终状态保持相同也必须拒绝。原始 CI 失败、两个 OS 的独立签名重算与本地新诊断身份分别保留,不改写旧结果。 + 两个测试 trace 在同一输入结束点执行 `--resize=2x6` 并追加同偏移检查点。双方实际尺寸均为 2×6,候选重排为 `123456`/`7890`、光标列 4,自研物理裁剪保留列 5,故记为 `resize_difference` 而非一致。`resize_covered=true`,但 `real_application_covered=false`、`semantic_acceptance=false`;重排合同由 #29 决定,本矩阵不提前实现产品功能。 ## 真实应用核心轨迹(#25) diff --git a/experiments/differential/decisions.md b/experiments/differential/decisions.md index ecd337c2..4e618ee9 100644 --- a/experiments/differential/decisions.md +++ b/experiments/differential/decisions.md @@ -35,3 +35,11 @@ 后续按 ADR-0003 的固定补丁路线,在 `0.26.1-dev+termforge.1` 中修正 ED1 前序行清理,并把 ED2 调整为 TermForge 已裁决的“清屏但不新增/清空历史”。补丁同时纳入上游零宽字符内存等修复;[来源与补丁身份](../../experiments/candidates/alacritty/PROVENANCE.md)独立保存。 [当前共同矩阵](results/2026-10-25-candidate-common-v4/summary.json)为 95 次、1011 检查点全部 `match`,真实 cmd/more.com/Vim 也全部一致。旧差异签名已从当前 `candidate-known-differences.json` 移除,防止旧候选差异被继续放行;上述旧批次与裁决保留原样。新差异仍须单独复现和裁决,95 次一致不扩大为完整 VT、WindTerm 或产品 TUI 认证。 + +## 1049 固定输入的参考差异(#135) + +本次只处理既有 `A\r\nB ESC[?1049h ALT ESC[?1049l Z` 的 24B、3×12、history=3 共同投影。自研进入备用屏后为零基 `(0,0)`,Alacritty 参考为 `(1,1)`,whole 最终主屏均为 `A` / `BZ` / 空行。原版 [#118 的固定观察](../../docs/research/windterm-alternate-reference-2026-10-28.md)中首次、重复与重入 `1049h` 均回复一基 `(1,1)`;依据 ADR-0006 的原版优先方向保留自研归首格,不为匹配参考修改生产核心或 Alacritty 实现。 + +原版证据来自独立合成 Telnet 末端,网格和完整输入与此参考例不同;它支持已经观察的进入光标方向,不证明原版全部 grid、背景、非颜色属性、其他模式或本地 shell 已对齐。本次没有运行 WindTerm,`reference_difference` 也不是审批 WindTerm 行为偏差或声明兼容等价。 + +Windows/Linux 初始 PR 原件的完整有序投影签名一致,四个有中间观察的计划逐项列入严格台账,whole 仍必须 match。旧首差异+最终哈希不足以约束后续检查点,已以双方全轨迹 SHA/检查点数补强;缺字段的旧条目不会继续授权。独立字面 fixture 固定首差异、最终状态及完整哈希,并使后续单一检查点变异失败。证据、旧 CI 失败与未覆盖项见[独立报告](results/2026-10-29-1049-reference/README.md)。 diff --git a/experiments/differential/results/2026-10-29-1049-reference/README.md b/experiments/differential/results/2026-10-29-1049-reference/README.md new file mode 100644 index 00000000..3cd9ddb8 --- /dev/null +++ b/experiments/differential/results/2026-10-29-1049-reference/README.md @@ -0,0 +1,45 @@ +# #135:固定 1049 的 Alacritty 参考差异与严格诊断门槛 + +本项只适配参考比较工具和台账,没有修改自主 C++、Alacritty 实现、既有输入、负载、期限或旧证据。原 `alternate_screen` 固定例已被新核心支持,旧 `supported=false` 分类过时;实际四项中间差异继续可见,不能为了 CI 改核心去追随 Alacritty。 + +## 保留初始失败与来源 + +[PR CI 40737560783](https://github.com/JavaZeroo/termforge/actions/runs/40737560783) 和 [push CI 40737501428](https://github.com/JavaZeroo/termforge/actions/runs/40737501428) 的 Windows/Linux 均在 `Compare extended capability traces` 失败,head 为 `c9f2eac`。PR 的实际 checkout 为 `eaf2cf43897a8ab45be3436db5ba6753d22e7dc4`(merge c9 into main5f7373f),已从两份 job 日志核对。push checkout 未单独取证,保留 null。 + +两份真实 PR artifact ZIP SHA 为 Windows `1f4851b3b8842cee652bcd7917c7dc350e3ca89497be8206a5b0b2d5a5396a1a`、Linux `daa39be3b256548c6305b6c800530deb9bb4b031306e64db633fbb90b3ed79b7`。原 25 runs 统计均为 **10 core_unsupported / 4 difference / 6 match / 5 resize_difference**,没有改写成初始通过。 + +[hosted-observations.json](hosted-observations.json)保留原摘要、双方真实 binary SHA、35 项原 source SHA、原各计划 report/input/chunks/JSONL SHA。Linux 35 项与 git blob 原字节一致;Windows 5 项一致、30 项精确对应同一 git 内容的 LF→CRLF 字节形式,分别保留实际 SHA,没有把它们伪装为同一文件字节。两平台的完整有序共同投影签名则逐项相同。旧原件留 local,不改摘要、不使用 source identity 未核的旧本地 candidate trace 作 pinned 依据。 + +## 有限原版依据与四项台账 + +原固定输入为 `A\r\nB ESC[?1049h ALT ESC[?1049l Z`,24B,3×12,history=3;输入 SHA 为 `6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76`。自研进入后为零基 row0/col0,Alacritty 继承主屏 row1/col1。双方最终屏幕相同,不代表中间轨迹一致。 + +原版 [#118](../../../../docs/research/windterm-alternate-reference-2026-10-28.md)的首次/重复/重入 `1049h` 均归一基 `(1,1)`。该观察支持自研已经实现的归首格方向;它是独立 Telnet 合成输入,不证明本例全部格子、完整属性、本地 shell 或其他模式都等价。没有新增 WindTerm 运行,也没有借参考台账批准原版行为偏差。 + +| 计划 | 检查点数(双方) | 首差异 offset / 字段 | 分类 | +|---|---:|---|---| +| byte | 25 | 12 / `.screen.row`,core0 / candidate1 | reference_difference | +| seed:42 | 6 | 14 / 同上 | reference_difference | +| seed:20261022 | 4 | 12 / 同上 | reference_difference | +| seed:8675309 | 4 | 13 / 同上 | reference_difference | +| whole | 2 | 无 | match | + +台账精确匹配 case/plan、输入/尺寸/历史、首差异、双方最终状态,以及双方**完整有序 canonical 轨迹 SHA 和检查点数**。哈希编码为 sort_keys、ensure_ascii=False、紧凑 UTF-8 JSON 的完整数组;数组包含所有 offset、屏幕、历史、光标及当前样式。沿用既有 NFC 和空白表示投影,mode_bits/replies 仍不在本比较范围,没有新增语义归一化。 + +## 实际红→绿及最终针对性验证 + +先以独立字面状态模型重建 24B 的全部检查点,字面 SHA 与两 OS 原件相同。旧首差异+最终哈希条目会错误授权,完整新条目当时反而不匹配,两项实际红保留在会话验证中;补入全轨迹 SHA/检查点数后转绿。固定首差异与最终状态、仅改变任一侧后续检查点也必须为 difference。 + +另有缺投影字段可成为相同比较的反例,以及缺初始/中间/最终/resize 检查点的拒绝;字段、样式与完整计划 offset 先验校验后转绿。缺 manifest 字段、截断、未列 seed:99 都不能复用已知规则;公共 CLI 的未列 seed 返回 exit1,未删除输入或放宽差异。 + +最终诊断源为 **`1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03`**。公共 trace-data/registry 6 项普通及 `python -O` 通过;固定该提交的合同+能力 **11 项全部通过、0 skip**,包括公共 CLI 正/负例,日志 SHA 与源码见[validation.json](validation.json)。候选 workflow 的原 common-test 步骤选择 `test_candidate*.py`,包含这六项新门槛,原负载和期限未改。[最终能力摘要](capability-summary.json)为 25 runs / 118 checkpoints:10 core_unsupported、4 reference_difference、6 match、5 resize_difference,`semantic_acceptance=false`。支持标志只针对该固定 1049 输入,不意味着 47/1047/1048 或全部备用屏模式已支持。 + +前置工作区 checkpoint 另外运行了 common 4 项(95 match)、fuzz 4 项(8 runs:6 match/2 known_failure)、Windows cmd/more/Vim 诊断 8 项(3 match、真实退出/文件/Job 边界通过)。其 compare tool SHA `3156f71393675d4efccf8415c8191cfe5f1e823c1b25d1bce00e2fbabe23f8d4` 与最终显式 input-length 校验/格式整理前不同,commit 身份为 null,单独列在 JSON。对应[前置源码档案](source-checkpoint-3156.py)由已记录修改恢复,完整字节 SHA 与三个原摘要完全相同;它不是当前入口。不能冒称最终1e5重跑全部应用矩阵。全部本地 exec 已监督到结束,没有跨代理移交运行会话。 + +本地 candidate 是在当前未修改的 c9 Rust/vendor 来源上新建 `cargo +1.92.0 build --release --locked`:实际 SHA `cd77d300f37f8d2ae8f5d9570f7544a4c65b7bc06c79a8f92169201a32d92686`,工具链和全部来源哈希单列。core trace SHA `3f8bda9d6b1443d02265089ed560941ab8c226cd0bd2900cbadea3812a55d081` 对应旧完整验证中的同一二进制;这些本地身份不替代 hosted 的四个 binary SHA,也不是实验后端维护或性能样本。 + +## 不转移验收与未知 + +原生产核心 `40bee8e`、完整验证源 `575bd282b7f61fc4c47da0cad7739b0c46d8c1f2` 的 **55/55 与 13 条内部 skip**、原 52/54 失败和全部输入清单仍按[原证据](../../../core/results/2026-10-29-cpp-1049/README.md)保存,文件 SHA 未变。本次没有重跑完整 55 项,不能把诊断新 head 冒称该完整运行源。 + +两 OS 旧原件在新诊断源码下的离线重分类不等于一次新的 hosted native CI。后续 PR/push CI 及双轴审查由当前 head 独立跟踪,不提前写绿。`semantic_acceptance=false`、性能未测;完整终端模式、原版全部 grid/背景/bold、GUI TUI/IME/真实 DPI、呈现、原生 margin 与 R2 总出口均保持未验收。 diff --git a/experiments/differential/results/2026-10-29-1049-reference/capability-summary.json b/experiments/differential/results/2026-10-29-1049-reference/capability-summary.json new file mode 100644 index 00000000..1924fc29 --- /dev/null +++ b/experiments/differential/results/2026-10-29-1049-reference/capability-summary.json @@ -0,0 +1,1693 @@ +{ + "schema": 1, + "candidate": "alacritty_terminal", + "version": "0.26.1-dev+termforge.4", + "platform": "Windows-11-10.0.26200-SP0", + "core_trace_sha256": "3f8bda9d6b1443d02265089ed560941ab8c226cd0bd2900cbadea3812a55d081", + "candidate_trace_sha256": "cd77d300f37f8d2ae8f5d9570f7544a4c65b7bc06c79a8f92169201a32d92686", + "source_sha256": { + "experiments/core/trace.cpp": "91e6f4594ae47a9e0c60a435c71687666ec114373899d033fa59e1e46b9945d2", + "experiments/differential/compare_candidate.py": "d2c974db45c64268b8dbe3b059a28159562cb6f6ca8288d6e703d4fddc9fffc3", + "experiments/differential/capability_matrix.py": "cb73e23ac403f437f8141565d92a83c419d26603d90d7cf8b38d6db4f82a958b", + "experiments/differential/candidate-known-differences.json": "8efa67296373f90fe3b545541e1bddbc61472cc3369f769b25dded8d7a06a05d", + "experiments/candidates/alacritty/src/main.rs": "078f238ded11e2eb6780140d29fb3eb1d41c66bbe2ecc4ed62f40304c43d6260", + "experiments/candidates/alacritty/run.py": "e84bfcd530a7a79bcb9e722e507257f9b92a60b2c3ca8043c15da432b6220a01", + "experiments/candidates/alacritty/vendor/alacritty_terminal/CHANGELOG.md": "97231d9beda30b536650c566169c692fa846be3f7b0405add3c9741f95f3af62", + "experiments/candidates/alacritty/vendor/alacritty_terminal/Cargo.toml": "bce82942276bab9c4967998d654316f9c85e698babd0945c66a55fcb91ef2333", + "experiments/candidates/alacritty/vendor/alacritty_terminal/LICENSE-APACHE": "8884289e3969c089cd556c53fa1d3f51d86b29e52a8c1d660a55ce8292986910", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event.rs": "e76c212f36bbfc43ea037a825dbc9c5b1174f5836fe8b69dfd158aadf3fc4048", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event_loop.rs": "6da2897b76d8c0e7f989daa1463fd6fdeb3469a0a63e0c6ba703a9562663163c", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/mod.rs": "be15d08b03a28a271aa927b7149346a1b5d29e92e9186891bf246fdd2a4c90fc", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/resize.rs": "4907427c9488435f1e1ee624629bc8445c4dde5399f0349955d1bbc2042080c4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/row.rs": "2f963299e52525828d9d0bf1de758d793661c908eb7c126aa8556a1c9945a83d", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/storage.rs": "27a9b5101833d57423ae34ccef3d82c1a1cf9f51cbc42cc836a6fce79c088348", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/tests.rs": "5f38819134540eeb0dff7047f57f5d06250ce59493839c66ec4cd56e43db62f8", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/index.rs": "46908b68508f4e4ea90313f0536a88c357f2d17ad211b14d44b7f92dfdaa4402", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/lib.rs": "b9cae8ed53a4be8f738111f8727dd86218e66c88df38f32f4904e56651a2bee1", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/selection.rs": "0d1373577602646e84a4ab3448c65ee181987327bdabceff3c827e76dd9bd0d8", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/sync.rs": "4410fbae64e8f80321b3569a1495fb323e3319812c441f9eac54048c65ff93fb", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/cell.rs": "8b31cf5389398c74f141bd1f3e7945a1dbde8944bb754f5fd623313c73262496", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/color.rs": "ad2e33b60f397fe30e5e8f2dde2096bad8f5e256d464ba279cbda4a93cbbe224", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/grapheme.rs": "1ef6450b8bf8735b85e7a6fc3bb55c849e317f04778d297020ba3cb4dd7ecf74", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/mod.rs": "b4a6fdaa4f8c3fdf56b614689ed381408acc68407bd05c8ea592fb6fd0021f78", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/search.rs": "84e04c5f0da21009dbbcfc2f8033e322d6240c8d227028b5ce8a784f1c55ccaf", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/thread.rs": "e2f9fdc5d950bbea6c710c7a974f2998127af6b434344c363afb38e849f86144", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/mod.rs": "8cca30ba29cee2df84603f560a8d26624a48979d96d78f1b6729a470ff34d8a1", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/unix.rs": "2e8d0edf1aea816ac95c1e442d60025ebdd20dacaa99d0fd4f7c7cf78ac369e4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/blocking.rs": "60121a65df120c4a227520d6672231c9e3c515cb75241241e6b37a0c5bc186ca", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/child.rs": "4782f173c639bff6891f474b068fee64b6e2ad411edabdf496bbfe6554ceb32e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/conpty.rs": "62abd7e72af144ae1f1c359538e18cceaa97741382efa94e001f397510eef416", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/mod.rs": "b08803dae0f192bc6737aff22992a37368ac505c7133554c495ffcacb4116733", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/vi_mode.rs": "f52c0d3248707c68295880acd7ad96610467110d6813f1172d4ae767365add2e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/GraphemeBreakTest-17.0.0.txt": "e2d134d2c52919bace503ebb6a551c1855fe1a1faec18478c78fff254a1793ec", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/UNICODE-LICENSE.txt": "e7a93b009565cfce55919a381437ac4db883e9da2126fa28b91d12732bc53d96" + }, + "runs": 25, + "checkpoints": 118, + "counts": { + "core_unsupported": 10, + "match": 6, + "reference_difference": 4, + "resize_difference": 5 + }, + "passed": true, + "execution_passed": true, + "semantic_acceptance": false, + "performance_measured": false, + "unsupported_is_not_a_pass": true, + "resize_covered": true, + "real_application_covered": false, + "records": [ + { + "case": "alternate_screen", + "plan": "byte", + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "bytes": 24, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "checkpoints": 25, + "status": "reference_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 12, + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "alternate_screen", + "expected_core_support": true, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "A", + "BZ", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ] + }, + { + "case": "alternate_screen", + "plan": "whole", + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "bytes": 24, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 24 + ], + "checkpoints": 2, + "status": "match", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "alternate_screen", + "expected_core_support": true, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "A", + "BZ", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "alternate_screen", + "plan": "seed:42", + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "bytes": 24, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 4, + 1, + 9, + 8, + 2 + ], + "checkpoints": 6, + "status": "reference_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 3, + "offset": 14, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "alternate_screen", + "expected_core_support": true, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "A", + "BZ", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "alternate_screen", + "plan": "seed:20261022", + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "bytes": 24, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 12, + 10, + 2 + ], + "checkpoints": 4, + "status": "reference_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 1, + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "alternate_screen", + "expected_core_support": true, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "A", + "BZ", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "alternate_screen", + "plan": "seed:8675309", + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "bytes": 24, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 13, + 7, + 4 + ], + "checkpoints": 4, + "status": "reference_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 1, + "offset": 13, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "alternate_screen", + "expected_core_support": true, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "A", + "BZ", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "scroll_region", + "plan": "byte", + "input_sha256": "090b82f96737c6c2e43b7efdfda5119bf4b1b957c30159faaf4308666e5e6b60", + "bytes": 33, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "scroll_region", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "B", + "D", + "X" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "scroll_region", + "plan": "whole", + "input_sha256": "090b82f96737c6c2e43b7efdfda5119bf4b1b957c30159faaf4308666e5e6b60", + "bytes": 33, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 33 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "scroll_region", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "B", + "D", + "X" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "scroll_region", + "plan": "seed:42", + "input_sha256": "090b82f96737c6c2e43b7efdfda5119bf4b1b957c30159faaf4308666e5e6b60", + "bytes": 33, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 4, + 1, + 9, + 8, + 8, + 3 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "scroll_region", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "B", + "D", + "X" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "scroll_region", + "plan": "seed:20261022", + "input_sha256": "090b82f96737c6c2e43b7efdfda5119bf4b1b957c30159faaf4308666e5e6b60", + "bytes": 33, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 12, + 10, + 6, + 2, + 3 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "scroll_region", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "B", + "D", + "X" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "scroll_region", + "plan": "seed:8675309", + "input_sha256": "090b82f96737c6c2e43b7efdfda5119bf4b1b957c30159faaf4308666e5e6b60", + "bytes": 33, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 13, + 7, + 13 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "scroll_region", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "B", + "D", + "X" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "cursor_query", + "plan": "byte", + "input_sha256": "cb7ba0ac55e9696a24eab6a33bbff33ce3b16c5b2e9630762390ed419eb7f4d5", + "bytes": 5, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "cursor_query", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [ + "\u001b[1;2R" + ], + "candidate_final_rows": [ + "A", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "cursor_query", + "plan": "whole", + "input_sha256": "cb7ba0ac55e9696a24eab6a33bbff33ce3b16c5b2e9630762390ed419eb7f4d5", + "bytes": 5, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 5 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "cursor_query", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [ + "\u001b[1;2R" + ], + "candidate_final_rows": [ + "A", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "cursor_query", + "plan": "seed:42", + "input_sha256": "cb7ba0ac55e9696a24eab6a33bbff33ce3b16c5b2e9630762390ed419eb7f4d5", + "bytes": 5, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 4, + 1 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "cursor_query", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [ + "\u001b[1;2R" + ], + "candidate_final_rows": [ + "A", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "cursor_query", + "plan": "seed:20261022", + "input_sha256": "cb7ba0ac55e9696a24eab6a33bbff33ce3b16c5b2e9630762390ed419eb7f4d5", + "bytes": 5, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 5 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "cursor_query", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [ + "\u001b[1;2R" + ], + "candidate_final_rows": [ + "A", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "cursor_query", + "plan": "seed:8675309", + "input_sha256": "cb7ba0ac55e9696a24eab6a33bbff33ce3b16c5b2e9630762390ed419eb7f4d5", + "bytes": 5, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 5 + ], + "checkpoints": 0, + "status": "core_unsupported", + "core_returncode": 2, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "cursor_query", + "expected_core_support": false, + "core_arguments": [], + "candidate_arguments": [], + "replies": [ + "\u001b[1;2R" + ], + "candidate_final_rows": [ + "A", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [] + }, + { + "case": "recovery_stream", + "plan": "byte", + "input_sha256": "c223697f5d82b5ded52404fa40bb26086e1f302d5e6eda0b1dacf639edf04511", + "bytes": 23, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "checkpoints": 24, + "status": "match", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "recovery_stream", + "expected_core_support": true, + "core_arguments": [ + "--recovery" + ], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "ABC�D", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ] + }, + { + "case": "recovery_stream", + "plan": "whole", + "input_sha256": "c223697f5d82b5ded52404fa40bb26086e1f302d5e6eda0b1dacf639edf04511", + "bytes": 23, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 23 + ], + "checkpoints": 2, + "status": "match", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "recovery_stream", + "expected_core_support": true, + "core_arguments": [ + "--recovery" + ], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "ABC�D", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "recovery_stream", + "plan": "seed:42", + "input_sha256": "c223697f5d82b5ded52404fa40bb26086e1f302d5e6eda0b1dacf639edf04511", + "bytes": 23, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 4, + 1, + 9, + 8, + 1 + ], + "checkpoints": 6, + "status": "match", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "recovery_stream", + "expected_core_support": true, + "core_arguments": [ + "--recovery" + ], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "ABC�D", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "recovery_stream", + "plan": "seed:20261022", + "input_sha256": "c223697f5d82b5ded52404fa40bb26086e1f302d5e6eda0b1dacf639edf04511", + "bytes": 23, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 12, + 10, + 1 + ], + "checkpoints": 4, + "status": "match", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "recovery_stream", + "expected_core_support": true, + "core_arguments": [ + "--recovery" + ], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "ABC�D", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "recovery_stream", + "plan": "seed:8675309", + "input_sha256": "c223697f5d82b5ded52404fa40bb26086e1f302d5e6eda0b1dacf639edf04511", + "bytes": 23, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 13, + 7, + 3 + ], + "checkpoints": 4, + "status": "match", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": null, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "recovery_stream", + "expected_core_support": true, + "core_arguments": [ + "--recovery" + ], + "candidate_arguments": [], + "replies": [], + "candidate_final_rows": [ + "ABC�D", + "", + "" + ], + "candidate_final_dimensions": [ + 3, + 12 + ], + "core_final_dimensions": [ + 3, + 12 + ], + "core_fragmentation_difference": null, + "candidate_fragmentation_difference": null + }, + { + "case": "resize_stream", + "plan": "byte", + "input_sha256": "66c3b671a270160eac126dfbe30211488efb70a66794a1936690c68a84374450", + "bytes": 18, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "checkpoints": 20, + "status": "resize_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 19, + "offset": 18, + "path": ".screen.column", + "expected": 5, + "actual": 4 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "resize_stream", + "expected_core_support": true, + "core_arguments": [ + "--resize=2x6" + ], + "candidate_arguments": [ + "--resize=2x6" + ], + "replies": [], + "candidate_final_rows": [ + "123456", + "7890" + ], + "candidate_final_dimensions": [ + 2, + 6 + ], + "core_final_dimensions": [ + 2, + 6 + ] + }, + { + "case": "resize_stream", + "plan": "whole", + "input_sha256": "66c3b671a270160eac126dfbe30211488efb70a66794a1936690c68a84374450", + "bytes": 18, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 18 + ], + "checkpoints": 3, + "status": "resize_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 2, + "offset": 18, + "path": ".screen.column", + "expected": 5, + "actual": 4 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "resize_stream", + "expected_core_support": true, + "core_arguments": [ + "--resize=2x6" + ], + "candidate_arguments": [ + "--resize=2x6" + ], + "replies": [], + "candidate_final_rows": [ + "123456", + "7890" + ], + "candidate_final_dimensions": [ + 2, + 6 + ], + "core_final_dimensions": [ + 2, + 6 + ] + }, + { + "case": "resize_stream", + "plan": "seed:42", + "input_sha256": "66c3b671a270160eac126dfbe30211488efb70a66794a1936690c68a84374450", + "bytes": 18, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 4, + 1, + 9, + 4 + ], + "checkpoints": 6, + "status": "resize_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 5, + "offset": 18, + "path": ".screen.column", + "expected": 5, + "actual": 4 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "resize_stream", + "expected_core_support": true, + "core_arguments": [ + "--resize=2x6" + ], + "candidate_arguments": [ + "--resize=2x6" + ], + "replies": [], + "candidate_final_rows": [ + "123456", + "7890" + ], + "candidate_final_dimensions": [ + 2, + 6 + ], + "core_final_dimensions": [ + 2, + 6 + ] + }, + { + "case": "resize_stream", + "plan": "seed:20261022", + "input_sha256": "66c3b671a270160eac126dfbe30211488efb70a66794a1936690c68a84374450", + "bytes": 18, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 12, + 6 + ], + "checkpoints": 4, + "status": "resize_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 3, + "offset": 18, + "path": ".screen.column", + "expected": 5, + "actual": 4 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "resize_stream", + "expected_core_support": true, + "core_arguments": [ + "--resize=2x6" + ], + "candidate_arguments": [ + "--resize=2x6" + ], + "replies": [], + "candidate_final_rows": [ + "123456", + "7890" + ], + "candidate_final_dimensions": [ + 2, + 6 + ], + "core_final_dimensions": [ + 2, + 6 + ] + }, + { + "case": "resize_stream", + "plan": "seed:8675309", + "input_sha256": "66c3b671a270160eac126dfbe30211488efb70a66794a1936690c68a84374450", + "bytes": 18, + "rows": 3, + "columns": 12, + "history": 3, + "chunk_sizes": [ + 13, + 5 + ], + "checkpoints": 4, + "status": "resize_difference", + "core_returncode": 0, + "candidate_returncode": 0, + "core_error": null, + "candidate_error": null, + "first_difference": { + "checkpoint": 3, + "offset": 18, + "path": ".screen.column", + "expected": 5, + "actual": 4 + }, + "difference_direction": "expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + "normalization": "NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + "reproduce": { + "core": [ + "terminal_trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ], + "candidate": [ + "termforge-alacritty-trace", + "input.bin", + "3", + "12", + "3", + "chunks.txt" + ] + }, + "capability": "resize_stream", + "expected_core_support": true, + "core_arguments": [ + "--resize=2x6" + ], + "candidate_arguments": [ + "--resize=2x6" + ], + "replies": [], + "candidate_final_rows": [ + "123456", + "7890" + ], + "candidate_final_dimensions": [ + 2, + 6 + ], + "core_final_dimensions": [ + 2, + 6 + ] + } + ] +} diff --git a/experiments/differential/results/2026-10-29-1049-reference/hosted-observations.json b/experiments/differential/results/2026-10-29-1049-reference/hosted-observations.json new file mode 100644 index 00000000..06a7cfe4 --- /dev/null +++ b/experiments/differential/results/2026-10-29-1049-reference/hosted-observations.json @@ -0,0 +1,623 @@ +{ + "schema": "termforge-1049-reference-hosted-audit-v1", + "issue": 135, + "diagnostic_source_commit": "1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03", + "two_os_complete_ordered_signatures_identical": true, + "new_windterm_runs": 0, + "semantic_acceptance": false, + "independent_signature_artifact_sha256": "5abe5122bf82f93da74ec493305923b356a862155c22c2dc6ed61120831a1089", + "observations": [ + { + "os": "windows", + "workflow_run": 40737560783, + "job_id": 122990111534, + "source_head": "c9f2eacff4540c2623552a72eaa5bab4fa6262c9", + "checkout_commit": "eaf2cf43897a8ab45be3436db5ba6753d22e7dc4", + "checkout_identity_source": "GitHub job checkout log", + "artifact_name": "candidate-windows-pr140.zip", + "artifact_sha256": "1f4851b3b8842cee652bcd7917c7dc350e3ca89497be8206a5b0b2d5a5396a1a", + "original_summary_sha256": "12baafd38e8b6e205604eeb836162735b618d840e4702f82dec73cfd16362d21", + "core_trace_sha256": "5ab6690c0a62d27265714b9b59a805ef0b814c782075bfb712a136767897d7c8", + "candidate_trace_sha256": "8832757f28655ab2a87fabe2865e16b1cabcba0ea59e87a614ace08a6685622f", + "original_counts": { + "core_unsupported": 10, + "difference": 4, + "match": 6, + "resize_difference": 5 + }, + "original_execution_passed": false, + "source_sha256": { + "experiments/core/trace.cpp": "96851af2243d92be2344a7a9786239196c20282b284b5a9e45c7a1f622c01a9a", + "experiments/differential/compare_candidate.py": "b823369ec73dd6d4de4678898271dc26357587ff3ff1dccb340c228ea93d75b3", + "experiments/differential/capability_matrix.py": "6b2bfe90101a56234389977d049dbfb880ecd3175c6d2d3ee35a7f8d8ac3e147", + "experiments/differential/candidate-known-differences.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356", + "experiments/candidates/alacritty/src/main.rs": "95c16e8ff9487396693ba9021c3cee676955e5a388d4952f4e134e26be7b1d17", + "experiments/candidates/alacritty/run.py": "e84bfcd530a7a79bcb9e722e507257f9b92a60b2c3ca8043c15da432b6220a01", + "experiments/candidates/alacritty/vendor/alacritty_terminal/CHANGELOG.md": "97231d9beda30b536650c566169c692fa846be3f7b0405add3c9741f95f3af62", + "experiments/candidates/alacritty/vendor/alacritty_terminal/Cargo.toml": "6b60e0b2db23e5d1fe16f23978fe7f6f9965c8663419cd6cce8e2b1e73df5b93", + "experiments/candidates/alacritty/vendor/alacritty_terminal/LICENSE-APACHE": "eb5fff7fd042bc7ad57e19612760ffb778a996c4ed63ce43526b1291a0677fb6", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event.rs": "2108ec97cec8270fccafd2a9b5a2b40e9c729f13b3d1c19f155cf86a53bb7537", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event_loop.rs": "7415a7105701f4553431f6f87db78717db4accb881d495e08c782b5e5d3f61b0", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/mod.rs": "721908760881f2e2cbdec2d9b8d3057cd8855473da1e910202b4f790c71c9d9b", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/resize.rs": "ce093c7624f7035f56e7a186460774c8348c8687a54334842f7e8d5f95a79bf6", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/row.rs": "e4e387a1191bea54a0435c0810a84a80f1af05db0e83610c2646fbe4678ae8a6", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/storage.rs": "948dca84310ab7c02f775234074eca5e33832c14ad72be2f88dcccfd0bf54f1a", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/tests.rs": "b36b4c036666f10e7c0f37eaae45bf48e095dbfad5bfa5326153d9bfe8ccf382", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/index.rs": "d657484285a5fc544dcbca5312c53dd285f04965ab52ec16206a0fc2e1b1e8ea", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/lib.rs": "58f73d973e17f16721c9f03588662e63f76239ea30f1b8a688af30840ae3719c", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/selection.rs": "768513926f7f8f6eb70dddab294f16af0d923321477a36c0136ca417d5ce959d", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/sync.rs": "bacdba521efa2b00b0edc38406d084b8dd0052ecb98a6ec3814f28923497849f", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/cell.rs": "c16b632b2b3670dd4ec3ac01aa0f79c506bcc230ba3997af3e164fafe463ac67", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/color.rs": "c74756c20de38809e8bf4e118d31c9036753b56cd9cbc2db6aac5e05d728c234", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/grapheme.rs": "e09d3b858c303864c6ad029089387b5c42442b34528f6c5043feb32f0ff3932c", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/mod.rs": "4a86c3e0a18400539a6e7c1d6117024f3ba868de278992140f6c7aa38c252f6e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/search.rs": "018cb9fb596ab7073c1d345a91193dc25513c5cc23e9d44627cb103961ba4f47", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/thread.rs": "4a4aa0d9ef52183671ceb349ba6614c36d557d58a25bc3025c6b7ef5b34ecdfd", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/mod.rs": "bc81f8a516604dcab3adefa7864ab35d8afc3de6bc93ef07edc623d2006f627a", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/unix.rs": "3628d62de1ea4e828ac48e538fc2497dd42316c9e4cd12b10c1565fd1b1178da", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/blocking.rs": "070d8ebbd112a5366c4adcd123373a6404c6b2bab4ab8118a7e2b3ab6cfbd257", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/child.rs": "b6ba22ee8ecc25cdc62c867a84007fb52deb824666bd8b9b9532bd3371910261", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/conpty.rs": "8db0ae46185d24a11c81f56d1604313ad627930758f1f314d3b1d1ac7fd716f0", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/mod.rs": "763868df8ebff4c46cf51d3f6e9907b80f60787b90f0b85be24f4b70ccd459a6", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/vi_mode.rs": "45dff469a348a3520bde102c5402c0d20f39101765379bd6337f9703d9bae236", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/GraphemeBreakTest-17.0.0.txt": "991ccad2ea69e6aa4adeddab0664e5e4c8a3c2383388a5183ab77941e9f06e26", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/UNICODE-LICENSE.txt": "8437ba5f4e4c8ae0268c3df5cf106006f2d045ff3452eedd1f27e8eb26c5f327" + }, + "source_byte_forms_verified_against_git_c9f2eac": { + "git_blob_exact": 5, + "git_blob_lf_to_crlf": 30 + }, + "alternate_records": [ + { + "plan": "byte", + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "offsets": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "8229315bee9585fa620254e0e294e51ac0bd81511abd114a225774a5ca19686b", + "canonical_candidate_trace_sha256": "f01576eb7ca499c8d3d72789b0cdf2411ba9479134cd6d85666f35e50c8c38b0", + "core_checkpoints": 25, + "candidate_checkpoints": 25 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "60798250cc2f13df7fb3167648973880905def46967603fe992144a9370b250a", + "core.jsonl": "31b64b2db4b60b243d864842e338b78accbd4a63bf113871a71883a990cfcd10", + "candidate.jsonl": "c36725b69747111ff4faac6f5c0f937d82c113ec5db8d5b5e56cff500bdb815f", + "report.json": "718692bd7e412562946268b7b69556f42a83de1c4a4d402a431051bbd2b05805" + } + }, + { + "plan": "whole", + "chunk_sizes": [ + 24 + ], + "offsets": [ + 0, + 24 + ], + "original_status": "match", + "offline_classification": "match", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": null, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "86de13c458934c4cc292837858e440a8fb90eddc8337c3f4daaabea46faab530", + "canonical_candidate_trace_sha256": "86de13c458934c4cc292837858e440a8fb90eddc8337c3f4daaabea46faab530", + "core_checkpoints": 2, + "candidate_checkpoints": 2 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "f6bca0e7f46a94bd3349fdb86511cbec4a9091e409b62dd2d6b8c1fdb9a3ce00", + "core.jsonl": "cb72cc993b49e648128f1b08dd8886e995bd50710c853918e4af28b93b8586db", + "candidate.jsonl": "a95b8912d440f4d2acc14a34ecbc1e1cf33e0946ef074bea5c0543d846d62291", + "report.json": "8a6f905ba58b13c0955fb58c038c10f846976901128e8412dfb34dc7a2f6017c" + } + }, + { + "plan": "seed:42", + "chunk_sizes": [ + 4, + 1, + 9, + 8, + 2 + ], + "offsets": [ + 0, + 4, + 5, + 14, + 22, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 14, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "3dd867db0c75e2ce79f5200865b7365093efe5bc82c83642331775f003b5aaf2", + "canonical_candidate_trace_sha256": "429c29f1b622626efb40eccf768a483e176ced7884e9e9d2dc731aa234f96244", + "core_checkpoints": 6, + "candidate_checkpoints": 6 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "8487ef7949085a23837866a5ed30f753ef78261bfeab640583bd2f783984ba62", + "core.jsonl": "91c73f9914d197e112d0ced548c8a92f1b2237fd7728f6c51564c9b0b0d92fca", + "candidate.jsonl": "cf3b3d263b4e1b8edcfec4c242312c51540f6cd3a9ad785c73313986ef9628e0", + "report.json": "19b0c475357bfcf652445b0b434c4673434b05571d712787217f2deebf406d47" + } + }, + { + "plan": "seed:20261022", + "chunk_sizes": [ + 12, + 10, + 2 + ], + "offsets": [ + 0, + 12, + 22, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "7fbc6a28fcfc045551ce577daf233df09b33d9eb15a2e87dc271c964cba765d8", + "canonical_candidate_trace_sha256": "c8d2626cae1eec2dd14ebfa89ce68c013125cfb77fe2bcadaf940eace57c6c24", + "core_checkpoints": 4, + "candidate_checkpoints": 4 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "6b7af5197377a27958f6b603d98bb0d6769df10333fbf612e9e657ec6e33f2b1", + "core.jsonl": "96a279a4088d0ee31e964eca62e2ba0bf53dab18466f6899845ee932e436bf8e", + "candidate.jsonl": "435051b53bc9a3662e2ac758d162609452f55ceee41b36cee61dda08defe37b9", + "report.json": "8c2af0dc448903289a2e795f90a5c9662d24d79108e3920798274be62d079506" + } + }, + { + "plan": "seed:8675309", + "chunk_sizes": [ + 13, + 7, + 4 + ], + "offsets": [ + 0, + 13, + 20, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 13, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "63be2fb28cef585a2c6c7e0f0ae3c8de5225dc9cd1e3385a9b26997096f42667", + "canonical_candidate_trace_sha256": "95572ad54172efd387646f2c9745cdca7f42920626a5b380129a65abb0c5c187", + "core_checkpoints": 4, + "candidate_checkpoints": 4 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "5f9d1a9b7a05dce02d4776c97cc2eb387817661d2290b94e3df413658239a507", + "core.jsonl": "97dfbcf74d07eed4a7aa5aa1ecde60c0f8e9737f3ccf24ec18074d06d3bbdb14", + "candidate.jsonl": "ed89ec6970e9ffd6e72428e29428f8128e99fcdeaea5debbb96cb43d6800782a", + "report.json": "dd4d6df49df79406461846c34f47e81973415a175eca776ae2b71711d2d28890" + } + } + ], + "offline_classification_is_new_ci_run": false + }, + { + "os": "linux", + "workflow_run": 40737560783, + "job_id": 122990111648, + "source_head": "c9f2eacff4540c2623552a72eaa5bab4fa6262c9", + "checkout_commit": "eaf2cf43897a8ab45be3436db5ba6753d22e7dc4", + "checkout_identity_source": "GitHub job checkout log", + "artifact_name": "candidate-linux-pr140.zip", + "artifact_sha256": "daa39be3b256548c6305b6c800530deb9bb4b031306e64db633fbb90b3ed79b7", + "original_summary_sha256": "58df566d24b8dc100234954f74e17e200c9972a8b417c222944eb56de1f6d0c5", + "core_trace_sha256": "86ef1d469c49c4548406f8d2c6ce1231a57742e5ff5934e02c512d9990e55878", + "candidate_trace_sha256": "2d8029e607e3fcd0c047f687829797a1de03e1f7455e2463ee5b90c924cf60f2", + "original_counts": { + "core_unsupported": 10, + "difference": 4, + "match": 6, + "resize_difference": 5 + }, + "original_execution_passed": false, + "source_sha256": { + "experiments/core/trace.cpp": "91e6f4594ae47a9e0c60a435c71687666ec114373899d033fa59e1e46b9945d2", + "experiments/differential/compare_candidate.py": "b823369ec73dd6d4de4678898271dc26357587ff3ff1dccb340c228ea93d75b3", + "experiments/differential/capability_matrix.py": "6b2bfe90101a56234389977d049dbfb880ecd3175c6d2d3ee35a7f8d8ac3e147", + "experiments/differential/candidate-known-differences.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356", + "experiments/candidates/alacritty/src/main.rs": "078f238ded11e2eb6780140d29fb3eb1d41c66bbe2ecc4ed62f40304c43d6260", + "experiments/candidates/alacritty/run.py": "e84bfcd530a7a79bcb9e722e507257f9b92a60b2c3ca8043c15da432b6220a01", + "experiments/candidates/alacritty/vendor/alacritty_terminal/CHANGELOG.md": "97231d9beda30b536650c566169c692fa846be3f7b0405add3c9741f95f3af62", + "experiments/candidates/alacritty/vendor/alacritty_terminal/Cargo.toml": "bce82942276bab9c4967998d654316f9c85e698babd0945c66a55fcb91ef2333", + "experiments/candidates/alacritty/vendor/alacritty_terminal/LICENSE-APACHE": "8884289e3969c089cd556c53fa1d3f51d86b29e52a8c1d660a55ce8292986910", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event.rs": "e76c212f36bbfc43ea037a825dbc9c5b1174f5836fe8b69dfd158aadf3fc4048", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event_loop.rs": "6da2897b76d8c0e7f989daa1463fd6fdeb3469a0a63e0c6ba703a9562663163c", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/mod.rs": "be15d08b03a28a271aa927b7149346a1b5d29e92e9186891bf246fdd2a4c90fc", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/resize.rs": "4907427c9488435f1e1ee624629bc8445c4dde5399f0349955d1bbc2042080c4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/row.rs": "2f963299e52525828d9d0bf1de758d793661c908eb7c126aa8556a1c9945a83d", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/storage.rs": "27a9b5101833d57423ae34ccef3d82c1a1cf9f51cbc42cc836a6fce79c088348", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/tests.rs": "5f38819134540eeb0dff7047f57f5d06250ce59493839c66ec4cd56e43db62f8", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/index.rs": "46908b68508f4e4ea90313f0536a88c357f2d17ad211b14d44b7f92dfdaa4402", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/lib.rs": "b9cae8ed53a4be8f738111f8727dd86218e66c88df38f32f4904e56651a2bee1", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/selection.rs": "0d1373577602646e84a4ab3448c65ee181987327bdabceff3c827e76dd9bd0d8", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/sync.rs": "4410fbae64e8f80321b3569a1495fb323e3319812c441f9eac54048c65ff93fb", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/cell.rs": "8b31cf5389398c74f141bd1f3e7945a1dbde8944bb754f5fd623313c73262496", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/color.rs": "ad2e33b60f397fe30e5e8f2dde2096bad8f5e256d464ba279cbda4a93cbbe224", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/grapheme.rs": "1ef6450b8bf8735b85e7a6fc3bb55c849e317f04778d297020ba3cb4dd7ecf74", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/mod.rs": "b4a6fdaa4f8c3fdf56b614689ed381408acc68407bd05c8ea592fb6fd0021f78", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/search.rs": "84e04c5f0da21009dbbcfc2f8033e322d6240c8d227028b5ce8a784f1c55ccaf", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/thread.rs": "e2f9fdc5d950bbea6c710c7a974f2998127af6b434344c363afb38e849f86144", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/mod.rs": "8cca30ba29cee2df84603f560a8d26624a48979d96d78f1b6729a470ff34d8a1", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/unix.rs": "2e8d0edf1aea816ac95c1e442d60025ebdd20dacaa99d0fd4f7c7cf78ac369e4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/blocking.rs": "60121a65df120c4a227520d6672231c9e3c515cb75241241e6b37a0c5bc186ca", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/child.rs": "4782f173c639bff6891f474b068fee64b6e2ad411edabdf496bbfe6554ceb32e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/conpty.rs": "62abd7e72af144ae1f1c359538e18cceaa97741382efa94e001f397510eef416", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/mod.rs": "b08803dae0f192bc6737aff22992a37368ac505c7133554c495ffcacb4116733", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/vi_mode.rs": "f52c0d3248707c68295880acd7ad96610467110d6813f1172d4ae767365add2e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/GraphemeBreakTest-17.0.0.txt": "e2d134d2c52919bace503ebb6a551c1855fe1a1faec18478c78fff254a1793ec", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/UNICODE-LICENSE.txt": "e7a93b009565cfce55919a381437ac4db883e9da2126fa28b91d12732bc53d96" + }, + "source_byte_forms_verified_against_git_c9f2eac": { + "git_blob_exact": 35, + "git_blob_lf_to_crlf": 0 + }, + "alternate_records": [ + { + "plan": "byte", + "chunk_sizes": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "offsets": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "8229315bee9585fa620254e0e294e51ac0bd81511abd114a225774a5ca19686b", + "canonical_candidate_trace_sha256": "f01576eb7ca499c8d3d72789b0cdf2411ba9479134cd6d85666f35e50c8c38b0", + "core_checkpoints": 25, + "candidate_checkpoints": 25 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "02f8d0c0f240020510e34d8578d0ac2adee94589cf76312619fcf4f5288e2362", + "core.jsonl": "4dd08b370b8460c71fe9b5580cfef34e918416d398171f6169180e7cc70f5c6e", + "candidate.jsonl": "c36725b69747111ff4faac6f5c0f937d82c113ec5db8d5b5e56cff500bdb815f", + "report.json": "0fefe8f41126b30569fd17a4c41f93861018c7de499b700b885104416d2882a3" + } + }, + { + "plan": "whole", + "chunk_sizes": [ + 24 + ], + "offsets": [ + 0, + 24 + ], + "original_status": "match", + "offline_classification": "match", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": null, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "86de13c458934c4cc292837858e440a8fb90eddc8337c3f4daaabea46faab530", + "canonical_candidate_trace_sha256": "86de13c458934c4cc292837858e440a8fb90eddc8337c3f4daaabea46faab530", + "core_checkpoints": 2, + "candidate_checkpoints": 2 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "68ca3fba3b7e864770cb61aeb306d4bd4354b68ab4dd38450860c5d823e42a53", + "core.jsonl": "1b0a6cd1a156748a15d7ceb3096ff1a396dddaa720d4bdc004339a986e7001c2", + "candidate.jsonl": "a95b8912d440f4d2acc14a34ecbc1e1cf33e0946ef074bea5c0543d846d62291", + "report.json": "1e4ebe73224f2da679959d4f477b03f503194479a4e8c39b64314315386b4209" + } + }, + { + "plan": "seed:42", + "chunk_sizes": [ + 4, + 1, + 9, + 8, + 2 + ], + "offsets": [ + 0, + 4, + 5, + 14, + 22, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 14, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "3dd867db0c75e2ce79f5200865b7365093efe5bc82c83642331775f003b5aaf2", + "canonical_candidate_trace_sha256": "429c29f1b622626efb40eccf768a483e176ced7884e9e9d2dc731aa234f96244", + "core_checkpoints": 6, + "candidate_checkpoints": 6 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "1039b70ae3c81e166529f465c72c06bd0778d2d98401c102b343f37d106c9481", + "core.jsonl": "1a4834341fe001fa19b243703903bbe65d5d07040f52ead2c020ecf151470207", + "candidate.jsonl": "cf3b3d263b4e1b8edcfec4c242312c51540f6cd3a9ad785c73313986ef9628e0", + "report.json": "a3200a632502347f2e30f1db1c8b6da1201bb497b6927f894045158365672a59" + } + }, + { + "plan": "seed:20261022", + "chunk_sizes": [ + 12, + 10, + 2 + ], + "offsets": [ + 0, + 12, + 22, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 12, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "7fbc6a28fcfc045551ce577daf233df09b33d9eb15a2e87dc271c964cba765d8", + "canonical_candidate_trace_sha256": "c8d2626cae1eec2dd14ebfa89ce68c013125cfb77fe2bcadaf940eace57c6c24", + "core_checkpoints": 4, + "candidate_checkpoints": 4 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "0eefa2f25e2d8957d807e18160101fa39511ee70b8b0b4a5ad40fbdc46ee65c2", + "core.jsonl": "dbf033c0b9e318b0e0503cb2af45258d69bf58a2585174472f03b35b4ecf235c", + "candidate.jsonl": "435051b53bc9a3662e2ac758d162609452f55ceee41b36cee61dda08defe37b9", + "report.json": "75af6ae250fc12e526e5f69d91c5233fb455295b175371ace2e170196cde3cd0" + } + }, + { + "plan": "seed:8675309", + "chunk_sizes": [ + 13, + 7, + 4 + ], + "offsets": [ + 0, + 13, + 20, + 24 + ], + "original_status": "difference", + "offline_classification": "reference_difference", + "signature": { + "input_sha256": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "rows": 3, + "columns": 12, + "history": 3, + "first_difference": { + "offset": 13, + "path": ".screen.row", + "expected": 0, + "actual": 1 + }, + "final_core_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "final_candidate_sha256": "624c2bd5d31b73bfba47dbbbb72260a54d9a9af663e65d5ad2a34d6f4559e067", + "canonical_core_trace_sha256": "63be2fb28cef585a2c6c7e0f0ae3c8de5225dc9cd1e3385a9b26997096f42667", + "canonical_candidate_trace_sha256": "95572ad54172efd387646f2c9745cdca7f42920626a5b380129a65abb0c5c187", + "core_checkpoints": 4, + "candidate_checkpoints": 4 + }, + "raw_files_sha256": { + "input.bin": "6ae16cedd522763cbbefccf3424d3195350d2d149d06a1e815e52ab73f96fe76", + "chunks.txt": "04d6f82166d12c2d9aba29aaea3787ea63e992e152666e8de5a121538b58c7e3", + "core.jsonl": "edf5abc876e62536705aab6dd533880340f7a817d2b6f74e95901daa461142da", + "candidate.jsonl": "ed89ec6970e9ffd6e72428e29428f8128e99fcdeaea5debbb96cb43d6800782a", + "report.json": "5721e6b0b7fbecdd14335938cf98c502b2a41c202b795dc1de33979a99027217" + } + } + ], + "offline_classification_is_new_ci_run": false + } + ] +} diff --git a/experiments/differential/results/2026-10-29-1049-reference/source-checkpoint-3156.py b/experiments/differential/results/2026-10-29-1049-reference/source-checkpoint-3156.py new file mode 100644 index 00000000..d6c4e992 --- /dev/null +++ b/experiments/differential/results/2026-10-29-1049-reference/source-checkpoint-3156.py @@ -0,0 +1,196 @@ +"""Execute common traces against TermForge and the Alacritty candidate; differences stay undecided.""" +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path +import platform +import subprocess + +from cases import cases +from run import ROOT, canonicalize_core, chunks, compare_traces, sha, state_sha, write_json +from experiments.candidates.alacritty.run import VERSION as CANDIDATE_VERSION +from experiments.candidates.alacritty.run import trace_binary as candidate_trace_binary, vendor_sources + + +def reference_status(case, plan, difference, core, candidate, known): + """Adjudicate only one complete ordered projection, never a prefix/final shortcut.""" + signature = dict(input_sha256=hashlib.sha256(case.data).hexdigest(), + rows=case.rows, columns=case.columns, history=case.history, + first_difference={key: value for key, value in difference.items() if key != "checkpoint"}, + final_core_sha256=state_sha(core[-1]["screen"]), + final_candidate_sha256=state_sha(candidate[-1]["screen"]), + canonical_core_trace_sha256=state_sha(core), + canonical_candidate_trace_sha256=state_sha(candidate), + core_checkpoints=len(core), candidate_checkpoints=len(candidate)) + expected = known.get(case.name, {}).get("plans", {}).get(plan) + return "reference_difference" if expected == signature else "difference" + + +def common_projection(records): + for record in records: + if not isinstance(record, dict) or type(record.get("offset")) is not int or record["offset"] < 0: + raise ValueError("invalid checkpoint offset") + screen = record.get("screen") + required = {"row", "column", "wrap_pending", "cells", "history", "current_style"} + if not isinstance(screen, dict) or not required.issubset(screen): + raise ValueError("missing screen projection fields") + for group in ("cells", "history"): + if not isinstance(screen[group], list) or any(not isinstance(row, list) for row in screen[group]): + raise ValueError("invalid projected row collection") + for row in screen[group]: + for cell in row: + if not isinstance(cell, dict) or not {"text", "width", "style"}.issubset(cell) or not isinstance(cell["text"], str) or type(cell["width"]) is not int or cell["width"] < 0: + raise ValueError("missing or invalid cell projection fields") + styles = [screen["current_style"]] + [cell["style"] for group in ("cells", "history") for row in screen[group] for cell in row] + if any(not isinstance(style, dict) or not {"fg", "bg", "bold"}.issubset(style) or type(style["fg"]) is not int or type(style["bg"]) is not int or type(style["bold"]) is not bool for style in styles): + raise ValueError("missing or invalid style projection fields") + cells = screen["cells"] + if not cells or not cells[0] or any(len(row) != len(cells[0]) for row in cells) or type(screen["row"]) is not int or not 0 <= screen["row"] < len(cells) or type(screen["column"]) is not int or not 0 <= screen["column"] < len(cells[0]) or type(screen["wrap_pending"]) is not bool: + raise ValueError("invalid screen geometry or cursor projection") + canonicalize_core(records) + result = [] + for record in records: + screen = record["screen"] + for group in ("cells", "history"): + for row in screen[group]: + for cell in row: + if cell["text"] in ("", " ") and cell["width"] in (0, 1): + cell["text"], cell["width"] = "", 0 + result.append(dict(offset=record["offset"], screen=screen)) + return result + + +def validate_checkpoints(records, sizes, arguments): + """Require every requested feed checkpoint, including an explicit resize tail.""" + offsets = [0] + for size in sizes: + if type(size) is not int or size <= 0: + raise ValueError("invalid requested chunk size") + offsets.append(offsets[-1] + size) + if any(argument.startswith("--resize=") for argument in arguments): + offsets.append(offsets[-1]) + if [record["offset"] for record in records] != offsets: + raise ValueError("missing or unexpected ordered checkpoint") + + +def execute(binary, prefix, case, sizes, output, arguments=()): + command = [str(binary), str(output / "input.bin"), str(case.rows), str(case.columns), + str(case.history), str(output / "chunks.txt"), *arguments] + try: + process = subprocess.run(command, capture_output=True, timeout=20) + stdout, stderr, returncode = process.stdout, process.stderr, process.returncode + except subprocess.TimeoutExpired as error: + stdout, stderr, returncode = error.stdout or b"", error.stderr or b"", None + except OSError as error: + stdout, stderr, returncode = b"", str(error).encode("utf-8"), None + (output / f"{prefix}.jsonl").write_bytes(stdout) + (output / f"{prefix}.stderr.txt").write_bytes(stderr) + records, error = [], None + if returncode == 0: + try: + records = common_projection([json.loads(line) for line in stdout.decode("utf-8").splitlines()]) + validate_checkpoints(records, sizes, arguments) + except (ValueError, KeyError, TypeError) as exc: + error = str(exc) + return records, returncode, error + + +def run_case(core_binary, candidate_binary, case, plan, output, core_arguments=(), candidate_arguments=()): + output.mkdir(parents=True, exist_ok=False) + sizes = chunks(len(case.data), plan) + (output / "input.bin").write_bytes(case.data) + (output / "chunks.txt").write_text("".join(f"{size}\n" for size in sizes), encoding="ascii") + core, core_code, core_error = execute(core_binary, "core", case, sizes, output, core_arguments) + candidate, candidate_code, candidate_error = execute(candidate_binary, "candidate", case, sizes, output, + candidate_arguments) + difference = None + if core_code == 0 and candidate_code == 0 and not core_error and not candidate_error: + difference = compare_traces(core, candidate) + status = "execution_failure" if core_code != 0 or candidate_code != 0 or core_error or candidate_error else "match" + if difference: + known_path = Path(__file__).with_name("candidate-known-differences.json") + known = json.loads(known_path.read_text(encoding="utf-8")) if known_path.exists() else {} + status = reference_status(case, plan, difference, core, candidate, known) + report = dict(case=case.name, plan=plan, input_sha256=sha(output / "input.bin"), + bytes=len(case.data), rows=case.rows, columns=case.columns, history=case.history, + chunk_sizes=sizes, checkpoints=len(core), status=status, + core_returncode=core_code, candidate_returncode=candidate_code, + core_error=core_error, candidate_error=candidate_error, + first_difference=difference, + difference_direction="expected=TermForge core; actual=Alacritty candidate; neither is an oracle", + normalization="NFC text; blank/empty cells share a projection; explicit-space semantics are excluded; mode_bits/replies are not compared here", + reproduce={"core": ["terminal_trace", "input.bin", str(case.rows), str(case.columns), + str(case.history), "chunks.txt"], + "candidate": ["termforge-alacritty-trace", "input.bin", str(case.rows), + str(case.columns), str(case.history), "chunks.txt"]}) + write_json(output / "report.json", report) + return report, core, candidate + + +def run_suite(core_binary, candidate_binary, output, selected=None, plans=None): + output.mkdir(parents=True, exist_ok=False) + records = [] + for case in selected or cases(): + byte_core, byte_candidate = None, None + for plan in plans or ["byte", "whole", "seed:42", "seed:20261022", "seed:8675309"]: + folder = output / case.name / plan.replace(":", "-") + report, core, candidate = run_case(core_binary, candidate_binary, case, plan, folder) + if plan == "byte": + byte_core, byte_candidate = core, candidate + elif byte_core is not None and len(byte_core) == len(case.data) + 1: + offsets = [item["offset"] for item in core] + report["core_fragmentation_difference"] = compare_traces([byte_core[i] for i in offsets], core) + report["candidate_fragmentation_difference"] = compare_traces( + [byte_candidate[i] for i in offsets], candidate) + if report["core_fragmentation_difference"] or report["candidate_fragmentation_difference"]: + report["status"] = "fragmentation_failure" + write_json(folder / "report.json", report) + records.append(report) + sources = ["experiments/core/trace.cpp", "experiments/core/terminal.hpp", "experiments/core/screen.hpp", + "experiments/core/unicode_width.hpp", "experiments/differential/run.py", + "experiments/differential/cases.py", "experiments/differential/compare_candidate.py", + "experiments/differential/candidate-known-differences.json", + "experiments/candidates/alacritty/src/main.rs", "experiments/candidates/alacritty/run.py", + "experiments/candidates/alacritty/Cargo.toml", "experiments/candidates/alacritty/Cargo.lock"] + vendor_sources() + execution_passed = all(record["status"] not in ("execution_failure", "fragmentation_failure") + for record in records) + summary = dict(schema=1, candidate="alacritty_terminal", version=CANDIDATE_VERSION, + platform=platform.platform(), python=platform.python_version(), + core_trace_sha256=sha(core_binary), candidate_trace_sha256=sha(candidate_binary), + source_sha256={path: sha(ROOT / path) for path in sources}, + runs=len(records), checkpoints=sum(record["checkpoints"] for record in records), + counts={status: sum(record["status"] == status for record in records) + for status in sorted({record["status"] for record in records})}, + passed=execution_passed, execution_passed=execution_passed, + semantic_acceptance=False, + differences_adjudicated=all(record["status"] in ("match", "reference_difference") + for record in records), + performance_measured=False, records=records) + write_json(output / "summary.json", summary) + return summary + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--trace", type=Path) + parser.add_argument("--candidate", type=Path) + parser.add_argument("--out", type=Path, required=True, help="new output directory; never overwritten") + parser.add_argument("--case", choices=[case.name for case in cases()]) + parser.add_argument("--plan", help="byte, whole, or seed:; default runs all five plans") + args = parser.parse_args() + core = args.trace.resolve(strict=True) if args.trace else None + if core is None: + from run import trace_binary + core = trace_binary() + candidate = args.candidate.resolve(strict=True) if args.candidate else candidate_trace_binary() + selected = [case for case in cases() if args.case is None or case.name == args.case] + result = run_suite(core, candidate, args.out.resolve(), selected, [args.plan] if args.plan else None) + print(json.dumps({key: result[key] for key in ("execution_passed", "runs", "checkpoints", "counts", + "semantic_acceptance")}, indent=2)) + return 0 if result["execution_passed"] else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/experiments/differential/results/2026-10-29-1049-reference/validation.json b/experiments/differential/results/2026-10-29-1049-reference/validation.json new file mode 100644 index 00000000..082eb761 --- /dev/null +++ b/experiments/differential/results/2026-10-29-1049-reference/validation.json @@ -0,0 +1,177 @@ +{ + "schema": "termforge-1049-reference-diagnostic-validation-v1", + "issue": 135, + "scope": "Strict reference-difference bookkeeping only; no C++ or Alacritty implementation change", + "diagnostic_source_commit": "1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03", + "final_targeted_tests": { + "source_commit": "1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03", + "tests": 11, + "failures": 0, + "errors": 0, + "skips": 0, + "passed": true, + "log_sha256": "6de5731388a269f753226d4362e0fc8a93555523d9152719db96851a0931dc3b", + "diagnostic_source_sha256": { + "experiments/differential/compare_candidate.py": "d2c974db45c64268b8dbe3b059a28159562cb6f6ca8288d6e703d4fddc9fffc3", + "experiments/differential/candidate-known-differences.json": "8efa67296373f90fe3b545541e1bddbc61472cc3369f769b25dded8d7a06a05d", + "experiments/differential/capability_matrix.py": "cb73e23ac403f437f8141565d92a83c419d26603d90d7cf8b38d6db4f82a958b", + "experiments/differential/test_capability_matrix.py": "8d12d6c6995a7b2b9b25524ec196b11b34c6ccd381df7eea78a09cca6747c3e9", + "experiments/differential/test_candidate_reference_contract.py": "d308b8d9a374449b310fee09c221dc3c114eb4e4fd94fc05c13711935ad15c89" + } + }, + "final_capabilities": { + "runs": 25, + "checkpoints": 118, + "counts": { + "core_unsupported": 10, + "match": 6, + "reference_difference": 4, + "resize_difference": 5 + }, + "semantic_acceptance": false, + "summary_sha256": "f04c377a945bfedb698ed7b0321292c66f385f1cedc76d11b20a2c606ca12c84" + }, + "locked_local_reference_build": { + "source_head_at_build": "c9f2eacff4540c2623552a72eaa5bab4fa6262c9", + "candidate_source_sha256": { + "experiments/candidates/alacritty/Cargo.lock": "896c6e60909d55d61fb26d277b1a98daf9245e8aee811caff37fc3e9d06ca627", + "experiments/candidates/alacritty/Cargo.toml": "2b4be12e31053e65dabca8ca9c234a59b73ab2ab3e1520a6092c7dc94e12ffd7", + "experiments/candidates/alacritty/PROVENANCE.md": "c27d90c196dab7481c56169a227c3c02aec68ebfa2152c7f21105b0bbc4f1f15", + "experiments/candidates/alacritty/README.md": "1d5f924fa44fdfe404fa4250ec9619c2ebe25bc50a854b3d27fb94dbeb879b46", + "experiments/candidates/alacritty/grapheme_checks.py": "2a3c816068638a78bc7e5e53be9c29e52ceb9e9e237beb5bb744ff5f0614ef87", + "experiments/candidates/alacritty/include/termforge_candidate.h": "999c635ecd6d4482303d39d6548312afb3179edaeb17d14d4683688d83334ecc", + "experiments/candidates/alacritty/run.py": "e84bfcd530a7a79bcb9e722e507257f9b92a60b2c3ca8043c15da432b6220a01", + "experiments/candidates/alacritty/src/ffi.rs": "8c6fffa0559f0ab5f6e776bab03a35a1375b2b9f977c047da9bc62b8e5c30bfa", + "experiments/candidates/alacritty/src/main.rs": "078f238ded11e2eb6780140d29fb3eb1d41c66bbe2ecc4ed62f40304c43d6260", + "experiments/candidates/alacritty/src/measure.rs": "701aecfd5bbd951434f7b8278b9efb700e7644c9eccfd19cec1b36aa6aeb3f8a", + "experiments/candidates/alacritty/test_candidate.py": "776fec0e62084e3a5626ca61abebf9a8605307c539faac9fb0ff70dfaef358f4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/CHANGELOG.md": "97231d9beda30b536650c566169c692fa846be3f7b0405add3c9741f95f3af62", + "experiments/candidates/alacritty/vendor/alacritty_terminal/Cargo.toml": "bce82942276bab9c4967998d654316f9c85e698babd0945c66a55fcb91ef2333", + "experiments/candidates/alacritty/vendor/alacritty_terminal/LICENSE-APACHE": "8884289e3969c089cd556c53fa1d3f51d86b29e52a8c1d660a55ce8292986910", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event.rs": "e76c212f36bbfc43ea037a825dbc9c5b1174f5836fe8b69dfd158aadf3fc4048", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/event_loop.rs": "6da2897b76d8c0e7f989daa1463fd6fdeb3469a0a63e0c6ba703a9562663163c", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/mod.rs": "be15d08b03a28a271aa927b7149346a1b5d29e92e9186891bf246fdd2a4c90fc", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/resize.rs": "4907427c9488435f1e1ee624629bc8445c4dde5399f0349955d1bbc2042080c4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/row.rs": "2f963299e52525828d9d0bf1de758d793661c908eb7c126aa8556a1c9945a83d", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/storage.rs": "27a9b5101833d57423ae34ccef3d82c1a1cf9f51cbc42cc836a6fce79c088348", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/grid/tests.rs": "5f38819134540eeb0dff7047f57f5d06250ce59493839c66ec4cd56e43db62f8", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/index.rs": "46908b68508f4e4ea90313f0536a88c357f2d17ad211b14d44b7f92dfdaa4402", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/lib.rs": "b9cae8ed53a4be8f738111f8727dd86218e66c88df38f32f4904e56651a2bee1", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/selection.rs": "0d1373577602646e84a4ab3448c65ee181987327bdabceff3c827e76dd9bd0d8", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/sync.rs": "4410fbae64e8f80321b3569a1495fb323e3319812c441f9eac54048c65ff93fb", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/cell.rs": "8b31cf5389398c74f141bd1f3e7945a1dbde8944bb754f5fd623313c73262496", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/color.rs": "ad2e33b60f397fe30e5e8f2dde2096bad8f5e256d464ba279cbda4a93cbbe224", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/grapheme.rs": "1ef6450b8bf8735b85e7a6fc3bb55c849e317f04778d297020ba3cb4dd7ecf74", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/mod.rs": "b4a6fdaa4f8c3fdf56b614689ed381408acc68407bd05c8ea592fb6fd0021f78", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/term/search.rs": "84e04c5f0da21009dbbcfc2f8033e322d6240c8d227028b5ce8a784f1c55ccaf", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/thread.rs": "e2f9fdc5d950bbea6c710c7a974f2998127af6b434344c363afb38e849f86144", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/mod.rs": "8cca30ba29cee2df84603f560a8d26624a48979d96d78f1b6729a470ff34d8a1", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/unix.rs": "2e8d0edf1aea816ac95c1e442d60025ebdd20dacaa99d0fd4f7c7cf78ac369e4", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/blocking.rs": "60121a65df120c4a227520d6672231c9e3c515cb75241241e6b37a0c5bc186ca", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/child.rs": "4782f173c639bff6891f474b068fee64b6e2ad411edabdf496bbfe6554ceb32e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/conpty.rs": "62abd7e72af144ae1f1c359538e18cceaa97741382efa94e001f397510eef416", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/tty/windows/mod.rs": "b08803dae0f192bc6737aff22992a37368ac505c7133554c495ffcacb4116733", + "experiments/candidates/alacritty/vendor/alacritty_terminal/src/vi_mode.rs": "f52c0d3248707c68295880acd7ad96610467110d6813f1172d4ae767365add2e", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/GraphemeBreakTest-17.0.0.txt": "e2d134d2c52919bace503ebb6a551c1855fe1a1faec18478c78fff254a1793ec", + "experiments/candidates/alacritty/vendor/alacritty_terminal/tests/data/UNICODE-LICENSE.txt": "e7a93b009565cfce55919a381437ac4db883e9da2126fa28b91d12732bc53d96" + }, + "command": "cargo +1.92.0 build --release --locked", + "rustc": "1.92.0 ded5c06cf21d2b93bffd5d884aa6e96934ee4234", + "cargo": "1.92.0 344c4567c", + "core_trace_sha256": "3f8bda9d6b1443d02265089ed560941ab8c226cd0bd2900cbadea3812a55d081", + "candidate_trace_sha256": "cd77d300f37f8d2ae8f5d9570f7544a4c65b7bc06c79a8f92169201a32d92686", + "build_log_sha256": "4321d71bf3d1aa5c15a5fe7229ae1d26387a2e17c361161402ceb470ec70e313" + }, + "pre_final_diagnostics": [ + { + "scope": "candidate-comparison", + "source_commit": null, + "source_identity": "Pre-final working-tree checkpoint; exact comparison tool SHA below, not final1e5 or original full575bd", + "compare_candidate_sha256": "3156f71393675d4efccf8415c8191cfe5f1e823c1b25d1bce00e2fbabe23f8d4", + "runs": 95, + "counts": { + "match": 95 + }, + "tests_passed": 4, + "summary_sha256": "6644865deb3415c36b782aaa132f4c5c4838097f51cec1afddc7361dd9a4134f", + "semantic_acceptance": false, + "archived_comparison_source": "source-checkpoint-3156.py" + }, + { + "scope": "candidate-fuzz", + "source_commit": null, + "source_identity": "Pre-final working-tree checkpoint; exact comparison tool SHA below, not final1e5 or original full575bd", + "compare_candidate_sha256": "3156f71393675d4efccf8415c8191cfe5f1e823c1b25d1bce00e2fbabe23f8d4", + "runs": 8, + "counts": { + "known_failure": 2, + "match": 6 + }, + "tests_passed": 4, + "summary_sha256": "a98bb58788d316a91001fc9afe89b76eee20d5c5132c94e6938bc743a345a947", + "semantic_acceptance": false, + "archived_comparison_source": "source-checkpoint-3156.py" + }, + { + "scope": "real-applications", + "source_commit": null, + "source_identity": "Pre-final working-tree checkpoint; exact comparison tool SHA below, not final1e5 or original full575bd", + "compare_candidate_sha256": "3156f71393675d4efccf8415c8191cfe5f1e823c1b25d1bce00e2fbabe23f8d4", + "runs": 3, + "counts": { + "match": 3 + }, + "tests_passed": 8, + "summary_sha256": "77bd5c0051da8394953ccb50964a7159cefd7a28bb4df0ffb40cbfb42845cb1c", + "semantic_acceptance": false, + "archived_comparison_source": "source-checkpoint-3156.py" + } + ], + "initial_failed_ci": [ + { + "run": 40737560783, + "event": "pull_request", + "head": "c9f2eacff4540c2623552a72eaa5bab4fa6262c9", + "checkout": "eaf2cf43897a8ab45be3436db5ba6753d22e7dc4", + "failed_step": "Compare extended capability traces", + "os": [ + "windows-2025", + "ubuntu-24.04" + ] + }, + { + "run": 40737501428, + "event": "push", + "head": "c9f2eacff4540c2623552a72eaa5bab4fa6262c9", + "checkout": null, + "failed_step": "Compare extended capability traces", + "os": [ + "windows-2025", + "ubuntu-24.04" + ] + } + ], + "preserved_full_cpp_validation": { + "validated_source_commit": "575bd282b7f61fc4c47da0cad7739b0c46d8c1f2", + "registered": 55, + "passed": 55, + "internal_skips": 13, + "validation_json_sha256": "0c31bc4b95c9f150b98a89ac0df9e9524b462a775e2f2e3554b586052e40a970", + "rerun_at_diagnostic_head": false + }, + "limits": { + "semantic_acceptance": false, + "new_windterm_execution": false, + "performance_measured": false, + "new_linux_native_execution_locally": false, + "complete_alternate_modes_accepted": false, + "original_full_grid_or_glyph_equivalence_accepted": false, + "important_original_behavior_deviation_approved": false + }, + "pre_final_source_archive": { + "file": "source-checkpoint-3156.py", + "sha256": "3156f71393675d4efccf8415c8191cfe5f1e823c1b25d1bce00e2fbabe23f8d4", + "commit": null, + "recovery": "Reconstructed from the final source and recorded predecessor edit; accepted only because full bytes SHA equals all three original summaries" + } +} From b3ae687fc2b9a60532a8c5edaa0db43a80d13d45 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Thu, 29 Oct 2026 02:22:27 +0800 Subject: [PATCH 6/6] docs: distinguish raw and LF reference summary identities (#135) --- .../differential/results/2026-10-29-1049-reference/README.md | 2 +- .../results/2026-10-29-1049-reference/validation.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/experiments/differential/results/2026-10-29-1049-reference/README.md b/experiments/differential/results/2026-10-29-1049-reference/README.md index 3cd9ddb8..a15431be 100644 --- a/experiments/differential/results/2026-10-29-1049-reference/README.md +++ b/experiments/differential/results/2026-10-29-1049-reference/README.md @@ -32,7 +32,7 @@ 另有缺投影字段可成为相同比较的反例,以及缺初始/中间/最终/resize 检查点的拒绝;字段、样式与完整计划 offset 先验校验后转绿。缺 manifest 字段、截断、未列 seed:99 都不能复用已知规则;公共 CLI 的未列 seed 返回 exit1,未删除输入或放宽差异。 -最终诊断源为 **`1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03`**。公共 trace-data/registry 6 项普通及 `python -O` 通过;固定该提交的合同+能力 **11 项全部通过、0 skip**,包括公共 CLI 正/负例,日志 SHA 与源码见[validation.json](validation.json)。候选 workflow 的原 common-test 步骤选择 `test_candidate*.py`,包含这六项新门槛,原负载和期限未改。[最终能力摘要](capability-summary.json)为 25 runs / 118 checkpoints:10 core_unsupported、4 reference_difference、6 match、5 resize_difference,`semantic_acceptance=false`。支持标志只针对该固定 1049 输入,不意味着 47/1047/1048 或全部备用屏模式已支持。 +最终诊断源为 **`1e5cc7ad83007e44fdcdd7f0f847afdfc453dd03`**。公共 trace-data/registry 6 项普通及 `python -O` 通过;固定该提交的合同+能力 **11 项全部通过、0 skip**,包括公共 CLI 正/负例,日志 SHA 与源码见[validation.json](validation.json)。候选 workflow 的原 common-test 步骤选择 `test_candidate*.py`,包含这六项新门槛,原负载和期限未改。[最终能力摘要](capability-summary.json)为 25 runs / 118 checkpoints:10 core_unsupported、4 reference_difference、6 match、5 resize_difference,`semantic_acceptance=false`。原始 Windows JSON 的 CRLF SHA 与公开 LF 文本 SHA 分列,解析数据未变。支持标志只针对该固定 1049 输入,不意味着 47/1047/1048 或全部备用屏模式已支持。 前置工作区 checkpoint 另外运行了 common 4 项(95 match)、fuzz 4 项(8 runs:6 match/2 known_failure)、Windows cmd/more/Vim 诊断 8 项(3 match、真实退出/文件/Job 边界通过)。其 compare tool SHA `3156f71393675d4efccf8415c8191cfe5f1e823c1b25d1bce00e2fbabe23f8d4` 与最终显式 input-length 校验/格式整理前不同,commit 身份为 null,单独列在 JSON。对应[前置源码档案](source-checkpoint-3156.py)由已记录修改恢复,完整字节 SHA 与三个原摘要完全相同;它不是当前入口。不能冒称最终1e5重跑全部应用矩阵。全部本地 exec 已监督到结束,没有跨代理移交运行会话。 diff --git a/experiments/differential/results/2026-10-29-1049-reference/validation.json b/experiments/differential/results/2026-10-29-1049-reference/validation.json index 082eb761..e15321a0 100644 --- a/experiments/differential/results/2026-10-29-1049-reference/validation.json +++ b/experiments/differential/results/2026-10-29-1049-reference/validation.json @@ -29,7 +29,9 @@ "resize_difference": 5 }, "semantic_acceptance": false, - "summary_sha256": "f04c377a945bfedb698ed7b0321292c66f385f1cedc76d11b20a2c606ca12c84" + "raw_summary_sha256": "f04c377a945bfedb698ed7b0321292c66f385f1cedc76d11b20a2c606ca12c84", + "public_summary_sha256": "70f1db93eb51503c15a5a5bfbb98c0cd4b0a61b3650e46c098a66542f2606221", + "public_text_policy": "LF JSON projection; parsed content unchanged from local raw summary" }, "locked_local_reference_build": { "source_head_at_build": "c9f2eacff4540c2623552a72eaa5bab4fa6262c9",