Skip to content

workbuddy: 5.5.6 / 5.6.0 field notes on opaque backplates, appearance pairing, and diagnosis - #6

Open
Daizhdd wants to merge 5 commits into
CodeDrobe:mainfrom
Daizhdd:patch-1
Open

Daizhdd wants to merge 5 commits into
CodeDrobe:mainfrom
Daizhdd:patch-1

Conversation

@Daizhdd

@Daizhdd Daizhdd commented Sep 16, 2026 •

Copy link
Copy Markdown

What this adds

Two files under skills/codedrobe-theme/references/:

  • workbuddy.md — mostly additions, plus two corrections to lines that were wrong (see Scope).
  • workbuddy.zh.md — new, the Chinese version of that file, following this repo's README.md / README_zh.md convention.

Field notes gathered while building a wallpaper skin for WorkBuddy on Windows:

  • The opaque backplates that hide an applied wallpaper — the ten surfaces the renderer paints on top of the injected background, with the three traps we hit: .wb-home-route exists on the home route only (so a theme can look right in a conversation and washed out on home); [class*="grid_"] over-matches (artifact-slot-panel__grid); and the content plate's CSS-Module hash class moves between releases (_gridViewItem_<hash> on 5.5.6 became _gridView_7xbcw_9 on 5.6.0, alongside a new .teams-grid-scroll-content), so it has to be matched by a stable prefix rather than a full name.
  • Routes and the appearance mechanism — .conversation-shell / .wb-home-route, and the fact that appearance is driven by the data-theme attribute rather than the light / cb-light classes, so html[data-theme="dark"] { … } lets one package adapt.
  • The wallpaper-brightness ↔ host-appearance pairing rule, with a closed-form scrim derived from the image's mean luminance, plus the caveat that mean luminance misses how busy an image is.
  • How to diagnose "apply succeeded but nothing changed" — two thirty-second pre-checks first (did this launch inject at all? a bare relaunch after an update carries no debug port; and is the asset actually fine? read the wallpaper property, fetch its blob, decode it), then walk the ancestor chain from elementFromPoint and enumerate opaque elements without an area threshold.
  • Why a scripted appearance switch must not be used to verify colours — hand-setting data-theme leaves colours the app writes in its own render pass at their previous values, which reads as "this colour ignores the theme".
  • The surfaces that should deliberately stay opaque — the right detail panel and conversation content cards.

Why

references/workbuddy.md describes the stable landmarks well, but not what the renderer paints on top of them. That gap is expensive in practice: an apply reports full success while the window looks completely untouched, and the cause turns out to be a solid backplate several ancestors up. Everything above is what it took to find it; writing it down should save the next person the same hunt.

Scope

