LearnNewsExamplesServices
Frontmatter
id15197
titlePreserve config-derived classes when cls is reapplied
stateOpen
labels
bugairefactoringtestingregressioncore
assignees[]
createdAtJul 15, 2026, 5:10 PM
updatedAtOct 19, 2026, 2:49 PM
githubUrlhttps://github.com/neomjs/neo/issues/15197
authorneo-gpt-euclid
commentsCount8
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Preserve config-derived classes when cls is reapplied

Open Backlog/active-chunk-3 bugairefactoringtestingregressioncore
neo-gpt-euclid
neo-gpt-euclid commented on Jul 15, 2026, 5:10 PM

Context

Readiness: scope restated; implementation remains stopped. No mechanism is selected.

Reapplying a Button's authored configuration can remove classes required by unchanged semantic configs. A pooled grid.column.Component uses that same set() path, so application configs should not need to duplicate engine-derived classes.

Design authority: D15200's finite compatibility contract, the author scope disposition, and its linked source/probe records. This restatement covers the bounded array-compatible repair; it does not graduate the longer-term object/Proxy migration or revive the dropped implementations.

The Problem

The effective cls array mixes caller input and current semantic contributions. Replacement can erase active contributions; a mixed batch can also restore a stale token after an owner hook removed it. Shared physical roots have an independent problem: replacing cls or wrapperCls can erase a token still present in the other logical input.

The current probes and their limits are retained on D15200. Candidate membership checks do not substitute for construction, root/wrapper, recreation, pooled rendering or cost evidence.

The Architectural Reality

component.Base owns class normalization/projection. Semantic configs remain owned by their existing classes; their effectful work must not be replayed merely to rebuild classes. core.Base#set and the generated getters can apply pending configs during another hook, so both key orders are part of the contract.

The finite token/source matrix covers existing base/extension contributions; Component UI/disabled; Button text/icon-position/pressed; Icon cell classes; StatusBadge state; CheckBox label position; Fieldset collapse/collapsibility; and CalendarWeek weekend visibility. Direct class writers and descendant/effect work are explicitly distinguished. Theme-carrier controls preserve their logical/physical ancestry rule.

The Fix

Repair those existing class boundaries while retaining arrays, effective getters and the existing class APIs. Preserve active named semantic contributions and retire released contributions. A different current named semantic input may retain the same token; a stale authored/effective snapshot alone may not resurrect a retired token. An authored token under an unchanged inactive config remains valid—this is not a global reserved-class filter.

For Icon, a shared token survives while either current semantic input requires it. Null contributes no Icon tokens while the public nullable config remains null; the generic String/String[] swap API need not become nullable.

Choose the mechanism from the evidenced candidates after the remaining checks. Do not introduce a persistent authored bag, owner registry, global Config transaction rewrite or blanket replay of effectful setters.

Contract Ledger

Surface Authority Required behavior Boundary / evidence
cls and existing base/extension contributions Component class boundary and finite owner matrix Keep array shape; replace caller input without losing active covered contributions; deduplicate without repeated reapply churn Authored relative order and supported ordering contract recorded; existing aggregate bindings exercised
Named semantic configs Existing owner hooks Released contribution retires; another active named semantic input can preserve the token Both batch orders, authored/effective/modified snapshots; changed owner work once, unchanged owner work not replayed
Icon nullable input Icon.afterSetCellIconCls / beforeSetCellIconCls Null is an empty contribution, public getter remains null Both shared-token release orders and eventual removal; no literal null in class arrays
cls / wrapperCls projection Existing physical root topology Union both logical inputs on one node; keep their separate nodes when wrapped Overlap removed from either input; layout-written wrapper classes; direct writers
Serialization / recreation Existing component snapshots and semantic config owners Do not turn effective derived tokens into permanent authored state Round-trip followed by owner change/clear; explicitly account for missing serialized owner state rather than inventing it
Pooled reuse / silent batches grid.column.Component and component.Abstract#set Preserve state/classes/geometry through reuse; silent staging remains silent until its ordinary flush Real pooled consumer, applied deltas and DOM state; repeated no-op and allocation/time controls

Acceptance Criteria

  • The finite owner/token matrix has explicit expected outcomes, including Icon overlap/null and ancestry-dependent theme controls.
  • Reapplying or replacing authored classes preserves covered active contributions, removes obsolete authored input, and remains idempotent.
  • Owner change/clear and class replacement obey the stated precedence in both batch orders, including stale effective snapshots and direct writers; owner effects are not replayed.
  • One-node and wrapped two-node cases preserve their logical inputs independently, including overlapping tokens and layout classes.
  • Construction and actual snapshot recreation preserve the covered owning configs and root class relationship, including Fieldset's collapsed / collapsible; remaining omissions are explicitly resolved or scoped with an owner.
  • A real pooled grid.column.Component reuses the same component across records in ordinary and silent modes with correct semantic state, classes and geometry.
  • Update invocations, applied deltas, DOM mutation records and paint observations remain separately reported; repeated/no-op and allocation/time evidence justify the chosen mechanism.
  • Focused regressions and the applicable existing suites pass at the chosen implementation head.

Out of Scope

  • Complete populated Container/Fieldset child or legend reconstruction from compact inspection JSON. Preserve the deliberate child-ID projection and the intact Fieldset's child/legend effects. The reversible-snapshot consumer question remains unresolved in D15200 under this ticket author's continuity.
  • The whole header sort-token family: neo-sort-hidden, neo-sort-asc, neo-sort-desc receives no new reassignment-safety guarantee. This is not a correctness claim.
  • The separate header policy/serialization outcome remains on D15200, with #4518 and #8254, until a native successor owns it.
  • Object/Proxy/leaf-binding migration, descendant-VDOM migration, theme redesign, a generic claims registry, forced component recreation or consumer-side duplication of engine classes.

Decision Record / Readiness

The existing architectural stop and D15200's applicable decision gates remain. Scope agreement alone does not select G, current-class G, H or the direct-writer variants. This author-adopted body replaces the original broad ownership prescription.

Restatement trail: adopted from Emmy's author-review draft under this ticket's existing authorship, with the scope and implementation stop preserved.

Origin Session ID: ed9c23e6-01d5-4dc2-8031-cb7c5a631f62

Retrieval Hint: "D15200 finite class contract current cls nested owner writes Icon semantic union direct writers pooling"

tobiu unassigned from @neo-opus-ada on Jul 28, 2026, 11:28 AM