Skip to content

feat(material): add gamut coverage and solver cache workbench - #299

Open
sandboxdream wants to merge 1 commit into
mainfrom
shmx/feat/material-gamut-workbench
Open

sandboxdream wants to merge 1 commit into
mainfrom
shmx/feat/material-gamut-workbench

Conversation

@sandboxdream

@sandboxdream sandboxdream commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Material Management lacked a dedicated workflow for comparing a combination’s reachable gamut and each material’s contribution. Fixed-layer cache controls were confined to a converter dialog. This PR adds Gamut Coverage and Solver Cache pages under the existing Material Management section. They share the material combination, layer height, and fixed layer count or dynamic layer range:

  • Gamut Coverage shows sRGB coverage in 5 ΔE Lab cells, match-error estimates by color family, lightness range, a scatter plot, and each material's contribution. A contribution is measured by removing that one material at the same layer count and candidate budget. Dynamic mode also shows cumulative coverage for each layer cap. If the selection changes, the previous result stays on screen with a stale warning.
  • Solver Cache reads only metadata to show status. It keeps the existing exhaustive/smart actions for fixed layer counts and adds prebuild and delete for dynamic mode. Async cache results that arrive after the selection changes are discarded.
  • View gamut and Manage cache links in the converter bring the current materials into the page. Changes made on the page do not change converter settings.

Dynamic per-layer candidates are stored apart from fixed-layer caches. Dynamic mode can reuse manual smart caches, but deleting prebuilt dynamic caches never removes the manual ones. Compute requests share the build concurrency limit. A request that waits more than 30 s for a slot gets a retryable structured 503. Endpoints are documented in docs/material-workbench.md.

Validation

Codex ran the backend checks with Python 3.12 and the frontend checks with the pinned pnpm toolchain:

  • The smoke workflow passed: 181 backend smoke cases, the frontend smoke suite, and lint. The existing -m smoke test selection was unchanged. Lint excluded only pre-existing untracked .scratch scripts.
  • Separately, 216 targeted backend cases and 91 targeted frontend cases passed.
  • A small log-level change was made last. After it, 44 API/error/logging retests and the fast log quality workflow passed.
  • pnpm build and git diff --check passed.

Not run: the full regression suite and manual browser checks.

AI assistance

Models and tools: GPT-6 Astra via Codex; Claude Fable 5.2 (claude-fable-5-2) via Claude Code; Claude Opus 5.5 (claude-opus-5-5) via Claude Code.

What each model helped with: GPT-6 Astra implemented the final change on a topic branch based on main, fixed review findings, added tests and documentation, and ran the checks. Claude Fable 5.2 reviewed the diff and re-checked the fixes without editing code. Claude Opus 5.5 (claude-opus-5-5) drafted this description.

Notes

  • Match error is an explicit approximation: for each target color, it is the minimum CIEDE2000 among the eight nearest Lab neighbors. It is not a guaranteed global minimum.
  • "Complete" candidates means colors from every possible stack are represented. Duplicate colors may be deduplicated. Bucketed or partially sampled caches are shown as "approximate".
  • Dynamic-mode contributions use the maximum layer count, so they are a different metric from total dynamic coverage.

摘要

耗材管理此前缺少组合色域与逐耗材贡献的分析入口,固定层数缓存管理集中在转换页弹窗中。本 PR 在现有「耗材管理」下新增「色域覆盖」与「求解缓存」两个页面,共享耗材组合、层高,以及固定层数或动态层数范围:

  • 色域覆盖:显示 5 ΔE Lab 单元下的 sRGB 覆盖率、按颜色组统计的匹配误差估计、亮度范围、散点图和各耗材的贡献。贡献的算法是在相同层数和候选预算下移除该耗材。动态模式还会显示每个层数上限下的累计覆盖率。选择变更后,旧结果仍然显示,并带有过期提示。
  • 求解缓存:只读取元数据来显示状态。固定层数沿用原有的穷举/智能缓存操作,动态模式新增预构建和删除。选择变更后才返回的异步缓存结果会被丢弃。
  • 转换页的「查看色域」「管理缓存」链接会把当前耗材带入该页面。在该页面所做的修改不会改动转换设置。

动态逐层候选与固定层数缓存分开存放。动态模式可以复用手动智能缓存,但删除动态预构建缓存时不会删除手动缓存。计算请求共享构建并发限制,等待构建名额超过 30 秒时返回可重试的结构化 503。接口说明见 docs/material-workbench.md。

验证

以下检查由 Codex 使用 Python 3.12 和项目固定版本的 pnpm 运行:

  • smoke 流程通过:181 个后端 smoke 用例、前端 smoke 套件和 lint 均通过。原有的 -m smoke 测试选择没有改动。lint 只排除了已有的、未跟踪的 .scratch 脚本。
  • 另外,216 个针对性后端用例和 91 个针对性前端用例通过。
  • 最后改了一处日志级别。改动后,44 个 API/错误/日志复测用例和 fast 日志质量流程通过。
  • pnpm build 和 git diff --check 通过。

未运行:完整回归测试、浏览器手动验证。

AI 协助

模型与工具: GPT-6 Astra,通过 Codex;Claude Fable 5.2(claude-fable-5-2),通过 Claude Code;Claude Opus 5.5 (claude-opus-5-5),通过 Claude Code。

各模型的作用: GPT-6 Astra 在基于 main 的主题分支上实现了最终改动,修复审阅中发现的问题,补充了测试和文档,并运行了检查。Claude Fable 5.2 审阅了 diff 并复核修复,没有修改代码。Claude Opus 5.5 (claude-opus-5-5) 撰写了本说明。

备注

  • 匹配误差是明确的近似值:对每个目标颜色,取其八个最近 Lab 邻居中的最小 CIEDE2000,不保证是全局最小值。
  • 候选「完整」表示每种可能叠层的颜色都有体现。重复颜色可能被去重。分桶或未完整采样的缓存标为「近似」。
  • 动态模式下的耗材贡献按最大层数计算,与动态总覆盖率不是同一个指标。

Add material gamut coverage and fixed/dynamic cache management pages.
Preserve current converter controls and harden cache concurrency, ownership,
asynchronous status updates, and domain error mapping.

新增耗材色域覆盖与固定、动态层数缓存管理页面。
保留当前转换界面,完善缓存并发与归属、异步状态及领域错误映射。
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-12T21:00:57.094934Z 12f889e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12f889ef63

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3613 to +3614
try:
return await anyio.to_thread.run_sync(run)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Dispatch heavy material computations to process workers

For cold-cache coverage, contribution analysis, and dynamic preparation, this executes candidate generation, catalog merging, and gamut analysis inside the API process rather than a process worker. Moving the closure to an AnyIO thread does not provide the required process isolation, and concurrent requests also occupy shared thread-pool slots while waiting up to 30 seconds for the build semaphore, potentially delaying unrelated synchronous API work. Dispatch the heavy operations through top-level, picklable worker entry points, keeping validation and error translation in the route. This violates the CPU-heavy-work placement requirement in AGENTS.md.

AGENTS.md reference: AGENTS.md:L33-L33

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant