LearnNewsExamplesServices
Frontmatter
id18389
titleUnify dock preview customization under one Neo owner
stateClosed
labels
bugaiarchitecturecoredashboard
assigneesneo-gpt-emmy
createdAtSep 6, 2026, 8:31 PM
updatedAtSep 6, 2026, 9:28 PM
githubUrlhttps://github.com/neomjs/neo/issues/18389
authorneo-gpt-emmy
commentsCount0
parentIssue18304
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 6, 2026, 9:28 PM

Unify dock preview customization under one Neo owner

Closed v13.2.0/archive-v13-2-0-chunk-19 bugaiarchitecturecoredashboard
neo-gpt-emmy
neo-gpt-emmy commented on Sep 6, 2026, 8:31 PM

Context

The extensibility audit and independent reproduction show a real disagreement: overriding Preview.ratioToSizes produces a 25% rendered fraction while Preview.previewToOperation still emits a 50/50 split. This is one bounded ownership cut within #18304.

The Problem

model/PreviewContract.mjs exports lexical functions without a Neo identity. The renderer exposes competing policy wrappers, while direct drop consumers import the converter independently. Customization therefore reaches only part of the preview-to-operation path.

The Architectural Reality

Base.applyOverwrites installs method/default overrides on the instance path. A fresh-process Base singleton probe confirmed that internal method dispatch observes a Neo.overwrites override and the exported instance is its registered namespace identity. Merely registering static wrappers or keeping captured function aliases would preserve the split.

The model folder already owns the pure preview grammar; this work changes its ownership/dispatch, not the grammar or window lifecycle. The earlier operator concern in #18064 / PR #18061 supplies the override-reach precedent; that guideline/guard ticket does not implement this module cut.

The Fix

Convert the existing PreviewContract.mjs into one Base-derived singleton registered as Neo.dashboard.dock.model.PreviewContract. Its methods own validation, candidate validation, split normalization and conversion, and call other policy methods through this.

Move pure ratio-derived helpers to that owner. Remove competing pure-policy wrappers from interaction/Preview.mjs; update every production caller to reach the owner dynamically, including callback entry points. No retained named-function compatibility layer or aliases capturing policy methods.

Keep schema strings, placement vocabulary, explicit-ratio meanings, plain DTO results, and fail-closed behavior unchanged. Document the one supported customization point.

Contract Ledger

Surface Authority Behavior Refusal/default Docs Evidence
New registered preview-policy owner Base overwrite path; #18304 audit One realm-local singleton, replaceable methods reached by all policy calls Existing defaults retained Class JSDoc Namespace identity and overwrite tests
Renderer and direct drop callers ADR 0029 preview → operation path Same policy result reaches rendered fraction and semantic conversion Invalid/rejected preview returns null Renderer and owner JSDoc Real overwrite consistency control
Runtime preview DTO Existing PreviewContract grammar Schema, item/group placement and explicit ratio remain unchanged Existing validation refusals Existing model reference as needed Current grammar/producer tests

Acceptance Criteria

  • The owner has a real Neo namespace identity and Base overwrite support; internal policy calls use that owner.
  • Production callers and callback adapters dynamically invoke it; competing renderer policy wrappers and named-function exports are removed.
  • A real Neo.overwrites customization reaches both the rendered fraction and converted/applied split for an omitted ratio; a pre-fix control demonstrates the disagreement.
  • Explicit ratios, before/after and edge placements, item/group previews, rejection behavior and non-mutation of input DTOs retain their defined behavior.
  • Focused preview/producer/indicator/drop tests and the unit suite pass; JSDoc/generated class hierarchy identify the new owner and customization path.

Out of Scope

VesselConversion and other state-machine conversions, Workspace decomposition beyond updating this policy's call sites, native lifecycle/geometry repairs, new preview kinds or schemas, general lint/skill changes, and any changes to merged PR #18383.

Avoided Traps

A registered wrapper around lexical helpers; two competing customization owners; converting every PascalCase module in one PR; preserving obsolete exports for historical callers; using passing default behavior as proof that customization works.

Decision Record impact: aligned-with ADR 0029; no wire or drag-protocol amendment. Decision Record: existing ADR 0029 remains authoritative.

Related

Parent: #18304 Related: #18064 Related: #18388

Freshness: live latest 20 open issues and all-status PreviewContract title search checked at 2026-09-06T18:30:29Z; no equivalent. Latest 30 all-state A2A messages confirm Emmy owns this cut and Euclid owns VesselConversion. MC problem-framed queries returned unrelated records; the public audit and #18064 provide prior decisions. Own-assignment sweep found four open items; the related guide epic #17540 is documentation, not this implementation.

Origin Session ID: d14f2413-4744-43e9-a6c1-191166d58fe9 Retrieval Hint: PreviewContract ratioToSizes override rendered fraction semantic split owner