Repository navigation
Description
当前限定诊断交付
PR163已以 35a323a3165dae6998237bfd768c7c54c9c8ae99 合入 main;#156继续开放。实际一次四-case执行源178faba:A/C保留2499B,B/D在第五段首次失效,且两者分配路径不同。1071B输入与旧CI member逐字节相等;只能证明机制足够产生坏状态,不能据相似version认定CI实际cut或唯一根因。限定报告保留51checkpoint/61记录、旧原件、监督器一次终止剩余未知成员的边界。
最终flush guard修正源bf56951仅独立构建成功,新EXE未执行,不改旧唯一执行。两轴最终0未解决发现;6个hosted工作流首次成功,PR默认Windows61/61、Linux41/41,实际checkout6458fd01d22836828fb00fb0fe2f861113c8f3ec;CI没有执行EXCLUDE_FROM_ALL witness。生产策略未修正,CI实际parser消费offset/cursor缺口仍需接续。
固定实际失败
PR154 push/default Windows job123101546682,HEAD/checkout 58fee2805cde34c67683a79473ca56f9df3cbf69,默认自主C++/system ConPTY/Win32原型,非正式Qt组合。完整CTest56/59、332.37s,本项只负责其中 text_actions 失败;另Node10s与shell选择期限失败分别归#144/#73,不合并根因。
ActionWindowTest.test_actual_system_copy_paste_and_shortcuts_twice(repeat=0) 的system-0返回2,非外层timeout,错误 actions geometry lost terminal selection。已有local-0/local-1和system-1结果独立保留,不覆盖此失败。记录显示geometry-192→geometry-96→geometry-zoom75→geometry-failure,native stage81→82→83→84;失败时controlled DPI96/实际window DPI96、logical/physical client均1360×860。bottom活动会话selection_status=invalidated、selected=false,而Find仍有范围;不能据此断言文字/行ID变化原因。
sample的自有Job active0/total11/terminated0,desktop_gone=true;不得将Job为空当自然child退出。完整actions-progress、原运输、受控图像/布局仅私有保留。artifact12851572745(4722483B)SHA256 ea38ca1099f6f52420d77bee16796d04e986eab02c8912a692e013bf4d12282a 已下载核对;LastTest162003B SHA 6ec38d3f098ade5f683f7c1fa0368843c642eb068aabb0cfa76ff8e0e7fe4a22。本批未重跑。
边界与下一步
关联#29已有候选重放/Find身份失败,但该旧评论来自不同候选配置,不能将其原因直接套到本次默认C++/system选择失效。也不因错误中有selection就并入#73首记录前等待或#85 OpenClipboard。R2与#38保持开放。
- 离线复核固定失败时stage、选区anchor/extent/行ID/版本、窗口/字体/网格与相邻真实运输;保存源码/EXE来源身份,未知不补造。
- 预声明一批有限样本/期限/停止条件,先在可独立复现入口区分物理resize、异步ConPTY重放和选区维护,不改原负载/等待/断言,不无限重跑取绿。
- 仅对可证伪的red做单变量修复并复验原文字/选择/Find/CF/焦点/回收;源码与配置独立留证,不扩展旧实验后端路线。
父项#38;与#29关联。只记录实际失败与待执行调查,不推断#152计量准备造成该失败,也不把独立PR CI绿记为根因修复。
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Activity
JavaZeroo commentedon Oct 28, 2026
追加离线事实:system-0 bottom stage82为111×7/文档82行;stage83 zoom75为149×10/文档85行、2499B选区仍ok;stage84回111×7时文档仍85行、top75→78,选择invalidated。原有位置78–81的同ID行98–101文字实际改变,位置82–84的空行ID102–104变为105–107;不能用“只有版本变化”解释。1071B geometry运输拆为210/210/210/231/210五段hide/home重绘,每段同一受控75–79/READY080标记;第四段清除扩大的空行后以CUP7;1恢复光标。ResizeWorker::settled仅声明native调用完成,没有parser/重绘完成语义。原日志没有每阶段已消费字节偏移和parser光标,现只能提出“连续resize与未消费完整重绘交叉”的假设,不能认定实际发生或据此改oracle。与base05f比较该PR未改Win32/Screen/selection代码;没有执行新重放或修改源码。
JavaZeroo commentedon Oct 29, 2026
本项的现象在今天的一次 push 回归中再次出现(PR #182,仅文档改动):
c1d4a2a。text_actions(7.77s):test_actual_system_copy_paste_and_shortcuts_twice(repeat=0)→ValueError: shell probe failed: actions geometry lost terminal selection。这与 #163 记录的四-case 机制诊断一致(动作几何恢复后选区失效),说明它在 hosted windows-2025 上是可复现的间歇失败,不是一次性事件。原有红例、机制见证与产品策略保持;本项继续开放,下一步仍是定位修复后的真实切点/根因。
JavaZeroo commentedon Oct 29, 2026
机制定位(代码级假设,待插桩验证)
已知失败签名(本轮再次出现):
actions geometry lost terminal selection,来自experiments/shell/workspace_actions_scenario.hpp:200–205——在该处current_find_range()仍存在,但has_selection()为 false,即 Find 命中在、选区丢了。沿着选区生命周期读代码,得到一个具体假设:
experiments/core/text_selection.hpp的TextSelection::reconcile(第 66 行起)维护:epoch变化 → 直接invalidate;行id/version/joins_next变化 → 重新读取并与保存的投影逐项比较,文字/跨度完全一致才修复。Screen::buffer_epoch只在invalidate_buffer_readers(第 194–198 行)与activate_buffer(第 204–221 行)递增;resize/DPI/zoom 本身不会改 epoch。transition(144) → 192 → 96 → zoom 75%之后立即检查选区(第 200 行)。这些几何变化会改变网格宽度,使行的投影宽度/裁剪状态变化;reconcile若此时看到的投影与保存的不一致,就按设计把整个选区置为失效。version先更新、内容投影稍后才稳定,reconcile在中间态比较到差异便永久失效。建议的下一步(不改产品行为):在
reconcile的各个失效分支加一次性诊断输出(epoch / id / version / text 不一致,及当时网格宽高),在 hosted 失败时抓取实际分支;若确认是中间态,再讨论"settle 后再 reconcile 一次"是否属于原版行为还是自研修补。本轮不做产品改动,#156 保持开放;该假设补充进本项的机制记录。
diagnose(shell): point the selection diagnostic at the preserved arti…
diagnose(shell): point the selection diagnostic at the preserved arti…
diagnose(core): keep the selection header newline refs #156
diagnose(core): keep the selection header newline refs #156
Merge pull request #186 from JavaZeroo/diag/selection-discard-reason
JavaZeroo commentedon Oct 29, 2026
诊断已合入并本地跑通,抓到了第一个分支:row-text-changed
PR #186 合入后(main
4b7d487),我在本地用 Release 构建跑了actions场景:产物目录里出现诊断文件:
含义
TERMFORGE_SELECTION_DIAG,失败时该文件随build/test-artifacts/保留;row-text-changed丢弃 —— 说明几何变化(DPI/zoom)过程中确有一次“行投影文本与保存快照不一致”的 reconcile;下一步(待 hosted 再红时执行)
selection-discard.jsonl,确认分支是row-text-changed还是其它;actions-progress.jsonl阶段时间对照;本条不改变产品行为;#156 保持开放。
JavaZeroo commentedon Oct 29, 2026
补充:诊断现在连行号一起记录(PR #187),本地 actions 场景每次运行的记录都是
{"schema":"termforge-selection-discard-v1","reason":"row-text-changed","row":0}即:几何变化过程中,选区第 0 行的投影文本与保存快照不一致,触发整体失效;场景仍通过说明这次丢弃发生在几何检查之后。
这对 #156 的意义:
row 0,则更可能是该行在 DPI/zoom 切换时确实被改写/裁剪,而不是任意行写入的干扰;actions-progress.jsonl的阶段记录对齐,确定丢弃发生在哪个 transition 之前/之后。仍未改 reconcile 行为,#156 保持开放。
Merge pull request #187 from JavaZeroo/diag/selection-row-detail
2 remaining items
Merge pull request #188 from JavaZeroo/diag/selection-timeline
JavaZeroo commentedon Oct 29, 2026
已按需复现,并拿到"丢弃发生在哪一步"的时序证据。
用 dispatch-only 作业在 hosted windows-2025 上重复跑
text_actions|selection_context(ctest --repeat until-fail:20),第 8 次text_actions即复现:失败那一轮的阶段时间线(
actions-progress.jsonl,t_ms):对照:其余 14 轮全部只出现一次丢弃,且都落在
live-selected与invalidated-copy-rejected之间(场景自己制造失效选区,row=0,属预期)。结论
geometry-zoom75之后、检查之前,即reset_zoom()把 75% 还原为 100% 的那次几何变化;find_range{id:97,version:134,0..11}),只是选区被置为 invalidated;reconcile按设计整段失效 → 场景在下一阶段断言失败。下一步
证据:run 40897620314 的
actions-repeat-evidence工件(含两份 JSONL);分支ci/actions-repeat只含这个复现作业的定义。Merge pull request #189 from JavaZeroo/diag/selection-details
JavaZeroo commentedon Oct 29, 2026
机制收敛:这不是"随机竞态",而是"物理裁剪导致选区失效"在特定网格宽度下被触发。
证据链:
row-text-changed,行号 78(选区末行),发生在geometry-zoom75之后、检查之前;TextSelection::reconcile只在投影文本与跨度逐项相同时修复,否则整段失效;experiments/core/selection_test.cpp中 "real crop invalidates range"(第 82 行)断言裁剪必然使选区失效;这解释了为什么本地(大屏、列数多)跑 20 次全绿,而 hosted 的 1024×768 桌面列数少、更容易裁剪:失败取决于环境网格宽度,不是计时运气。
由此得到的两个方向(都需用户确认,属重要行为)
在确认前不改产品代码;诊断(含 saved/current bytes+columns)已就绪,下一次命中即可确认失败帧确实是"列数变化 + 文本截断"。
JavaZeroo commentedon Oct 29, 2026
抓到失败帧的行级数据后,线索指向产品侧:resize 后"行 id 不变但内容被换掉"。
失败帧(run 40897620314,
run-x25yyqjk/system-0)关键对比,bottom 终端:TF_FIND_078TF_FIND_079TF_FIND_READY 080TF_FIND_078TF_FIND_079TF_FIND_READY 080TF_FIND_075TF_FIND_076TF_FIND_077TF_FIND_078也就是说:回到 100% 后,id 98–101 这些行的内容整体上移了 3 行,同时末尾出现 id 105–107。
选区快照里第 78 行(对应 id 98 的内容
TF_FIND_078)因此比对失败 → 整段失效。为什么这值得当成产品问题
ADR-0005 的既定语义是物理行裁剪、不 reflow:缩放/DPI 变化应当只改变可见裁剪范围,不应改写既有行 id 的内容。
现在观察到的却是"id 保留、内容被替换",这更像 resize 路径上的行重建/复用,而不是"内容真的变了"。
下一步(建议)
Screen::resize后各行 id 与文本是否保持;诊断字段(saved/current bytes+columns)已在 main,下一次命中可再确认是否为"列数变化 + 文本截断"。
JavaZeroo commentedon Oct 29, 2026
核心层验证:
Screen::resize保持行 id 与内容正确;异常来自 shell/滚动层(或 resize 期间并发输出)。复现方案(本地、不依赖托管):构造
Parser(7, 111, 2000),写入 82 行TF_FIND_%03d needle abc,然后按失败帧的几何序列 resize:结论:核心 resize 不会出现"id 保留、内容被换";行 id 与文本在 111→149→111 往返后完全保持,新增可见行获得新 id,回收时被丢弃。
因此失败帧里看到的"id 98–101 内容整体位移 3 行 + 末尾出现 id 105–107",不是核心 Screen 的 resize 行为,更可能来自:
下一步
termforge_shell做同样的 111→149→111 变化(可复用现有 scenario 的 transition 序列),对比document_lines的 id/文本;本轮结论把 #156 的排查范围从"核心"缩小到"shell/并发",且给出了可重复的本地核心对照。
JavaZeroo commentedon Oct 29, 2026
核心层第二次对照:带历史的 resize 也不产生重复/错位行。
构造
Parser(7, 111, 2000),写入 200 行后按失败帧序列 resize:即:核心层在有历史的情况下,resize 往返同样保持行 id/内容、不产生重复行。
因此失败帧里看到的"id 98–101 内容与前面 3 行重复"更可能来自观测路径的采样时机(
observed_document_lines()在 resize/publish 过程中读到过渡态),而不是终端状态本身。这改变了 #156 的下一步
document_lines(或用visible_lines交叉校验),若两次不一致,说明现象是采样竞态;row-text-changed row=78)本身是真实的,仍需要决定 A(容忍裁剪差异)或 B(调整场景期望)。本地对照程序在
local/resize_id_test.cpp与local/resize_scroll_test.cpp(未入库)。JavaZeroo commentedon Oct 29, 2026
失败帧的可见行与文档行一致,但文档里出现了"重复行"——更像 resize 缩小时把可见行既推入历史又留在原位。
同一失败帧(
run-x25yyqjk/system-0,phase=geometry-failure,grid 111×7):visible_lines正好等于document_lines的最后 7 行 → 观测路径一致,不是采样错位;document_lines里 075/076/077 出现两份(id 95–97 与 id 98–100)→ 文档层面确实出现了重复行;我上一轮的核心对照(
Parser(7,111)写 200 行后 10 行→7 行)没有复现重复;差别很可能在光标/滚动状态:对照里光标始终在底部,场景里底部终端由子进程持续输出、光标位置与滚动起点不同。下一步(本地可做):把核心对照改成"先向上滚动若干行/把光标移出底部"再做 10→7 缩小,检查是否出现重复行;若复现,则是
Screen::resize在"非底部光标 + 缩小高度"路径下的真实缺陷,可直接修并加回归测试。选区丢弃(row 78)在形式上仍是
row-text-changed,但根因若是这个重复行,则属于产品缺陷而非场景期望问题。JavaZeroo commentedon Oct 29, 2026
尝试用现场录制的字节流在核心层复现(进展 + 一个限制)
失败帧目录里有底部终端的录制流
actions-geometry-bottom.transport.bin(1071 B),内容确实是原始 VT:但把它喂给核心
Parser会在第一条序列就抛错:即核心只接受
?1049与?7两种私有 CSI,而子进程实际会发?25l(隐藏光标)。说明 shell 的输入路径上还有一层过滤/忽略逻辑,直接回放录制流无法等价复现 shell 的实际状态。下一步
JavaZeroo commentedon Oct 29, 2026
定位完成:失败由子进程重复重绘引起,不是产品缺陷
决定性复现(本地、同源字节)
失败帧目录里保存了底部终端的原始输出流
actions-geometry-bottom.transport.bin(946 字符)。直接统计:即:子进程在这段时间里从原点重绘了 5 次(每次
ESC[?25l ESC[H后重打整块内容)。把这个流用
Parser(7,111,2000,ParseMode::recovery)回放(recovery 模式与 shell 一致),立刻复现出重复行:在 resize 之前就已经如此,说明几何变化只是"重绘落点"的时机,不是原因。
与失败帧吻合
失败帧文档尾部出现 075/076/077 各两份(id 95–97 与 id 98–100),与重绘产生的历史重复完全一致;选区第 78 行正是被重绘改写的那一行,于是
row-text-changed整段失效。结论
TextSelection::reconcile的既定正确行为:文档内容确实变了;ESC[H重画整块),不是 resize/DPI/zoom 逻辑,也不是核心行身份缺陷;后续(不属于产品缺陷)
场景侧需要避免在子进程可能重绘时断言"选区跨几何变化存活":可在几何阶段前让子进程静默,或把断言改为"内容未变时才要求选区存活"。这条作为测试卫生问题跟踪(#38 的失败形状记录里已多次出现同类时序抖动)。
据此关闭本项:定位目标已达成,产品代码不需要修改。
JavaZeroo commentedon Oct 29, 2026
补充修正(关闭后新增证据):这份"重复重绘"其实是ConPTY 在 resize 后的重绘,不是子进程自己重画。
把录制流按转义符拆开后,结构非常规整——5 次完全相同的尾部重绘,与 5 次几何变化(144/192/96/zoom75/restored)一一对应:
而场景里的文本夹具
text_client.cpp只在启动时打印一次(ESC[2J ESC[H+ 81 行 + READY),之后只在收到+ # ~ -时输出。它不会周期性重绘。所以这 5 次"从 home 重打尾部 6 行"更可能是 ConPTY/conhost 在窗口尺寸变化后发出的重绘(光标隐藏→回 home→重打可见尾部→恢复光标)。
这对结论的影响:
reconcile判 invalid 正确);我先保持 #156 关闭(定位目标已达成),把这条修正留在这里,避免后续误判归因。
diagnose(shell): capture the full output stream for replay refs #156
Merge pull request #190 from JavaZeroo/diag/output-capture