Skip to content
Closed
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1 align="center">Awesome Codex Theme</h1>

<p align="center">
Full visual skins for Codex Desktop, backed by real app captures and code-free theme packs.
Full visual skins for Codex Desktop, backed by version-bound app-capture evidence and code-free theme packs.
</p>

<p align="center">
Expand All @@ -23,9 +23,9 @@
<img alt="Code-free packs" src="https://img.shields.io/badge/theme%20packs-code--free-059669">
</p>

![Saint Tibo theme running in the real ChatGPT Beta test bench](screenshots/codex-beta-26.715.3651.0/tibo-reset-saint-dark.png)
![Saint Tibo theme in the ChatGPT Beta v2 reference capture](screenshots/codex-beta-26.715.3651.0/tibo-reset-saint-dark.png)

The screenshot above comes from ChatGPT Beta `26.715.3651.0` after the skin was applied and read back from the live renderer. It is not a wallpaper pasted into an app mockup.
The screenshot above is a real `act-full-skin-runtime-v2` capture from ChatGPT Beta `26.715.3651.0`, after the skin was applied and read back from the live renderer. It is not a wallpaper pasted into an app mockup. The current v3 runtime is source-tested and marked recapture-required, so this image is reference evidence rather than a claim of current v3 app verification.

> Desktop builds are published only on the official [GitHub Releases page](https://github.com/rwang23/awesome-codex-theme/releases). If that page has no asset compatible with your operating system and CPU, there is no supported public installer for that target.

Expand Down Expand Up @@ -131,7 +131,7 @@ The collection currently includes 68 themes and 136 light/dark modes. The Englis
- 2 disclosed, unofficial Codex community tributes;
- the broader original and fan-art catalog, available through language-aware discovery in the Gallery.

Every mode has a 1440×810 capture from the pinned Beta test bench. Registry records bind each capture to the exact app version, background hash, runtime hash, byte count, and renderer readback.
Every mode has a 1440×810 v2 reference capture from the pinned Beta test bench. Registry records bind each capture to the exact app version, background hash, runtime hash, byte count, and renderer readback; the current v3 runtime remains recapture-required until that exact test bench is rerun.

“Saint Tibo” is an affectionate, unofficial community parody. It is not endorsed by OpenAI or by the person depicted, and no official product artwork is bundled.

Expand Down Expand Up @@ -189,7 +189,7 @@ schemas/ Theme Pack and Registry schemas
themes/catalog.json Hand-maintained theme catalog
themes/source-art/ Image jobs, source art, and provenance
themes/registry.json Generated public Registry
screenshots/ Version-pinned real app captures
screenshots/ Version-pinned app-capture evidence
scripts/ Build, validation, capture, and site tooling
site/ Dependency-free Gallery
```
Expand Down
10 changes: 5 additions & 5 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1 align="center">Awesome Codex Theme</h1>

<p align="center">
面向 Codex 桌面版的完整视觉皮肤。主题包不带代码,展示图来自真实应用
面向 Codex 桌面版的完整视觉皮肤。主题包不带代码,展示图是绑定版本的应用截图证据
</p>

<p align="center">
Expand All @@ -23,9 +23,9 @@
<img alt="主题包不带代码" src="https://img.shields.io/badge/theme%20packs-code--free-059669">
</p>

![提博大神主题在真实 ChatGPT Beta 测试台中的效果](screenshots/codex-beta-26.715.3651.0/tibo-reset-immortal-light.png)
![提博大神主题在 ChatGPT Beta v2 参考截图中的效果](screenshots/codex-beta-26.715.3651.0/tibo-reset-immortal-light.png)

上图来自 ChatGPT Beta `26.715.3651.0`:皮肤真正应用到页面并完成运行时读回后才截图,不是把壁纸贴进应用效果图。
上图是 ChatGPT Beta `26.715.3651.0` 中 `act-full-skin-runtime-v2` 的真实截图:皮肤真正应用到页面并完成运行时读回后才截图,不是把壁纸贴进应用效果图。当前 v3 运行时已完成源码测试但标为需要重新采集,因此该图是参考证据,不是对当前 v3 实机验证的声明

> 桌面安装包只会发布在官方 [GitHub Releases 页面](https://github.com/rwang23/awesome-codex-theme/releases)。如果页面上没有与你的操作系统和 CPU 匹配的文件,就表示当前没有支持该目标的公开安装包。

Expand Down Expand Up @@ -132,7 +132,7 @@ Windows 版“应用并保持完整皮肤”已经通过 ChatGPT Beta `26.715.36
- 5 套面向美国工作场景的原创主题,包括海岸工作室和深夜餐馆;
- 1 套 2007 桌面怀旧 Q 版主题,以及 2 套 Codex 社区致意主题。

每个模式都有固定 Beta 测试台生成的 1440×810 实机截图。Registry 会把截图与准确应用版本、背景哈希、运行时哈希、字节数和页面读回结果绑定。
每个模式都有固定 Beta 测试台生成的 1440×810 v2 参考截图。Registry 会把截图与准确应用版本、背景哈希、运行时哈希、字节数和页面读回结果绑定;当前 v3 运行时要在该准确测试台重新采集后,才可成为当前实机验证

“提博大神”是社区表达喜爱的非官方戏仿与致意,不代表 OpenAI 或被描绘者背书,也不包含官方产品素材。

Expand Down Expand Up @@ -189,7 +189,7 @@ schemas/ Theme Pack 与 Registry Schema
themes/catalog.json 人工维护的主题目录
themes/source-art/ image job、源图与 provenance
themes/registry.json 自动生成的公共 Registry
screenshots/ 绑定版本的真实应用截图
screenshots/ 绑定版本的应用截图证据
scripts/ 构建、校验、截图与站点工具
site/ 无依赖 Gallery
```
Expand Down
50 changes: 50 additions & 0 deletions apps/theme-manager/src-tauri/src/catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,46 @@ fn valid_sha256(value: &str) -> bool {
value.len() == 64 && value.chars().all(|character| character.is_ascii_hexdigit())
}

fn validate_runtime_evidence(value: &Value) -> Result<(), String> {
// Registries produced before evidence state existed remain safe to display as
// reference-only in the renderer. New registries must make that state explicit.
if value.is_null() {
return Ok(());
}
let evidence = object(value, "runtimeEvidence")?;
let status = evidence["status"].as_str().unwrap_or_default();
if !matches!(status, "verified" | "reference") {
return fail("Runtime 证据状态无效");
}
let captured = object(&evidence["capturedRuntime"], "capturedRuntime")?;
let current = object(&evidence["currentRuntime"], "currentRuntime")?;
let captured_version = captured["implementationVersion"]
.as_str()
.unwrap_or_default();
let captured_sha = captured["sha256"].as_str().unwrap_or_default();
let current_version = current["implementationVersion"]
.as_str()
.unwrap_or_default();
let current_sha = current["sha256"].as_str().unwrap_or_default();
let verification = current["verification"].as_str().unwrap_or_default();
if captured_version.is_empty()
|| current_version.is_empty()
|| !valid_sha256(captured_sha)
|| !valid_sha256(current_sha)
{
return fail("Runtime 证据记录无效");
}
if (status == "verified"
&& (verification != "verified"
|| captured_version != current_version
|| captured_sha != current_sha))
|| (status == "reference" && verification != "source-tested-recapture-required")
{
return fail("Runtime 证据状态与版本不一致");
}
Ok(())
}

fn valid_hex_color(value: &str) -> bool {
value.len() == 7
&& value.starts_with('#')
Expand Down Expand Up @@ -331,6 +371,7 @@ pub fn validate_registry(bytes: &[u8]) -> Result<Value, String> {
{
return fail("Registry 标准不受支持");
}
validate_runtime_evidence(&registry["runtimeEvidence"])?;

let collections = array(&registry["collections"], "collections")?;
let themes = array(&registry["themes"], "themes")?;
Expand Down Expand Up @@ -670,6 +711,15 @@ mod tests {
assert_eq!(registry["themes"].as_array().map(Vec::len), Some(68));
}

#[test]
fn registry_rejects_malformed_runtime_evidence() {
let mut registry: Value =
serde_json::from_slice(REGISTRY).expect("registry JSON should parse");
registry["runtimeEvidence"]["status"] = json!("unknown");
let encoded = serde_json::to_vec(&registry).expect("registry JSON should encode");
assert!(validate_registry(&encoded).is_err());
}

#[test]
fn native_lookup_rejects_unknown_ids_and_modes() {
let registry = validate_registry(REGISTRY).expect("registry should validate");
Expand Down
8 changes: 4 additions & 4 deletions apps/theme-manager/src-tauri/src/skin_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
const RUNTIME_CSS: &str = include_str!("../../../../packages/full-skin/runtime.css");
const RUNTIME_JS: &str = include_str!("../../../../packages/full-skin/runtime.js");
const RUNTIME_FORMAT: &str = "act-full-skin-v1";
const RUNTIME_IMPLEMENTATION: &str = "act-full-skin-runtime-v2";
const RUNTIME_IMPLEMENTATION: &str = "act-full-skin-runtime-v3";
const MAX_ART_BYTES: usize = 16 * 1024 * 1024;
const APPLY_TIMEOUT: Duration = Duration::from_secs(45);
const CDP_CALL_TIMEOUT: Duration = Duration::from_secs(20);
Expand All @@ -49,7 +49,7 @@ const TARGET_RUNTIME_STATE_TEMPLATE: &str = r#"(() => {
healthy: Boolean(
root.classList.contains("act-full-skin")
&& state?.version === "act-full-skin-v1"
&& state?.implementationVersion === "act-full-skin-runtime-v2"
&& state?.implementationVersion === "act-full-skin-runtime-v3"
&& state?.themeId === expected.themeId
&& state?.mode === expected.mode
&& state?.artwork?.loaded === true
Expand Down Expand Up @@ -1145,7 +1145,7 @@ mod tests {
};
let script = runtime_script(&skin, b"\x89PNG\r\n\x1a\n").expect("runtime should build");
assert!(script.contains("act-full-skin-v1"));
assert!(script.contains("act-full-skin-runtime-v2"));
assert!(script.contains("act-full-skin-runtime-v3"));
assert!(script.contains("test-theme"));
assert!(script.contains("DOMContentLoaded"));
assert!(!script.contains("__ACT_THEME_JSON__"));
Expand Down Expand Up @@ -1189,7 +1189,7 @@ mod tests {
assert!(expression.contains("test-theme"));
assert!(expression.contains("state?.version === \"act-full-skin-v1\""));
assert!(
expression.contains("state?.implementationVersion === \"act-full-skin-runtime-v2\"")
expression.contains("state?.implementationVersion === \"act-full-skin-runtime-v3\"")
);
assert!(expression.contains("state.artUrl.startsWith(\"blob:\")"));
assert!(expression.contains("artValue.includes(state.artUrl)"));
Expand Down
36 changes: 32 additions & 4 deletions apps/theme-manager/src/renderer/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const translations = {
archiveEyebrow: "THEME LIBRARY",
archiveTitleOne: "Find your next",
archiveTitleTwo: "workspace.",
archiveDescription: "Filter by style and collection, then check the real Beta capture before applying.",
archiveDescription: "Filter by style and collection, then check the recorded Beta capture before applying.",
searchPlaceholder: "Search themes, cities, or moods",
allCollections: "All",
rightsFacet: "Source",
Expand All @@ -46,6 +46,11 @@ const translations = {
verifiedCapture: "Real Beta capture",
captureAlt: "real Beta capture",
captureProof: "REAL APP CAPTURE",
referenceCapture: "Recorded Beta capture",
referenceCaptureAlt: "recorded Beta capture",
referenceCaptureProof: "RECORDED APP CAPTURE · RECAPTURE REQUIRED",
captureVersionVerified: "Beta {version} · current",
captureVersionReference: "Beta {version} · reference",
originalRights: "Original · CC0",
fanArtRights: "Unofficial fan art · non-commercial",
applyStep: "APPLY TO CODEX",
Expand Down Expand Up @@ -141,7 +146,7 @@ const translations = {
archiveEyebrow: "主题浏览",
archiveTitleOne: "找到适合你的",
archiveTitleTwo: "工作区。",
archiveDescription: "按风格和系列筛选,应用前先看真实 Beta 截图。",
archiveDescription: "按风格和系列筛选,应用前先看已记录的 Beta 截图。",
searchPlaceholder: "搜索主题、城市或氛围",
allCollections: "全部",
rightsFacet: "来源",
Expand All @@ -160,6 +165,11 @@ const translations = {
verifiedCapture: "Beta 实机截图",
captureAlt: "Beta 实机截图",
captureProof: "真实应用截图",
referenceCapture: "已记录 Beta 截图",
referenceCaptureAlt: "已记录 Beta 截图",
referenceCaptureProof: "已记录应用截图 · 需要重新采集",
captureVersionVerified: "Beta {version} · 当前验证",
captureVersionReference: "Beta {version} · 参考证据",
originalRights: "原创 · CC0",
fanArtRights: "非官方 Fan Art · 非商业",
applyStep: "应用到 Codex",
Expand Down Expand Up @@ -282,8 +292,10 @@ const elements = {
themeList: document.querySelector("#themeList"),
emptyState: document.querySelector("#emptyState"),
modeSwitch: document.querySelector("#modeSwitch"),
captureBadgeLabel: document.querySelector("#captureBadgeLabel"),
captureVersion: document.querySelector("#captureVersion"),
themeCapture: document.querySelector("#themeCapture"),
captureProofLabel: document.querySelector("#captureProofLabel"),
captureHash: document.querySelector("#captureHash"),
collectionName: document.querySelector("#collectionName"),
themeName: document.querySelector("#themeName"),
Expand Down Expand Up @@ -376,6 +388,11 @@ function currentCollection() {
return state.catalog?.collections.find((collection) => collection.id === theme?.collection);
}

function captureEvidenceIsVerified() {
const evidence = state.catalog?.runtimeEvidence;
return evidence?.status === "verified" && evidence.currentRuntime?.verification === "verified";
}

function audiencePriority(record) {
const audience = record?.audience || "global";
if (audience === state.locale) return 0;
Expand Down Expand Up @@ -604,6 +621,10 @@ function renderThemeList() {
} else {
elements.themeCapture.removeAttribute("src");
elements.themeCapture.alt = "";
elements.captureBadgeLabel.textContent = "";
elements.captureVersion.textContent = "";
elements.captureProofLabel.textContent = "";
elements.captureHash.textContent = "";
elements.collectionName.textContent = "";
elements.themeName.textContent = t("emptyState");
elements.themeTagline.textContent = "";
Expand All @@ -619,9 +640,16 @@ function renderSelectedTheme() {
if (!theme) return;
elements.applySkin.disabled = state.targets.length === 0;
const preview = theme.previews[state.mode];
const captureVerified = captureEvidenceIsVerified();
elements.themeCapture.src = preview.imageUrl;
elements.themeCapture.alt = localized(theme.name) + " · " + t(state.mode) + " · " + t("captureAlt");
elements.captureVersion.textContent = preview.capture.appVersion;
elements.themeCapture.alt = localized(theme.name) + " · " + t(state.mode) + " · "
+ t(captureVerified ? "captureAlt" : "referenceCaptureAlt");
elements.captureBadgeLabel.textContent = t(captureVerified ? "verifiedCapture" : "referenceCapture");
elements.captureVersion.textContent = t(
captureVerified ? "captureVersionVerified" : "captureVersionReference",
{ version: preview.capture.appVersion },
);
elements.captureProofLabel.textContent = t(captureVerified ? "captureProof" : "referenceCaptureProof");
elements.captureHash.textContent = shortHash(preview.capture.sha256);
elements.collectionName.textContent = localized(currentCollection()?.name) + " / " + t(theme.variant).toUpperCase();
elements.themeName.textContent = localized(theme.name);
Expand Down
6 changes: 3 additions & 3 deletions apps/theme-manager/src/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
<div class="catalog-copy">
<p class="eyebrow" data-i18n="archiveEyebrow">主题浏览</p>
<h1 id="catalogTitle"><span data-i18n="archiveTitleOne">找到适合你的</span><span data-i18n="archiveTitleTwo">工作区。</span></h1>
<p class="catalog-intro" data-i18n="archiveDescription">按风格和系列筛选,应用前先看真实 Beta 截图。</p>
<p class="catalog-intro" data-i18n="archiveDescription">按风格和系列筛选,应用前先看已记录的 Beta 截图。</p>
</div>
<div class="catalog-update-control">
<span class="catalog-update-copy">
Expand Down Expand Up @@ -111,7 +111,7 @@ <h1 id="catalogTitle"><span data-i18n="archiveTitleOne">找到适合你的</span
</div>
<div class="verified-badge">
<span aria-hidden="true">✓</span>
<strong data-i18n="verifiedCapture">Beta 实机截图</strong>
<strong id="captureBadgeLabel">已记录 Beta 截图</strong>
<small id="captureVersion"></small>
</div>
</div>
Expand All @@ -120,7 +120,7 @@ <h1 id="catalogTitle"><span data-i18n="archiveTitleOne">找到适合你的</span
<div class="capture-glow" aria-hidden="true"></div>
<img id="themeCapture" alt="">
<figcaption>
<span data-i18n="captureProof">真实应用截图</span>
<span id="captureProofLabel">已记录应用截图 · 需要重新采集</span>
<span id="captureHash"></span>
</figcaption>
</figure>
Expand Down
5 changes: 5 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

- Preserved native Full Skin semantic colors and states, scoped runtime repair to
relevant document mutations, and added a synthetic long-session performance
budget. Existing Beta v2 screenshots are now explicit reference evidence;
the current v3 runtime is source-tested and recapture-required rather than
being presented as current app verification.
- Changed the Gallery community section to clearly state that public community
submissions are not open and removed its hosted-community link. Added a
direct Theme Manager download action to the Gallery hero.
Expand Down
Loading