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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/adr/0008-codex-startup-shadow-and-composer-surface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ADR 0008:Codex 初始化阴影与输入区装饰层

- 日期:2026-10-23
- 状态:接受
- 范围:Codex adapter;保持现有背景档案、存储键及其他客户端行为。

## 问题与证据

用户报告初始化阴影与设置不符,并提供输入框外围黑色矩形截图。
现场 Codex 包版本为 26.1016.6573.0,CDP 与探索下的背景入口可识别。
读取现场时保存值、API、根节点 CSS 变量及清单都为 46%,背景未活动;这次快照不代表已经复现真实客户端的启动时序。

浏览器回归使用真实媒体载荷,复现两个初始化缺口:只有控制台负责恢复阴影,独立媒体启动不恢复;宿主替换 html.style 后,界面仍显示 46%,媒体阴影却回到 0%。
现场还发现 composer 后有空的、不可交互、绝对定位的 bg-surface 元素;现有样式没有清除它的底色,与用户截图一致。生成的 CSS 模块哈希不作为适配契约。

## 决定

将阴影偏好的读取、校验、持久化及 CSS 同步移入独立 dim.js,媒体初始化前安装,控制台仅调用同一 API。继续使用 beauticode-dim 存储键与 0~1 值域,0 是有效设置,非法值回退自动。

只监听 html 的 style 与 data-bc-dim-user 属性。幂等写入避免自身触发循环;重复安装复用同版本实例,替换版本释放旧监听。窗口关闭结束生命周期,清除媒体保留用户偏好供下次应用。自动滑块位置分别对应深色 0%、浅色 48%。

只在背景活动时,将 main 内底部定位容器的空、不可交互 bg-surface 子装饰层设为透明。输入框、对话框和其他 surface 保留底色;清除背景恢复宿主样式。不引入通用 surface 透明规则。

2026-10-26 补充:用户继续报告输入框上方的黑色渐变。现场确认它属于 thread-scroll-container 内 sticky bottom-0 页脚的空、不可交互、横向绝对定位 from-surface 子层;实际背景为从 #181818 到透明的线性渐变。旧的 bg-gradient-to-t/from-token-main-surface-primary 规则不匹配该结构。新增仅针对这一布局职责的规则,不依赖 _background_ / _fade_ 生成类名,不改变有内容的节点、非粘滞结构或聊天区之外的渐变。背景清除后由 data-bc-active 门控恢复宿主渐变。

## 验证与边界

appearance.browser.test.js 使用 Edge 实际渲染,覆盖首次恢复、根样式替换、零值、非法值、浅深色、清除偏好不重建舞台及输入区边界。通过 BEAUTICODE_PLAYWRIGHT_MODULE 指向已有 Playwright 运行时;没有运行时时显式跳过,不添加发布依赖。

其他客户端现场均未运行,安装状态不能代表新版 DOM 验收。另一个已有五端浅色检查发现,四个非 DSH 客户端默认 48% 白色遮罩在纯黑壁纸上只有约 3.75:1 对比度,本次保留既有亮度策略,未将其宣称为通过。

回滚可恢复安装目录 current.json 指向上一版本,再重启 beautiCode 辅助进程;无需重启或修改 Codex 二进制。源码回滚同时恢复 payload、console、CSS 并移除 dim.js,原存储键无需迁移。
101 changes: 101 additions & 0 deletions docs/adr/0009-codex-wallpaper-surface-and-guest-lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# ADR 0009:Codex 壁纸外壳与 guest 生命周期

- 日期:2026-10-24
- 状态:接受;现场与自动化证据的范围分别列于验收记录。
- 基线:main aea3220;来源 PR #96 head d5f3252。
- 关联:[实施与验收记录](../pr96-owner-completion.md)、PR #96。

## 问题与现场事实

PR 把原生圆角、tooltip、功能浮层、内容路由和 guest 注入混在两个文件中。
固定浅色背景与宿主深色文字体系冲突;同代次短路前创建观察器会泄漏。
尺寸扫描不能辨认页面外壳和阅读底板,直接修改内联背景还必须保存声明优先级。

26.1016.6573.0 的宿主静态资源声明 /plugins、/library、/sites、/images 原生路由。
实际切页也确认这些入口在宿主文档呈现;不能据路由声明推断所有版本均无 webview。
当前存在独立的定价预热 webview:src 是 about:blank,toUrl 是相对路径,实际地址为 chatgpt.com。
因此排除 sandbox 或仅限制 chatgpt.com 都不能形成正确的页面边界。
支付与工作区设置资源还包含独立 webview 流程,本适配不进入这些流程。

