Skip to content

Migrate PyQt to shared form declarations and typed paths - #33

Merged
trissim merged 8 commits into
mainfrom
refactor/native-formbridge
Oct 16, 2026
Merged

trissim merged 8 commits into
mainfrom
refactor/native-formbridge

Conversation

@trissim

@trissim trissim commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Shared form declarations and typed field paths

Draft, source/library checks only. Owner: core-route-counts. Current pushed head: 3bca3be9aea97fc9a5b38ee811f1e8b20b4d29bc. Codex retains integration and installation; the large-draft source review is still required.

Completed dispatch checkpoint

Nested managers already have absolute IDs. The old factory prepended ancestors again, so actual managers produced config.child.value for mutation but config.config.child.value for notification, including with a nonempty root ID.

  • Existing FieldDispatchContext now carries one DottedFieldPath. Mutation and both root signals consume it. Its constructor uses the manager's binding and existing form-tree root owner. Delete the entire dispatch factory, both string path fields and ancestor reconstruction.
  • Keep typed inline owners through all three structural resolver callers: manager flash routing and both scrolling helpers. Use owner equality/field name/direct-child behavior. Keep StructuralFieldPath.relative_path unchanged, including indexed cell routing and the existing whole-child fallback. Delete caller hints, owner tuples/slicing/rejoining.
  • State-facing qualifications use DottedFieldPath.child throughout declaration/type lookup, metadata, chrome, resets, placeholders, enabled actions and preview/hierarchy readers. Delete competing chrome/bridge path helpers and widget-creation root walks. Generic chrome/validation readers use the path type directly rather than acquiring a private manager dependency. Display aliases, ScopeKey, filesystem paths and structural suffixes remain separate.

85 focused PyQt checks passed in 3.32s. Real QApplication/ObjectState/ParameterFormManager instances cover empty/nonempty root IDs, normal/reset dispatch, actual reset_parameter, callback execution, reentrancy suppression and both root signals. Real form-backed sectioned editors cover root/nested/deep owners and row-0/column-1 structural routing. Existing chrome/tree/navigation/viewport/reset-flash/projection/enabled-title checks are included. This is not a full suite or installed application acceptance.

The duplicated 83-line checkpoint report has been deleted without replacement. Production code and tests are unchanged by that deletion; the 85-case result above is retained, not rerun for this documentation-only change. The existing NRA source census spans 1,145 modules, with 5,760 original / 5,734 nominal projections before → 5,759 / 5,733 after; the dispatch factory is the one removed class. 26 OPEN remain; zero parse omissions. Dynamic aliases, external Qt bases/C3 and invocation effects are not proven by the census.

Concrete fact search in services/field_change_dispatcher.py: rg -n 'field_path: DottedFieldPath|context.field_path' reports the sole stored address declaration at line 44 and its mutation/signal/trace consumers. The root signal boundary derives its local string from that same value. Package source/test/doc searches find no old factory, source/root path fields, structural child-hint keyword or deleted helper. Named-source searches in OpenHCS and paired Toad/FormBridge/ObjectState roots find no outside consumers of the changed private/context/resolver APIs; this does not resolve dynamic aliases.

Earlier changes retained

  • Remove the unused fourth FormBridge conversion argument from both PyQt production callers and the existing test. Replace two removed signature_default readers with recorded declaration defaults. All 24 known family conversion calls use three arguments (5 production, 19 tests; no alias-resolution proof).
  • Complete the leaf/parent/lineage/direct-child/intersection consumer migration; five former helpers and their callers are removed. Inline identity still rejects root; immediate-child order/deduplication remain.
  • Pair with ObjectState #61 82a6213 and FormBridge Accept qualified ZMQRuntime 0.4 endpoint lifecycle dependency #13 1a45b8e, not older installed libraries. Dependency requirements are owned by pyproject.toml; the obsolete CI version comments are deleted. Toad #670 retains its exact paired pins unchanged by this PyQt-only checkpoint.
  • Earlier separate checks: 19 ObjectState, 67 PyQt path consumers, 30 PyQt converter/chrome consumers, 25 FormBridge and 3 dependency-declaration checks passed. These are historical results, not additional tests in the new 85-case run.

