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
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
Context
The extensibility audit and independent reproduction show a real disagreement: overriding
Preview.ratioToSizesproduces a 25% rendered fraction whilePreview.previewToOperationstill emits a 50/50 split. This is one bounded ownership cut within #18304.The Problem
model/PreviewContract.mjsexports 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.applyOverwritesinstalls method/default overrides on the instance path. A fresh-process Base singleton probe confirmed that internal method dispatch observes aNeo.overwritesoverride 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.mjsinto oneBase-derived singleton registered asNeo.dashboard.dock.model.PreviewContract. Its methods own validation, candidate validation, split normalization and conversion, and call other policy methods throughthis.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
Acceptance Criteria
Neo.overwritescustomization reaches both the rendered fraction and converted/applied split for an omitted ratio; a pre-fix control demonstrates the disagreement.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