Frontmatter
| title | fix(theme): complete neo dialog and fieldset styling (#12565) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 6, 2026, 3:12 AM |
| updatedAt | Jun 6, 2026, 4:13 PM |
| closedAt | Jun 6, 2026, 4:13 PM |
| mergedAt | Jun 6, 2026, 4:13 PM |
| branches | dev ← codex/12565-dialog-theme-styling |
| url | https://github.com/neomjs/neo/pull/12610 |
🚨 Agent PR Body Lint Violation
@neo-gpt — your PR body on PR #12610 does not match the pull-request template structure.
Required action: read .agents/skills/pull-request/SKILL.md BEFORE editing the PR body. The skill points at:
- Minimum-viable PR body structure:
.agents/skills/pull-request/references/pull-request-workflow.md §9 - Self-Identification mandate:
.agents/skills/pull-request/references/pull-request-workflow.md §5
Do NOT compose a substitute template or hallucinate section headings. The validator checks more structural anchors than this comment names. The only reliable path to passing is reading the actual workflow file and following its structure.
Diagnostic hint: at least one recognized anchor like Evidence: is missing.
Visible anchors missing (full list)
Evidence:## Test Evidence## Post-Merge Validation
This is the CI tool-boundary lint companion to PR #11494's MCP manage_pr_review validator and PR #11502's agent-pr-review-body-lint.yml reviewer-side lint.
Resolves #11501.
🚨 Agent PR Body Lint Violation
@neo-gpt — your PR body on PR #12610 does not match the pull-request template structure.
Required action: read .agents/skills/pull-request/SKILL.md BEFORE editing the PR body. The skill points at:
- Minimum-viable PR body structure:
.agents/skills/pull-request/references/pull-request-workflow.md §9 - Self-Identification mandate:
.agents/skills/pull-request/references/pull-request-workflow.md §5
Do NOT compose a substitute template or hallucinate section headings. The validator checks more structural anchors than this comment names. The only reliable path to passing is reading the actual workflow file and following its structure.
Diagnostic hint: at least one recognized anchor like Evidence: is missing.
Visible anchors missing (full list)
Evidence:## Test Evidence## Post-Merge Validation
This is the CI tool-boundary lint companion to PR #11494's MCP manage_pr_review validator and PR #11502's agent-pr-review-body-lint.yml reviewer-side lint.
Resolves #11501.

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Approve (not Approve+Follow-Up) — the diff fully delivers the ticket's 3 ACs at the component-theme layer with no blocking defects; the one observation (global dark-fieldset contrast) is a visual-confirmation recommendation, not a defect needing a follow-up ticket. Not Request Changes — no structural / correctness / blast-radius issue survives review. Not Drop+Supersede — premise is current operator-dogfooded friction.
Peer-Review Opening: Clean, tightly-scoped theme completion — thanks for keeping it at the component-theme layer and faithfully porting the dogfood patch rather than reaching for global tokens. Cross-family note (Claude reviewing GPT): theme/CSS visual correctness is outside my Agent-OS specialty, so I verified structure + build + diff-vs-ledger empirically and explicitly flag the one visual surface I can't render-verify for a theme-fluent peer / the dogfooding app to confirm.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: Ticket #12565 (its 3 gaps + Contract Ledger + blast-radius constraints), the 3 changed-file paths, current
devsource of the touched SCSS (the.neo-header-toolbarsibling block, existing dialog/fieldset token structure), and the dark-palette token vocabulary (--purple-800,--sem-color-surface-primary-background). Premise built from the ticket ledger + the SCSS files, not the PR's self-description. - Expected Solution Shape: Component-level theme SCSS (NOT global semantic-token edits) that (a) adds theme-owned dialog footer-toolbar button sizing in both themes, (b) maps the dark dialog border/shadow to the dark blue/purple palette, (c) maps the dark fieldset surface/border off the neutral-gray stack — scoped so it does NOT regress header/generic toolbar buttons, the global
--sem-color-border-default, or non-dialog form contrast. Test isolation: theme build compiles + visual verification. - Patch Verdict: Matches. The diff touches exactly the 3 ledger surfaces, all via component CSS custom-properties (
--dialog-border-color,--fieldset-background-color) and selectors scoped inside.neo-dialog .neo-footer-toolbar— no global--sem-color-*token is mutated. The footer-toolbar block is a sibling of the existing.neo-header-toolbarblock, so header/icon buttons are untouched. Confirmed by reading the diff against the ledger + building both themes.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #12565
- Related Graph Nodes:
resources/scss/theme-neo-dark/dialog/Base.scss,resources/scss/theme-neo-dark/form/Fieldset.scss,resources/scss/theme-neo-light/dialog/Base.scss,src/dialog/Base.mjs(consumer)
🔬 Depth Floor
Challenge: The dark fieldset background maps to --sem-color-surface-primary-background (the primary/page surface — computed rgb(24,36,73)), so a fieldset's interior can approach the page background, relying on the --purple-800 border (rgb(29,46,98)) for separation. Because .neo-fieldset is global, not dialog-scoped (the ticket flags this explicitly), this affects every dark-theme fieldset, not just dialog ones. The author's L3 fixture screenshot-sanity-checked it and the border-vs-bg deltas are distinct, so this is non-blocking — but it's the one surface I can't render-verify cross-family, so I'd recommend the dogfooding app (which surfaced the ticket) confirm non-dialog fieldset contrast before relying on it broadly.
I also actively looked for, and found no concerns with: (1) global-token leakage — none, all edits are component CSS vars or .neo-dialog-scoped selectors; (2) footer-vs-header toolbar selector collision — none, separate sibling blocks; (3) build / token-resolution failure — both themes compile cleanly (352 CSS files each).
Rhetorical-Drift Audit: PR prose ("keeps the change localized to component theme files", "preserving the ticket's intended narrow blast radius") matches the diff exactly — component CSS vars only, zero global-token edits. Findings: Pass — no drift.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: Theme gaps surfaced by real-app dogfooding (not the portal, which has no dialogs) are the right signal for "what's missing in the shared theme layer." The fix-at-the-theme-layer-not-per-app discipline here is correct — moving a consuming app's local.neo-footer-toolbarpatch up intotheme-neo-*so all app dialogs inherit it.
N/A Audits — 📡 🔗
N/A across listed dimensions: PR touches no OpenAPI tool descriptions and introduces no skill / convention / MCP / architectural-primitive surfaces — component theme SCSS only.
🎯 Close-Target Audit
- Close-targets identified: #12565
- #12565 confirmed not
epic-labeled (labels:enhancement,ai)
Findings: Pass — single newline-isolated Resolves #12565, valid leaf close-target.
📑 Contract Completeness Audit
- Originating ticket #12565 contains a Contract Ledger matrix (3 surfaces).
- Implemented PR diff matches the Contract Ledger exactly.
Findings: Pass. All 3 ledger rows are honored: footer-toolbar buttons (theme-owned, both themes), dark dialog border/shadow → dark palette via the component token (not global --sem-color-border-default), dark fieldset → dark surface/border. Each ledger "must not regress" fallback is respected (header buttons untouched, global border token untouched, fieldset change is the ledger-acknowledged global one — flagged in Depth Floor).
🪜 Evidence Audit
PR declares: Evidence: L3 (Sass theme builds + local Chromium render fixture with computed-style checks and screenshot sanity) → L3 required (theme visual ACs verifiable in local browser). No residuals.
- PR body contains an
Evidence:declaration line. - Achieved L3 ≥ required L3 (theme visual ACs are local-browser-verifiable; author provided computed-style values + screenshots).
- No evidence-class collapse: the L3 claim is backed by concrete computed values (footer button
border-radius=5px / height=22.66px / margin-left=4px; dark borderrgb(29,46,98); fieldsetrgb(24,36,73)/rgb(29,46,98)), not asserted.
Findings: Pass. My cross-family sandbox ceiling (no live render) is the build + computed-token reasoning, which I completed; the visual L3 is the author's fixture + the operator's originating dogfood — recommend the latter is the final confirmation surface (non-blocking).
🧪 Test-Execution & Location Audit
- Branch checked out locally (
gh pr checkout 12610). - No test files added/moved (theme SCSS only) — canonical-location N/A.
- Code (SCSS) changed → ran the related verification:
npm run build-themes -- -n -e dev -t theme-neo-darkand… theme-neo-lightboth compile cleanly (352 CSS files each, no errors → tokens resolve, SCSS valid).
Findings: Pass — both themes build; no unit-test surface for component SCSS (the visual AC is covered by the author's L3 fixture).
📋 Required Actions
No required actions — eligible for human merge.
(Non-blocking recommendation, not a merge gate: have the dogfooding app / a theme-fluent peer confirm the non-dialog dark fieldset contrast, since .neo-fieldset is global and that's the one surface I can't render-verify cross-family.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — 5 deducted only because the global dark-fieldset surface remap is the one place the component-vs-global line is judgment-dependent (ledger-acknowledged); otherwise flawless component-theme-layer discipline (CSS vars + scoped selectors, no global-token reach).[CONTENT_COMPLETENESS]: 90 — 10 deducted: PR body is a strong Fat Ticket with Deltas + L3 Evidence, but the SCSS carries no inline note on WHY the fieldset bg moved to the primary surface (the one non-obvious choice a future reader hits). Theme SCSS has no JSDoc surface, so minor.[EXECUTION_QUALITY]: 95 — Both themes build clean; diff is minimal + correct; EOF-newline hygiene fixed. 5 deducted: the visual outcome is author-fixture-verified, not independently render-confirmed by me (cross-family sandbox ceiling), so I can't assert 100 on the visual AC.[PRODUCTIVITY]: 100 — Delivers all 3 ticket ACs (footer buttons both themes, dark dialog border/shadow, dark fieldset) and enables the acceptance goal (consuming app drops its local patch). I confirmed each AC maps to a diff hunk; none deferred. I actively checked that no AC was partially-met or silently dropped.[IMPACT]: 45 — Routine theme completion (localized component styling); meaningful for real-app dogfooding adoption but not framework-architectural.[COMPLEXITY]: 25 — Low: 3 component SCSS files, ~21 added lines, CSS-custom-property + scoped-selector edits; no new code paths or cross-substrate integration.[EFFORT_PROFILE]: Quick Win — High ROI (unblocks per-app patch removal + fixes dark-theme dialog/fieldset) at low complexity (small, localized, build-verified).
Clean and merge-ready. Nice discipline keeping it at the theme layer. The only thing I'd watch post-merge is the global dark-fieldset contrast outside dialogs — flagged above as a non-blocking visual confirmation for the dogfooding app, since that's the surface my cross-family review can't render-verify.

this mixes THEMES and structural SCSS SRC. themes only contain vars. this is uber important, since we can switch themes at run-time AND we can nest themes inside component trees. new selectors => SRC. available for ALL themes => other themes need to keep their defaults.

Input from GPT-5.5 (Codex Desktop, extra-high thought budget):
● Author Response — Cycle 1
[ADDRESSED]@tobiu's structural review on theme/src separation.The review was correct: my prior footer-toolbar button fix introduced new selectors in
resources/scss/theme-neo-*, which mixes theme values with structural SCSS. Pushed commitd2390d27ato move the footer-toolbar button selector intoresources/scss/src/dialog/Base.scssand leave the theme files as variable-value surfaces only.What changed:
resources/scss/src/dialog/Base.scssnow owns.neo-dialog.neo-panel .neo-footer-toolbar .neo-buttonstructure once.theme-neo-light/theme-neo-darknow set the compact dogfooded footer-button values through dialog variables.theme-light/theme-darkdefine fallback dialog footer-button variables that preserve existing button defaults, so the globally available source selector does not change classic theme behavior.- The dark neo dialog border/shadow and fieldset surface/border changes remain theme-variable changes.
Verification on rebased head:
npm run build-themes -- -n -e dev -t theme-neo-lightnpm run build-themes -- -n -e dev -t theme-neo-darknpm run build-themes -- -n -e dev -t theme-lightnpm run build-themes -- -n -e dev -t theme-darkgit diff --checkgit diff --cached --checkbefore commit- Staged selector sweep: no added
.neo-*selectors in theme dialog filesPR body updated to reflect the repaired source/theme split and current evidence. Current head is
d2390d27a; CI is pending, so I am not requesting re-review yet.

Input from GPT-5.5 (Codex Desktop, extra-high thought budget):
● [CI GREEN / RE-REVIEW READY]
Current head
d2390d27ab6e2763d02ace3f3dce25c807378830is now green after the Cycle 1 source/theme split fix for @tobiu's review:
mergeStateStatus:CLEANlint-pr-body:SUCCESSAnalyze (javascript):SUCCESSintegration-unified:SUCCESSunit:SUCCESSCodeQL:SUCCESSThe structural selector now lives in
resources/scss/src/dialog/Base.scss; theme files only provide variables/defaults.

minor: we are missing the cyberpunk theme, but this most likely does not have a dialog styling yet => enhancing that theme would need follow-up tickets.
Resolves #12565
Authored by GPT-5.5 (Codex Desktop, extra-high thought budget). Session 019e98ad-5af5-7981-be15-dfc740a81d46.
Completes the neo light/dark dialog theme gaps surfaced by dogfooding while preserving Neo's source/theme split. The source layer now owns the dialog footer-toolbar button selector once, all dialog themes define footer-button variables, and the neo light/dark themes set the dogfooded compact footer-button values. The dark neo theme still maps the dialog border/shadow and fieldset surface/border to the dark purple palette.
Evidence: L3 (Sass theme builds for neo and classic light/dark themes + local Chromium render fixture from cycle 1 + source/theme split verification) -> L3 required (theme visual ACs are local-browser-verifiable). Residual: CI/re-review pending on current head.
Deltas from ticket
resources/scss/src/dialog/Base.scss, because selectors are structural source CSS; themes now only provide variable values for this new footer behavior.theme-lightandtheme-darkso the globally available source selector preserves existing classic-theme defaults.resources/scss/src/form/Container.scssonly owns spacing; the actionable dark surface gap maps to.neo-fieldset.Test Evidence
npm run build-themes -- -n -e dev -t theme-neo-lightnpm run build-themes -- -n -e dev -t theme-neo-darknpm run build-themes -- -n -e dev -t theme-lightnpm run build-themes -- -n -e dev -t theme-darkgit diff --checkgit diff --cached --check.neo-*selectors in theme dialog files.border-radius=5px,height=22.6562px,margin-left=4pxborder-radius=5px,height=22.6562px,margin-left=4pxrgb(29, 46, 98)(--purple-800)rgba(17, 20, 28, 0.85) 0px 5px 10px 0pxrgb(24, 36, 73)/rgb(29, 46, 98)origin/devata18271676; current head isd2390d27a.Post-Merge Validation
.neo-footer-toolbar .neo-buttonoverride while dialogs still render correctly intheme-neo-lightandtheme-neo-dark.Commits
623f534e7-fix(theme): complete neo dialog and fieldset styling (#12565)d2390d27a-fix(theme): move dialog footer structure to src (#12565)Evolution
Cycle 1 corrected the PR from a theme-selector implementation to the source/theme split required by @tobiu's review: structural selector in
resources/scss/src/dialog/Base.scss; theme files only define the new footer-button variable values.