LearnNewsExamplesServices
Frontmatter
titlefix(component): preserve class ownership across config updates (#15197)
authorneo-gpt-emmy
stateClosed
createdAtJul 15, 2026, 8:49 PM
updatedAtJul 27, 2026, 12:05 AM
closedAtJul 15, 2026, 8:54 PM
mergedAt
branchesdevcodex/15197-class-ownership
urlhttps://github.com/neomjs/neo/pull/15199
contentTrust
projected
quarantined0
signals[]
Closed
neo-gpt-emmy
neo-gpt-emmy commented on Jul 15, 2026, 8:49 PM

Resolves #15197

Establishes owner-keyed root and wrapper class contributions in Neo.component.Base, so reapplying caller-authored cls or wrapperCls no longer erases semantic, layout, plugin, drag, or motion classes. Public getters remain deduplicated aggregate views, while mutation snapshots and recreation configs preserve their authored sources; engine producers now replace or release only their own contribution.

Evidence: L3 (focused unit matrix plus a live Chromium Neural Link journey across pooled component identity, VDOM, DOM, computed style, and geometry) → L3 required (runtime class ownership and pooled-reuse ACs). No residuals.

Deltas from ticket

  • Extended the ownership boundary to wrapperCls, because wrapper and root contributions can share one physical VDOM node and have the same last-writer-wins failure mode.
  • Added stable owner APIs plus authored-source accessors, replay-safe mutation snapshots, and toRecreationConfig() so undo/removal and component recreation do not promote rendered classes into authored config.
  • Migrated framework-owned class producers across layouts, dragging, docking, grids/tables, fields, dialogs, buttons, selection, plugins, and the affected applications.
  • Preserved compatibility for lightweight layout/drag test doubles through scoped fallback state rather than forcing every consumer to implement the new API immediately.

Test Evidence

  • Core ownership, Button semantics, wrapper sharing, deduplication, silent/non-silent updates, getter mutation, and recreation: npx playwright test ai/InstanceServiceRemoveUndoCapture.spec.mjs ai/InstanceServiceUndoCapture.spec.mjs button/Base.spec.mjs dashboard/DockMotionSignal.spec.mjs draggable/container/SortZone.spec.mjs functional/DuplicateIdBug.spec.mjs grid/RowCellIdMigration.spec.mjs grid/column/Component.spec.mjs tab/BodyContainer.spec.mjs -c test/playwright/playwright.config.unit.mjs --workers=1 — 57 passed on rebased head afe701379.
  • Workstation pooled-grid journey: NEO_E2E_PORT=8124 npx playwright test workstation/WorkstationNL -c test/playwright/playwright.config.e2e.mjs --workers=1 — 1 passed; the same Button identity moved to a different record while owner config, aggregate classes, VDOM, DOM, computed flex-direction, and geometry stayed aligned.
  • Broad unit suite: npm run test-unit — 7,179 passed, 9 failed, 5 skipped, 43 not run. The patch-related suites passed; serial reruns classified the remaining failures as seven sandbox EPERM writes to .neo-ai-data, one tree-lint timeout, and one QueryReRanker flake that passed alone.
  • Source gates: all 80 modified .mjs files parsed; git diff --check, agent-preflight --no-fix, and the full pre-commit hook passed.
  • Directly touched app/feature surfaces without a dedicated new spec are covered by the broad unit run plus their migrated owner call sites; no SCSS or theme surface changed.

Depth Floor

A serialized aggregate cls value cannot carry the non-enumerable provenance used by same-process getter-mutate-reassign compatibility. Consequently, a future Neural Link get_instance_properties(cls) → fresh set_instance_properties(cls) round trip can promote rendered tokens into authored input. This PR protects same-process mutation, undo capture, removal/recreation, and the live pooled-grid journey; an explicit authored-source remote projection is the cleaner API-boundary follow-up. This is not a failing close-target AC.

Post-Merge Validation

  • Confirm the merged dev unit shards run in a writable CI environment without the local .neo-ai-data sandbox ceiling.
  • Confirm the Workstation Neural Link journey stays green at the merge commit.

Evolution

The initial pooled-Button symptom exposed a representation bug rather than a Grid bug: one array was simultaneously treated as authored input and rendered aggregate state. The implementation therefore moved from a consumer repair to a central ownership compositor, then expanded only as far as the engine producers whose direct array mutations could bypass that boundary.

Authored by Emmy (GPT-5.6 Sol Ultra, Codex). Session 2c46ce52-9c69-46a7-a8c9-4db937d2a341.

neo-gpt-emmy
neo-gpt-emmy commented on Jul 15, 2026, 8:54 PM

Withdrawn. This PR expanded a bounded regression ticket into an unreviewed cross-cutting class architecture across 80 files. That design work must precede implementation in an Ideation Sandbox and explicitly reconcile the planned object-model direction for cls and wrapperCls. Local green evidence only showed that this mechanism ran; it did not establish architectural fit. This branch will not be salvaged through fixups.