Preserved restrictions

The retained diagnostic for failed input 9481 records WebSocket close 1012 and prohibits replay. It was inspected read-only; the failed input was not replayed and the blocked persistent goal was not changed. The separate uncertain candidate/build attempt still needs explicit disposition.

No build, dependency installation, global pin change or application installation occurred in this completion turn. The disposable verifier was removed after an active-borrower check; concise results/source evidence remain. No installed Settings/Sort or complete paired application acceptance is claimed. CI remains deferred.

@trissim

trissim commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

9453 / 9455: complete PyQt path-fact migration

Source only. No app build, global installation, saved-state acceptance, UNKNOWN retry or active-owner restart.

Published source:

Owner and consumers

DottedFieldPath owns leaf naming, parts, immediate parent, lineage, direct-child selection and intersection. PyQt's inline identities/chrome, form target access, changed-path chrome/flash routing, structural-owner addressing, provenance navigation, form/window scrolling, and config-tree ancestor markers consume those existing operations directly. Raw leaf/parent splits, dot-presence decisions, typed-part slicing and ancestor-prefix loops are removed across the complete named family. The additional scroll-target decomposition and config-tree prefix loop found in the wider source pass are migrated too.

Root direct-child selection was implemented separately by ParameterFormTreeIndex. That behavior now belongs to DottedFieldPath.direct_child_name, which preserves the existing nested/structural-name behavior while handling the empty root as well. Its implementation uses one owned child-prefix decision. General containment semantics are unchanged. InlineDataclassChildFieldIdentity retains its stronger root rejection with the same error message; inline child selection still excludes the root, parent itself, unrelated paths and deeper descendants, while retaining order and deduplication.

Five replaced forwarding helpers are deleted, with all consumers migrated: _relative_child_field_name, _direct_child_field_for_path, direct_child_field_for_path, path_intersects_field_scope, path_belongs_to_field_scope. Structural-display parsing stays in the existing StructuralFieldPath/structural-table code. Enum/repr/module/editor-completion splitting, filesystem paths, Qt parents and ScopeKey operations are separate identities and unchanged. Flash trace output retains canonical string addresses at its boundary.

Production diff: PyQt nine files (plus two existing-test migrations/extensions), commit 78+/131− overall. ObjectState one production file plus existing-test cases, commit 22+/5− overall. No new production class, registry, cache, alias, codec or helper.

Source evidence

Existing NRA parser/class-family tooling enumerated declarations, imports, writes, calls, checks and consumers across the six production repositories and actual registry python-introspect 0.3.0. Expanded retrieval includes the complete PyQt production root. Before/after: 1,145 modules, 5,760 original / 5,734 nominally projected classes, 26 OPEN, no parse omissions. No production class change. Nominal indexing is not a dynamic alias, C3 invocation or behavioral proof.

Actual after-search across the six candidate production roots:

rg -n 'def direct_child_name|def (direct_child_field_for_path|_direct_child_field_for_path|_relative_child_field_name|path_intersects_field_scope|path_belongs_to_field_scope)' /home/ts/wt/{objectstate-native-forms,pyqt-native-formbridge,formbridge-native-forms,toad-context-pages,core-route-counts,textual-native-forms}/src --glob '*.py'
/home/ts/wt/objectstate-native-forms/src/objectstate/field_access.py:75:    def direct_child_name(self, candidate: str | "DottedFieldPath") -> str | None:

This finds exactly one declaration of direct-child selection, in ObjectState's owning class, and none of the five replaced helper declarations. Remaining raw dot splitting is structural-display, enum/repr, module-name or editor-source parsing, not the migrated field-path facts. Source/search/index evidence lives under /home/ts/.cache/agent-scratch/core-native-formbridge/pyqt-path-{before,after}-*.

