LearnNewsExamplesServices
Frontmatter
id18476
titleConsume declarative panes and zones in DockWorkspace
stateClosed
labels
enhancementdeveloper-experienceaiarchitecturedashboard
assigneesneo-gpt
createdAtSep 8, 2026, 3:39 PM
updatedAtSep 8, 2026, 10:15 PM
githubUrlhttps://github.com/neomjs/neo/issues/18476
authorneo-gpt
commentsCount1
parentIssue18474
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 18475 Lower declarative dock layouts into the existing document model
blocking[x] 18479 Explain declarative DockLayouts adoption in real applications, [x] 18478 Write the first declarative DockLayouts tutorial, [x] 18477 Adopt declarative configuration in the dock example
closedAtSep 8, 2026, 10:15 PM

Consume declarative panes and zones in DockWorkspace

Closed v13.2.0/archive-v13-2-0-chunk-20 enhancementdeveloper-experienceaiarchitecturedashboard
neo-gpt
neo-gpt commented on Sep 8, 2026, 3:39 PM

Part of #18474. Blocked by #18475.

Context

This is the stage-one engine adoption contract: a basic consumer declares panes and zones and receives working dock components without implementing a constructor seed, pane resolver, cache or projection hook. The pure conversion is supplied by #18475; this leaf owns the real Workspace behavior and its normative documentation together.

The Problem

Nicer graph data does not itself instantiate a component. LayoutAdapter tries a resolver before a blueprint, while the base Workspace resolver returns a placeholder. Ordinary/lazy pane declarations therefore need an engine-owned resolution path, and initial declaration consumption must not become a second way to overwrite an active layout.

The Architectural Reality

Source baseline: Engine dev b537d0a3c8101c7d9fcb2a23317b6133d8d356ec, containing merged PRs #18470 and #18472.

The Fix

Add plain initial panes and zones configs to Neo.dashboard.dock.Workspace. A pane key is the default persisted reference to its runtime declaration; header, module/ntype/className and normal component configuration use existing container idioms. Keep constructor functions and live bindings outside the dock document.

Consume the effective seed once, before the first dock projection. This leaf chooses and documents the precise framework lifecycle point, with static and computed initial values covered. A valid explicitly supplied dockModel takes precedence over zones; a supplied invalid document fails visibly rather than silently falling back to defaults.

Stage-one later-assignment contract: assigning panes or zones after seed consumption has no effect on the active document or the consumed declaration used for pane resolution. Document and test that behavior. Live declaration changes are not supported by this plain-config tier.

The consumed declaration registry remains available independently of the current dock document's catalog. Closing an item removes its catalog record; it does not erase the declaration needed to reopen that pane.

Resolve declared panes through the existing component lifecycle. Two declarations of one class remain separate instances/configurations. Existing instances are reused across ordinary moves and rail transitions. Standard declared-pane close/reopen uses the merged addItem operation when the record was deleted; creation/replacement is not performed by writing document.items outside the operation path. Document the supported public host call for reopening so consumers do not build their own seeding hook.

Amend ADR 0029 §§2.1/2.6 and the normative Decisions 1–2 of DockLayoutsAdoption.md in this same PR. The broad adoption tutorial rewrite remains a separate dependent guide leaf.

Contract Ledger Matrix

Target surface Source of authority Required behavior Refusal / fallback Docs Evidence
panes / zones first use D#18468 stage one; normal Base/Container initialization Consume literal or computed seed once before first projection; use #18475 conversion Invalid declaration reports its path; no partial shell/document Workspace JSDoc; ADR §2.1 Real Workspace first-projection tests
Supplied document and later assignments Existing dockModel owner; stage-one initial-only decision Supplied valid document wins; later panes/zones assignments do not reset document or replace consumed definitions Invalid supplied document remains a named failure API reference and adoption Decisions 1–2 Distinct saved/default documents; post-move assignment control
Declared component resolution Container/Card; LayoutAdapter; ADR §2.6 Plain/lazy modules render without consumer resolver/cache; same-class keys keep independent bindings; ordinary operations retain live identity Existing visible unresolved-pane behavior; errors identify declaration Workspace resolver contract Lazy activation plus repeated-class identity controls
Close and reopen Operations.closeItem / addItem / addTab Declared pane can be reopened through the public host path without consumer catalog mutation Duplicate/invalid addItem refusals retained Public lifecycle example and JSDoc Close removes record; reopen restores one record and one pane
Optional subsystem cost Existing static-closure instrument and DockImportDirection spec Engine entry keeps Group/history/topology persistence outside the standalone static dependency closure No eager import used to simplify authoring PR closure/deletion receipt File-list absence with positive controls; report host+normalizer delta
Normative consumer authority ADR 0029 and DockLayoutsAdoption.md Declarations become the basic contribution; custom hooks remain explicit advanced extension points No later-stage API advertised Same-PR ADR/reference edits Source-to-doc comparison at the reviewed head

Discussion Criteria Mapping

Source criteria 1–6: actual declaration consumption and timing, lazy repeated-class identity, declared-pane close/reopen, supplied-document compatibility, host/dependency delta and same-PR normative authority. The model corpus is supplied by #18475.

Acceptance Criteria

  • AC-1: A real minimal Workspace subclass containing only normal class config plus panes/zones renders the intended tabs/splits/edge rail. It defines no constructor, custom resolver, cache or projection hook.

  • AC-2: Literal and computed seeds are consumed at the documented lifecycle point exactly once. Supplied-document precedence and post-consumption assignments behave as stated, without extra projection or document writes.

  • AC-3: Lazy panes load through existing framework machinery when needed. Two keys using the same module keep distinct per-pane config/state, and moves/rail transitions retain the correct live instances.

  • AC-4: Closing and reopening a declared pane works through the documented host entry and merged addItem contract, with no consumer-side catalog mutation. Exercise a removed catalog record and duplicate/open-pane refusal. Standard declared-pane lifecycle remains covered; no separate recreation feature is introduced.

  • AC-5: Existing consumers that supply dockModel or override resolution continue to work. Reuse first-mount ownership, and keep declaration seeding out of projectDockZoneDocument; retain the Group-context repair from #18472.

  • AC-6: Measure the static closure of src/dashboard/dock/Workspace.mjs before/after this PR. Report normalizer+host bytes/modules, and assert absence of src/manager/Transaction.mjs, src/manager/transaction/History.mjs and src/dashboard/dock/persistence/TopologyLibrary.mjs with a non-vacuous file-list control. Do not freeze the previous byte total.

  • AC-7: ADR 0029 §§2.1/2.6, Workspace API JSDoc and the normative Decisions 1–2 of learn/guides/uibuildingblocks/DockLayoutsAdoption.md describe exactly this shipped contract in the same PR.

  • AC-8: Run the current file-size ratchet against the PR base. If Workspace.mjs growth requires an exception, put an exact size-guard-growth: src/dashboard/dock/Workspace.mjs — <specific reason> line in the PR body. Explain why the new seed/consumption/resolution responsibility belongs in this host; pure lowering stays in the model. The guard checks the declaration, while review judges the rationale—do not claim the script proves architectural placement or inflate the baseline to hide growth.

Validation

Load the repository unit/component testing guidance before execution. Add focused real-Workspace tests beside the existing dashboard suites, including the first-projection and import-direction controls. Run:

npx playwright test -c test/playwright/playwright.config.unit.mjs unit/dashboard --reporter=list
npx playwright test -c test/playwright/playwright.config.component.mjs dashboard
node buildScripts/util/static-closure.mjs --list src/dashboard/dock/Workspace.mjs

Record an exact-head rendered declaration receipt, the supplied-document and later-assignment controls, and the closure file-list/delta. Model-only scratch success is insufficient for ACs 1–4.

Dependencies and Decision Record

Native blocked-by dependency: #18475. Before editing the hot host, verify the implementation base contains merged PR #18470 (addItem; closes #18467) and PR #18472 (Group projection context; closes #18471). Those are completed prerequisites, not new children or ownership claims.

Decision Record: REQUIRED. Decision Record impact: amends ADR 0029 §§2.1/2.6 in this PR; neither supersedes it nor changes persisted schemas.

Out of Scope

perspectives/persistence/workspaces configuration; storage-key ownership; popup materialization; reactive panes_; authorization revocation and history invalidation; general Workstation decomposition; standalone tutorial authoring.

Avoided Traps

No second initial-mount loop; no resolver that rereads mutable post-consumption declarations; no callback serialization; no aliasing two pane keys to one instance; no eager Group import; no delayed normative-doc companion.

Related and Pickup

Related: #18474; #18467; #18471; #18456; #18475. unowned-rationale: Available for peer self-selection after the model dependency; existing hot-file ownership must be checked at intake. Retrieval Hint: D18468 stage-one plain panes/zones, first-mount consumption, supplied dockModel precedence, no consumer resolver, standard close/reopen, closure absence.

Origin Session ID: 4f9b7bbe-9dbc-4d36-a167-38fe0d288113

Creation checks

Latest 20 live open issues, latest 30 all-state A2A, a problem-oriented Memory Core query (placeholder/custom resolver/constructor burden), and eight own assignments checked immediately before filing. #18475 is the intended model dependency; no competing host leaf exists. Vega confirmed this packet is ours to file. Recall surfaced no actionable conflicting ruling. Existing #18303 Group/history work is separate. Engine structure-map command is unavailable; placement is the existing Workspace and its existing dashboard unit/component siblings. No new source directory is introduced.