Skip to content

Commit a58e63c

Browse files
authored
[codex] fix community theme import and renderer compatibility (#324)
* fix community theme import and renderer compatibility * fix injector probe privacy gate * fix: align community theme import and renderer verification * fix: keep PowerShell import output deterministic * fix: harden renderer identity and legacy import checks * fix: support Codex 26.727 shell surfaces * docs: record Codex 26.727 follow-up * fix: harden cross-platform community themes * fix: close community theme review gaps * fix: require complete renderer scope on home * docs: record final PR 324 CI * fix: recover interrupted theme replacements * docs: record PR 324 recovery verification
1 parent cd71dfd commit a58e63c

47 files changed

Lines changed: 5872 additions & 483 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.en.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,11 @@ The local simplified ZIP must contain exactly non-empty `theme.json`, non-empty
219219
manifest integrity or compatibility declaration and should come from a trusted
220220
source. Limits are 32 MiB per archive, 32 entries, and 64 MiB expanded. Import
221221
adds the pack to **Saved Themes** without changing the active theme. Identical
222-
content is not duplicated, and a distinct pack with an existing ID is
223-
preserved under a new safe ID.
222+
content is not duplicated. A newer pack with the same ID updates the saved theme
223+
in place after the old directory identity is confirmed, and only legacy `-2`/`-3`
224+
directories with an identical semantic fingerprint are cleaned up. If the
225+
existing directory identity cannot be confirmed, import fails closed instead of
226+
overwriting it; names alone are never used to delete another theme.
224227

225228
For a manual fallback, extract the archive and move the complete directory
226229
containing `theme.json`, `theme.css`, and its image into the saved-theme folder:

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,9 @@ macOS 菜单栏和 Windows 托盘都有「主题库 Gallery」和「在线 Studi
186186

187187
本地简化 ZIP 也必须恰好包含非空 `theme.json`、非空 `theme.css` 和其引用图片;该格式没有正式清单的
188188
完整性与兼容性声明,只应从可信来源使用。压缩包最大 32 MiB、最多 32 个条目、解压后最多 64 MiB。
189-
导入成功后主题只会加入“已保存的主题”,不会自动替换当前主题;相同内容不会重复写入,同 ID 的不同
190-
主题会使用新的安全标识保存。
189+
导入成功后主题只会加入“已保存的主题”,不会自动替换当前主题;相同内容不会重复写入。同 ID 的新版本会在
190+
确认旧目录身份后原地更新,并仅清理语义指纹完全一致、已确认属于同一主题的旧版 `-2`/`-3` 重复目录;无法
191+
确认身份时会拒绝覆盖,也不会根据名称猜测并删除其他主题。
191192

192193
也可以先手动解压,再把包含 `theme.json``theme.css` 和背景图的完整主题目录移动到本机主题库:
193194

TASK_PROGRESS.md

Lines changed: 425 additions & 1 deletion
Large diffs are not rendered by default.

docs/platforms.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Windows 普通启动、失败回滚与恢复重开均从已注册的 `OpenAI.Cod
8787
- 两端只接受普通 `.zip`,明确不兼容 `.dreamskin` 后缀。新的正式 Studio 包必须包含 `manifest.json`、非空 `theme.json`、非空 `theme.css`、恰好一张 `background.webp|jpg|png`,并可选带 `LICENSE.txt``manifest.sig`;文件位于 ZIP 根目录或唯一一层顶级主题目录。仅供本机可信工作流使用的简化格式也必须恰好包含 `theme.json``theme.css` 与其引用图片。
8888
- 导入前限制为 32 MiB 压缩文件、32 个条目和 64 MiB 解压总量,并拒绝路径穿越、链接/reparse、嵌套压缩包、未注册负载以及未通过主题/图片校验的内容。正式包还会核对平台、最低客户端版本及清单中每个负载文件的大小与 SHA-256。
8989
- `theme.css` 必须通过同一份 Safe CSS allowlist,本机在导入和每次应用时都会复验;通过后只作用于 12 个注册 `data-ds-part` 部件。升级前已经保存且没有 CSS 的 legacy 主题仍可使用,但不会注入额外 CSS。`manifest.sig` 是预留文件,当前不验证签名也不写入主题库;`LICENSE.txt` 随主题保留。
90-
- 导入目标始终是 saved themes;不会自动覆盖或应用 active / last-known-good。完全相同的内容返回重复结果同 ID 的不同主题自动保存到新的安全目录
90+
- 导入目标始终是 saved themes;不会自动覆盖或应用 active / last-known-good。完全相同的内容返回重复结果同 ID 的新版本会在确认旧目录身份后原地更新,并仅清理语义指纹完全一致、已确认属于同一主题的旧版 `-2`/`-3` 重复目录;无法确认身份时拒绝覆盖,名称不作为删除其他主题的依据
9191
- 手动解压时,把直接包含 `theme.json``theme.css` 与背景图的完整目录放到 macOS `~/Library/Application Support/CodexDreamSkinStudio/themes/` 或 Windows `%LOCALAPPDATA%\CodexDreamSkin\themes\`。两端控制菜单均提供“打开主题文件夹”;该路径绕过归档校验,只应用于可信内容。
9292

9393
## 预设与图片类型

docs/pr-324-windows-validation.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# PR #324 Windows validation
2+
3+
This document is for the Windows machine or AI validating PR #324. Test the
4+
PR branch only. Do not merge it, publish a Release, or test a binary from an
5+
older workflow run.
6+
7+
## Scope
8+
9+
PR #324 addresses three community-theme failures while keeping macOS and
10+
Windows behavior aligned:
11+
12+
- #318: importing a newer ZIP with the same `theme.json.id` updates the saved
13+
theme in place instead of creating another `-2` entry.
14+
- #320: shared Safe CSS can reach the registered main, sidebar, home, and
15+
composer parts on newer renderer DOMs. This applies to every community theme,
16+
not only colors-only themes.
17+
- #322/#326: Codex `26.727.40816` replaced the legacy main/header classes with
18+
app-shell data attributes and CSS Module classes. The shared selector and CSS
19+
contract now recognizes the current main surface, header, and top-fade while
20+
retaining the legacy anchors. A visible current Codex `app://` renderer can
21+
pass target verification when it has both Codex/ChatGPT identity evidence and
22+
the required structure; unrelated targets still fail closed.
23+
24+
The final review also covers regressions found after the first Windows pass:
25+
26+
- Missing, non-string, or Windows-reserved source IDs are normalized to the
27+
same stable cross-platform ID before the mandatory final payload check. That
28+
check must finish before an existing saved theme is moved or replaced.
29+
- Hidden transaction/recovery directories are never listed as saved themes,
30+
even if an obsolete backup cannot be deleted immediately.
31+
- Validated Safe CSS keeps the website/server glass-filter contract (blur up
32+
to 30 px plus bounded saturate/brightness/contrast), does not erase the
33+
registered wallpaper merely because a root or surface sets a background
34+
color, and still reaches the real composer when a search input appears first.
35+
36+
The import repair is deliberately conservative. A legacy `id-2`/`id-3`
37+
directory is removed only when its stored suffix identity and semantic
38+
fingerprint both prove that it is the same package. A matching display name is
39+
not evidence. Ambiguous directories, unrelated numeric-suffix themes, files,
40+
junctions, and reparse points must be preserved and rejected rather than
41+
overwritten.
42+
43+
## Crash and restart recovery gate
44+
45+
The replacement protocol is shared with macOS and must be checked as a
46+
transaction, not only through the normal `catch` rollback path:
47+
48+
```text
49+
journal -> durable backup -> publish candidate -> verify fingerprint
50+
-> durable committed marker -> cleanup
51+
```
52+
53+
Run the complete Windows ZIP-import suite in both PowerShell 5.1 and 7. It
54+
contains a real process-termination/restart test for the first uncatchable
55+
window and deterministic restart-state coverage for all three windows:
56+
57+
1. after the old canonical directory is moved to its backup;
58+
2. after the candidate is published at the canonical path; and
59+
3. after the durable `committed` marker is published.
60+
61+
The first two states are uncommitted and must restore the exact old semantic
62+
fingerprint on the next importer/store invocation. The third state is committed
63+
and must retain the verified new fingerprint. Every recovery must remove its
64+
transaction files after successful verification and must never show dotted
65+
transaction directories in the tray menu.
66+
67+
The suite also has fail-closed cases for a corrupt candidate, a malformed or
68+
path-conflicting journal, duplicate journals targeting one destination, and an
69+
impossible committed-plus-temporary marker. In those cases the verified old
70+
theme (when available) stays visible, the journal and suspicious payload remain
71+
for diagnosis, and no cleanup or overwrite is attempted. A legacy cleanup
72+
failure after commit is only a bounded warning; it must not roll back the new
73+
canonical theme.
74+
75+
When reporting results, distinguish the exact phase tested (`prepared`,
76+
`old-moved`, `new-published`, or `committed`) and state whether it used the real
77+
FailFast child process or a deterministic restart-state fixture.
78+
79+
## Checkout and automated checks
80+
81+
Record the exact commit before testing:
82+
83+
```powershell
84+
git fetch origin pull/324/head:pr-324
85+
git switch pr-324
86+
git rev-parse HEAD
87+
node --version
88+
```
89+
90+
Use `RemoteSigned`; do not use `ExecutionPolicy Bypass` and do not change the
91+
machine or user execution policy. A normal Git clone should not carry browser
92+
download zone marks. If Windows says a cloned test file is blocked, unblock
93+
only this checkout before retrying:
94+
95+
```powershell
96+
Get-ChildItem -LiteralPath . -Recurse -File | Unblock-File
97+
powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
98+
-File .\windows\tests\run-tests.ps1
99+
```
100+
101+
Also run the portable parity checks:
102+
103+
```powershell
104+
node .\tools\sync-runtime-assets.mjs --check
105+
node .\tools\renderer-runtime.test.mjs
106+
node .\windows\tests\injector-bootstrap.test.mjs
107+
node .\windows\tests\injector-window-readiness.test.mjs
108+
```
109+
110+
If PowerShell 7 is installed, repeat the Windows suite without replacing the
111+
required Windows PowerShell 5.1 run:
112+
113+
```powershell
114+
pwsh.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
115+
-File .\windows\tests\run-tests.ps1
116+
```
117+
118+
All commands must exit `0`. Keep the complete failure output if one does not.
119+
120+
Before manual renderer testing, close Codex and exit the Dream Skin tray, then
121+
install the runtime from this checkout. Do not reuse the engine left by an
122+
older PR head or Release:
123+
124+
```powershell
125+
powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
126+
-File .\windows\scripts\install-dream-skin.ps1
127+
128+
$engine = Join-Path $env:LOCALAPPDATA 'CodexDreamSkin\engine'
129+
foreach ($relative in @(
130+
'assets\dream-skin.css',
131+
'assets\renderer-inject.js',
132+
'assets\safe-css-validator.mjs',
133+
'scripts\injector.mjs',
134+
'scripts\theme-windows.ps1'
135+
)) {
136+
$source = Join-Path (Resolve-Path .\windows) $relative
137+
$installed = Join-Path $engine $relative
138+
if ((Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash -cne
139+
(Get-FileHash -LiteralPath $installed -Algorithm SHA256).Hash) {
140+
throw "Installed engine does not match PR source: $relative"
141+
}
142+
}
143+
```
144+
145+
Record `git rev-parse HEAD` after installation. If any hash differs, stop; the
146+
manual result belongs to another build and is not evidence for this PR head.
147+
148+
The automated generic renderer fixture is deliberately minimal: it contains
149+
only structural anchors such as main, sidebar, composer, and the registered
150+
Codex identity marker. Its typography, native form controls, placeholder copy,
151+
and layout are not product UI and are not visual acceptance evidence. Do not
152+
return a screenshot of that fixture as proof that #320 or #322 is fixed; the
153+
manual checks below must use the real current Codex app.
154+
155+
## Manual import checks (#318)
156+
157+
Use ZIPs that contain non-empty `theme.json`, `theme.css`, and one registered
158+
background image. Importing a ZIP must not change the currently active theme.
159+
160+
1. Import version A, then import a modified version B with the same
161+
`theme.json.id`.
162+
2. Confirm the second notification says that the saved theme was updated.
163+
3. Confirm the Gallery has one entry for that ID and
164+
`%LOCALAPPDATA%\CodexDreamSkin\themes\` has no newly-created `id-2` folder.
165+
4. Import version B again. It must report an exact duplicate and write nothing.
166+
5. Reproduce an old exact `id` plus `id-2` duplicate, then import that same
167+
semantic package. It must consolidate to the canonical `id` directory.
168+
6. Create an independent `id-2` theme with different content, even with the
169+
same display name. Importing `id` must preserve the independent `id-2`.
170+
7. Put a normal file at a candidate canonical theme path. Import must fail and
171+
leave that file byte-for-byte unchanged.
172+
8. Import packages whose source ID is missing, non-string, or Windows-reserved.
173+
Each must receive the documented stable fallback ID and a later equivalent
174+
package must update that same directory. Invalid payloads must fail before
175+
the existing canonical directory is moved.
176+
9. Simulate or retain an obsolete hidden `.theme-replace-*` recovery copy.
177+
The committed new theme may report a cleanup warning, but no dotted
178+
transaction directory may appear in the tray's saved-theme menu.
179+
180+
After each case, confirm there are no hidden `.theme-import-*`,
181+
`.theme-replace-*`, `.theme-legacy-cleanup-*`, or `.theme-failed-*` residues.
182+
If an import fails, the previous canonical theme must still open and its
183+
semantic fingerprint must be unchanged. Any rollback or cleanup failure must
184+
be reported explicitly; it must not be silently swallowed.
185+
186+
## Renderer and target checks (#320/#322)
187+
188+
Use the source-installed engine verified above, then launch the current official
189+
Microsoft Store Codex through DreamSkin. Do not test an older Setup.exe.
190+
191+
1. Apply at least three complete community themes with different Safe CSS,
192+
backgrounds, and token sets. Do not limit this to colors-only themes.
193+
2. Check Home and a normal task view. Main content, sidebar, home surface, and
194+
composer must receive the intended shared styling without styling search,
195+
settings, modal, or unrelated textbox containers as the composer.
196+
Include a view where a search textbox occurs in DOM order before the prompt
197+
composer; the prompt composer must still receive `data-ds-part="composer"`.
198+
3. On Codex `26.727.40816` or newer, confirm the real outer main surface has the
199+
theme background from the very top of the window. There must be no native
200+
white strip or white top-fade left behind. The header controls must remain
201+
visible and keep their native fixed position while scrolling.
202+
4. Confirm the installed verification output reports `scope.level` as `L1` and
203+
an empty `missingL1` list on both Home and the normal task view. A report that
204+
only says injection succeeded is insufficient if any required L1 anchor is
205+
missing. `L0` is accepted only while the Settings route is visibly replacing
206+
the normal shell; it is never a successful Home or task-view result.
207+
5. Confirm sidebar navigation, project selection, task content, composer input,
208+
and send controls remain interactive and readable.
209+
6. Include at least one full-wallpaper theme whose Safe CSS sets a root or main
210+
`background-color`. Its registered wallpaper must remain visible. Also test
211+
a theme using `blur(21px..30px)` with bounded `saturate`, `brightness`, or
212+
`contrast`; it must import and render instead of being rejected by the
213+
client validator.
214+
7. Run the installed verification script and save its screenshot:
215+
216+
```powershell
217+
powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
218+
-File "$env:LOCALAPPDATA\CodexDreamSkin\engine\scripts\verify-dream-skin.ps1" `
219+
-ScreenshotPath "$env:TEMP\dreamskin-pr324.png"
220+
```
221+
222+
8. Restart Codex, reapply a theme, and verify again. A visible real Codex
223+
`app://` renderer must pass exact payload, theme ID, and revision checks.
224+
9. The automated bootstrap negative fixture must still reject an unbranded
225+
`app://` page with only generic main/input structure. Loopback endpoints not
226+
owned by the verified Codex package must also remain rejected.
227+
228+
Windows confirms the shared runtime and Windows adapter. It does not by itself
229+
prove the macOS-specific issue report on Codex 26.727.40816; that remains a
230+
separate macOS/user acceptance check before release.
231+
232+
## Result to return
233+
234+
Report all of the following:
235+
236+
- exact PR commit SHA;
237+
- Windows edition/build, Codex version, and Node version;
238+
- Windows PowerShell 5.1 result and optional PowerShell 7 result;
239+
- first import, same-ID update, exact duplicate, legacy cleanup, independent
240+
suffix preservation, file-collision, fallback-ID, rollback, cleanup-warning,
241+
and hidden-directory menu-filter results;
242+
- the names of the three non-colors-only themes used for renderer testing;
243+
- wallpaper-preservation, composite-filter, and search-before-composer results;
244+
- verification output, screenshot path, and whether restart/reapply passed;
245+
- confirmation that the screenshot came from the real Codex app, not the
246+
generic renderer fixture;
247+
- sanitized `injector.log`, `injector-error.log`, and `verify.log` excerpts for
248+
any failure. Remove tokens, private paths, and conversation content.

macos/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ themes without CSS remain switchable and inject no additional CSS.
135135

136136
An import only adds to **已保存的主题**. It never replaces or applies the
137137
active/last-known-good copy. Reimporting identical content reports a duplicate;
138-
a different pack using an existing ID is saved under a new safe ID.
138+
a newer pack with the same ID replaces the saved copy in place after its stored
139+
identity is confirmed. Only a legacy suffix directory (`-2`, `-3`, and so on)
140+
with an identical semantic fingerprint is consolidated; names alone never prove
141+
that a directory is a duplicate, so ambiguous entries are preserved.
139142

140143
Manual fallback: choose **打开主题文件夹**, or open
141144
`~/Library/Application Support/CodexDreamSkinStudio/themes/`, then move in the

0 commit comments

Comments
 (0)