站点页的外壳由 workspace slot、全高 bg-surface、contents、滚动容器及居中 tabpanel 构成。
资料库复用滚动标题结构,但不具有站点页的全高 bg-surface 根节点。
两者的标题底板是滚动内容标题壳的 ::before;清理 h1 本身无效。
真实 DOM 中存在生成类名,但它们只作为调查证据,不作为本次适配选择器。

## 决策

### 宿主样式

只删除 beautiCode 对左栏、main 和首页卡片圆角的清零,保留宿主实际圆角。
当前宿主部分外层原生圆角为 0;本修复不承诺把这些外层改成指定像素。
普通 tooltip 保留原生底色与前景;Radix 定位壳透明,真正菜单面板保留主题底色。
浮层及 sidebar peek 使用 --bc-readable-fill;peek 仅裁切并修正直接底板,沿用宿主圆角。
所有新浮层规则排除 beautiCode 自身 UI 及其后代。

保留 ADR 0008 的空、非交互 composer 装饰层规则。
原生页面只匹配观测到的 workspace/滚动/标题/tabpanel 结构。
不清空所有 bg-surface,不使用视口大小推断语义,也不新增生成类名兜底。
布局契约失效时保持宿主底板,而不是回退到更宽泛的透明规则。

### 模块与所有权

媒体入口只负责代次、组合、舞台及销毁;工作态、用户播放偏好、媒体来源、图片、
视频节点、就绪/重试和既有 API 分别拥有状态。
图片与视频附件均需要可取消的原生事件等待,因此复用小型 media-wait 模块。
销毁会取消等待并解绑事件;旧图片完成后不能更新下一代根属性。
公开七个注入参数、既有方法名及健康快照字段保持不变。
修正偏好恢复调用:沿用已有 isBackgroundTone 方法,不新增兼容别名。
模块通过操作、只读 getter 和回调协作,不共享可变状态包。

payload 在注入表达式的词法作用域内组合工厂,避免浏览器端 ESM/CSP 或新增全局注册框架。
主入口从约 2022 行降到不足 400 行,新增媒体与 guest 模块均小于 500 行。
保留现有 renderer 资产复制和插件打包机制,不引入运行时依赖。

### guest 契约与生命周期

guest 控制器内部接口为 setActive(boolean)、sync()、dispose()。
同一文档同版本复用;媒体交接不捕获旧代次闭包,完整销毁释放实例。
未激活时不创建宿主观察器,也不绑定 guest 事件或注入 CSS。

条件允许的内容根路由仅 /plugins、/library、/sites、/images。
还要求宿主 main 中的已连接 webview、about:blank 的预期路径和当前 HTTPS
chatgpt.com 精确路径一致;不接受端口、用户凭据、相似域名或任意子路径。
prewarm、sandbox、定价/结算/工作区 partition 及所有未知路由均拒绝。
/pricing-plan、/checkout、/admin、认证流程和未验证的 /plans 不在允许表中。
查询参数不作为账号授权依据,不将它们写入日志。

“候选页面”只允许绑定就绪事件,只有实际地址通过校验才可注入。
dom-ready、主框架导航、页内导航与动态挂载均重新检查。
不支持或尚未验证的版本保持原生;没有合适现场实例时不得宣称 guest 现场验收通过。

用 Electron insertCSS/removeInsertedCSS 的键管理根外壳样式。
guest 自身表单、卡片、弹层及主题变量不改写;不安装 guest DOM 观察器、不改内联背景。
样式只涉及 html/body 及直接根节点,内层没有已验证契约时不扩展清理范围。
宿主视图使用宿主 CSS 处理其原生内层外壳。

每个登记实例只有一个未完成插入调用;操作版本随导航、清除和销毁递增。
过期结果通过自己的样式键撤销,不能删除重新激活后的新样式。
旧调用阻塞过新文档时,完成后只为变化过的版本补同步一次;拒绝/超时不无限重试。
超时为 3000ms。Electron Promise 不能真正取消;超时保留原生显示并诊断,
迟到的成功结果仍会回收,底层 Promise 永不完成时不再堆积新调用。
清理依赖登记表,能够处理已脱离 DOM 的 webview。
撤销 API 拒绝时给出阶段/类别诊断,不能把 API 失败宣称为成功恢复。

## 验证与限制

Node 测试覆盖边界、候选就绪、动态新增/移除、100 次实例复用、清理竞态、超时、
错误脱敏、视频交接后永久错误和图片取消。
真实 Edge 浏览器执行完整载荷,覆盖主题切换、圆角、保留阅读卡片、媒体和交接;
最终 Codex 插件包内载荷重复执行同组关键回归。
合成浏览器中的 webview API 替身不是 Electron 现场证明。
真实客户端检查仅临时替换 CSS,检查原生内容页后恢复;不安装新运行时或修改媒体档案。
详细通过数、截图、采样视频及未验收边界见实施记录。

## 演进与回滚

