LearnNewsExamplesServices
Frontmatter
id18460
titleSimplify Workstation vessel integration around existing Neo owners
stateClosed
labels
enhancementdeveloper-experienceairefactoringdashboard
assigneesneo-opus-vega
createdAtSep 8, 2026, 8:44 AM
updatedAtSep 13, 2026, 4:15 PM
githubUrlhttps://github.com/neomjs/neo/issues/18460
authorneo-gpt-emmy
commentsCount20
parentIssue18456
subIssues
18545 Workstation''s topology bar is authored by its controller, not the view
18532 Native vessel re-show has no runtime witness that the outer footprint is preserved (mechanism mapped, preconditions measured)
18562 Workstation''s Viewport reaches past a component into its controller
subIssuesCompleted3
subIssuesTotal3
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 18533 VesselPark requires a park/re-show transaction it does not ship, so two consumers wrote it and their receipts have drifted, [x] 18501 Three consumers hand-roll a native route check weaker than Main''s
blocking[x] 18461 Finish Workstation as a compact composition entrypoint
closedAtSep 13, 2026, 4:15 PM

Simplify Workstation vessel integration around existing Neo owners

Closed v13.2.0/archive-v13-2-0-chunk-19 enhancementdeveloper-experienceairefactoringdashboard
neo-gpt-emmy
neo-gpt-emmy commented on Sep 8, 2026, 8:44 AM

Context

Workstation is the flagship DockLayouts consumer. Its parent #18456 requires a readable 500–1,000-line Workspace entrypoint and no replacement module above 2,000 physical lines. This leaf simplifies vessel integration while preserving the existing native-window behavior.

The Problem

apps/workstation/view/Workspace.mjs combines view definition, product decisions and native vessel effects. Moving those methods behind hardcoded calls to another object does not make the consumer easier to understand or configure.

Prescription correction — 2026-09-08

Disposition: ticket-prescription-off. I authored the earlier instruction to create a separate VesselController beside WorkspaceController. That selected a superclass and file before establishing the responsibility's semantic owner. I withdraw that prescription and my subsequent acceptance of its architectural shape in PR #18473.

This amended, still-open ticket is the successor landing pad for dropping #18473 at 93d93ef74185a9deb1fb73590dc61ac0e0b1e5c5. It does not authorize further repairs of that extraction. The problem and parent outcome remain valid.

The Architectural Reality

  • Neo declares a view controller through the component's controller config. src/component/Base.mjs:1120 constructs it; :1318 destroys it; :1399 resolves it. A plain secondary field does not participate in that contract.
  • View handlers resolve through the configured controller chain (src/util/Function.mjs:158). A controller reaches other view components through declared references and getReference(); an event-provided component is also valid. See Component References and Events.
  • apps/portal/view/home/FooterContainer.mjs and its controller are an executed MVC precedent: configured controller, declarative handler names, referenced child. A sibling filename alone is not placement evidence.
  • Dock Workspace currently supplies native callbacks to Group NativeLifecycle through bindNativeWindowSource() (src/dashboard/dock/Workspace.mjs:579). That requires callbacks; it does not require a view to forward into a second view controller. Group NativeLifecycle, VesselPark and existing window capabilities remain the native authorities.

The Fix

Reduce Workstation's integration responsibilities using the existing engine and MVC contracts. Establish the production caller and semantic owner of open, close, park, restore, retirement, target selection and observation before choosing an implementation home.

UI interactions belong to configured view controllers and declarative listeners/handlers. Controllers use references to operate on view components; view methods must not manually dispatch into controller methods. View composition should provide real component boundaries where a distinct controller is warranted. Do not move the entire vessel implementation into the existing WorkspaceController or replace VesselController with a renamed helper as the default solution.

Separate Workstation-specific product decisions from reusable native effects. Consume existing engine owners for shared mechanism. If a missing engine seam prevents removing app-owned plumbing, identify and link that exact prerequisite to its engine ticket before implementing the dependent app change. This ticket does not authorize a new generic window lifecycle or registry.

Contract Ledger Matrix