Docs only.

  • No runtime code, no new Skill, no selector added to the adapter.
  • Everything is version-scoped to 5.5.6 / 5.6.0 and labelled as such — these are class names that move between releases (the content plate's hash class already did), and the file now says to re-derive rather than trust the table.
  • Existing content is unchanged apart from two corrections: the .wb-home-route note (it really is a <main>, but it is a sibling underlay, so the ancestor walk never reaches it) and the .collapsible-section-header note (it is clearable with a higher-specificity selector — the earlier "cannot be cleared" conclusion came from reading getComputedStyle in the same JS evaluation that injected the style, which returns the stale value).
  • No generated packages, screenshots, credentials or reference images.

Deliberately not in this PR

  • The scrim computation itself. We solved it with a small out-of-band script (mean luminance → one scrim per appearance). Per CONTRIBUTING, deterministic runtime behaviour belongs in Core rather than Skills, so I left it out. Happy to open a separate issue on CodeDrobe/core if that direction is interesting — the pairing rule is what makes "point it at any image" work without hand-tuning.
  • A Windows batch hygiene trap. If a workflow hands the user a .bat launcher it must be CRLF and ASCII-only; LF-only endings make cmd mis-split lines and execute rem comment text as commands, and non-ASCII bytes in the body get mangled by the code page. Kept out because it is not WorkBuddy-specific. Say the word if you want it somewhere.

Validation

A doc-only change to a references/ file, so the catalog discovery in npm test (and the Skill Creator validator) is unaffected.

Being upfront: I did not run npm test or the validator locally — this environment has no clone of the repo. Happy to do that first if you prefer.


中文摘要

references/workbuddy.md 现在已经写清了稳定的地标,但没写渲染层在地标之上又画了什么。这个缺口代价很高:apply 完整报告成功,窗口却看起来毫无变化,原因是有个实色底板在好几层祖先之上。下面这些就是把它们找出来所花的功夫:

  • 5.5.6 / 5.6.0 上会盖住壁纸的 10 个实色底板,含三个坑:.wb-home-route 只有首页路由有(所以会出现「会话页正常、首页发白」);[class*="grid_"] 会误伤 artifact-slot-panel__grid;内容区白板的 CSS Module 哈希类名会随版本变(5.5.6 是 _gridViewItem_<hash>,5.6.0 变成 _gridView_7xbcw_9,还多了一层 .teams-grid-scroll-content),只能按稳定前缀匹配。
  • 路由与外观机制:会话容器是 .conversation-shell、首页是 .wb-home-route;外观由 data-theme 属性驱动,只换 light/cb-light 类名无效 —— 因此 html[data-theme="dark"] { … } 能让一个主题包自适应。
  • 壁纸明暗必须与宿主外观配对,附由图片平均亮度推出的闭式解蒙层公式,以及「平均亮度看不出图案密疏」这个补充。
  • 诊断「apply 成功但没变化」:先做两步 30 秒的前置检查(这次启动到底注入了没 —— 升级后裸启动没有调试端口;图和 CSS 是不是好的 —— 读变量、fetch blob、解码确认),再从 elementFromPoint 往上回溯;枚举不透明元素时不要用面积阈值过滤。
  • 不要用脚本切外观来验颜色:手改 data-theme 后读到的还是上一个外观的值,看起来像「颜色不跟随主题」。
  • 应当刻意保持不透明的表面:右侧详情面板、会话内容卡片、按钮与头像。

范围声明:纯文档。不含运行时代码、不新增 Skill、不给适配器加选择器。全部按 5.5.6 / 5.6.0 限定并已注明需随版本重新推导(内容区白板的哈希类名已经变过一次)。原有内容基本未动,有两处是修正:.wb-home-route 那条(它确实是 <main>,但它是兄弟层,回溯法到不了它)和 .collapsible-section-header 那条(它可以用更高优先级的选择器清掉 —— 先前「清不掉」的结论,是因为在同一次 JS 求值里「注入样式 + 读 getComputedStyle」读到了旧值)。

刻意没放进本 PR 的两件事:

  1. 蒙层的计算本身 —— 我们用一个外挂脚本解决(平均亮度 → 每种外观一个值)。按 CONTRIBUTING,确定性运行时行为应归 Core,所以没放进来,可另开 issue 讨论。
  2. 一个 Windows 批处理的坑 —— 交给用户的 .bat 必须 CRLF + 纯 ASCII,否则 cmd 会错切行、把 rem 注释当命令执行。因为它与 WorkBuddy 无关,故未包含。

中文版另附 workbuddy.zh.md,沿用本仓库 README.md / README_zh.md 的分文件惯例。

…ring, and diagnosis

Expanded documentation on UI elements, themes, and appearance handling. Added details on wallpaper brightness and diagnosing rendering issues.
- `.wb-home-route` is a real `<main>` but not an ancestor of the home
  content: it is a sibling underlay, so walking up from `elementFromPoint`
  never reaches it. That is the mechanism behind "right in a conversation,
  white on home". Write the selector without a tag name.
- The ancestor walk has that blind spot in general; enumerate opaque
  elements whenever it comes back clean and the result is still wrong.
  Verify clears by reading the computed background, not by reading the CSS.
- `.collapsible-section-header` cannot be cleared from a theme: the app's
  own important rule wins against a (0,4,1) important override, and
  redefining --cb-sidebar-bg / --wb-sidebar-bg does not help. Leave it native.
- New section: a wallpaper-only theme contains no geometry. The home hero is
  a centred title painted over by the plate, so any width / max-width / gap /
  min-height / padding on .wb-home-page or .wb-home-header clips it and
  detaches the scene tabs. Symptom, cause, and the minimal shape of the file.
- New scrim caveat: an over-heavy veil inverts a bimodal image's tonality.
  At .93 the light half landed at 28 while the dark half sat at 46 under a
  lighter .62, collapsing the sidebar into a flat black band. Pick the floor
  so the light-art region matches the rest of the window, and measure a row
  of the screenshot rather than eyeballing it.

Docs only; no runtime code, no new Skill, no adapter selectors.
…arable

The previous commit claimed `.collapsible-section-header` cannot be cleared
from a theme. That was wrong, and it was wrong because of how it was measured.

The app paints it from `.conversation-section-content
[class^="collapsible-section"] > [class*="header"]` at (0,3,0) with
!important, so the obvious (0,2,1) selector loses. Adding [data-theme] and a
container class reaches (0,4,1) and clears all five headers.

The real trap: injecting a style and reading getComputedStyle in the SAME JS
evaluation returns the stale value. That looks exactly like "this plate cannot
be overridden" and is how the working override got written off. Inject in one
call, let a frame pass, read in the next.

Also record that redefining --cb-sidebar-bg / --wb-sidebar-bg does not work
(the app defines them at higher specificity), so overriding the conflicting
property directly is the simpler route. Dark appearance makes the difference
unmistakable: the native rgb(31,31,31) header against a veiled sidebar of ~72
is five flat black bars.

Docs only.
The content plate was renamed and a second one appeared, so a theme that
clears 5.5.6 correctly paints nothing on 5.6.0:

  * `_gridViewItem_<hash>` is now `_gridView_7xbcw_9`
  * `.teams-grid-scroll-content` is new, also 1256x746 of solid white

Neither is reachable by the ancestor walk, so the window just goes white and
looks identical to "the theme never applied".

The lesson is to match the stable prefix (`[class*="gridView"]`) instead of a
full name, and specifically not to narrow a documented prefix for the sake of
precision — the narrowed form is what caused this here. Note that `_gridView_`
does not match `_gridViewItem_` nor the reverse, because the trailing
underscore is part of the substring, so both spellings are needed to span both
releases.

Add two pre-checks to the diagnosis section, because both cost real time before
the plate was found:

  * whether this launch injected anything at all — a bare relaunch after an
    update carries no debug port, so nothing was ever applied
  * whether the image and stylesheet are fine — read the wallpaper property,
    fetch its blob, decode it with Image(); if all three pass, the only
    remaining explanation is occlusion, which skips a detour into CSP and
    object-URL-lifetime theories that were all wrong

Also record the home composer plate (`.cr-input-box__main`): it paints a
gradient on `background-image` while `background-color` reads transparent, so
checking only the colour channel declares it clear when it is not.

Docs only.
@Daizhdd Daizhdd changed the title workbuddy: add 5.5.6 field notes on opaque backplates, appearance pairing, and diagnosis workbuddy: 5.5.6 / 5.6.0 field notes on opaque backplates, appearance pairing, and diagnosis Sep 19, 2026
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