宿主变更后先更新脱敏 DOM 样例和对应回归,再调整结构或允许表。
新增 guest 页面必须有真实 URL、身份及根外壳证据,不扩大域名或尺寸扫描兜底。
现有日志不会包含正文、账号或完整 URL。
本次不改存储键及档案协议;回滚本组提交并重新打包即可恢复旧运行时。
若已经安装某个包,应先停止该包的辅助注入进程,再切换到上一包,避免两代注入竞争;
不修改 Codex 二进制,也无需数据迁移。
130 changes: 130 additions & 0 deletions docs/pr96-owner-completion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# PR #96:owner 实施与验收记录

日期:2026-10-24。基线 origin/main aea32209f02de0e14b7248ac870f5868e195d167;
来源 PR head d5f3252,经执行前在线复核未变。

实施位于附加 worktree 的 codex/pr96-owner-completion 分支。
原 E:/WoRk/beautiCode 工作区未修改;其 tracked patch 与 untracked 文件先复制后整合,
包括阴影恢复、空 composer 装饰层、相关浏览器测试及 ADR 0008。
其他复制的本地 DSH 文档/脚本不属于本次新增实现,不混入本次修复提交。
实施与初次验收阶段未发布、推送或合并,也未把新运行时安装到用户应用。

2026-10-26 提交准备:远程主线已通过 405fd81 合并 #96,本分支同步该主线,
作为后续修复提交。冲突仅涉及旧运行时和 CSS;保留本分支已验证的新控制器、
模块拆分和精确样式规则,没有重新引入被替换的尺寸扫描或宽泛透明规则。
同步后重新执行类型检查及全仓测试:435 通过、20 显式跳过、0 失败;
串行执行两组真实 Edge 浏览器回归共 9 项,全部通过、零跳过。
对应日志为 pr-submission-typecheck.log、pr-submission-tests.log、pr-submission-browser.log。

## 已实现

- 保留宿主圆角与普通 tooltip 配色;定位壳透明,菜单/浮层/peek 随宿主主题。
- 排除 beautiCode 自身 UI;保留输入框、普通卡片和无关 aside 底色。
- 按现场结构清理站点的三层外壳及资料库/站点的标题伪元素,不新增生成类名选择器。
- 媒体按职责拆分,修改后的主运行时及新增模块小于 500 行;既有大测试文件也按职责分拆。
- guest 按预期/实际地址和宿主插槽验证;支付、预热、认证、sandbox 与未知页面保持原生。
- 样式键替代内联修改和尺寸扫描;登记表管理事件、观察器和异步操作。
- 同代次复用、交接、完整清除、销毁、动态节点、导航期间延迟完成均有行为回归。
- 修正旧有图片等待取消及色调读取方法不一致,保留原公开方法。

架构与明确的允许/拒绝规则见 [ADR 0009](adr/0009-codex-wallpaper-surface-and-guest-lifecycle.md)。

## 实施过程与可复现证据

基线 Codex:74 通过、5 跳过、0 失败;显式浏览器基线 4 通过、0 跳过。
失败先于修复的记录保存在 artifacts/pr96/:

| 失败证据 | 检查内容 |
| --- | --- |
| red.log | 固定样式、未实现 guest 行为 |
| guest-readiness-red.log | about:blank 候选页面需要等待 dom-ready |
| handoff-error-red.log | 交接已结束后,永久视频错误不能继续 pending |
| navigation-race-red.log | 旧插入调用不能阻断新文档注入 |
| image-cancel-red.log | 已销毁的图片附件不能更新下一代 |
| guest-timer-red.log | 销毁必须释放插入超时计时器 |
| owned-ui-red.log | 自有 UI 的嵌套浮层也必须排除 |
| header-red.log / library-header-red.log | 清 h1 无效,且 Library 与 Sites 外壳不同 |
| tone-red.log | 通过已有公开方法恢复色调偏好 |

独立只读审查发现并复现 handoff 快照和 pending 导航收敛两项 Important;
均已按失败测试→修复→通过完成,未发现 Critical。
首次视频测试的 MediaRecorder 只产生文件头,原生 video 也无法解码;
补充真实帧录制后才用于运行时验收,没有通过放宽断言绕过失败。

## 自动化验收

| 检查 | 结果 / 原始日志 |
| --- | --- |
| 全仓类型检查 | 通过;typecheck.log |
| 全仓构建 | 通过;build.log |
| 全仓最终确认 | 435 通过、19 跳过、0 失败;full-test-confirmation.log |
| 最新 Codex 测试 | 106 通过、9 跳过、0 失败;adapter-final.log |
| 完整载荷 Edge 浏览器 | 8 通过、0 跳过;browser-final.log |
| 最终插件包内完整载荷 | 4 通过、0 跳过;packaged-browser.log |
| 打包模块加载/语法 | 进入必跑 Node 测试,未遗漏私有模块 |
| 空白与规模检查 | git diff --check;主入口及新运行时模块均不超过 500 行 |

