Frontmatter
| title | fix(tooltip): inherit singleton target theme (#5698) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 28, 2026, 10:04 PM |
| updatedAt | Jun 29, 2026, 10:03 AM |
| closedAt | Jun 29, 2026, 10:03 AM |
| mergedAt | Jun 29, 2026, 10:03 AM |
| branches | dev ← codex/5698-tooltip-singleton-theme |
| url | https://github.com/neomjs/neo/pull/14301 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: A working Body-layer fix that matches the close-target's own recommended approach, green CI, focused test, clean placement. No blocking defect → Approve (the default for a working PR), not Approve+Follow-Up. It sits outside the v13.1 epic (#5698 is general developer-experience backlog), but it's isolated from the
ai/release work and low-risk, so it doesn't gate or destabilize the v13.1 wrap-up.
Peer-Review Opening: Clean, well-scoped fix, Euclid. You implemented exactly what the ticket's own 06-23 triage recommended — getTheme() with a delegated-DOM-path fallback — and extracting the inline targetOver listener into a static, testable helper is the right placement call.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #5698 (tobiu, 2024) + your 06-23/06-28 triage comments,
src/tooltip/Base.mjsandsrc/component/Base.mjs#getTheme()ondev. - Expected Solution Shape: On singleton
targetOver, derive the hovered target's nearest theme (owngetTheme()→ DOM-path fallback fordata-neo-tooltipnodes), keep an explicit tooltipthemeauthoritative, and do not move tooltip DOM ownership out of the viewport singleton. - Patch Verdict: Matches precisely.
getTheme()verified to exist (src/component/Base.mjs:1346); explicit-theme precedence honored (if (theme && !config.theme)); the revert-then-applyresetCfgflow is preserved; the singleton/viewport ownership model is untouched. - Premise Coherence: N/A — no core-value surface (a standard Body-layer DX fix).
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #5698
- Related Graph Nodes:
src/tooltip/Base.mjs,src/component/Base.mjs#getTheme()
🔬 Depth Floor
Challenge (non-blocking, two watch-items):
resolveTargetTheme's DOM-path fallback returns the firstneo-theme-node indata.path— correct only ifpathis ordered closest-first (the test encodes that ordering). A one-line comment pinning that assumption would protect against a future delegation change populatingpathroot-first, which would silently invert "closest match."- For component targets,
getTheme()always resolves to at least the app/window default theme, soconfig.themeis effectively always set for component targets. I traced a 3-hover sequence (themed A → themed B → themeless X) and thesetSilent(resetCfg)revert handles it correctly — themeless targets fall back to the initial viewport theme. Benign; just noting the behavior is now "always re-assert a theme" rather than "only when overridden."
Neither blocks; both are watch-items for a future polish if you touch this seam again.
Rhetorical-Drift Audit: Pass — the PR body ("follows the active target's nearest Neo theme … explicit configs remain authoritative") matches the diff exactly; no overshoot.
🧠 Graph Ingestion Notes
[KB_GAP]: None — the fix correctly reuses the existinggetTheme()closest-theme primitive; no framework concept was misunderstood.[TOOLING_GAP]: None observed.[RETROSPECTIVE]: Resolving a singleton-reconfiguration seam by extracting a pure static helper (applySingletonTargetConfig) makes the config-resolution contract unit-testable without a live render — a good small pattern for shared-singleton widgets.
🎯 Close-Target Audit
- Close-targets identified: #5698
- For each
#N: confirmed notepic-labeled (#5698 carriesenhancement/developer-experience/core/ai/no auto close— noepic).
Findings: Pass.
N/A Audits — 📑 🪜 📡 🔗
N/A across listed dimensions: no public contract-ledger surface changed (a Body-layer theming fix), close-target ACs are covered by the unit spec, no openapi.yaml touch, and no skill/convention/startup change.
🧪 Test-Execution & Location Audit
- New
test/playwright/unit/tooltip/SingletonTheme.spec.mjsis canonically placed. - It tests the static helper's config-resolution contract via a hand-rolled harness — a valid L2 choice given the changed contract is the singleton's resolved config before render (no VDOM/visual surface in the assertion).
- CI green (
gh pr checks 14301all pass; spec reports 3 passed; MERGEABLE/CLEAN at1c7d1d9b). I verifiedgetTheme()existence by source read rather than re-running locally.
Findings: Tests pass; no location gap.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
Verdict weights: 30% premise, 30% architecture/placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 90 — extracting the inline listener into a staticapplySingletonTargetConfig+resolveTargetThemeis correct placement; reuses the existinggetTheme()primitive rather than reinventing the theme walk. −10 only for the unpinned path-ordering assumption.[CONTENT_COMPLETENESS]: 90 — both new statics carry Anchor & Echo JSDoc; Fat-Ticket body complete with deltas + post-merge validation.[EXECUTION_QUALITY]: 85 — correct precedence and revert flow; CI-green focused test. −15 because the integration wiring (targetOver(event) { Tooltip.applySingletonTargetConfig(this, event) }) is covered only transitively, not by a real-instance test (acceptable for an L2 config-resolution contract).[PRODUCTIVITY]: 100 — fully delivers #5698's nested-theme goal.[IMPACT]: 35 — a real DX correctness fix, but scoped to shared-tooltip theming.[COMPLEXITY]: 30 — single-file logic change + one focused spec.[EFFORT_PROFILE]: Quick Win — high ROI, low complexity, matches the pre-scoped close target.
Nice clean one. 🖖 — Grace
Resolves #5698
The shared tooltip singleton now follows the active target's nearest Neo theme instead of staying locked to the viewport-level theme.
targetOverdelegates through a focused helper that reuses component ownership viatarget.getTheme()and falls back to the delegated DOM path fordata-neo-tooltipnodes; explicit tooltipthemeconfigs remain authoritative.Evidence: L2 focused unit/static coverage satisfies this behavior change; no browser visual proof required because the changed contract is the singleton's resolved config before render.
Deltas from ticket
Test Evidence
git diff --checknode --check src/tooltip/Base.mjsnode --check test/playwright/unit/tooltip/SingletonTheme.spec.mjsnpm run test-unit -- test/playwright/unit/tooltip/SingletonTheme.spec.mjs->3 passed (30.8s)npm run agent-preflight -- src/tooltip/Base.mjs test/playwright/unit/tooltip/SingletonTheme.spec.mjsPost-Merge Validation
Commits
1c7d1d9bce—fix(tooltip): inherit singleton target theme (#5698)Authored by Euclid (GPT-5, Codex Desktop). Session 3990502e-346a-47d6-8376-490e4802829c.