Migrate Nano Programs to the shared XML/Lua window component
Parallel window migration from merged develop adde9d039997805fcd0090e4c75f63a8d8589449. Worktree /home/mathias/Projects/worktrees/engines-client-lua-nano-programs; branch feature/client-lua-nano-programs. Siblings own Stats and player NCU. Own uploaded Nano Programs presentation and its thin native data/command adapter only. Shared dependencies bc39fd9b9 and local sizing fix b54c7291008f41190247d48c841719cf3b727612 integrated by authorized fast-forwards on the assigned feature branch. Current HEAD is 3fcf250a564b49919219c8be4e98ca3b1112f567; all dependency integrations were authorized local fast-forwards and no Git remotes were contacted. Before sizing integration, saved private git diff --binary HEAD plus all15 nonignored untracked source files under .dev-data/before-sizing-20261021T222536Z/ (migration-head.patch, untracked-source.tar.gz, source-sha256.json, head.txt). All19 changed/new/deleted migration paths matched their pre-integration hashes after the fast-forward. No source changes made during this integration. Post-integration targeted baseline: 109 passed, 2 installed-asset skips, 0 failed. Local migration implemented with merged typed activation, real text/drag events, opacity and core.preferences arrays. Shared XML sound fix 3fcf250a564b49919219c8be4e98ca3b1112f567 integrated by explicitly authorized local fast-forward, with all19 migration paths unchanged by hash verification. Current HEAD is 3fcf250a564b49919219c8be4e98ca3b1112f567. Private binary HEAD diff,15 untracked source files and hash manifest saved under .dev-data/before-sound-20261021T223935Z/. Sound blocker resolved against integrated native XML support. Package-local click_sound=false on row.xml/slot.xml passes the enabled real-input regression; ordinary school/header/frame feedback remains audible. Local functional migration is validated; combined full-client AOT, other platforms and live/asset rendering remain explicitly unverified and are not separate batch blockers. No remote operations or migration commits. Earlier prerequisite audit below is historical and addressed by PR2803. No shared infrastructure/harness files edited; no commit/push/PR or other merge performed. Outcome: Nano Programs composes the shared Core Window and owns toolbar/search/school selection, grid/list reconciliation, sorting, menu and presentation-state persistence in Lua. C# retains uploaded membership/identity/revision, canonical nano information/resources/nanoline/mechanics and validated casting. Preserve current default/list behavior and original columns/preference compatibility, school-toggle behavior, search matches FIRST with unmatched entries DIMMED rather than hidden, shared grid/list ordering, icon/row inspection/hotbar identities and unavailable-favorites behavior. Native target/casting checks must remain authoritative and unchanged. Inspect UI/Windows/NanoProgramsPresenter.cs, UI/Layouts/NanoPrograms.xml, NanoPresentationProvider, NanoProgramSnapshot/client nano state, CharacterInterface.BuildNanoPrograms/CastNano and related update/inspection paths, NanoProgramTests.cs and relevant target/shortcut/tooltip tests. Contracts grouped in Contracts/Game/NanoPrograms.cs and Components/NanoPrograms.cs if needed. Remove only the old Nano Programs presentation path; do not migrate NCU or rewrite shared nano mechanics. Keep CharacterInterface modifications to own fields/build/apply/inspection hunks, no broad formatting. Shared Core/runtime/widget host/activation policy/API attributes/generator/graphics/input/window manager/preference store/CI/AOT harness are centrally coordinated. Audit missing capabilities first: text-change input, dimming/opacity and validated non-ActionRef nano activation may need shared work. Report concrete signatures, event provenance/ownership and exact semantics; do not patch shared code independently, reuse ActionRef/game.actions.execute or use a native UI mutation bypass. Do not silently drop search/columns/sorting/inspection or change match-dimming semantics to fit existing APIs. Independent domain extraction/contracts/tests may proceed; mark blocked where a shared prerequisite prevents safe completion. Acceptance: frame/content/filter/sort/mode/preferences Lua-owned with no parallel C# Nano Programs presenter; real-input regressions preserve filtering/search ordering+dimming, grid/list and preferences; stale or background cast requests refused; native casting rules/identities/info unchanged; cleanup and unchanged-snapshot allocation gating verified. Relevant targeted client tests required, common AOT coverage coordinated centrally. No done status with unmet requirements. Verified shared prerequisites / coordinator request (proposed signatures): - ui.on_text_changed(view: WidgetRef, callback: fun(text: string)): bridge GuiInputManager's GuiView.TextChanged events, not polling or synthesized clicks. Package owns callback replacement/release on destroy/dispose, protected budgeted calls and retained-text accounting. No game activation; ui.text does not synthesize input. Preserve max_length=64 for search. - ui.opacity(view: WidgetRef, opacity: number): reject nonfinite/out-of-range values (0..1); Lua sets 1 or 0.4 on both list rows and grid slots. Dimming must not disable casting or hide unmatched entries. - Generalize RequiresActivation from exactly ActionRef to declared opaque Binding-derived game refs, preserving generated dispatch authorization. Domain export will be game.nano_programs.cast(nano: NanoProgramRef): boolean with native LuaNanoProgramReference(long Value), BaseType=Binding. Only synchronous genuine click scope may consume the captured binding, once. Text, drag, resize, popup, apply and state callbacks must grant no activation. Rebinding during a click must not authorize another nano. Native adapter must re-read current snapshot/session identity and revision/membership before existing CastNano target/grid rules; hidden/unavailable/wrong-session requests refused. Shared activation should honor LuaWindowServices.CanInteract, not merely GuiView effective visibility. - ui.on_drag_start(view: WidgetRef, callback: fun()) and ui.on_drag(view: WidgetRef, callback: fun(offset: number)): bridge existing native column-handle DragStarted/Dragged with total horizontal offset from press, native capture/release semantics and package lifetime/budget checks; never grant casting activation. Lua owns widths and updates header/row geometry. Existing XML column_resize handles can supply native input, but host exports no drag callbacks. - ui.preference.read_array(path: string): (string|number)[] and ui.preference.write_array(path: string, values: (string|number)[], kind: 'text'|'float') (or coordinated equivalent typed generic array API): preserve scoped listview_config.col_id text array and col_width float array. Current ReadUiScalar refuses arrays and float values; WriteUiScalar only supports text/bool/int. Need bounded counts/values, finite floats, whole-array replacement and preservation of unrelated fields. Existing scalar mode/sort paths already work; do not migrate widths to incompatible scalar keys. Evidence: LuaWidgetHost.Api.cs has no text/opacity exports; LuaWidgetHost.cs only owns Clicked callbacks; PRK.LuaApiGenerator/Contract.cs enforces ActionRef; LuaWidgetHost.Activate does not consult CanInteract. UiTable.cs attaches native DragStarted/Dragged; UiLayoutStore.ReadListView/WriteListView use col_id/col_width arrays. Existing NanoProgramTests exercise genuine GuiInputManager text/clicks and prove search match-first/dim rather than filtering. Baseline validation passed on Linux container: ./run-client-tests.sh -p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903 --filter 'FullyQualifiedName~NanoProgramTests|FullyQualifiedName~NanoTargetRulesTests|FullyQualifiedName~ShortcutBarTests|FullyQualifiedName~TooltipContentTests|FullyQualifiedName~TooltipViewTests|FullyQualifiedName~LuaWindowComponentTests|FullyQualifiedName~ScriptedActionsTests|FullyQualifiedName~UiListViewPersistenceTests|FullyQualifiedName~UiTableTests|FullyQualifiedName~WindowResizeTests' --logger 'trx;LogFileName=nano-programs-baseline.trx'. 109 passed, 2 skipped, 0 failed (111 total). Skips: installed GUI tooltip rendering and original Nano Programs assets rendering because assets were not configured. Log .dev-data/nano-programs-baseline.log; TRX .dev-data/test-results/client/nano-programs-baseline.trx. This validates existing presentation only, not a migration. That earlier baseline did not verify migrated behavior. Current implementation and verification follow. Local implementation: UI/Packages/NanoPrograms owns frame, toolbar, default list, real-input search, school toggles, all ten original columns, numeric/string sorting with stable ties, grid/list reconciliation and match-first opacity (not filtering), mode/sort and original col_id/col_width arrays. Uses core.window/core.icon_grid/core.preferences. C# ScriptedNanoProgramsWindow plus Windows/NanoProgramPresentationSource retain canonical data/resources/nanoline and player identity/revision/membership checks, delegate unchanged native CastNano rules, and use a distinct generated NanoProgramRef (never ActionRef). Contracts grouped under Game/NanoPrograms.cs and Components/NanoPrograms.cs. Removed old NanoProgramsPresenter.cs and Layouts/NanoPrograms.xml. CharacterInterface changes are own constants/fields/build/update only; regular Refresh runs even hidden. Domain source is beside adapter under Windows rather than shared Scripting/*.cs so it does not accidentally add unlinked domain dependencies through the shared AOT wildcard. Resolved sound prerequisite: shared commit3fcf250a564b49919219c8be4e98ca3b1112f567 initializes GuiView.ClickSound from XML. No additional Lua setter is needed. The following request/evidence records the pre-integration behavior only. Confirmed again at b54c7291008f41190247d48c841719cf3b727612: GuiDocumentLoader/GuiViewFactory pass XML attributes to a plain GuiView; its constructor does not read a click-sound field, ClickSound is a separate auto-property initialized true, SetAttribute only stores attributes and invalidates layout/paint, and GuiInputManager mouse/keyboard paths check ClickSound directly. No existing supported XML attribute preserves silence. Minimal coordinator request: support click_sound='false' in XML, default true. Package-local attributes are now present only on NanoPrograms/row.xml and slot.xml (including empty slots); school buttons, headers and frame templates remain unchanged. A Lua setter remains an alternative, not a requirement. Previous native Nano Programs explicitly set false for rows and slots (including empty cells), while school controls keep normal click sounds. The new Lua package cannot preserve this without the shared capability. CastingFromTheWindowPlaysNoClickButTheSchoolButtonsDo remains enabled and fails (one real row cast emits one native Activated event). Do not bypass through native adapter widget mutation or disable this regression. Once shared native capability is actually integrated, rerun the enabled tests against the already-prepared XML. No native adapter mutation or global sound suppression was added. Current Linux container validation, warnings-as-errors (-p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903): final targeted ./run-client-tests.sh using the same NanoProgram/target/shortcut/tooltip/shared-window/Actions/preference/table/resize filter reports106 passed,2 skipped,1 failed (109 total). Full ./run-client-tests.sh --logger 'trx;LogFileName=nano-programs-full.trx' reports3997 passed,180 skipped,1 failed (4178 total). Sole failure in both is click sound above. Final targeted includes real text edits, school toggle, canonical columns/numbers/inspection IDs, header sorting/reversal, grid/list order+dimming and empty slots, saved widths through real drag and reopen, native pointer resize, typed command anti-substitution/single-use/no snapshot or text activation, current snapshot revision/membership/identity/player and CanInteract refusal,500-upload library, teardown, and zero-allocation unchanged snapshots. Two installed-asset render tests skip without PRK_GUIROOT. Full-suite skips remain unavailable installed assets/native runtime/display/audio fixtures. Logs .dev-data/nano-programs-targeted.log, nano-programs-full.log; TRX under .dev-data/test-results/client/. Negative controls verified: remove source revision guard -> stale-cast regression fails (mutation-revision log); change search ranking into filtering -> real-input search regression fails (mutation-filter log). Both restored before final targeted run. Generator self-tests passed via docker run with prk-client-tests:10.0, dotnet run --project PRK.Client/PRK.LuaApiGenerator -- --self-test; log .dev-data/nano-programs-generator.log. git diff --check clean. Native AOT coordination request: centrally add Nano Programs adapter/data-source plus actual domain dependencies (NanoPresentation and NanoProgramSnapshot/canonical NCU math) to source-linked harness, and exercise package load/apply, real input/activation refusal, mode/preferences and disposal in the common publish. Existing contract/package discovery is recursive. No AOT runner/project edits or publish launched here. Exact coordinated Nano Programs AOT dependency handoff: source-link UI/Windows/ScriptedNanoProgramsWindow.cs and NanoProgramPresentationSource.cs; use actual NanoProgramSnapshot from SessionState/ClientNanoProgramState.cs and NanoPresentation from UI/NanoPresentationProvider.cs. Identity, FullCharacterMessage, CharacterActionMessage and StatModifierMath.NanoNcuCost are in PRK.Common/AOEmu.Common/AOEmu.Common.csproj (not a separate NCU-math helper project); NanoSchool/NanoFlags are in PRK.Common.Enums. Existing LuaRuntime/host/GuiView/Skia dependencies are already in the shared harness. Contracts/Scripting and Packages are already recursively included. The canonical presentation record is currently co-located with its provider, so linking that entire file also requires RDBLib2, NanoTargetRules, its CharacterRecord model dependency and PRK.TDBLib; coordinate real domain extraction or reference the actual PRK.Client project rather than inventing harness-only stand-in records or mechanics. Do not change source ownership/shape merely to hide these dependencies. Coordinated AOT scenarios: load/apply real bundled package; canonical ten columns and borrowed icon identity; native text match-first/dimming without filtering; toggle schools; numeric/string sort/reversal/stable ties; list/grid order, slots and real resizing; text/float width-array plus mode/sort preference round trip; no casts during apply/text/drag/menu observers; captured-binding substitution and reuse refusal; current identity/revision/membership/background checks before native cast delegate; uploaded-list changes; hidden Refresh; callback/resource cleanup and unchanged-snapshot zero-allocation gate; silent mouse/keyboard cast activation in rows/slots once XML support lands, with school controls still audible. Per user decision, a separate per-window AOT smoke is not a hard acceptance blocker for this batch. Shared AOT mechanisms are established; combined full-client AOT publish will be coordinated later and remains unverified here. Combined full-client Native AOT, Windows/macOS and live game/asset rendering remain unverified, with deferred AOT explicitly not a separate batch acceptance blocker. Cast-click-sound preservation is now verified after shared integration; no local functional blocker remains. Post-sizing local targeted validation: ./run-client-tests.sh -p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903 --filter 'FullyQualifiedName~NanoProgramTests|FullyQualifiedName~NanoTargetRulesTests|FullyQualifiedName~ShortcutBarTests|FullyQualifiedName~TooltipContentTests|FullyQualifiedName~TooltipViewTests|FullyQualifiedName~LuaWindowComponentTests|FullyQualifiedName~LuaContentSizedWindowTests|FullyQualifiedName~ScriptedActionsTests|FullyQualifiedName~UiListViewPersistenceTests|FullyQualifiedName~UiTableTests|FullyQualifiedName~WindowResizeTests' --logger 'trx;LogFileName=nano-programs-local-sizing.trx' ->108 passed,2 skipped,1 failed (111 total). Sole failure remains CastingFromTheWindowPlaysNoClickButTheSchoolButtonsDo (expected0 native Activated events,actual1). New content-sizing tests pass. Two skipped rendering tests need installed GUI assets. Log .dev-data/nano-programs-local-sizing.log; TRX .dev-data/test-results/client/nano-programs-local-sizing.trx. git diff --check clean. Migration source unchanged from backup; no harness/shared/peer edits, commits or remote operations. Do not mark done until shared XML sound support is actually integrated and the retained sound/input regressions pass. Keep deferred combined full-client AOT and platform/live rendering limits explicitly unverified; do not hold completion solely on a separate smoke project. Only the own-branch dependency fast-forwards through3fcf250a564b49919219c8be4e98ca3b1112f567 were explicitly authorized. No migration commit/push/PR/rebase/other merge permission; hand off local code, results and limitations. Package sound follow-up: click_sound='false' added only to row.xml and slot.xml. Audited actual cast targets: Lua registers casting on row.root and grid cell.root only; list text and explicitly noninteractive icon descendants hit the row, so no child-specific mute or adapter changes are needed. Retained CastingFromTheWindowPlaysNoClickButTheSchoolButtonsDo now drives real mouse clicks on row, name descendant, icon descendant, populated slot and empty slot, checks exact cast identities/counts, exercises real search text plus Enter (no cast/feedback), and checks school feedback before its final silence assertion. Rows and slots cannot receive native keyboard focus (GuiInputManager.Focus/IsTextFocusable accept only TextInputView/ComboBox); no synthetic focus or invented keyboard cast path was added. Generic keyboard ClickSound semantics are the shared agent's native-input responsibility. Added SchoolHeadersAndFrameControlsRetainOrdinaryClickFeedback using real clicks and exact Activated targets for school, header, pin and icon; this passes and prevents accidental global muting. Validation on unintegrated b54 shared code: ./run-client-tests.sh -p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903 with the same post-sizing targeted filter and --logger 'trx;LogFileName=nano-programs-xml-sound-pending.trx' reports109 passed,2 asset-dependent skips,1 failed (112 total). Retained sound regression is the sole failure: all new cast/input assertions execute successfully, then final silence check reports3 row/descendant Activated events instead of0, because shared XML parsing is not integrated. Log .dev-data/nano-programs-xml-sound-pending.log; TRX .dev-data/test-results/client/nano-programs-xml-sound-pending.trx. git diff --check clean. No shared files, peer worktrees, Git remotes or commits touched. Final integrated validation on actual feature branch HEAD3fcf250a564b49919219c8be4e98ca3b1112f567: targeted ./run-client-tests.sh -p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903 with the prior Nano/target/shortcut/tooltip/window/Actions/preferences/table/resize filter and --logger 'trx;LogFileName=nano-programs-sound-integrated.trx' ->110 passed,2 installed-GUI skips,0 failed. Retained CastingFromTheWindowPlaysNoClickButTheSchoolButtonsDo passes, including row/name/icon mouse hits, populated/empty slots, unchanged cast identities, real search typing/Enter without casting, and audible school feedback. SchoolHeadersAndFrameControlsRetainOrdinaryClickFeedback passes. Native graphics input tests run through docker prk-client-tests:10.0: dotnet test PRK.Client/PRK.GraphicsEngine.Tests/PRK.GraphicsEngine.Tests.csproj --nologo --verbosity minimal -m:1 -p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903 --filter 'FullyQualifiedName~GuiInteractionTests|FullyQualifiedName~GuiKeyboardNavigationTests|FullyQualifiedName~ColumnResizeInputTests|FullyQualifiedName~InputDispatchTests|FullyQualifiedName~InputEventBufferTests' ->68 passed,0 skipped,0 failed, covering generic real mouse/keyboard XML silence and native override compatibility. Native Nano rows/slots still do not accept text focus; no artificial keyboard casting path was introduced. Final full ./run-client-tests.sh -p:TreatWarningsAsErrors=true -p:WarningsNotAsErrors=NU1903 --logger 'trx;LogFileName=nano-programs-final-full.trx' ->4001 passed,180 skipped,0 failed. Skips are unavailable install/native display/audio/runtime fixtures, not disabled regression tests. Logs .dev-data/nano-programs-sound-integrated.log, nano-programs-sound-input.log, nano-programs-final-full.log; client TRX under .dev-data/test-results/client/. git diff --check clean; old NanoProgramsPresenter/layout references absent from live source/tests. No new source changes needed after integrating native support. Local implementation and functional validation complete; private backup preserved all19 migration paths. Migration remains uncommitted. Combined full-client Native AOT publish, Windows/macOS and live/installed-asset rendering are deferred/unverified as agreed, not claimed passed. Never expose private tracking metadata in repository/team content.
Checklist
3 of 3 complete- Audit Nano Programs behavior and shared text-input/opacity/activation gaps; report precise prerequisites without shared-code edits.
- Verify real-input search match-first/dimming, school toggles, sorting/modes, stale cast refusal, preferences and cleanup; coordinate AOT coverage.
- Move Nano Programs frame/search/school/filter/sort/modes/preferences to Lua while preserving canonical native information, identities and validated casting.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Feature
- Task ID
tsk_26fvmaj77c- Updated