Final checks

  • ObjectState field-access and inspection cases: 19 passed in 0.07s, including root/nested/unrelated/structural direct-child selection with both string and typed candidates.
  • Existing PyQt inline chrome, tree routing, window/provenance navigation, viewport context, reset/flash, widget projection and release-declaration cases: 67 passed in 2.10s. Extensions cover identity root rejection, strict immediate children, root input, ordering/deduplication, and actual root/nested tree routing instead of the deleted helper API.
  • 107 packages resolved; uv lock --check --offline passes. Toad pins the exact ObjectState source above.
  • git diff --check passes; implementation checkouts clean/pushed.

These are serial, CPU-pinned source/library checks, not paired application acceptance. Host pressure remained critical (7 GiB /home free; 16.8 GiB swap used), so the run reused existing Qt binaries read-only and six cached pure-Python dependencies in an isolated Python 3.12 test environment. No scientific application/data load or dependency download. The borrowed OpenHCS checkout environment's package metadata remains unchanged. The owned test environment is retired after checking for active borrowers; concise logs are retained. Claude's large-draft review and explicit disposition of the older UNKNOWN candidate command still gate a new exact-cohort app build and Settings/Sort acceptance.

@trissim trissim changed the title Migrate PyQt callers to the shared native-form library API Migrate PyQt to shared form declarations and typed paths Oct 15, 2026
Unfinished source, not ready for integration or installation. Factory inheritance and frontend consumer migration are checkpointed. Nullable group editing and canonical topology transitions remain incomplete; Qt helper bodies still need to move into their behavior owners. Syntax and whitespace checked only; no behavioral tests, application or provider runs. Original refactor/native-formbridge branch is unchanged.
@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

P45 checkpoint 2a1e5a8: 177 net lines deleted in the lifecycle cleanup. ParameterInfo MRO selects behavior-owning Qt creation classes. Optional title, presence binding, placement and reset now live in OptionalNestedWidgetCreation; nested/inline/ordinary classes own their shared behavior. is_optional and is_nested flags, LayoutKind and the parallel layout-strategy family are deleted. WidgetBuildContext owns manager, parameter, container and layout; 59 reads were moved there and the runtime copies plus three unused type slots were deleted. The pipeline only orders the shared lifecycle. No replacement case roster or string widget table.

NRA: 1,820 modules including the OpenHCS consumer, classes 10,678 → 10,672, indexed 10,642 → 10,636, no parse failures; 36 original declarations remain outside the index. The first six-root census omitted OpenHCS; the corrected before snapshot reads HEAD for the two edited Qt files. Evidence: /home/ts/.cache/agent-scratch/forms-migration/qt-source-{before,after}.json and qt-lifecycle-consumers-before.txt. Actual Qt creation module imports with the paired ObjectState/FormBridge sources and installed PyQt. No automated tests or synthetic apps were run. Physical forms verification and dependency publication remain unfinished.

Two reset/placeholder tests built fake managers without the field-path
method that reset and placeholder refresh now call; they bind the real
ParameterFormManager method instead of a stub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

claude-forms: checked and merging as part of P45 together with ObjectState #61, FormBridge #13 and PyQt #33. Versions: objectstate 5.0.0, formbridge 0.2.0, pyqt-reactive 0.9.0 (public names removed; see CHANGELOG). Tests run from source together: ObjectState 407 passed; FormBridge 116 passed; PyQt failures identical to the three mains' (67, offscreen window-snapshot tests). Two stale PyQt test fakes now bind the real ParameterFormManager path method. Outside this PR: PyQt main already imports formbridge.forms.raw_display_value, which exists only in open FormBridge #14.

🤖 Generated with Claude Code

@trissim
trissim marked this pull request as ready for review October 16, 2026 22:09
Copilot AI balanced review requested due to automatic review settings October 16, 2026 22:09
@trissim
trissim merged commit 12a9e44 into main Oct 16, 2026
1 of 12 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants