LearnNewsExamplesServices
Frontmatter
id17838
titleCommit active tabs and resizable edge zones in DockLayouts
stateClosed
labels
documentationenhancementaitestingarchitecturecore
assigneesneo-gpt
createdAtAug 28, 2026, 11:10 PM
updatedAtAug 29, 2026, 2:47 PM
githubUrlhttps://github.com/neomjs/neo/issues/17838
authorneo-gpt
commentsCount1
parentIssue17836
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 17837 Cut DockLayouts anatomy and wire vocabulary to final form
blocking[x] 39 Adopt the rewritten DockLayouts API in Agent Institution
closedAtAug 29, 2026, 2:47 PM

Commit active tabs and resizable edge zones in DockLayouts

Closed Backlog/active-chunk-19 documentationenhancementaitestingarchitecturecore
neo-gpt
neo-gpt commented on Aug 28, 2026, 11:10 PM

Context

Epic #17836 and graduated Discussion #17818 define the v13.2 DockLayouts target. Anatomy/wire leaf #17837 establishes the final package, namespace, schema family, and behavior-preserving ownership boundaries. This leaf begins only after that cut and delivers the missing Engine semantics in one behavior-complete PR.

Two user-visible defects share one root: the committed dock document does not own all layout state the UI exposes.

  1. Selecting a non-first tab updates only the live TabContainer.activeIndex; a later size commit re-projects stale activeItemId and returns to tab one.
  2. Initial left/right/bottom edge-zone bands have no splitters or committed extents, while drag-created split nodes do; initial and evolved layouts expose inconsistent resize affordances.

The Problem

Tab activation and edge sizing currently live outside the reducer’s single mutation path:

  • projected tab selection is live UI state until another operation re-projects the document;
  • edge-band sizes come from CSS/default/reveal fallbacks and cannot be resized semantically;
  • auto-hide reveal may borrow an ancestor split extent or fall back to its default because the edge descriptor owns no committed extent;
  • adding direct UI mutation or per-edge side maps would create parallel authorities and make perspective capture/restore inconsistent.

The fix must preserve ADR 0029’s state classes: normalized document state is worker-owned and serializable; drag pixels remain per-window runtime state; successful terminal operations commit once; cancellation commits nothing.

The Architectural Reality

This leaf consumes the exact binding file-level architecture in #17837 (The Fix); it does not infer or redefine that tree. It does not reopen package, namespace, wire, or migration decisions.

  • Neo.dashboard.dock.model.Document validates/normalizes the committed tree.
  • Neo.dashboard.dock.model.Operations is the sole semantic reducer vocabulary.
  • Neo.dashboard.dock.Workspace owns document commit and atomic re-projection.
  • projected tabs report user activation independently of close-action configuration.
  • edge-zone descriptors own their node id and optional normalized extent/resizable state together; no parallel edge maps exist.
  • CSS min/max values constrain runtime preview and committed output but never become document authority.
  • split-node sizes remain authoritative only for split nodes.
  • generic Splitter/GestureClaimArbiter mechanics and #17820’s split-preview feature remain separate; this leaf owns edge-zone semantics and active-item persistence.

The Fix

Commit tab activation

Add the semantic descriptor:

{
    operation : 'setActiveItem',
    tabsNodeId: 'stream-tabs',
    itemId    : 'memories'
}

Every projected tab strip reports user activation. The reducer validates that tabsNodeId names a tabs node and itemId belongs to it, then updates activeItemId. The initiating projection and every other projection converge on the committed document. Invalid descriptors fail closed.

Commit edge-zone extent

Use nested edge descriptors as the sole edge authority:

{
    type : 'edge-zone',
    zones: {
        center: {nodeId: 'main'},
        left  : {nodeId: 'left-tabs',   extent: 0.20, resizable: true},
        right : {nodeId: 'right-tabs',  extent: 0.25, resizable: true},
        bottom: {nodeId: 'bottom-tabs', extent: 0.25, resizable: true}
    }
}

Add the semantic descriptor:

{
    operation : 'resizeEdgeZone',
    edgeZoneId: 'root',
    edge      : 'left',
    extent    : 0.22
}

An edge splitter previews adjacent geometry with runtime pixels only. CSS min/max constraints bound both preview and the normalized terminal value. Successful release commits exactly one operation; Escape, rejection, or destruction restores the prior projection and commits zero. Auto-hide retains the committed edge extent, and reveal consumes it instead of the current ancestor-split/default branch.

Engine consumer proofs

Update Workstation and the dashboard docking example to seed resizable initial edges and prove:

  • non-first tabs survive split and edge size commits;
  • initial left/right/bottom/Inspector boundaries expose the intended splitter affordances;
  • edge resize survives auto-hide/reveal and perspective capture/restore;
  • close-action enabled and disabled tab paths both report activation;
  • re-projection does not jump away from the final preview.

Contract Ledger

Target surface Source of authority Proposed behavior Fallback / refusal Docs Evidence
setActiveItem D#17818 semantic contract; tabs-node activeItemId Every user activation commits through the reducer and survives unrelated projections Unknown node/item rejects without document or live-selection drift Operations/Workspace JSDoc + guides model tests + Workstation/example real interaction
Nested edge descriptor D#17818 OQ2; final Document model {nodeId, extent?, resizable?} is the sole committed edge authority Missing extent uses pre-commit presentation fallback; non-resizable edge emits no splitter Document/adapter JSDoc + ADR/guide validation and projection matrix
resizeEdgeZone D#17818 operation contract Runtime-only preview; one normalized terminal commit Escape/rejection/destruction restores projection and commits zero interaction/model JSDoc unit + real-pointer whitebox evidence
Auto-hide/reveal extent committed edge descriptor Hidden edge preserves extent; reveal uses the exact committed value No committed extent uses the existing default only reveal/adapter JSDoc + guide resize→hide→reveal witness
Engine consumers Workstation + dashboard example Initial edges are resizable; active item persists across size-only operations n/a application/example code + guides headed journeys across close-action false/true

Decision Record Impact

Decision Record impact: amends ADR 0029 where the final edge descriptor, setActiveItem, and resizeEdgeZone extend the committed document/operation contract; all existing worker/runtime/arbitration/JSON-first rules remain binding.

Decision Record

Required. Amend ADR 0029 and the DockLayouts/model guides with the final state/operation contracts, ownership order, refusal semantics, and consumer witnesses.

Acceptance Criteria

  • setActiveItem validates tabs node and member item, commits activeItemId through the sole reducer path, and rejects invalid descriptors without mutation.
  • Every projected tab strip reports activation independently of close-action configuration; at least one enabled and one disabled close-action consumer are proven.
  • A non-first selected tab remains selected in document truth and rendered content after split resize, edge resize, perspective capture/restore, and unrelated re-projection.
  • Edge-zone descriptors use the final nested {nodeId, extent?, resizable?} shape with no parallel extent/resizable maps.
  • resizeEdgeZone validates node, edge, resizable permission, normalized extent, and CSS min/max bounds before one terminal commit.
  • Mid-drag pixels and preview styles remain per-window runtime state; document/perspective bytes stay unchanged during move frames.
  • Successful release commits exactly one operation matching the final bounded preview; re-projection does not jump.
  • Escape, rejection, stale generation, and destruction restore prior projection and commit zero operations.
  • Auto-hide preserves committed edge extent and reveal uses it; only a never-committed edge uses the existing default fallback.
  • Workstation exposes initial left, right, and bottom edge splitters; the dashboard example exposes the Inspector boundary.
  • Workstation and example headed journeys prove active-item persistence, both-axis edge resizing, resize→hide→reveal, and perspective round trips.
  • Existing split resizing, cross-window, auto-hide, projection reconciliation, and perspective witnesses remain green at final #17837 paths.
  • ADR 0029, ArchitectureOverview where needed, and DockLayouts/model guides describe the executable final semantics.
  • This PR does not reintroduce old paths/wire strings, compatibility code, a second Splitter engine, or Agent Institution consumer migration.

Out of Scope

  • package/namespace/wire migration owned by #17837;
  • DockSplitter live split-preview feature owned by #17820;
  • Agent Institution imports/styles/runtime witnesses, owned by neomjs/neo-agent-institution#39;
  • new perspective projection Store, transport, or workspace-set behavior from superseded #17779 unless independently required by these two semantic operations;
  • generic Neo.component.Splitter redesign;
  • migration/compatibility tooling, diagnostic ledgers, census artifacts, or unrelated Qt-parity work.

Avoided Traps

  • Live-only tab state: reintroduces the reproduced reset after any size commit.
  • Per-edge side maps: can drift from node ownership and perspective capture.
  • Commit on every move: violates runtime/document separation and creates persistence churn.
  • CSS as persisted truth: makes projection outcome theme-dependent.
  • Full workspace projection per frame: rebuilds the tree unnecessarily; preview only the local boundary.
  • Absorbing #17820: conflates split-preview feature work with new edge/document semantics.

Related

Parent: #17836
BLOCKED_BY #17837
Related: #17820
Related: #13158
Consumer: neomjs/neo-agent-institution#39
Source: Discussion #17818

Origin Session ID: 01a03dec-efe5-71b3-8c19-e6b29187b970

Retrieval Hint: query_raw_memories("D#17818 setActiveItem resizeEdgeZone active tab reset committed edge extent")

Creation freshness: live exact searches for setActiveItem and resizeEdgeZone, the created-descending latest 20 open Engine issues, and the all-status latest 30 A2A messages were checked at 2026-08-28T21:10Z; only Epic #17836 and anatomy leaf #17837 matched, with no competing claim. Knowledge Base/local mirrors returned prior docking authorities but no equivalent semantic leaf; the known-stale local corpus was not treated as live authority.