浏览器回归直接执行 loadRendererSource/buildInjectionExpression 产生的真实载荷,
覆盖浅→深→浅、圆角、tooltip、peek、自有 UI、原生路由外壳及普通阅读卡片,
以及真实视频解码、交接、静音、定位、摸鱼、色调继承和清除。
包内验证通过 BEAUTICODE_RENDERER_PAYLOAD 指向 staged vendor/payload.js,
不是只检查源文件字符串或包文件清单。

全仓复跑曾在未修改的 DSH pack.test.mjs 出现一次 Node 测试器
“Unable to deserialize cloned data due to invalid or unsupported version”。
DSH 单独重跑 122 通过、10 跳过、0 失败,记录为 dsh-recheck.log;
该异常记录保留为 full-test-final.log,不将其抹掉或归因于已证实的业务缺陷。
最后一轮全仓确认 435 通过、19 跳过、0 失败,见 full-test-confirmation.log。

## 真实客户端与视觉边界

现场版本:Codex Desktop 26.1016.6573.0 / Windows,深色主题。
通过当前 9335 CDP 读取 DOM/静态资源、切换内容入口并临时替换壁纸 CSS;
finally 恢复原 CSS,并恢复本聊天,没有改动背景档案或安装包。

- Plugins、Library、Sites、Images 均实际打开并采集截图。
- Sites 的根外壳、内容容器、tabpanel 背景确认透明;普通卡片保留自身外观。
- 初次截图暴露 Library 标题仍不透明,随后增加独立结构样例及回归再修复。
- sandbox 未绑定旧式透明事件;定价预热保持排除。
- 外层 sidebar 在本版本原生值可为 0px;保留原生不是强制增加圆角。

截图:artifacts/pr96/live-route-0.png 至 live-route-3.png,
合成但真实渲染的主题对照:fixture-dark.png、fixture-light.png。
navigation-00.png 至 navigation-05.png 是实际切页采样;
navigation-sampled.webm 是这六帧的回放,不是连续录屏,不能证明采样间绝无闪烁。
原始无正文结构快照及结果为 live-*.json / live-css-results.json。
这些本地证据位于忽略目录,不随提交公开。

未宣称通过的范围:

- 用户应用的浅色主题:已在真实 Edge + 脱敏结构中覆盖,未现场更改用户主题设置。
- 允许的 Electron guest 现场:当前目标入口为原生页面,只有被排除的预热 guest;
不能把 API 替身测试或方法存在当作此项现场验收。
- Plans/结算/认证等未验证页面:保留原生,不扩大透明范围。
- 未安装旧版客户端,没有将本版本结论推广至 PR 描述的旧版本。

## 2026-10-26 输入框上方渐变补充

现场定位并清除了聊天滚动区粘滞页脚的空 from-surface 渐变层。
当前窗口应用独立、带背景活动门控的样式修正;不修改安装包,窗口重载后须由更新的载荷重新注入。
读取修正前后的计算样式:渐变由 linear-gradient 变为 none,输入框仍为 rgb(31, 31, 31)。
截图 composer-fade-after.png 与脱敏计算结果 composer-fade-live.json 位于本地 artifacts/pr96。
新增回归先失败后通过,覆盖浅→深→浅、相似元素不受影响及 dispose 后恢复。
appearance 浏览器测试实际执行 5 项,全部通过、零跳过(composer-fade-browser.log)。
本次全仓复跑为 435 通过、20 显式跳过、0 失败(composer-fade-full-test.log);
新打包 CSS 与源码 SHA256 一致。包内载荷浏览器测试首次视频用例仅录得 171 字节文件头而失败,
未改测试或运行时代码,原样复跑 4 项全部通过、零跳过。
首次失败与复跑日志分别为 composer-fade-packaged-browser.log、composer-fade-packaged-recheck.log;
这是现有实时录制样例的时序波动,不能将该次首次执行记为通过。

## 复跑

从仓库根运行 npm run typecheck、npm test、npm run build。
浏览器测试使用现有 BEAUTICODE_PLAYWRIGHT_MODULE,Windows 下赋值为 file:/// 模块 URL,
运行 node --test packages/adapter-codex/test/appearance.browser.test.js
packages/adapter-codex/test/wallpaper.browser.test.js。
未配置该变量时浏览器测试会显式跳过,不能算视觉通过。

运行 node scripts/pack-codex-plugin.mjs --no-build 后,
将 BEAUTICODE_RENDERER_PAYLOAD 指向包内 vendor/adapter-codex/payload.js 的 file URL,
再运行 wallpaper.browser.test.js 即可验证最终载荷。
Loading
Loading