Surface Authority Required outcome Refusal/recovery Evidence
View interaction Neo component/controller config, handler resolution and references Declarative wiring; no view-to-controller forwarding network Normal component/controller disposal Executed handler, reference lookup and configured-controller teardown witnesses
Product vessel decisions Current Workstation production callers Small explicit product policy, with demonstrated app-specific reasons Preserve current target and native route decisions Caller/owner map and ordinary docking journey
Native effects and lifetime Group NativeLifecycle, VesselPark and native window APIs Existing engine ownership; remove duplicated consumer mechanism where the engine supplies it Same generation, exact acknowledgement, restoration and retirement obligations Native return/refusal/retry and deferred-grant witnesses
Receipts and diagnostics Actual production and test readers Truthful observation at the owning boundary No lost success or recovery claim after an await Baseline/head comparison; truthful evidence level

Acceptance Criteria

  • The PR records the executed caller and owner for each vessel responsibility, grounded in the controller/reference guides and live engine seams. Any required engine prerequisite is linked and satisfied; a class-name change or body move does not discharge this criterion.
  • View interaction uses configured controller lifecycle, declarative handlers and references. No manually attached second view controller, hardcoded view-to-controller method calls, or new forwarding façade remains in the delivered slice. An executed routing/reference/lifecycle witness proves the chosen composition.
  • Workstation loses unnecessary vessel integration code and required consumer concepts. Report before/after Workspace, replacement-module and combined physical line counts, plus the hooks/config a consumer needs. No replacement module exceeds 2,000 lines; the parent entrypoint ceiling remains 1,000.
  • Pointer conversion and native-titlebar conversion retain their distinct VesselPark owners, exact native route and vessel generation, refusal/retry behavior, size/position restoration and exact-once retirement. Already-dispatched grants and recovery obligations cannot be abandoned by view cancellation.
  • Update real callers and tests with the owning boundary. Preserve ordinary docking and optional tour behavior, pane/store identity and borrowed engine-owner survival. Provide current-head evidence with baseline failures distinguished from introduced failures; do not weaken tests to meet the size goal.

Salvage map from PR #18473

Candidate Successor disposition
Deferred tests for platform grants and acknowledgements during owner disposal Retain behavior assertions; rewrite setup around the actual owner. A granted OS window must not become unowned.
Local receipt objects and captured pre-dispatch platform context Revalidate against current dev and the chosen owner; preserve where they prevent a demonstrated stale read or lost acknowledgement. These are candidates, not already-proven baseline defects.
Baseline-versus-head parity measurements Retain the method and historical attribution; rerun for replacement code and disclose the resulting evidence limits.
Secondary VesselController, four delegators, receipt façade and custom teardown guards Discard this extraction. Do not port scaffolding whose only justification is the extra lifetime it introduced.
Missing import caused by the extraction No standalone baseline fix: the absent new class needs no import on dev.

Source: PR #18473, head 93d93ef74185a9deb1fb73590dc61ac0e0b1e5c5. This map is the preserved input to the terminal D+S review and replacement intake.

Out of Scope

Group/history/topology redesign, new native-window capability APIs, the new declarative-config design, broad demo repair, and changing parked-vessel product behavior. This is one consumer leaf, not an expansion of the parent epic.

Avoided Traps

No LOC-only extraction, giant helper, superclass chosen from a filename, ritual getReference() call added to legitimize the wrong role, shadow registry, second native authority or blanket cancellation of already-dispatched effects. Automatic controller disposal does not itself settle in-flight platform work.

Decision Record impact

Preserve ADR 0029's engine host, Group, projection and native-window contracts. Any required engine-contract change needs its own linked authority before this consumer leaf can close.

Ownership: the former implementation is stopped. Restart requires fresh intake against this amended outcome; assignment alone is not a reservation of a replacement approach.

Origin Session ID: 153d2e0a-ebae-4087-bcd5-3c92d213132c

Parent: #18456 Related: #18304 · #18303 · PR #18473

tobiu referenced in commit ab6b281 - "refactor(workstation): the cross-window observation surface gets its own boundary (#18460) (#18499) on Sep 9, 2026, 1:32 PM
tobiu referenced in commit 19e4e83 - "fix(workstation): the topology commands live on the component, and Save saves (#18460) (#18655) on Sep 13, 2026, 4:15 PM
tobiu closed this issue on Sep 13, 2026, 4:15 PM