diff --git a/CMakeLists.txt b/CMakeLists.txt index ce9dae4d..779a9998 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -306,6 +306,7 @@ if(BUILD_TESTING) termforge_add_python_test(windterm_alternate_style_reference -m unittest research.ui.test_export_alternate_style_reference research.ui.test_alternate_style_peer -v) termforge_add_python_test(windterm_raster_style_reference -m unittest research.ui.test_raster_style_reference -v) termforge_add_python_test(windterm_raster_selection_proposal -m unittest research.ui.test_raster_selection_reference -v) + termforge_add_python_test(windterm_raster_raw_proposal -m unittest research.ui.test_raster_raw_reference -v) termforge_add_python_test(differential -m unittest discover -s experiments/differential -p test_*.py -v) termforge_add_python_test(ime_inventory -m unittest research.ime.test_hosted_inventory research.ime.test_prepare_hosted research.ime.test_product_ime -v) termforge_add_python_test(text_actions -m unittest experiments.shell.test_actions -v) diff --git a/docs/EVIDENCE.md b/docs/EVIDENCE.md index 84f74250..030eb596 100644 --- a/docs/EVIDENCE.md +++ b/docs/EVIDENCE.md @@ -150,6 +150,7 @@ python -m unittest experiments.shell.test_workflow_sessions -v | 工作区结构/几何 | [首轮 UI 报告](research/windterm-ui-2026-10-23.md)、[主标签/字体报告](research/windterm-ui-typography-2026-10-23.md)、[探针与准备守卫](../research/ui/README.md) | 发行资源、定向二进制和隔离运行时交叉核对;默认缩放两次及 Qt 1.5 倍一次。旧首启自动导入和错误状态样本已明确排除,不能混作最终纯合成证据 | | 可公开的 UI 精简结果 | [默认样本 1](research/ui-typography/normal-01.json)、[默认样本 2](research/ui-typography/normal-02.json)、[Qt 1.5 倍样本](research/ui-typography/scale-150.json) | 白名单矩形、字体、DPI 和身份;不是完整像素、逐字形 fallback、真实跨屏或性能证明 | | 基础文字交互参考合同 | [行为合同](research/windterm-r1-text-contract.md)、[hosted 事实摘要](research/r1-text/hosted-39960732305.json)、[Actions 39960732305](https://github.com/JavaZeroo/termforge/actions/runs/39960732305) | `c386494` 的 text/menu-wrap 各两轮及 repeat 门槛通过:历史/选择/查找、键盘及实际 Select All/Find/Copy/Paste 菜单、精确 CF 软折行/CRLF/尾空白与严格粘贴基线均有证据;四轮 Job 清空。满足 #11 限定参考合同,不代表产品功能等价或性能验收 | +| 五阶段 raw H/space 输出参考(#129) | [固定采集合同](research/windterm-raster-raw-capture-plan.md)、[执行与独立审计](research/windterm-raster-raw-reference-2026-10-29.md)、[脱敏结果](../research/ui/results/2026-10-29-raster-raw-reference/validation.json) | `f6d9a97` 的唯一授权执行取得 5 grab、17 组完整 H/space;phase2 双 H 的 16/16 墨迹并列保留 null,未中断采集。phase1/3 原样 H 唯一匹配同帧 SGR0,phase4 匹配同帧 SGR31;44 的完整有序签名;仅为固定样本输出,不证明内部 pen、完整 grid、presented、local-shell 或性能。旧 #126 0 grab 和旧 #129 3 grab partial 均独立保留,父项未关闭。 | 主对照为官方 Windows x64 2.7.0:ZIP SHA-256 `b05c3c7371340ff1302967247ffcd3a3ba27b237f72010e9157086143c453e50`,EXE SHA-256 `7b10531dccc7cd614ae559f36f1ef518e0c96335637431b4646354823b2804d0`。最初本机安装的 EXE 身份不同;其历史静态报告不得冒充官方包结果。其他目标平台仍需各自固定包身份。 diff --git a/docs/research/windterm-raster-raw-capture-plan.md b/docs/research/windterm-raster-raw-capture-plan.md new file mode 100644 index 00000000..35f3100b --- /dev/null +++ b/docs/research/windterm-raster-raw-capture-plan.md @@ -0,0 +1,53 @@ +# #129 raw-capture-v1:采集与分析分离 + +本方案完成复核后,另建授权计划并执行一次新原版,已取得[五阶段完整 raw ROI 与离线签名证据](windterm-raster-raw-reference-2026-10-29.md)。原 `execution_authorized=false` proposal 保持不可运行且未修改。旧 [#126 的 0 grab 停止](windterm-1049-raster-reference-2026-10-28.md)和 [#129 的 3 grab partial](windterm-raster-selection-reference-2026-10-29.md)随 [PR #132](https://github.com/JavaZeroo/termforge/pull/132) 独立保留,均未改写,也没有关闭 parent 颜色调查。 + +新 case 为 `raw-capture-v1`,独立工作树及分支 `research/windterm-raster-raw-capture`,固定生产源 `f6d9a97e2b2685b6ce39c83dc7107cb52aec7a6a`。[不可运行计划](../../research/ui/results/2026-10-29-raster-raw-proposal/plan.json)列出七个生产源 SHA、分析源 SHA、四个完整模块 SHA、五段输入的 hex/长度/SHA 与单次预算。最终复核及明确运行指令后,必须另建新授权计划和唯一目录,不能把此 false proposal 改为 true 或复用旧批目录。 + +## 本次改变的合同 + +[GUI 采集器](../../research/ui/raster_raw_reference.js)在一次 grab 得到的同一 QImage 内,先读完本阶段每个已绑定 H 与其前置 space 的完整 ROI 数组。它不计算主要墨迹、不比较颜色、不以双 H 颜色是否相等作为推进条件。只有结构验证和原生对象回收完成后,`capture_valid=true` 并写 `captured` 确认,允许 peer 发送下一阶段。 + +| 情况 | 采集推进 | 离线处理 | +|---|---|---| +| 主要墨迹频数并列 | 收完全部 ROI 后继续 | dominant 为 null,保留全部并列候选及频数 | +| space 非单色 | 收完全部 ROI 后继续 | 背景及墨迹分类未知,保留完整 histogram/hash | +| H 与背景无差异 | 收完全部 ROI 后继续 | `no-marker-ink`,不据此匹配样式 | +| 双 H 的输出不一致、正控别名或无匹配 | 继续采集后续阶段 | 保留各自签名,多义或无匹配为 null,不推定 reset | +| 身份、端点、标签、caret、ROI/DPR/空图或原生调用失败 | 保存真实 partial 并停止 | 不移动 ROI、不补抓、不重跑 | + +`capture_valid` 只指结构采集有效,不表示颜色、样式、active grid、presented 或产品验收通过。结构失败允许保留已取得的部分 ROI,不能把缺失像素补造为完整阶段。 + +## 不变的五阶段及边界 + +五段仍为 `43/38/20/53/54` 字节,各另追加 `CSI 6n`,详见新计划及[生产器](../../research/ui/raster_raw_reference.py)。D0=`SGR0`,S1=`SGR31;44`,S2=`SGR32;45`。 + +| 阶段 | 内容 | 结束前 SGR | +|---|---|---| +| 0 | 一图内 D0 双 H、M0/S1 双 H | S1 | +| 1 | `1049h` 后原样 A0 H,同一行 S1/D0 正控 | D0 | +| 2 | S2 的 A1 双 H | S2 | +| 3 | 重复 `1049h` 后原样 A2 H,同一行 D0/S1/S2 正控 | S2 | +| 4 | `1049l` 后原样 M1 H,同一行 S1/S2/D0 正控 | D0 | + +保留每个前导空格和完整 token 匹配,M1 不匹配 M1S1。运行中逐条完整 NAWS 事件守卫、独立 DSR 回复与阶段确认均保留。GUI 主线程主动读取实际 isAltScreen/isMainScreen 和有限非负 P 端点;caret=anchor 才允许采集,selectionText 只记 type/length。实际 caret(零宽仍按至少 1 逻辑像素)不得与任何 H/space 相交。marker 的 ordinal/完整 label/group/sample 必须按固定身份一一对应,不能以重复条目补齐数量。 + +仍使用固定官方 WindTerm 2.7.0、隔离 WindowStation/Desktop、OwnedJob、单合成 loopback/profile。最多一次原版运行、每阶段一次 grab、总最多五次;REA capture45、CLI wait60,原版更早启动并另等 2 秒,整程上限未知。禁止用户输入桌面、剪贴板、DPI 变更及计时结论。 + +Qt5 API/ABI 沿用已核实的完整模块 SHA、实际模块路径与固定导出 RVA:QWidget::grab→QPixmap::toImage→QImage::pixel,QRect 为 inclusive 边界;QPixmap/QImage 各分配 32B、不预构造,正常返回后 image→pixmap 普通析构。仍以 QImage::pixel 逐点读 QRgb,不猜 format/stride。原生 bool 的精确 bool 或整数 0/1 表示显式核对并保留原类型。 + +## 离线分析与公开出口 + +[分析器](../../research/ui/raster_raw_analysis.py)先独立检查结构、完整 token 位置、ROI 顺序/唯一身份、DPR、样本数量和 uint32 值,再为每个 H/space 保留完整 RGBA histogram、样本数和有序 QRgb 数组 SHA。数组本身留 local。主墨迹并列只生成 null 和候选,不抛出采集失败,也不改变原批结果。 + +同帧比较要求目标与正控都在同一文档行及逻辑行,并且都观察到墨迹。匹配条件是 H 和 space 各自的**有序数组 SHA、宽高与样本数完全相同**;只靠主要颜色或 histogram 相同不足以匹配。匹配多个控或未匹配时唯一结论为 null。即使匹配唯一,也只称该同帧原样 H/space 的输出签名与显式正控一致,不声称读到了内部 pen、完整 current_style 或 reset。 + +[公开 CLI](../../research/ui/export_raster_raw_reference.py)使用显式 require/ValueError,只有身份、合成文本、消息、生命周期及结构审计全部完成后才创建输出目录。公开只有合成源、histogram/频数/尺寸标量和 hash;raw 像素、日志、路径、PID、资源及 profile 均留 local。`raw_capture_complete=true` 与颜色分类未知可以同时成立,不转化为五阶段样式对齐通过。 + +## 离线复现与验证 + +[既有 phase2 回放](../../research/ui/results/2026-10-29-raster-raw-proposal/replay.json)绑定原 Evidence ID `ev_432abe8baf4fc86efd4994cd12cc3ab5fe0b5120476d22540c5b26e2e3c693a4` 和原 raster-result SHA `3887faaa8d055f42388eafc4b0a9ee2e2b8111d3fa1384e07ec5f0a50585f34d`。新分析器正确保留两个 16 次候选;旧批第二个 H 没有采样、phase3/4 没有发送,这些缺口均未补造。既有 phase1 的完整 raw 签名也唯一匹配同帧 D0。该回放的新原版运行数为 0,不能把旧 partial 变成新完整采集。 + +[公共测试](../../research/ui/test_raster_raw_reference.py)与[合成 Qt 边界](../../research/ui/test_raster_raw_native.js)按已确认的采集入口/离线 CLI seam 逐项红→绿:旧逻辑遇 tie 只留 1/4 ROI,新逻辑收全 4;tie 分类从异常变为 null/candidates;重复 marker、重复 ROI 和错误完整 label 从可通过变为拒绝。完整合成五阶段即使 phase2 tie 也能导出全部 ROI;同 histogram 但不同排列不匹配,别名及无墨迹保持未知。另覆盖普通/优化解释器的隐私/身份/结构拒绝不得生成公开输出、32B sret 和异常析构边界,以及 false proposal 不得启动或产生 attempt。 + +离线普通及 `python -O` 各 11 项通过,相关 CTest `windterm_raster_style_reference`、`windterm_raster_selection_proposal`、`windterm_raster_raw_proposal` 在 Debug 配置下 3/3 通过。`core.autocrlf=true` 的 fresh checkout 也核对新 JS 与 Qt 前缀 SHA 一致。后续唯一授权执行及独立离线审计见[结果报告](windterm-raster-raw-reference-2026-10-29.md);该结果只支持固定样本输出事实,不提升为内部样式、完整栅格、presented 或产品验收。 diff --git a/docs/research/windterm-raster-raw-reference-2026-10-29.md b/docs/research/windterm-raster-raw-reference-2026-10-29.md new file mode 100644 index 00000000..4549f204 --- /dev/null +++ b/docs/research/windterm-raster-raw-reference-2026-10-29.md @@ -0,0 +1,53 @@ +# #129 raw-capture-v1:五阶段原始 ROI 完整采集与离线签名 + +按[固定方案](windterm-raster-raw-capture-plan.md)完成一次新原版运行:5 个阶段各一次 grab,17 组 H/前置 space、34 个完整 QRgb 数组全部取得。phase2 两个 H 都有 16/16 主要墨迹并列,离线分类保留 `dominant_ink_rgba=null`,采集仍完成 phase3/4。`raw_capture_complete=true` 只表示这批固定 ROI 完整,不表示五阶段样式、内部 pen 或完整终端行为验收通过。 + +同帧、同文档行及逻辑行的完整有序 H/space 输出签名比较:phase1 首次 `1049h` 后的原样 A0,以及 phase3 重复 `1049h` 后的原样 A2,均唯一匹配该帧显式 `SGR0` 正控;phase4 `1049l` 后的原样 M1 唯一匹配该帧显式 `SGR31;44` 正控。这里的匹配要求 H 和 space 各自有序 QRgb 数组、尺寸和数量完全相同,不依据主要颜色或 histogram 相同推断内部样式、reset 或完整恢复语义。 + +## 执行与源身份 + +- 固定生产源为 `f6d9a97e2b2685b6ce39c83dc7107cb52aec7a6a`,执行前准备 HEAD 为 `46f90d89e5b80b96989861f437b4b10e75ccb199`。七个生产源逐字节匹配固定生产提交、false proposal 与新授权计划;本次证据收尾未改生产源或原件。 +- 原 `execution_authorized=false` proposal 保持不变。复核明确授权后另建新计划,私有 SHA 为 `8dbeaae26ed19c6d8f3c22a16308fdf3b85f1d02a14aaa7e20af96c76405d288`;启动前新输出目录及 attempt marker 均不存在,唯一 attempt 随后保留,没有第二次原版运行。 +- [授权计划的脱敏投影](../../research/ui/results/2026-10-29-raster-raw-reference/plan.json)列出全部五段 `43/38/20/53/54` 字节及 hex/SHA,每段另追加 `CSI 6n`。本批五段均实际发送。 +- 固定官方 WindTerm 2.7.0 EXE SHA 为 `7b10531dccc7cd614ae559f36f1ef518e0c96335637431b4646354823b2804d0`,4,047 文件清单 SHA 为 `e459adf2f12adb6a1b7f55e66a9da1c22794185e66e848057d21e0c60d669203`。离线重审逐个核对实际复制文件,以及 WindTerm/Qt5Core/Qt5Gui/Qt5Widgets 四个原件和副本的完整 SHA;运行时实际模块路径与固定导出 RVA 守卫通过。 +- 独立 WindowStation/Desktop、OwnedJob、隔离 HOME/profile、单个合成 loopback Telnet 会话。没有操作用户输入桌面、个人剪贴板或 DPI。Telnet 直达终端观察不代表 WinPTY/ConPTY local-shell 合同。 + +REA Evidence ID 为 `ev_931e2e152246d132fdf497ec9f4180843ef6244beb4cc9c1ec2fb6e19805326f`。源、模块、输入、白名单标量、histogram/有序签名和原件 SHA 见[脱敏结果](../../research/ui/results/2026-10-29-raster-raw-reference/validation.json)。 + +## 五阶段实际观察 + +| 阶段 | DSR 回复 | isAltScreen / isMainScreen | P caret / anchor | selectionText type / length | 完整 H/space 组数 | +|---|---|---|---|---|---| +| 0 D0/M0 双 H | `(4,9)` | false / true | 19 / 19 | string / 10 | 4 | +| 1 A0 与同帧正控 | `(1,19)` | true / false | 38 / 38 | string / 20 | 3 | +| 2 A1 S2 双 H | `(4,11)` | true / false | 51 / 51 | string / 12 | 2 | +| 3 A2 与同帧正控 | `(1,26)` | true / false | 45 / 45 | string / 27 | 4 | +| 4 M1 与同帧正控 | `(4,35)` | false / true | 45 / 45 | string / 36 | 4 | + +五条 DSR 回复均为无 `?` 前缀的 `CSI row;column R`,没有额外应用字节。逐条完整 NAWS 事件为 `91×24 → 91×25`,冻结事件数 2,冻结后未观察到变化;终端 API capacity 为 25。五个 ack 文件内容均为 `captured`,只在完整读取该阶段所有 ROI 并完成 image→pixmap 析构后释放下一阶段。所有 `capture_valid=true`,不是颜色分类通过标志。 + +五次选择端点都是已知、相等、有限非负安全整数;`selectionText` 仅保留 type/length。每个 marker 的完整 token、ordinal/group/sample 和位置独立核对,未将 `M1S1` 等前缀绑定为 `M1`。H/space 与实际 caret 占用均不相交,零宽 caret 按至少一个逻辑像素检查。 + +五张图均为 `888×451`,QPixmap/QImage DPR 均为 1,inclusive grab QRect 为 `[0,0,887,450]`。每个 H 和 space 均为 `8×18`,各有 144 个 uint32 QRgb;合计 34 个数组、4,896 个采样值。Qt 的 QPixmap/QImage 各分配 32B、不预构造,正常返回后每阶段均按 image→pixmap 普通析构。真实 `QImage::isNull` 原值为整数 `0`,公开保留精确原值/类型并规范为 false。 + +## 输出签名事实与未知 + +phase0 的 D0 两组完整 H/space 签名相同,S1 两组也相同,D0 与 S1 可区分。phase2 两个 H 的完整有序签名也相同:其 space 为单一背景 `[138,110,201,255]`,H 中 `[137,110,201,255]` 与 `[138,120,137,255]` 各 16 个样本并列最高;两组均为 `dominant-ink-ambiguous`、`dominant_ink_rgba=null`,保留所有候选、频数和 histogram,没有选定一种颜色。 + +| 目标 | 同帧显式正控 | 完整 H/space 有序签名结果 | +|---|---|---| +| phase1 A0,首次 `1049h` 后原样写入 | S1、D0 | 唯一匹配 D0 (`SGR0`) | +| phase3 A2,重复 `1049h` 后原样写入 | D0、S1、S2 | 唯一匹配 D0 (`SGR0`) | +| phase4 M1,`1049l` 后原样写入 | S1、S2、D0 | 唯一匹配 S1 (`SGR31;44`) | + +匹配只陈述这几个合成 H/space 的局部输出事实。没有读取内部 pen、完整 current_style、非颜色属性或全部 active grid;不据此声称 reset、完整屏幕清空、局部滚动区域、resize、WinPTY/ConPTY local-shell、实际 presented 或性能等价已验证。主要墨迹并列与完整 raw 采集同时成立,不能将 `raw_capture_complete` 改称五阶段样式对齐通过。 + +## 离线审计与回收 + +原始 CLI 真正结束、exit=0 后才导出,stderr 为空,REA 无脚本错误、消息截断或清理错误;provider subject/environment 仍为 null。Job 为 `active=0,total=3,terminated=0`,profile 保持唯一合成会话。启动器主动结束原版,Job0 不证明自然 GUI 退出。REA capture 为 45 秒、CLI wait 为 60 秒,原版在单独 2 秒等待前已启动,后续还有清理;整程上限未知,不提供计时结论。 + +普通和 `python -O` 对同一真实原件的公开出口逐字节相同,SHA 为 `a93b34233806fe3f32bf5fe70a0a5953ad43156d0a574cb79677784e9f3b9cca`,公开 validation 原样保留该出口。独立审计不调用现有分析器:从原消息核对五阶段/最终结果,重建实际注入脚本(含 Windows 写入换行),逐一重算 34 个数组的 histogram、有序 SHA、尺寸和数量,并以完整数组直接比较同帧正控;另核对源/模块/包、plan/attempt、DSR、ack、NAWS、marker/端点/caret/DPR/边界、构造析构和回收,结果一致。 + +将 main `4f34146ab81f5b156537b080df2156f484793cc4` 合入交付分支后,七个生产源、false proposal、旧批公开原记录与实际执行身份保持不变;独立离线审计再次通过,Debug 配置的 CTest `windterm_raster_style_reference`、`windterm_raster_selection_proposal`、`windterm_raster_raw_proposal` 为 3/3。只运行合成/离线测试,没有重新启动原版;这些测试不增加原版样本数。 + +原始 ROI 像素、日志、路径、PID、复制资源和 profile 留在唯一私有目录 `local/r129-raw-capture-v1-0`;公开仅有合成输入、审计后的颜色/尺寸/频数标量及哈希。[旧 #126 的 0 grab 停止](windterm-1049-raster-reference-2026-10-28.md)、[旧 #129 的 3 grab partial](windterm-raster-selection-reference-2026-10-29.md)、旧 false proposal 和原件均未改写;旧批第二个 H 与 phase3/4 的缺口没有补造或与本批拼接。本批不关闭 #129、#126、#123、#27 或 R2。 diff --git a/research/ui/export_raster_raw_reference.py b/research/ui/export_raster_raw_reference.py new file mode 100644 index 00000000..a8555719 --- /dev/null +++ b/research/ui/export_raster_raw_reference.py @@ -0,0 +1,109 @@ +"""Independent raw-capture-v1 publication gate; color ambiguity never means capture failure.""" +from __future__ import annotations +import argparse +import hashlib +import json +from pathlib import Path +import re +import sys + +ROOT=Path(__file__).resolve().parents[2] +sys.path.insert(0,str(ROOT)) +from research.ui.raster_raw_reference import MODULE_SHA256,SOURCE_FILES,MANIFEST_SHA256,phases +from research.ui.raster_raw_analysis import audit_capture,frame_comparisons,require + +SYNTHETIC_LINE=re.compile(r" *(?:(?:D0 H H|M0 H H|A0 H|A0S1 H|A0D0 H|A1 H H|A2 H|A2D0 H|A2S1 H|A2S2 H|M1 H|M1S1 H|M1S2 H|M1D0 H) *)*") +REASONS={None, + "selection-endpoints-unavailable","selection-not-collapsed", + "pinned-module-path","pinned-export-rva","invalid-marker-rectangle","noninteger-roi-boundary","roi-out-of-bounds", + "owned-viewport-ambiguous","viewport-dimensions","mode-getters-unavailable","marker-binding-ambiguous","extra-grab-for-phase","pixmap-return-address","image-return-address","empty-image", + "dpr-inconsistent","image-viewport-dpr-inconsistent","caret-location-unknown","marker-text-mismatch","caret-overlaps-roi","h-space-size-inconsistent","h-space-adjacency-inconsistent","native-or-observation-error", + "object-destruction-failed","first-run-guard","scenario-deadline","peer-failed","driver-observation-error","bounded-observation-timer"} + + +def export(directory,plan_path,destination): + sha=lambda path:hashlib.sha256(path.read_bytes()).hexdigest() + read=lambda name:json.loads((directory/name).read_text(encoding="utf-8")) + plan=json.loads(plan_path.read_text(encoding="utf-8")) + run,peer,captured=read("run.json"),read("peer.json"),read("raster-raw-result.json") + outer=read("evidence.json");evidence=outer["data"]["evidence"];normalized=evidence["normalized_result"] + require(plan["issue"]==129 and plan.get("case_id")=="raw-capture-v1" and plan.get('execution_authorized') is True and plan["maximum_original_runs"]==1 and plan["phase_count"]==5,"Plan scope or execution authorization differs") + require(plan["maximum_grabs_per_phase"]==1 and plan["maximum_grabs"]==5 and re.fullmatch(r"[0-9a-f]{40}",plan["source_base_commit"]),"Plan capture/source bound differs") + require(plan["rea_capture_seconds"]==45 and plan["cli_wait_timeout_seconds"]==60 and plan["whole_lifecycle_bound_seconds"] is None,"Plan duration differs") + require(plan["module_sha256"]==MODULE_SHA256 and plan["files_manifest_sha256"]==MANIFEST_SHA256,"Module/package plan identity differs") + require(run["sha256"]==MODULE_SHA256["WindTerm.exe"] and run["files_sha256"]==MANIFEST_SHA256,"Observed package identity differs") + require(set(plan["source_files_sha256"])==set(SOURCE_FILES),"Executed source inventory differs") + require(all(sha(ROOT/name)==expected for name,expected in plan["source_files_sha256"].items()),"Executed source changed") + require(normalized["source_sha256"]==run["script_sha256"]==sha(directory/"probe.js"),"Injected source differs") + require(outer["ok"] and not outer["data"]["cleanup_error"] and not normalized["cleanup_error"] and not normalized["messages_truncated"],"Capture incomplete or cleanup failed") + require(not any(message["type"]=="error" for message in normalized["messages"]),"Provider script error") + require(evidence["provider"]=={"id":"frida","name":"Frida","version":None} and evidence["confidence"]=="observed" and evidence["subject"] is None and evidence["environment"] is None,"Provider identity differs") + require(re.fullmatch(r"ev_[0-9a-f]{64}",evidence["evidence_id"]),"Provider evidence identity differs") + require(all(value in {"Artifact identity is unavailable for this observation.","The target operating system and architecture were not reported by this observation."} for value in evidence["limitations"]),"Unexpected provider limitation text") + messages=[message["payload"] for message in normalized["messages"] if message["type"]=="send" and isinstance(message.get("payload"),dict)] + captured_phases=[{key:value for key,value in message.items() if key!="kind"} for message in messages if message.get("kind")=="raw_raster_phase"] + finals=[{key:value for key,value in message.items() if key!="kind"} for message in messages if message.get("kind")=="raw_raster_result"] + require(captured_phases==captured["captures"] and finals==[captured],"Private captures differ from provider messages") + require(captured["status"] in ("captured-five-raw-raster-phases","partial-raw-raster-capture") and captured["reason"] in REASONS,"Unknown capture status/reason") + guards=captured["module_guards"] + require({guard["name"] for guard in guards}==set(MODULE_SHA256) and len(guards)==4 and all(guard=={"name":guard["name"],"path_guard_passed":True} for guard in guards),"Runtime module path guard failed") + count=len(captured_phases);require(0<=count<=5,"Too many captures") + expected=phases(*reversed(peer["frozen_grid"])) + require(peer["frozen_grid"]==[peer["columns"],peer["rows"]],"Frozen grid changed") + freeze=peer["freeze_event_count"] + require(type(freeze) is int and 0<=freeze<=len(peer["naws_history"])<=64,"NAWS event bound differs") + require(all(grid==peer["frozen_grid"] for grid in peer["naws_history"][freeze:]),"NAWS changed after freeze") + require(all(isinstance(grid,list) and len(grid)==2 and all(type(value) is int and 0=0: + end=at+len(label) + if (at==0 or line[at-1]==' ') and (end==len(line) or line[end]==' '):hits.append((row,at+offset)) + at=line.find(label,at+1) + require(hits==[(marker['document_line'],marker['column'])],'Complete marker token is not bound uniquely') + + +def pixel_summary(pixels): + require(isinstance(pixels,list) and 0=0 and cursor['height']>0,'caret-location-unknown') + occupancy={**cursor,'width':max(1,cursor['width'])} + for logical in (marker['h_rect'],marker['space_rect']): + intersects=logical['x']>>16)&255,(value>>>8)&255,value&255,(value>>>24)&255];} +function requireCollapsedSelection(caret,anchor){must(Number.isSafeInteger(caret)&&Number.isSafeInteger(anchor)&&caret>=0&&anchor>=0,'selection-endpoints-unavailable');must(caret===anchor,'selection-not-collapsed');return true;} +function completeTokenIndices(line,label){var result=[];for(var at=line.indexOf(label);at>=0;at=line.indexOf(label,at+1)){var end=at+label.length;if((at===0||line.charAt(at-1)===' ')&&(end===line.length||line.charAt(end)===' '))result.push(at);}return result;} +function terminalState(index){ + const descriptor=targets[index]||{markers:[]}; + const source=`JSON.stringify((function(){var t=window.activeText;if(!t)return null;var descriptors=${JSON.stringify(descriptor.markers)};${completeTokenIndices.toString()}function get(k){try{var v=typeof t[k]==='function'?t[k]():t[k];return v===undefined?null:v;}catch(e){return null;}}var count=get('visibleLineCount'),lines=[],found=[];if(typeof count==='number'&&count>=0&&count<=200){for(var i=0;i=0?t.visibleRectFromPosition(caret):null};})())`; + const result=evalText(source);return result?JSON.parse(result):null; +} +function overlap(a,b){return a.x=0&&rect.height>0,'caret-location-unknown');return {x:rect.x,y:rect.y,width:Math.max(1,rect.width),height:rect.height};} +function physicalRect(rect,dpr,width,height){ + must(rect&&[rect.x,rect.y,rect.width,rect.height].every(x=>Number.isFinite(x)),'invalid-marker-rectangle'); + const values=[rect.x*dpr,rect.y*dpr,rect.width*dpr,rect.height*dpr]; + must(values.every(Number.isInteger),'noninteger-roi-boundary'); + const [x,y,w,h]=values;must(w>0&&h>0&&w*h<=8192&&x>=0&&y>=0&&x+w<=width&&y+h<=height,'roi-out-of-bounds');return [x,y,w,h]; +} +function readRoi(image,rectangle){const [x,y,w,h]=rectangle,pixels=[];for(let row=y;row>>0);return pixels;} +function sampleViewport(index,terminal,cursor){ + const capture={phase:index,label:targets[index].label,cursor_reply:cursor,terminal,grab_attempted:false,module_guards:moduleGuards,image:null,rois:[],constructed:[],destroyed:[],capture_valid:null,reason:null}; + const pixmap=Memory.alloc(32),image=Memory.alloc(32);let pixmapReady=false,imageReady=false; + try{ + scan();const candidates=cached.filter(row=>row.name==='qt_scrollarea_viewport'&&row.parent===editor.toString());must(candidates.length===1,'owned-viewport-ambiguous'); + const viewport=ptr(candidates[0].ptr),g=rect(viewport),width=g[2]-g[0]+1,height=g[3]-g[1]+1; + must(width>0&&height>0&&width<=4096&&height<=4096,'viewport-dimensions'); + must(typeof terminal.is_alt==='boolean'&&typeof terminal.is_main==='boolean'&&terminal.is_alt!==terminal.is_main,'mode-getters-unavailable'); + requireCollapsedSelection(terminal.selection_caret,terminal.selection_anchor); + must(terminal.markers.length===targets[index].markers.length,'marker-binding-ambiguous'); + for(let ordinal=0;ordinal0&&ih>0,'empty-image'); + must(Number.isFinite(pdpr)&&pdpr>0&&pdpr<=4&&pdpr===idpr,'dpr-inconsistent'); + must(Number.isInteger(width*pdpr)&&Number.isInteger(height*pdpr)&&iw===width*pdpr&&ih===height*pdpr,'image-viewport-dpr-inconsistent'); + const caret=caretOccupancy(terminal.caret_rect); + for(const marker of terminal.markers){ + must(marker.character==='H'&&marker.preceding_character===' ','marker-text-mismatch'); + must(!overlap(marker.h_rect,caret)&&!overlap(marker.space_rect,caret),'caret-overlaps-roi'); + const hRect=physicalRect(marker.h_rect,pdpr,iw,ih),spaceRect=physicalRect(marker.space_rect,pdpr,iw,ih); + must(hRect[2]===spaceRect[2]&&hRect[3]===spaceRect[3],'h-space-size-inconsistent'); + must(hRect[1]===spaceRect[1]&&spaceRect[0]+spaceRect[2]===hRect[0],'h-space-adjacency-inconsistent'); + const hPixels=readRoi(image,hRect),spacePixels=readRoi(image,spaceRect); + const record={ordinal:marker.ordinal,group:marker.group,sample:marker.sample,h_rect:hRect,space_rect:spaceRect,h_pixels:hPixels,space_pixels:spacePixels};capture.rois.push(record); + } + capture.capture_valid=true; + }catch(error){capture.capture_valid=false;capture.reason=error.code||'native-or-observation-error';capture.private_error=String(error);} + finally{ + for(const object of [{ready:imageReady,name:'image',value:image,destroy:destroyImage},{ready:pixmapReady,name:'pixmap',value:pixmap,destroy:destroyPixmap}]){ + if(object.ready)try{object.destroy(object.value);capture.destroyed.push(object.name);} + catch(error){capture.capture_valid=false;capture.reason='object-destruction-failed';capture.private_error=String(error);} + } + } + return capture; +} +function finish(status,reason){ + if(finished)return;finished=true; + const result={status,reason:reason||null,captures,grab_phases:grabs,module_guards:moduleGuards,presented_done:null}; + const file=new File(__RUN_DIRECTORY_JSON__+'/raster-raw-result.json','w');file.write(JSON.stringify(result));file.close();send({kind:'raw_raster_result',...result}); +} +send({kind:'probe_ready',station_isolated:true,scenario:'five-stage-raw-raster-capture-v1',module_guards:moduleGuards}); +Interceptor.attach(user.getExportByName('DispatchMessageW'),{onEnter(){ + if(busy||finished||Process.getCurrentThreadId()!==uiThread||Date.now()finish('partial-raw-raster-capture','bounded-observation-timer'),42000); diff --git a/research/ui/raster_raw_reference.py b/research/ui/raster_raw_reference.py new file mode 100644 index 00000000..efba9953 --- /dev/null +++ b/research/ui/raster_raw_reference.py @@ -0,0 +1,120 @@ +"""Independent raw-capture-v1; classification is offline and never advances the source.""" +from __future__ import annotations +import argparse +import hashlib +import json +from pathlib import Path +import subprocess +import sys + +ROOT=Path(__file__).resolve().parents[2] +sys.path.insert(0,str(ROOT)) +from research.ui.alternate_style_reference import peer_class, require + +MODULE_SHA256={ + "WindTerm.exe":"7b10531dccc7cd614ae559f36f1ef518e0c96335637431b4646354823b2804d0", + "Qt5Core.dll":"8d2ff4ce9096ddccc4f4cd62c2e41fc854cfd1b0d6e8d296645a7f5fd4ae565a", + "Qt5Gui.dll":"5e7d2d41b8b92a880e83b8cc0ca173f5da61218604186196787ee1600956be1e", + "Qt5Widgets.dll":"3788c669d4b645e5a576de9fc77fca776bf516d43c89143dc2ca28291ba14358", +} +SOURCE_FILES=("research/ui/raster_raw_reference.py","research/ui/raster_raw_reference.js","research/ui/alternate_style_reference.py","research/ui/alternate_reference.py","research/ui/r1_launch.py","research/ui/launch.py","research/ui/qt_r1_text.js") +MANIFEST_SHA256="e459adf2f12adb6a1b7f55e66a9da1c22794185e66e848057d21e0c60d669203" + + +def phases(rows,columns): + require(10<=rows<=60 and 40<=columns<=160,"Controlled grid out of bounds") + return [ + ("default-and-main-calibration",b"\x1b[0m\x1b[2J\x1b[H\x1b[2;3HD0 H H\x1b[4;3H\x1b[31;44mM0 H H"), + ("alternate-entry-with-controls",b"\x1b[?1049hA0 H\x1b[31;44m A0S1 H\x1b[0m A0D0 H"), + ("alternate-reference",b"\x1b[4;5H\x1b[32;45mA1 H H"), + ("alternate-repeat-with-controls",b"\x1b[?1049hA2 H\x1b[0m A2D0 H\x1b[31;44m A2S1 H\x1b[32;45m A2S2 H"), + ("main-return-with-controls",b"\x1b[?1049l M1 H\x1b[31;44m M1S1 H\x1b[32;45m M1S2 H\x1b[0m M1D0 H"), + ] + + +_BasePeer=peer_class() +_BasePeer._serve.__globals__["phases"]=phases + + +class Peer(_BasePeer): + def _record(self): + if self.state.get("frozen_grid") and "freeze_event_count" not in self.state: + self.state["freeze_event_count"]=len(self.state.get("naws_history",[])) + super()._record() + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def check_full_hashes(directory,identities=MODULE_SHA256): + measured={name:sha(directory/name) for name in identities} + require(measured==identities,"Pinned executable or Qt DLL full hash differs") + return measured + + +def prepare_plan(source,out,rea,destination,execution_authorized=False): + source,out,rea,destination=[path.resolve() for path in (source,out,rea,destination)] + require(not out.exists() and not destination.exists(),"Plan/output must be new") + require(out.is_relative_to(ROOT/"local") and destination.is_relative_to(ROOT/"local"),"Plan/output must belong to this worktree local directory") + require(rea.is_file(),"Locked REA CLI is missing") + package=rea.parent.parent/"rea-agents/package.json" + require(json.loads(package.read_text(encoding="utf-8"))["version"]=="6.7.0","REA version differs") + measured=check_full_hashes(source) + plan={"schema":"termforge-raster-raw-plan-v1","issue":129,"case_id":"raw-capture-v1","maximum_original_runs":1,"execution_authorized":execution_authorized, + "source_base_commit":subprocess.check_output(["git","rev-parse","HEAD"],cwd=ROOT,text=True).strip(), + "source":str(source),"out":str(out),"rea":str(rea),"module_sha256":measured,"files_manifest_sha256":MANIFEST_SHA256, + "rea_capture_seconds":45,"cli_wait_timeout_seconds":60,"whole_lifecycle_bound_seconds":None, + "source_files_sha256":{name:sha(ROOT/name) for name in SOURCE_FILES}, + "phases":[{"phase":index,"label":label,"source_hex":content.hex(),"source_bytes":len(content),"source_sha256":hashlib.sha256(content).hexdigest(),"dsr_suffix_hex":"1b5b366e"} for index,(label,content) in enumerate(phases(25,91))], + "phase_count":5,"maximum_grabs_per_phase":1,"maximum_grabs":5, + "scope":"Five-stage raw H/space capture before offline histogram/signature analysis; no internal pen, presented or performance claim", + "selection_guard":"Known nonnegative safe-integer selectionCaretP equals selectionAnchorP; selectionText is retained only as type/length", + "stop":"Structure, identity, empty image, DPR/coordinates, endpoints or caret failure stops; color ties, nonuniform backgrounds and missing ink stay offline unknown and do not stop the next phase; no shifted ROI, extra grab or retry"} + destination.parent.mkdir(parents=True,exist_ok=True) + destination.write_text(json.dumps(plan,indent=2)+"\n",encoding="utf-8",newline="\n") + print(json.dumps({"prepared":True,"phase_count":5,"maximum_original_runs":1,"plan":destination.as_posix()})) + + +def run_plan(plan_path): + plan_path=plan_path.resolve() + plan=json.loads(plan_path.read_text(encoding="utf-8")) + require(plan["issue"]==129 and plan.get("case_id")=="raw-capture-v1" and plan["maximum_original_runs"]==1,"Unexpected raster plan") + require(plan.get("execution_authorized") is True,"Offline proposal only; new original execution has not been authorized") + require(plan["source_base_commit"]==subprocess.check_output(["git","rev-parse","HEAD"],cwd=ROOT,text=True).strip(),"Source commit changed after plan") + require(plan["module_sha256"]==MODULE_SHA256,"Plan module identity differs") + require(plan["source_files_sha256"]=={name:sha(ROOT/name) for name in SOURCE_FILES},"Probe source changed after plan") + require(plan["phases"]==[{"phase":index,"label":label,"source_hex":content.hex(),"source_bytes":len(content),"source_sha256":hashlib.sha256(content).hexdigest(),"dsr_suffix_hex":"1b5b366e"} for index,(label,content) in enumerate(phases(25,91))],"Plan source differs") + source,out,rea=[Path(plan[key]) for key in ("source","out","rea")] + check_full_hashes(source) + require(not out.exists(),"This run output already exists") + # Exclusive marker is deliberately retained after every attempted launch. + with plan_path.with_suffix(".attempted").open("x",encoding="utf-8") as marker: + marker.write("One authorized original launch attempt; never retry this plan.\n") + from research.ui import r1_launch + launcher=Path(r1_launch.__file__) + code=launcher.read_text(encoding="utf-8") + replacements={"from research.ui.r1_vt_fixture import Peer":"from research.ui.raster_raw_reference import Peer", + 'Path(__file__).with_name("r1_menu_wrap.js").read_text(encoding="utf-8")':'Path(__file__).with_name("raster_raw_reference.js").read_text(encoding="utf-8")'} + for old,new in replacements.items(): + require(code.count(old)==1,"Protected launcher source changed") + code=code.replace(old,new) + namespace={"__file__":str(launcher),"__name__":"termforge_raster_launcher"} + exec(compile(code,str(launcher),"exec"),namespace) + namespace["run"](source,out,rea,45,False,"menu-wrap") + + +if __name__=="__main__": + parser=argparse.ArgumentParser() + parser.add_argument("--plan",type=Path,required=True) + parser.add_argument("--prepare",action="store_true") + parser.add_argument("--authorize-execution",action="store_true",help="Use only after a separate explicit authorization of this new run") + parser.add_argument("--source",type=Path) + parser.add_argument("--out",type=Path) + parser.add_argument("--rea",type=Path) + args=parser.parse_args() + if args.prepare: + require(args.source and args.out and args.rea,"Source/output/REA required") + prepare_plan(args.source,args.out,args.rea,args.plan,args.authorize_execution) + else: + run_plan(args.plan) diff --git a/research/ui/replay_raster_raw_tie.py b/research/ui/replay_raster_raw_tie.py new file mode 100644 index 00000000..3431e280 --- /dev/null +++ b/research/ui/replay_raster_raw_tie.py @@ -0,0 +1,49 @@ +"""Re-analyze fixed #129 private ROI samples without inventing uncaptured cells.""" +from __future__ import annotations +import argparse +import hashlib +import json +from pathlib import Path +import sys + +ROOT=Path(__file__).resolve().parents[2] +sys.path.insert(0,str(ROOT)) +from research.ui.raster_raw_analysis import classify_pixels,compare_frame,raw_signature,require + +RAW_SHA256='3887faaa8d055f42388eafc4b0a9ee2e2b8111d3fa1384e07ec5f0a50585f34d' +EVIDENCE_ID='ev_432abe8baf4fc86efd4994cd12cc3ab5fe0b5120476d22540c5b26e2e3c693a4' + + +def replay(raw,evidence_path,destination): + sha=lambda path:hashlib.sha256(path.read_bytes()).hexdigest() + require(sha(raw)==RAW_SHA256,'Original partial record differs') + original=json.loads(raw.read_text(encoding='utf-8')) + evidence=json.loads(evidence_path.read_text(encoding='utf-8'))['data']['evidence'] + require(evidence['evidence_id']==EVIDENCE_ID,'Evidence identity differs') + finals=[row['payload'] for row in evidence['normalized_result']['messages'] if row['type']=='send' and isinstance(row.get('payload'),dict) and row['payload'].get('kind')=='raster_result'] + require([{key:value for key,value in row.items() if key!='kind'} for row in finals]==[original],'Evidence and fixed raw differ') + require(original['status']=='partial-raster-observation' and original['reason']=='dominant-ink-ambiguous' and original['grab_phases']==[0,1,2],'Original stop differs') + stopped=original['captures'][2] + require(stopped['calibration'] is False and len(stopped['rois'])==1 and len(stopped['terminal']['markers'])==2,'Uncaptured second ROI must stay missing') + def summarize(roi): + value={key:roi[key] for key in ('ordinal','group','sample','h_rect','space_rect')} + value.update(classify_pixels(roi['h_pixels'],roi['space_pixels'])) + value['raw_signature']=raw_signature(value) + return value + tied=summarize(stopped['rois'][0]) + require(tied['status']=='dominant-ink-ambiguous' and [row['count'] for row in tied['dominant_ink_candidates']]==[16,16],'Fixed ambiguity changed') + entry=[summarize(roi) for roi in original['captures'][1]['rois']] + summary={'schema':'termforge-raster-raw-offline-replay-v1','case_id':'raw-capture-v1','new_original_runs':0, + 'analysis_sha256':sha(ROOT/'research/ui/raster_raw_analysis.py'),'analysis_helpers_sha256':sha(ROOT/'research/ui/raster_selection_analysis.py'),'replay_source_sha256':sha(Path(__file__)), + 'source_evidence_id':EVIDENCE_ID,'source_raw_sha256':RAW_SHA256,'source_evidence_sha256':sha(evidence_path), + 'source_production_commit':'e302fa3acb6a2ed2982aad5550e027d37c772da6','original_status':original['status'],'original_reason':original['reason'], + 'original_grab_phases':[0,1,2],'original_phase2_rois_captured':1,'original_phase2_markers':2,'missing_rois_fabricated':False,'new_capture_inferred':False, + 'phase2_observed_first_roi':tied,'phase1_same_frame_raw_signature_comparison':compare_frame(entry), + 'limitation':'Offline replay only. It cannot recover the uncaptured second H or unsent phases3/4, and does not reclassify the original batch as complete.'} + destination.parent.mkdir(parents=True,exist_ok=True) + destination.write_text(json.dumps(summary,indent=2)+'\n',encoding='utf-8',newline='\n') + print(json.dumps({'replayed':True,'new_original_runs':0,'phase2_candidates':tied['dominant_ink_candidates'],'phase1_unique_control':summary['phase1_same_frame_raw_signature_comparison']['unique_control']})) + + +if __name__=='__main__': + parser=argparse.ArgumentParser();parser.add_argument('--raw',type=Path,required=True);parser.add_argument('--evidence',type=Path,required=True);parser.add_argument('--destination',type=Path,required=True);args=parser.parse_args();replay(args.raw,args.evidence,args.destination) diff --git a/research/ui/results/2026-10-29-raster-raw-proposal/plan.json b/research/ui/results/2026-10-29-raster-raw-proposal/plan.json new file mode 100644 index 00000000..6b300e70 --- /dev/null +++ b/research/ui/results/2026-10-29-raster-raw-proposal/plan.json @@ -0,0 +1,84 @@ +{ + "schema": "termforge-raster-raw-plan-v1", + "issue": 129, + "case_id": "raw-capture-v1", + "maximum_original_runs": 1, + "execution_authorized": false, + "source_base_commit": "f6d9a97e2b2685b6ce39c83dc7107cb52aec7a6a", + "module_sha256": { + "WindTerm.exe": "7b10531dccc7cd614ae559f36f1ef518e0c96335637431b4646354823b2804d0", + "Qt5Core.dll": "8d2ff4ce9096ddccc4f4cd62c2e41fc854cfd1b0d6e8d296645a7f5fd4ae565a", + "Qt5Gui.dll": "5e7d2d41b8b92a880e83b8cc0ca173f5da61218604186196787ee1600956be1e", + "Qt5Widgets.dll": "3788c669d4b645e5a576de9fc77fca776bf516d43c89143dc2ca28291ba14358" + }, + "files_manifest_sha256": "e459adf2f12adb6a1b7f55e66a9da1c22794185e66e848057d21e0c60d669203", + "rea_capture_seconds": 45, + "cli_wait_timeout_seconds": 60, + "whole_lifecycle_bound_seconds": null, + "source_files_sha256": { + "research/ui/raster_raw_reference.py": "942902683fac816aa4271faaab31b01505aaab8ea6624f131f272e03a4548824", + "research/ui/raster_raw_reference.js": "bc427feb65650b1f90e6f882af405bbc88f93d1df2e2e249fb7960a90696869e", + "research/ui/alternate_style_reference.py": "3136e620a462a36ea3358c917eb4e207f32aa52db7c75ae14ba8856eba1eafcd", + "research/ui/alternate_reference.py": "94b85d49347e0e9813f7acddf0244f58520a7d1fce14084677c91cf4ddafffea", + "research/ui/r1_launch.py": "54fb41872c6abcc48242a0938044184854b016785cc13659c66b1bf404da0d8a", + "research/ui/launch.py": "6970e0d4f2fe5e7ec4827df7aa1026cd0e74aeb828cdc9b7a0b42b3c887eb4e6", + "research/ui/qt_r1_text.js": "f5820d413fdd72c13dffcefbf4d0ade615abfe15754c6b0b52e1e098814eea6f" + }, + "phases": [ + { + "phase": 0, + "label": "default-and-main-calibration", + "source_hex": "1b5b306d1b5b324a1b5b481b5b323b33484430204820481b5b343b33481b5b33313b34346d4d3020482048", + "source_bytes": 43, + "source_sha256": "0ef069f3327716b0cb410680ca441980b3b455ed102dfb666fd8b72f249ae610", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 1, + "label": "alternate-entry-with-controls", + "source_hex": "1b5b3f3130343968413020481b5b33313b34346d204130533120481b5b306d20413044302048", + "source_bytes": 38, + "source_sha256": "6415951f7219de9f93387c4060307fee943fd4c0549513fff788400936d8a895", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 2, + "label": "alternate-reference", + "source_hex": "1b5b343b35481b5b33323b34356d413120482048", + "source_bytes": 20, + "source_sha256": "ecd2495dd89fe551626069c64fec582eaac774bee29c4100a42ef159dd7009ff", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 3, + "label": "alternate-repeat-with-controls", + "source_hex": "1b5b3f3130343968413220481b5b306d204132443020481b5b33313b34346d204132533120481b5b33323b34356d20413253322048", + "source_bytes": 53, + "source_sha256": "b33165a1da96062941d0f73e09f76c69726b67c14c8098d885b1804472610d7d", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 4, + "label": "main-return-with-controls", + "source_hex": "1b5b3f313034396c204d3120481b5b33313b34346d204d31533120481b5b33323b34356d204d31533220481b5b306d204d3144302048", + "source_bytes": 54, + "source_sha256": "11af8a2f9cede6def3a9fbeadc169683ca321dcf5e34539cc06a9b438bde5574", + "dsr_suffix_hex": "1b5b366e" + } + ], + "phase_count": 5, + "maximum_grabs_per_phase": 1, + "maximum_grabs": 5, + "scope": "Five-stage raw H/space capture before offline histogram/signature analysis; no internal pen, presented or performance claim", + "selection_guard": "Known nonnegative safe-integer selectionCaretP equals selectionAnchorP; selectionText is retained only as type/length", + "stop": "Structure, identity, empty image, DPR/coordinates, endpoints or caret failure stops; color ties, nonuniform backgrounds and missing ink stay offline unknown and do not stop the next phase; no shifted ROI, extra grab or retry", + "actual_original_runs": 0, + "production_source_commit": "f6d9a97e2b2685b6ce39c83dc7107cb52aec7a6a", + "private_plan_sha256": "52229884e5279600c091bcd26bff32c5b7f6dd0e2b8a87ffbc195889c4aa94af", + "analysis_files_sha256": { + "research/ui/raster_raw_analysis.py": "019d2c2616ac3942160da19289c7d4ee0fa7560dcd3c6d27f732cf724da98e50", + "research/ui/export_raster_raw_reference.py": "581b034eb18944e91e4cc07b23702e224e62939c4616686a15430eca0959261a", + "research/ui/replay_raster_raw_tie.py": "3a96884728cf4bc822574f26fc70c8dc40f9d794dbfc7d366015410773b81b9f", + "research/ui/raster_selection_analysis.py": "745cda14921a383ca9baf6ec85242982ca587396b8464a3d27047ecf204a8845" + } +} diff --git a/research/ui/results/2026-10-29-raster-raw-proposal/replay.json b/research/ui/results/2026-10-29-raster-raw-proposal/replay.json new file mode 100644 index 00000000..c81d2d11 --- /dev/null +++ b/research/ui/results/2026-10-29-raster-raw-proposal/replay.json @@ -0,0 +1,237 @@ +{ + "schema": "termforge-raster-raw-offline-replay-v1", + "case_id": "raw-capture-v1", + "new_original_runs": 0, + "analysis_sha256": "019d2c2616ac3942160da19289c7d4ee0fa7560dcd3c6d27f732cf724da98e50", + "analysis_helpers_sha256": "745cda14921a383ca9baf6ec85242982ca587396b8464a3d27047ecf204a8845", + "replay_source_sha256": "3a96884728cf4bc822574f26fc70c8dc40f9d794dbfc7d366015410773b81b9f", + "source_evidence_id": "ev_432abe8baf4fc86efd4994cd12cc3ab5fe0b5120476d22540c5b26e2e3c693a4", + "source_raw_sha256": "3887faaa8d055f42388eafc4b0a9ee2e2b8111d3fa1384e07ec5f0a50585f34d", + "source_evidence_sha256": "8004b69182f5fa9caf0b4c51acb9a179bf353cab27885d016cd98c7356536d5e", + "source_production_commit": "e302fa3acb6a2ed2982aad5550e027d37c772da6", + "original_status": "partial-raster-observation", + "original_reason": "dominant-ink-ambiguous", + "original_grab_phases": [ + 0, + 1, + 2 + ], + "original_phase2_rois_captured": 1, + "original_phase2_markers": 2, + "missing_rois_fabricated": false, + "new_capture_inferred": false, + "phase2_observed_first_roi": { + "ordinal": 0, + "group": "alternate", + "sample": 0, + "h_rect": [ + 203, + 54, + 8, + 18 + ], + "space_rect": [ + 195, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 134, + 165, + 84, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 134, + 165, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 84, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 135, + 165, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 135, + 180, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 180, + 112, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 137, + 120, + 181, + 255 + ], + "count": 3 + }, + { + "rgba": [ + 137, + 120, + 201, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 137, + 131, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ] + }, + "space": { + "samples": 144, + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 138, + 110, + 201, + 255 + ], + "dominant_ink_rgba": null, + "dominant_ink_candidates": [ + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "dominant-ink-ambiguous", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "samples": 144 + } + } + }, + "phase1_same_frame_raw_signature_comparison": { + "matching_controls": [ + "SGR0" + ], + "unique_control": "SGR0", + "result": "unique-raw-match", + "signature": "Exact ordered H and space QRgb SHA-256 plus shapes and sample counts", + "unmatched_does_not_imply_reset": true + }, + "limitation": "Offline replay only. It cannot recover the uncaptured second H or unsent phases3/4, and does not reclassify the original batch as complete." +} diff --git a/research/ui/results/2026-10-29-raster-raw-reference/plan.json b/research/ui/results/2026-10-29-raster-raw-reference/plan.json new file mode 100644 index 00000000..b2eebe87 --- /dev/null +++ b/research/ui/results/2026-10-29-raster-raw-reference/plan.json @@ -0,0 +1,85 @@ +{ + "schema": "termforge-raster-raw-plan-v1", + "issue": 129, + "case_id": "raw-capture-v1", + "maximum_original_runs": 1, + "execution_authorized": true, + "source_base_commit": "46f90d89e5b80b96989861f437b4b10e75ccb199", + "module_sha256": { + "WindTerm.exe": "7b10531dccc7cd614ae559f36f1ef518e0c96335637431b4646354823b2804d0", + "Qt5Core.dll": "8d2ff4ce9096ddccc4f4cd62c2e41fc854cfd1b0d6e8d296645a7f5fd4ae565a", + "Qt5Gui.dll": "5e7d2d41b8b92a880e83b8cc0ca173f5da61218604186196787ee1600956be1e", + "Qt5Widgets.dll": "3788c669d4b645e5a576de9fc77fca776bf516d43c89143dc2ca28291ba14358" + }, + "files_manifest_sha256": "e459adf2f12adb6a1b7f55e66a9da1c22794185e66e848057d21e0c60d669203", + "rea_capture_seconds": 45, + "cli_wait_timeout_seconds": 60, + "whole_lifecycle_bound_seconds": null, + "source_files_sha256": { + "research/ui/raster_raw_reference.py": "942902683fac816aa4271faaab31b01505aaab8ea6624f131f272e03a4548824", + "research/ui/raster_raw_reference.js": "bc427feb65650b1f90e6f882af405bbc88f93d1df2e2e249fb7960a90696869e", + "research/ui/alternate_style_reference.py": "3136e620a462a36ea3358c917eb4e207f32aa52db7c75ae14ba8856eba1eafcd", + "research/ui/alternate_reference.py": "94b85d49347e0e9813f7acddf0244f58520a7d1fce14084677c91cf4ddafffea", + "research/ui/r1_launch.py": "54fb41872c6abcc48242a0938044184854b016785cc13659c66b1bf404da0d8a", + "research/ui/launch.py": "6970e0d4f2fe5e7ec4827df7aa1026cd0e74aeb828cdc9b7a0b42b3c887eb4e6", + "research/ui/qt_r1_text.js": "f5820d413fdd72c13dffcefbf4d0ade615abfe15754c6b0b52e1e098814eea6f" + }, + "phases": [ + { + "phase": 0, + "label": "default-and-main-calibration", + "source_hex": "1b5b306d1b5b324a1b5b481b5b323b33484430204820481b5b343b33481b5b33313b34346d4d3020482048", + "source_bytes": 43, + "source_sha256": "0ef069f3327716b0cb410680ca441980b3b455ed102dfb666fd8b72f249ae610", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 1, + "label": "alternate-entry-with-controls", + "source_hex": "1b5b3f3130343968413020481b5b33313b34346d204130533120481b5b306d20413044302048", + "source_bytes": 38, + "source_sha256": "6415951f7219de9f93387c4060307fee943fd4c0549513fff788400936d8a895", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 2, + "label": "alternate-reference", + "source_hex": "1b5b343b35481b5b33323b34356d413120482048", + "source_bytes": 20, + "source_sha256": "ecd2495dd89fe551626069c64fec582eaac774bee29c4100a42ef159dd7009ff", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 3, + "label": "alternate-repeat-with-controls", + "source_hex": "1b5b3f3130343968413220481b5b306d204132443020481b5b33313b34346d204132533120481b5b33323b34356d20413253322048", + "source_bytes": 53, + "source_sha256": "b33165a1da96062941d0f73e09f76c69726b67c14c8098d885b1804472610d7d", + "dsr_suffix_hex": "1b5b366e" + }, + { + "phase": 4, + "label": "main-return-with-controls", + "source_hex": "1b5b3f313034396c204d3120481b5b33313b34346d204d31533120481b5b33323b34356d204d31533220481b5b306d204d3144302048", + "source_bytes": 54, + "source_sha256": "11af8a2f9cede6def3a9fbeadc169683ca321dcf5e34539cc06a9b438bde5574", + "dsr_suffix_hex": "1b5b366e" + } + ], + "phase_count": 5, + "maximum_grabs_per_phase": 1, + "maximum_grabs": 5, + "scope": "Five-stage raw H/space capture before offline histogram/signature analysis; no internal pen, presented or performance claim", + "selection_guard": "Known nonnegative safe-integer selectionCaretP equals selectionAnchorP; selectionText is retained only as type/length", + "stop": "Structure, identity, empty image, DPR/coordinates, endpoints or caret failure stops; color ties, nonuniform backgrounds and missing ink stay offline unknown and do not stop the next phase; no shifted ROI, extra grab or retry", + "production_source_commit": "f6d9a97e2b2685b6ce39c83dc7107cb52aec7a6a", + "private_plan_sha256": "8dbeaae26ed19c6d8f3c22a16308fdf3b85f1d02a14aaa7e20af96c76405d288", + "actual_original_runs": 1, + "authorization_evidence": "Parent final review explicitly authorized one new original execution after offline preparation; the false proposal is unchanged.", + "analysis_files_sha256": { + "research/ui/raster_raw_analysis.py": "019d2c2616ac3942160da19289c7d4ee0fa7560dcd3c6d27f732cf724da98e50", + "research/ui/export_raster_raw_reference.py": "581b034eb18944e91e4cc07b23702e224e62939c4616686a15430eca0959261a", + "research/ui/replay_raster_raw_tie.py": "3a96884728cf4bc822574f26fc70c8dc40f9d794dbfc7d366015410773b81b9f", + "research/ui/raster_selection_analysis.py": "745cda14921a383ca9baf6ec85242982ca587396b8464a3d27047ecf204a8845" + } +} diff --git a/research/ui/results/2026-10-29-raster-raw-reference/validation.json b/research/ui/results/2026-10-29-raster-raw-reference/validation.json new file mode 100644 index 00000000..539e1d65 --- /dev/null +++ b/research/ui/results/2026-10-29-raster-raw-reference/validation.json @@ -0,0 +1,4102 @@ +{ + "schema": "termforge-original-raster-raw-reference-v1", + "issue": 129, + "case_id": "raw-capture-v1", + "status": "captured-five-raw-raster-phases", + "reason": null, + "scope": "Independent raw-capture-v1; full ROI histograms and ordered signatures, no internal pen or presented claim", + "source_base_commit": "46f90d89e5b80b96989861f437b4b10e75ccb199", + "source_files_sha256": { + "research/ui/raster_raw_reference.py": "942902683fac816aa4271faaab31b01505aaab8ea6624f131f272e03a4548824", + "research/ui/raster_raw_reference.js": "bc427feb65650b1f90e6f882af405bbc88f93d1df2e2e249fb7960a90696869e", + "research/ui/alternate_style_reference.py": "3136e620a462a36ea3358c917eb4e207f32aa52db7c75ae14ba8856eba1eafcd", + "research/ui/alternate_reference.py": "94b85d49347e0e9813f7acddf0244f58520a7d1fce14084677c91cf4ddafffea", + "research/ui/r1_launch.py": "54fb41872c6abcc48242a0938044184854b016785cc13659c66b1bf404da0d8a", + "research/ui/launch.py": "6970e0d4f2fe5e7ec4827df7aa1026cd0e74aeb828cdc9b7a0b42b3c887eb4e6", + "research/ui/qt_r1_text.js": "f5820d413fdd72c13dffcefbf4d0ade615abfe15754c6b0b52e1e098814eea6f" + }, + "exporter_sha256": "581b034eb18944e91e4cc07b23702e224e62939c4616686a15430eca0959261a", + "analysis_sha256": "019d2c2616ac3942160da19289c7d4ee0fa7560dcd3c6d27f732cf724da98e50", + "analysis_helpers_sha256": "745cda14921a383ca9baf6ec85242982ca587396b8464a3d27047ecf204a8845", + "module_sha256": { + "WindTerm.exe": "7b10531dccc7cd614ae559f36f1ef518e0c96335637431b4646354823b2804d0", + "Qt5Core.dll": "8d2ff4ce9096ddccc4f4cd62c2e41fc854cfd1b0d6e8d296645a7f5fd4ae565a", + "Qt5Gui.dll": "5e7d2d41b8b92a880e83b8cc0ca173f5da61218604186196787ee1600956be1e", + "Qt5Widgets.dll": "3788c669d4b645e5a576de9fc77fca776bf516d43c89143dc2ca28291ba14358" + }, + "files_manifest_sha256": "e459adf2f12adb6a1b7f55e66a9da1c22794185e66e848057d21e0c60d669203", + "runtime_module_path_guards": [ + { + "name": "WindTerm.exe", + "path_guard_passed": true + }, + { + "name": "Qt5Core.dll", + "path_guard_passed": true + }, + { + "name": "Qt5Gui.dll", + "path_guard_passed": true + }, + { + "name": "Qt5Widgets.dll", + "path_guard_passed": true + } + ], + "plan_sha256": "8dbeaae26ed19c6d8f3c22a16308fdf3b85f1d02a14aaa7e20af96c76405d288", + "actual_original_runs": 1, + "maximum_original_runs": 1, + "rea_capture_seconds": 45, + "cli_wait_timeout_seconds": 60, + "whole_lifecycle_bound_seconds": null, + "frozen_grid": [ + 91, + 25 + ], + "naws_history": [ + [ + 91, + 24 + ], + [ + 91, + 25 + ] + ], + "freeze_event_count": 2, + "naws_history_scope": "Each complete valid NAWS event parsed by the owned peer, including repeats", + "naws_changed_after_freeze": false, + "planned_phase_count": 5, + "observed_phase_count": 5, + "grab_phases": [ + 0, + 1, + 2, + 3, + 4 + ], + "maximum_grabs_per_phase": 1, + "phases": [ + { + "phase": 0, + "label": "D0/M0 H references", + "cursor_reply": [ + 4, + 9 + ], + "grab_attempted": true, + "constructed": [ + "pixmap", + "image" + ], + "destroyed": [ + "image", + "pixmap" + ], + "capture_valid": true, + "reason": null, + "image": { + "viewport_width": 888, + "viewport_height": 451, + "grab_rect": [ + 0, + 0, + 887, + 450 + ], + "pixmap_dpr": 1, + "image_dpr": 1, + "width": 888, + "height": 451, + "is_null": false, + "is_null_raw_value": 0, + "is_null_raw_type": "number" + }, + "rois": [ + { + "ordinal": 0, + "group": "default", + "sample": 0, + "h_rect": [ + 187, + 18, + 8, + 18 + ], + "space_rect": [ + 179, + 18, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "ce9cc6e26fcac941b9c35983ed687e95365f43a53d335eb86c91d4f815dd1de4", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 28, + 28, + 28, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 28, + 66, + 131, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 66, + 28, + 28, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 66, + 66, + 28, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 66, + 66, + 65, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 66, + 101, + 131, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 101, + 28, + 28, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 101, + 66, + 65, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 204, + 204, + 131, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 204, + 204, + 199, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 204, + 204, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 204, + 248, + 165, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 204, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 204, + 131, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 204, + 199, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "7329cea64ce6dd833ed30b12e595eeab02c1da13962c22ccd99256ba8dcc0e8b", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 28, + 28, + 28, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 28, + 28, + 28, + 255 + ], + "dominant_ink_rgba": [ + 28, + 66, + 131, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 28, + 66, + 131, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "ce9cc6e26fcac941b9c35983ed687e95365f43a53d335eb86c91d4f815dd1de4", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "7329cea64ce6dd833ed30b12e595eeab02c1da13962c22ccd99256ba8dcc0e8b", + "samples": 144 + } + } + }, + { + "ordinal": 1, + "group": "default", + "sample": 1, + "h_rect": [ + 203, + 18, + 8, + 18 + ], + "space_rect": [ + 195, + 18, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "ce9cc6e26fcac941b9c35983ed687e95365f43a53d335eb86c91d4f815dd1de4", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 28, + 28, + 28, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 28, + 66, + 131, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 66, + 28, + 28, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 66, + 66, + 28, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 66, + 66, + 65, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 66, + 101, + 131, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 101, + 28, + 28, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 101, + 66, + 65, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 204, + 204, + 131, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 204, + 204, + 199, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 204, + 204, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 204, + 248, + 165, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 204, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 204, + 131, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 204, + 199, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "7329cea64ce6dd833ed30b12e595eeab02c1da13962c22ccd99256ba8dcc0e8b", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 28, + 28, + 28, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 28, + 28, + 28, + 255 + ], + "dominant_ink_rgba": [ + 28, + 66, + 131, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 28, + 66, + 131, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "ce9cc6e26fcac941b9c35983ed687e95365f43a53d335eb86c91d4f815dd1de4", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "7329cea64ce6dd833ed30b12e595eeab02c1da13962c22ccd99256ba8dcc0e8b", + "samples": 144 + } + } + }, + { + "ordinal": 2, + "group": "main", + "sample": 0, + "h_rect": [ + 187, + 54, + 8, + 18 + ], + "space_rect": [ + 179, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 82, + 86, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 82, + 95, + 159, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 95, + 169, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 104, + 169, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 103, + 95, + 159, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 103, + 104, + 169, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 168, + 38, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 38, + 125, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 168, + 54, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 54, + 112, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 168, + 54, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 196, + 54, + 112, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 196, + 54, + 137, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 61, + 104, + 169, + 255 + ], + "dominant_ink_rgba": [ + 61, + 95, + 137, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "samples": 144 + } + } + }, + { + "ordinal": 3, + "group": "main", + "sample": 1, + "h_rect": [ + 203, + 54, + 8, + 18 + ], + "space_rect": [ + 195, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 82, + 86, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 82, + 95, + 159, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 95, + 169, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 104, + 169, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 103, + 95, + 159, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 103, + 104, + 169, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 168, + 38, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 38, + 125, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 168, + 54, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 54, + 112, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 168, + 54, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 196, + 54, + 112, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 196, + 54, + 137, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 61, + 104, + 169, + 255 + ], + "dominant_ink_rgba": [ + 61, + 95, + 137, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "samples": 144 + } + } + } + ], + "selection": { + "caret": 19, + "anchor": 19, + "text_type": "string", + "text_length": 10 + }, + "source_label": "default-and-main-calibration", + "source_hex": "1b5b306d1b5b324a1b5b481b5b323b33484430204820481b5b343b33481b5b33313b34346d4d3020482048", + "source_sha256": "0ef069f3327716b0cb410680ca441980b3b455ed102dfb666fd8b72f249ae610", + "dsr_request_hex": "1b5b366e", + "cursor_reply_hex": "1b5b343b3952", + "is_alt": false, + "is_main": true + }, + { + "phase": 1, + "label": "A0 H controls", + "cursor_reply": [ + 1, + 19 + ], + "grab_attempted": true, + "constructed": [ + "pixmap", + "image" + ], + "destroyed": [ + "image", + "pixmap" + ], + "capture_valid": true, + "reason": null, + "image": { + "viewport_width": 888, + "viewport_height": 451, + "grab_rect": [ + 0, + 0, + 887, + 450 + ], + "pixmap_dpr": 1, + "image_dpr": 1, + "width": 888, + "height": 451, + "is_null": false, + "is_null_raw_value": 0, + "is_null_raw_type": "number" + }, + "rois": [ + { + "ordinal": 0, + "group": "entry", + "sample": 0, + "h_rect": [ + 171, + 0, + 8, + 18 + ], + "space_rect": [ + 163, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 75, + 40, + 50, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 75, + 75, + 50, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 75, + 81, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 107, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 107, + 40, + 50, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 107, + 75, + 81, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 205, + 140, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 205, + 202, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 205, + 205, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 248, + 171, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 202, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 40, + 40, + 50, + 255 + ], + "dominant_ink_rgba": [ + 40, + 75, + 140, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "samples": 144 + } + } + }, + { + "ordinal": 1, + "group": "control-main", + "sample": 0, + "h_rect": [ + 227, + 0, + 8, + 18 + ], + "space_rect": [ + 219, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 82, + 86, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 82, + 95, + 159, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 95, + 169, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 104, + 169, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 103, + 95, + 159, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 103, + 104, + 169, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 168, + 38, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 38, + 125, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 168, + 54, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 54, + 112, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 168, + 54, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 196, + 54, + 112, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 196, + 54, + 137, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 61, + 104, + 169, + 255 + ], + "dominant_ink_rgba": [ + 61, + 95, + 137, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "samples": 144 + } + } + }, + { + "ordinal": 2, + "group": "control-default", + "sample": 0, + "h_rect": [ + 283, + 0, + 8, + 18 + ], + "space_rect": [ + 275, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 75, + 40, + 50, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 75, + 75, + 50, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 75, + 81, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 107, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 107, + 40, + 50, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 107, + 75, + 81, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 205, + 140, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 205, + 202, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 205, + 205, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 248, + 171, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 202, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 40, + 40, + 50, + 255 + ], + "dominant_ink_rgba": [ + 40, + 75, + 140, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "samples": 144 + } + } + } + ], + "selection": { + "caret": 38, + "anchor": 38, + "text_type": "string", + "text_length": 20 + }, + "source_label": "alternate-entry-with-controls", + "source_hex": "1b5b3f3130343968413020481b5b33313b34346d204130533120481b5b306d20413044302048", + "source_sha256": "6415951f7219de9f93387c4060307fee943fd4c0549513fff788400936d8a895", + "dsr_request_hex": "1b5b366e", + "cursor_reply_hex": "1b5b313b313952", + "is_alt": true, + "is_main": false + }, + { + "phase": 2, + "label": "A1 H H", + "cursor_reply": [ + 4, + 11 + ], + "grab_attempted": true, + "constructed": [ + "pixmap", + "image" + ], + "destroyed": [ + "image", + "pixmap" + ], + "capture_valid": true, + "reason": null, + "image": { + "viewport_width": 888, + "viewport_height": 451, + "grab_rect": [ + 0, + 0, + 887, + 450 + ], + "pixmap_dpr": 1, + "image_dpr": 1, + "width": 888, + "height": 451, + "is_null": false, + "is_null_raw_value": 0, + "is_null_raw_type": "number" + }, + "rois": [ + { + "ordinal": 0, + "group": "alternate", + "sample": 0, + "h_rect": [ + 203, + 54, + 8, + 18 + ], + "space_rect": [ + 195, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 134, + 165, + 84, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 134, + 165, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 84, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 135, + 165, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 135, + 180, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 180, + 112, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 137, + 120, + 181, + 255 + ], + "count": 3 + }, + { + "rgba": [ + 137, + 120, + 201, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 137, + 131, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ] + }, + "space": { + "samples": 144, + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 138, + 110, + 201, + 255 + ], + "dominant_ink_rgba": null, + "dominant_ink_candidates": [ + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "dominant-ink-ambiguous", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "samples": 144 + } + } + }, + { + "ordinal": 1, + "group": "alternate", + "sample": 1, + "h_rect": [ + 219, + 54, + 8, + 18 + ], + "space_rect": [ + 211, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 134, + 165, + 84, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 134, + 165, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 84, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 135, + 165, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 135, + 180, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 180, + 112, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 137, + 120, + 181, + 255 + ], + "count": 3 + }, + { + "rgba": [ + 137, + 120, + 201, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 137, + 131, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ] + }, + "space": { + "samples": 144, + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 138, + 110, + 201, + 255 + ], + "dominant_ink_rgba": null, + "dominant_ink_candidates": [ + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "dominant-ink-ambiguous", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "samples": 144 + } + } + } + ], + "selection": { + "caret": 51, + "anchor": 51, + "text_type": "string", + "text_length": 12 + }, + "source_label": "alternate-reference", + "source_hex": "1b5b343b35481b5b33323b34356d413120482048", + "source_sha256": "ecd2495dd89fe551626069c64fec582eaac774bee29c4100a42ef159dd7009ff", + "dsr_request_hex": "1b5b366e", + "cursor_reply_hex": "1b5b343b313152", + "is_alt": true, + "is_main": false + }, + { + "phase": 3, + "label": "A2 H controls", + "cursor_reply": [ + 1, + 26 + ], + "grab_attempted": true, + "constructed": [ + "pixmap", + "image" + ], + "destroyed": [ + "image", + "pixmap" + ], + "capture_valid": true, + "reason": null, + "image": { + "viewport_width": 888, + "viewport_height": 451, + "grab_rect": [ + 0, + 0, + 887, + 450 + ], + "pixmap_dpr": 1, + "image_dpr": 1, + "width": 888, + "height": 451, + "is_null": false, + "is_null_raw_value": 0, + "is_null_raw_type": "number" + }, + "rois": [ + { + "ordinal": 0, + "group": "repeat", + "sample": 0, + "h_rect": [ + 171, + 0, + 8, + 18 + ], + "space_rect": [ + 163, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 75, + 40, + 50, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 75, + 75, + 50, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 75, + 81, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 107, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 107, + 40, + 50, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 107, + 75, + 81, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 205, + 140, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 205, + 202, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 205, + 205, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 248, + 171, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 202, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 40, + 40, + 50, + 255 + ], + "dominant_ink_rgba": [ + 40, + 75, + 140, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "samples": 144 + } + } + }, + { + "ordinal": 1, + "group": "control-default", + "sample": 0, + "h_rect": [ + 227, + 0, + 8, + 18 + ], + "space_rect": [ + 219, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 75, + 40, + 50, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 75, + 75, + 50, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 75, + 81, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 107, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 107, + 40, + 50, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 107, + 75, + 81, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 205, + 140, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 205, + 202, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 205, + 205, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 248, + 171, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 202, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 40, + 40, + 50, + 255 + ], + "dominant_ink_rgba": [ + 40, + 75, + 140, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "samples": 144 + } + } + }, + { + "ordinal": 2, + "group": "control-main", + "sample": 0, + "h_rect": [ + 283, + 0, + 8, + 18 + ], + "space_rect": [ + 275, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 82, + 86, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 82, + 95, + 159, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 95, + 169, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 104, + 169, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 103, + 95, + 159, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 103, + 104, + 169, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 168, + 38, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 38, + 125, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 168, + 54, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 54, + 112, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 168, + 54, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 196, + 54, + 112, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 196, + 54, + 137, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 61, + 104, + 169, + 255 + ], + "dominant_ink_rgba": [ + 61, + 95, + 137, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "samples": 144 + } + } + }, + { + "ordinal": 3, + "group": "control-alternate", + "sample": 0, + "h_rect": [ + 339, + 0, + 8, + 18 + ], + "space_rect": [ + 331, + 0, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 134, + 165, + 84, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 134, + 165, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 84, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 135, + 165, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 135, + 180, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 180, + 112, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 137, + 120, + 181, + 255 + ], + "count": 3 + }, + { + "rgba": [ + 137, + 120, + 201, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 137, + 131, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ] + }, + "space": { + "samples": 144, + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 138, + 110, + 201, + 255 + ], + "dominant_ink_rgba": null, + "dominant_ink_candidates": [ + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "dominant-ink-ambiguous", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "samples": 144 + } + } + } + ], + "selection": { + "caret": 45, + "anchor": 45, + "text_type": "string", + "text_length": 27 + }, + "source_label": "alternate-repeat-with-controls", + "source_hex": "1b5b3f3130343968413220481b5b306d204132443020481b5b33313b34346d204132533120481b5b33323b34356d20413253322048", + "source_sha256": "b33165a1da96062941d0f73e09f76c69726b67c14c8098d885b1804472610d7d", + "dsr_request_hex": "1b5b366e", + "cursor_reply_hex": "1b5b313b323652", + "is_alt": true, + "is_main": false + }, + { + "phase": 4, + "label": "M1 H controls", + "cursor_reply": [ + 4, + 35 + ], + "grab_attempted": true, + "constructed": [ + "pixmap", + "image" + ], + "destroyed": [ + "image", + "pixmap" + ], + "capture_valid": true, + "reason": null, + "image": { + "viewport_width": 888, + "viewport_height": 451, + "grab_rect": [ + 0, + 0, + 887, + 450 + ], + "pixmap_dpr": 1, + "image_dpr": 1, + "width": 888, + "height": 451, + "is_null": false, + "is_null_raw_value": 0, + "is_null_raw_type": "number" + }, + "rois": [ + { + "ordinal": 0, + "group": "return", + "sample": 0, + "h_rect": [ + 243, + 54, + 8, + 18 + ], + "space_rect": [ + 235, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 82, + 86, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 82, + 95, + 159, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 95, + 169, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 104, + 169, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 103, + 95, + 159, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 103, + 104, + 169, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 168, + 38, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 38, + 125, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 168, + 54, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 54, + 112, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 168, + 54, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 196, + 54, + 112, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 196, + 54, + 137, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 61, + 104, + 169, + 255 + ], + "dominant_ink_rgba": [ + 61, + 95, + 137, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "samples": 144 + } + } + }, + { + "ordinal": 1, + "group": "control-main", + "sample": 0, + "h_rect": [ + 299, + 54, + 8, + 18 + ], + "space_rect": [ + 291, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 82, + 86, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 82, + 95, + 159, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 95, + 169, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 82, + 104, + 169, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 103, + 95, + 159, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 103, + 104, + 169, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 168, + 38, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 38, + 125, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 168, + 54, + 94, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 168, + 54, + 112, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 168, + 54, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 196, + 54, + 112, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 196, + 54, + 137, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 61, + 104, + 169, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 61, + 104, + 169, + 255 + ], + "dominant_ink_rgba": [ + 61, + 95, + 137, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 61, + 95, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "f6642337d745cadfe45070fa83e612c7f23c7967e7b0ecc30a16c95f4dd86e7d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "f1edc9cafac03cba9da3cb802e4efa7e3cca8b50597f9ad408d6901ede1105ac", + "samples": 144 + } + } + }, + { + "ordinal": 2, + "group": "control-alternate", + "sample": 0, + "h_rect": [ + 355, + 54, + 8, + 18 + ], + "space_rect": [ + 347, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 134, + 165, + 84, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 134, + 165, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 165, + 84, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 135, + 165, + 137, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 135, + 180, + 43, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 135, + 180, + 112, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 137, + 120, + 181, + 255 + ], + "count": 3 + }, + { + "rgba": [ + 137, + 120, + 201, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 137, + 131, + 137, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ] + }, + "space": { + "samples": 144, + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 138, + 110, + 201, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 138, + 110, + 201, + 255 + ], + "dominant_ink_rgba": null, + "dominant_ink_candidates": [ + { + "rgba": [ + 137, + 110, + 201, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 138, + 120, + 137, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "dominant-ink-ambiguous", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "3cf5bdfb208ef523705b9a71cd88347c8f7357a34010775c2d0ae28d0ed0d90d", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "a19388d1e35ab74c77c6f32cda0521c92f6868beba1a407a8adec72d93e9ad07", + "samples": 144 + } + } + }, + { + "ordinal": 3, + "group": "control-default", + "sample": 0, + "h_rect": [ + 411, + 54, + 8, + 18 + ], + "space_rect": [ + 403, + 54, + 8, + 18 + ], + "h": { + "samples": 144, + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 84 + }, + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + }, + { + "rgba": [ + 75, + 40, + 50, + 255 + ], + "count": 9 + }, + { + "rgba": [ + 75, + 75, + 50, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 75, + 81, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 75, + 107, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 107, + 40, + 50, + 255 + ], + "count": 7 + }, + { + "rgba": [ + 107, + 75, + 81, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 205, + 140, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 205, + 202, + 255 + ], + "count": 2 + }, + { + "rgba": [ + 205, + 205, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 205, + 248, + 171, + 255 + ], + "count": 8 + }, + { + "rgba": [ + 205, + 248, + 242, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 140, + 255 + ], + "count": 1 + }, + { + "rgba": [ + 248, + 205, + 202, + 255 + ], + "count": 1 + } + ] + }, + "space": { + "samples": 144, + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "hash_encoding": "UTF-8 compact JSON array of unsigned QRgb values", + "histogram": [ + { + "rgba": [ + 40, + 40, + 50, + 255 + ], + "count": 144 + } + ] + }, + "background_rgba": [ + 40, + 40, + 50, + 255 + ], + "dominant_ink_rgba": [ + 40, + 75, + 140, + 255 + ], + "dominant_ink_candidates": [ + { + "rgba": [ + 40, + 75, + 140, + 255 + ], + "count": 16 + } + ], + "ink_observed": true, + "status": "unique-dominant-ink", + "raw_signature": { + "h": { + "shape": [ + 8, + 18 + ], + "sha256": "1ecf635bbea0bfeb40dc95f2aeb2161678cfcde544dc0ffa8f581a93d6c02f54", + "samples": 144 + }, + "space": { + "shape": [ + 8, + 18 + ], + "sha256": "8e572b4409fc2c661ec8df07be7fa3e2e40b39110b2a3696f5cd724efa3839be", + "samples": 144 + } + } + } + ], + "selection": { + "caret": 45, + "anchor": 45, + "text_type": "string", + "text_length": 36 + }, + "source_label": "main-return-with-controls", + "source_hex": "1b5b3f313034396c204d3120481b5b33313b34346d204d31533120481b5b33323b34356d204d31533220481b5b306d204d3144302048", + "source_sha256": "11af8a2f9cede6def3a9fbeadc169683ca321dcf5e34539cc06a9b438bde5574", + "dsr_request_hex": "1b5b366e", + "cursor_reply_hex": "1b5b343b333552", + "is_alt": false, + "is_main": true + } + ], + "stop_guard_observation": null, + "same_frame_raw_signature_comparisons": [ + { + "phase": 1, + "matching_controls": [ + "SGR0" + ], + "unique_control": "SGR0", + "result": "unique-raw-match", + "signature": "Exact ordered H and space QRgb SHA-256 plus shapes and sample counts", + "unmatched_does_not_imply_reset": true + }, + { + "phase": 3, + "matching_controls": [ + "SGR0" + ], + "unique_control": "SGR0", + "result": "unique-raw-match", + "signature": "Exact ordered H and space QRgb SHA-256 plus shapes and sample counts", + "unmatched_does_not_imply_reset": true + }, + { + "phase": 4, + "matching_controls": [ + "SGR31;44" + ], + "unique_control": "SGR31;44", + "result": "unique-raw-match", + "signature": "Exact ordered H and space QRgb SHA-256 plus shapes and sample counts", + "unmatched_does_not_imply_reset": true + } + ], + "provider": { + "evidence_id": "ev_931e2e152246d132fdf497ec9f4180843ef6244beb4cc9c1ec2fb6e19805326f", + "provider": { + "id": "frida", + "name": "Frida", + "version": null + }, + "confidence": "observed", + "subject": null, + "environment": null, + "messages_truncated": false, + "cleanup_error": null, + "limitations": [ + "Artifact identity is unavailable for this observation.", + "The target operating system and architecture were not reported by this observation." + ] + }, + "lifecycle": { + "outer_job": { + "active": 0, + "total": 3, + "terminated": 0 + }, + "profile": { + "only_synthetic_session": true, + "session_count": 1 + }, + "deliberate_original_termination": true, + "natural_gui_exit_verified": false + }, + "raw_files": { + "run.json": { + "bytes": 619, + "sha256": "654805c580a0996837478a9971fee27f131f36b6e3760cb6945da834a32e1a96" + }, + "probe.js": { + "bytes": 28433, + "sha256": "64b3fe0f0602afecb071faf287e7bf398a2b8f4b678cfed86c68da8543fdb4b4" + }, + "peer.json": { + "bytes": 1914, + "sha256": "1c262237ecc29eed68e61e4a2864451b4006fdb7fb137b89da7df92c039776be" + }, + "raster-raw-result.json": { + "bytes": 66778, + "sha256": "6cee5e5f4178e9f7fd19a54f3cb9ca7c6caedf92f245123bb02530825e69a088" + }, + "evidence.json": { + "bytes": 136191, + "sha256": "d777cbc9b8d67cea5d80c7b8d12c5bb47d2b1fbbce42650a48fd27dffc0401d5" + }, + "cleanup.json": { + "bytes": 42, + "sha256": "8400f93b6a4a4a50cde35b5d474660590ed215732f55772a9d8afac138da4f1d" + }, + "profile-check.json": { + "bytes": 52, + "sha256": "5e522a64e98197722ccd084639b1ce50258b238e03be2f016e81c8af023b5ee1" + }, + "stderr.txt": { + "bytes": 0, + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + "controlled_raster_observed": true, + "raw_capture_complete": true, + "internal_current_style_verified": false, + "full_grid_verified": false, + "local_shell_transport_verified": false, + "presented_done": null, + "r2_complete": false, + "windterm_parity": false, + "limitations": [ + "QWidget grab is a controlled raster, not physical display/presented proof.", + "Histograms and candidate colors are sampled output scalars, not the internal QPainter pen or full terminal style state.", + "Only the five fixed sources and one grab per phase are covered. Structural failure stops; offline color ties, nonuniform backgrounds or missing ink remain unknown without shifted ROI, additional grab or retry.", + "Same-frame raw signatures may alias or differ. Nonunique or empty matches stay null and never establish reset or full style; no dominant-color tie breaks are used.", + "Telnet direct-terminal observations do not establish WinPTY/ConPTY local-shell behavior or resolve margins.", + "45seconds is capture duration and60seconds is CLI wait timeout; target starts before a separate2-second delay and cleanup follows. No whole-lifecycle bound or performance conclusion.", + "Raw image/ROI pixels, paths, PIDs, copied original resources and profile stay local; only audited color/size scalars and hashes are published.", + "Provider subject/environment may remain null. Preparation enforces full module/package hashes and the injected script checks actual module paths and exact export RVAs.", + "Owned launcher deliberately terminates the original GUI; Job active0 is cleanup, not natural-exit proof." + ] +} diff --git a/research/ui/test_raster_raw_native.js b/research/ui/test_raster_raw_native.js new file mode 100644 index 00000000..904e0221 --- /dev/null +++ b/research/ui/test_raster_raw_native.js @@ -0,0 +1,42 @@ +'use strict'; +// Synthetic Qt is the external boundary; no original process or real image is used. +const fs=require('fs'),vm=require('vm'),assert=require('assert'),path=require('path'); +const source=fs.readFileSync(path.join(__dirname,'raster_raw_reference.js'),'utf8'); +function equal(a,b){assert.strictEqual(JSON.stringify(a),JSON.stringify(b));} +function observe(failure){ + const allocations=[],events=[]; + function pointer(){const result={data:[],equals(other){return result===other;},writeS32(value){result.data[0]=value;},add(offset){return {writeS32(value){result.data[offset/4]=value;}};}};return result;} + const editor={toString(){return 'owned-editor';}},viewport={}; + const markers=[0,1,2,3].map(ordinal=>({ordinal,label:ordinal<2?'D0 H H':'M0 H H',group:ordinal<2?'default':'main',sample:ordinal%2,character:'H',preceding_character:' ',h_rect:{x:ordinal*4+2,y:0,width:2,height:2},space_rect:{x:ordinal*4+(failure==='adjacency'?1:0),y:0,width:2,height:2}})); + const descriptors=markers.map(marker=>({label:marker.label,group:marker.group,sample:marker.sample})); + if(failure==='identity')markers[1]={...markers[0]}; + const context=vm.createContext({Number,Map,JSON,Error,targets:[{label:'D0/M0 H references',markers:descriptors}],moduleGuards:[],captures:[],grabs:[],editor, + scan(){},cached:[{name:'qt_scrollarea_viewport',parent:'owned-editor',ptr:'owned-viewport'}],ptr(){return viewport;},rect(){return [0,0,15,1];}, + Memory:{alloc(size){allocations.push(size);return pointer();}}, + grab(widget,result,region){events.push('grab');equal(region.data,[0,0,15,1]);if(failure==='grab')throw Error('synthetic grab failure');return result;}, + toImage(pixmap,result){events.push('toImage');if(failure==='toImage')throw Error('synthetic toImage failure');return result;}, + imageWidth(){return 16;},imageHeight(){return 2;},imageNull(){return failure==='empty'?1:0;},pixmapDpr(){return 1;},imageDpr(){return failure==='dpr'?2:1;}, + // Every H has a tied two-color histogram; all four H/space pairs must survive. + pixel(image,x,y){events.push('pixel');if(failure==='pixel')throw Error('synthetic pixel failure');if(x%4<2)return 0xff101010;return y===0?0xff112233:0xff445566;}, + destroyImage(){events.push('destroy-image');if(failure==='destroy')throw Error('synthetic destructor failure');},destroyPixmap(){events.push('destroy-pixmap');}}); + vm.runInContext(source.slice(source.indexOf('function modulePathMatches'),source.indexOf('const moduleGuards')),context); + vm.runInContext(source.slice(source.indexOf('function must'),source.indexOf('function terminalState')),context); + vm.runInContext(source.slice(source.indexOf('function overlap'),source.indexOf('function finish')),context); + const capture=context.sampleViewport(0,{is_alt:false,is_main:true,selection_caret:failure==='unknown'?null:9,selection_anchor:failure==='unknown'?null:failure==='active'?10:9,selection_text_type:'string',selection_text_length:10,markers,caret_rect:{x:failure==='caret'?0:16,y:0,width:0,height:2}},[4,9]); + return {capture,events,allocations}; +} +const tied=observe(); +assert.strictEqual(tied.capture.rois.length,4,'collect the whole phase before any color classification'); +assert.strictEqual(tied.capture.capture_valid,true,'color ties cannot stop structural capture'); +for(const roi of tied.capture.rois){assert.strictEqual(roi.h_pixels.length,4);assert.strictEqual(roi.space_pixels.length,4);assert(!('colors' in roi));} +assert.strictEqual(tied.events.filter(event=>event==='pixel').length,32); +equal(tied.capture.destroyed,['image','pixmap']);equal(tied.allocations,[32,32,16]); +for(const failure of ['unknown','active','identity','caret','adjacency','empty','dpr','grab','toImage','pixel','destroy']){ + const result=observe(failure);assert.strictEqual(result.capture.capture_valid,false,failure+' remains a stop'); + if(failure==='unknown'||failure==='active'||failure==='identity')assert(!result.events.includes('grab')); + if(failure==='grab')equal(result.capture.constructed,[]); + if(failure==='toImage')equal(result.capture.destroyed,['pixmap']); + if(failure==='pixel')equal(result.capture.destroyed,['image','pixmap']); + if(failure==='destroy')equal(result.capture.destroyed,['pixmap']); +} +process.stdout.write('all tied H/space ROIs captured; structural/endpoint/caret/DPR guards still stop\n'); diff --git a/research/ui/test_raster_raw_reference.py b/research/ui/test_raster_raw_reference.py new file mode 100644 index 00000000..d11a9efc --- /dev/null +++ b/research/ui/test_raster_raw_reference.py @@ -0,0 +1,164 @@ +"""Public capture/export seams with synthetic pixels; no original launch.""" +from __future__ import annotations +import hashlib +import copy +import json +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + +ROOT=Path(__file__).resolve().parents[2] +from research.ui.raster_raw_analysis import classify_pixels +from research.ui.test_raster_selection_reference import fixture as selection_fixture + + +def fixture(root): + from research.ui.raster_raw_reference import SOURCE_FILES + directory,planpath,data=selection_fixture(root) + result=data.pop('raster-result.json') + result.update(status='captured-five-raw-raster-phases',reason=None) + for capture in result['captures']: + capture['capture_valid']=capture.pop('calibration') + for roi in capture['rois']:roi.pop('colors') + # All phase2 H pixels have a genuine tie; collection is complete regardless. + for roi in result['captures'][2]['rois']: + roi['h_pixels']=[0xff112233,0xff445566,0xff112233,0xff445566] + data['raster-raw-result.json']=result + messages=[{'type':'send','payload':{'kind':'raw_raster_phase',**copy.deepcopy(capture)}} for capture in result['captures']] + messages.append({'type':'send','payload':{'kind':'raw_raster_result',**copy.deepcopy(result)}}) + data['evidence.json']['data']['evidence']['normalized_result']['messages']=messages + for name,value in data.items():(directory/name).write_text(json.dumps(value)) + for index in range(5):(directory/f'ack-{index}').write_text('captured') + plan=json.loads(planpath.read_text());plan.update(case_id='raw-capture-v1',source_files_sha256={name:hashlib.sha256((ROOT/name).read_bytes()).hexdigest() for name in SOURCE_FILES}) + planpath.write_text(json.dumps(plan)) + return directory,planpath,data + + +def write_records(directory,data): + result=data['raster-raw-result.json'] + messages=[{'type':'send','payload':{'kind':'raw_raster_phase',**copy.deepcopy(capture)}} for capture in result['captures']] + messages.append({'type':'send','payload':{'kind':'raw_raster_result',**copy.deepcopy(result)}}) + data['evidence.json']['data']['evidence']['normalized_result']['messages']=messages + for name,value in data.items():(directory/name).write_text(json.dumps(value)) + + +class RawRasterTests(unittest.TestCase): + def test_fixed_proposal_is_non_executable_and_preserves_exact_five_sources(self): + plan=json.loads((ROOT/'research/ui/results/2026-10-29-raster-raw-proposal/plan.json').read_text()) + self.assertFalse(plan['execution_authorized']);self.assertEqual(plan['actual_original_runs'],0) + self.assertEqual(plan['case_id'],'raw-capture-v1') + self.assertEqual([row['source_bytes'] for row in plan['phases']],[43,38,20,53,54]) + self.assertEqual(plan['maximum_grabs_per_phase'],1);self.assertEqual(plan['maximum_grabs'],5) + from research.ui.raster_raw_reference import SOURCE_FILES,phases + self.assertEqual([row['source_hex'] for row in plan['phases']],[source.hex() for _,source in phases(25,91)]) + self.assertEqual(plan['source_files_sha256'],{name:hashlib.sha256((ROOT/name).read_bytes()).hexdigest() for name in SOURCE_FILES}) + + @unittest.skipUnless(shutil.which('node'),'Node required for the external Qt boundary') + def test_all_rois_survive_a_tied_color_histogram(self): + result=subprocess.run(['node',str(ROOT/'research/ui/test_raster_raw_native.js')],capture_output=True,text=True,timeout=10) + self.assertEqual(result.returncode,0,result.stderr) + + def test_tied_ink_is_unknown_with_candidates_and_complete_signatures(self): + # Public synthetic arrangement reproduces the observed 16/16 count, not original pixels. + h=[0xff112233]*16+[0xff445566]*16+[0xff101010]*112 + space=[0xff101010]*144 + result=classify_pixels(h,space) + self.assertEqual(result['status'],'dominant-ink-ambiguous') + self.assertIsNone(result['dominant_ink_rgba']) + self.assertEqual(result['dominant_ink_candidates'],[{'rgba':[17,34,51,255],'count':16},{'rgba':[68,85,102,255],'count':16}]) + self.assertTrue(result['ink_observed']) + self.assertEqual(result['h']['histogram'],[{'rgba':[16,16,16,255],'count':112},{'rgba':[17,34,51,255],'count':16},{'rgba':[68,85,102,255],'count':16}]) + self.assertEqual(result['h']['samples'],144) + self.assertEqual(result['h']['sha256'],hashlib.sha256(json.dumps(h,separators=(',',':')).encode()).hexdigest()) + self.assertNotIn('pixels',json.dumps(result)) + + def test_same_frame_matching_uses_ordered_raw_signature_and_preserves_aliases(self): + from research.ui.raster_raw_analysis import compare_frame + def roi(group,h): + value=classify_pixels(h,[0xff101010]*4) + return {'group':group,'h_rect':[0,0,2,2],'space_rect':[0,0,2,2],**value} + target=roi('repeat',[0xff112233,0xff445566,0xff112233,0xff445566]) + controls=[roi('control-default',[0xff445566,0xff112233,0xff445566,0xff112233]),roi('control-main',[0xff112233,0xff445566,0xff112233,0xff445566])] + result=compare_frame([target,*controls]) + self.assertEqual(result['matching_controls'],['SGR31;44']) + self.assertEqual(result['unique_control'],'SGR31;44') + self.assertIsNone(target['dominant_ink_rgba']) + controls.append(roi('control-alternate',[0xff112233,0xff445566,0xff112233,0xff445566])) + result=compare_frame([target,*controls]) + self.assertEqual(result['matching_controls'],['SGR31;44','SGR32;45']) + self.assertIsNone(result['unique_control']) + self.assertEqual(result['result'],'ambiguous') + + def test_complete_capture_exports_all_five_phases_despite_tied_ink(self): + for optimized in (False,True): + with self.subTest(optimized=optimized),tempfile.TemporaryDirectory() as temporary: + root=Path(temporary);directory,plan,_=fixture(root);destination=root/'public/result.json' + result=subprocess.run([sys.executable,*(['-O'] if optimized else []),str(ROOT/'research/ui/export_raster_raw_reference.py'),'--directory',str(directory),'--plan',str(plan),'--destination',str(destination)],capture_output=True,text=True,timeout=10) + self.assertEqual(result.returncode,0,result.stderr) + public=json.loads(destination.read_text()) + self.assertTrue(public['raw_capture_complete']);self.assertEqual(public['observed_phase_count'],5) + self.assertEqual(len(public['phases'][2]['rois']),2) + self.assertIsNone(public['phases'][2]['rois'][0]['dominant_ink_rgba']) + self.assertEqual(public['phases'][2]['rois'][0]['status'],'dominant-ink-ambiguous') + self.assertFalse(public['internal_current_style_verified']) + self.assertNotIn('h_pixels',destination.read_text());self.assertNotIn('space_pixels',destination.read_text()) + + def reject_cli(self,change): + for optimized in (False,True): + with self.subTest(optimized=optimized),tempfile.TemporaryDirectory() as temporary: + root=Path(temporary);directory,plan,data=fixture(root);change(data);write_records(directory,data);destination=root/'public/result.json' + result=subprocess.run([sys.executable,*(['-O'] if optimized else []),str(ROOT/'research/ui/export_raster_raw_reference.py'),'--directory',str(directory),'--plan',str(plan),'--destination',str(destination)],capture_output=True,text=True,timeout=10) + self.assertNotEqual(result.returncode,0,result.stdout) + self.assertFalse(destination.exists());self.assertFalse(destination.parent.exists()) + + def test_duplicate_roi_identity_is_rejected_without_public_output(self): + self.reject_cli(lambda data:data['raster-raw-result.json']['captures'][0]['rois'].__setitem__(1,copy.deepcopy(data['raster-raw-result.json']['captures'][0]['rois'][0]))) + + def test_wrong_marker_label_is_rejected_without_public_output(self): + self.reject_cli(lambda data:data['raster-raw-result.json']['captures'][1]['terminal']['markers'][0].update(label='A0S1 H')) + + def test_missing_ink_or_nonuniform_space_stays_unknown_with_raw_signatures(self): + from research.ui.raster_raw_analysis import compare_frame + for h,space,status in (([1,1],[1,1],'no-marker-ink'),([2,2],[1,3],'space-background-ambiguous')): + with self.subTest(status=status): + value=classify_pixels(h,space) + self.assertEqual(value['status'],status);self.assertIsNone(value['dominant_ink_rgba']) + self.assertEqual(value['h']['samples'],2);self.assertEqual(value['space']['samples'],2) + target={**value,'group':'entry','h_rect':[0,0,1,2],'space_rect':[0,0,1,2]} + control={**target,'group':'control-default'} + result=compare_frame([target,control]) + self.assertEqual(result['result'],'unknown');self.assertIsNone(result['unique_control']) + + def test_unauthorized_raw_proposal_cannot_launch_or_create_attempt(self): + from research.ui.raster_raw_reference import run_plan + with tempfile.TemporaryDirectory() as temporary: + plan=Path(temporary)/'proposal.json' + plan.write_text(json.dumps({'issue':129,'case_id':'raw-capture-v1','maximum_original_runs':1,'execution_authorized':False})) + with self.assertRaisesRegex(ValueError,'not been authorized'):run_plan(plan) + self.assertFalse(plan.with_suffix('.attempted').exists()) + + def test_structural_identity_and_privacy_failures_create_no_public_output(self): + changes=[ + lambda data:data['raster-raw-result.json']['captures'][0]['terminal'].update(selection_anchor=10), + lambda data:data['raster-raw-result.json']['captures'][0]['terminal'].update(selection='PRIVATE/host/path'), + lambda data:data['raster-raw-result.json']['captures'][0]['terminal']['lines'].__setitem__(0,'PRIVATE_REVIEW_MARKER'), + lambda data:data['raster-raw-result.json']['captures'][0]['image'].update(image_dpr=2), + lambda data:data['raster-raw-result.json']['captures'][0]['image'].update(is_null='0'), + lambda data:data['peer.json']['naws_history'].append([92,25]), + lambda data:data['raster-raw-result.json']['grab_phases'].append(0)] + for index,change in enumerate(changes): + with self.subTest(case=index):self.reject_cli(change) + + def test_real_partial_replay_does_not_fabricate_missing_roi_or_later_phases(self): + replay=json.loads((ROOT/'research/ui/results/2026-10-29-raster-raw-proposal/replay.json').read_text()) + self.assertEqual(replay['new_original_runs'],0);self.assertFalse(replay['new_capture_inferred']) + self.assertEqual(replay['original_phase2_rois_captured'],1);self.assertEqual(replay['original_phase2_markers'],2) + self.assertFalse(replay['missing_rois_fabricated']);self.assertEqual(replay['original_grab_phases'],[0,1,2]) + self.assertEqual([row['count'] for row in replay['phase2_observed_first_roi']['dominant_ink_candidates']],[16,16]) + self.assertIsNone(replay['phase2_observed_first_roi']['dominant_ink_rgba']) + + +if __name__=='__main__':unittest.main()