Skip to content

Declare inherited and unset values, then bind field operations to declarations - #62

Draft
trissim wants to merge 15 commits into
mainfrom
fix/32-46-declared-field-state
Draft

trissim wants to merge 15 commits into
mainfrom
fix/32-46-declared-field-state

Conversation

@trissim

@trissim trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Work in progress for #32 and #46. The field-read contract, existing owners, complete consumer migration and saved-data cutover are in docs/declared-field-state.md. Source implementation and actual application acceptance follow. No compatibility aliases, fallback readers or second path registry.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Unready producer prototype pushed. See docs/declared-field-state.md for the working #32 paired-source checkpoint and the current #46 API/probe. Current producer head is deliberately NOT compatible with the still-unported companion frontend branches. Declaration identity across schema replacement/undo and the overloaded topology owner index remain structural work; do not install or merge as complete.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Checkpoint cc83a3e fixes an invalid inheritance claim: RootFields is a namespace, not a declared field. Before: RootFields(FieldProxy) inherited default/value metadata with no declaration, and a root field named value collided with whole-root value. After: FieldNamespace owns state/structure discovery, children, attribute binding and the single subscription-lifetime implementation; FieldProxy and RootFields consume it as siblings. Root datum/default/reset/write methods were deleted. Delegate admission synchronizes before checking the owner. Consumer search across ObjectState, FormBridge, PyQt, OpenHCS, Toad and Core found no root fields.write/reset/raw or external FieldProxy isinstance dependencies. Eleven focused tests pass, including value-named declaration and delegate replacement; 24 source-paired Toad checks and actual native-input/undo/unmount journey pass. NRA module_syntax_index drove the ownership move; prior full-corpus evidence and source relationships are in docs/declared-field-state.md. Dynamic field_type factory resolution is still open-ended, not a proof of external subtype behavior. Issues #32/#46 remain incomplete; no installation/completion claim.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Qt progress belongs here, not in the repository API contract: PyQt ef7243c pairs with ObjectState cc83a3e production and FormBridge 881157d. Six source-paired Qt cases pass, including actual default/explicit form construction, native text/reset clicks with one mutation/publication, null/absence/inheritance, existing/nested views reacting to backend enablement, stale checkbox paint not becoming data, observer release and nested signal blocking. Details: PyQt #34 comment 6212298431. The API document now contains only lasting contract, without issue numbers, status, plan or evidence inventory, as requested in 11356. Both issues remain incomplete: Qt window/list/bridge callers, OpenHCS/Core consumers, optional/inline forms, saved-source migration, mutation omission/null admission and coherent installed acceptance remain. Pausing new UI/provider/build runs for the announced Codex migration; all production changes are pushed.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Inspection/member correction delivered (not completion of the entire cutover)

Pair: ObjectState 9faba28, FormBridge 37a0556, PyQt 02db991.

  • FieldInspection declares exactly one effective value: resolved: FieldValue. The parallel resolved_value, availability flag and broad exception fallback are deleted. Original resolver exception identity propagates.
  • Five original inspection/projection consumer methods migrated: null classification, inherited classification, type projection, JSON projection and preview projection. Inheritance relation is owned by the member and shared with structural-owner projection. Thirty additional AST-selected flag uses now invoke member behavior across resolver, structural projection, construction and Qt services.
  • FieldValue has no inherited, has_value or is_none class flags. project has no absence default: it passes the real directive or datum through existing polymorphic resolution to the view. Bridge absence is a visible Unset preview/member spelling, not fabricated null. Public DTO wire resolved_value and its wire null-description fields remain unchanged; their similarly named reads are not FieldInspection aliases.
  • SpinBoxValueAdapter owns integer/double rendering, placeholder/range behavior and native admission. Leaves retain numeric type/range and floating formatting only. None renders as literal None; directives render their preview; real minima are data. No numeric value is None/value is not None branch or magic one-space remains in the AST-selected numeric class family (scoped rg: zero).
  • Native signal declarations include their actual receiver. Qt emits textEdited before updating its number, so unchanged-number text admission is separate from valueChanged; no sender() guess or duplicated publication. Input tracking begins at control construction. Retiring special paint does not repeatedly repaint partial input and erase a minus sign.

Source evidence

NRA ModuleSyntaxIndex/class-family census covers eight production/dependency roots: 1,585 modules; 9,875 before/9,876 after class rows; zero parse errors. Conditional Qt declarations/runtime signal bindings are not claimed statically resolved. Actual C3 MRO and shared implementation identity were checked for base/no-scroll int/double controls. A new numeric leaf supplies its native Qt base, type/range and any real formatter; it does not copy data-state or subscription algorithms.

Requested raw rg is_none|has_value|\\.inherited\\b: 156 -> 115 across the same corpus. Remaining matches are wire DTO/null-description names, unrelated source fields and logging; FieldValue flag declarations/reads are gone. resolved_value_available production hits: 0. Five inspection consumers are not counted as thirty separate callers; the latter number is AST-selected expression sites.

Owned evidence: /home/ts/.cache/agent-scratch/objectstate-declared-fields/inspection-spinbox-{before,after}.json, meaning-flags-{before,after}.txt, meaning-member-migrations.json, inspection-spinbox-owners-after.json, spinbox-runtime-mro.txt and spinbox-members-after.txt. Transformations remain under the persistent producer checkout .scratch/. The first signal tuple selection also selected the outer tuple; that unsupported site was corrected before acceptance, not claimed as semantic proof from parsing.

Confirmed behavior

  • 30 producer tests passed: existing handles plus inspection/scopeless resolution; literal null/absence/inheritance, exact read failure, dirty/provenance and source rules retained.
  • 68 real Qt cases passed: localized float roundtrips, literal/wrapped null and directives, exact minima, one native zero admission, unchanged numeric minimum, range/signal-block restoration, default form, existing/nested refresh and reset.
  • 5 bridge projection cases passed: absent member versus null and literal strings.
  • Real source-paired Qt control journey and real bridge mutation/catalog/history journey passed, including original-handle undo.

Earlier import, signal-ordering, tuple-selection, constructor-tracking and negative-entry failures are retained separately; acceptance is the corrected run, not a silent retry. Test expectation that None means inherited display was replaced by explicit Inherit plus a distinct literal-null assertion; no skip/xfail, weakened count, timeout increase or provider replay.

This is source-paired acceptance, not shared installation or full OpenHCS/Core/Qt-window cutover. Existing drafts and saved-data migration remain unfinished.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Typed field members across the bridge boundary

Paired source checkpoints: ObjectState 1479884, FormBridge b7c4ad5, PyQt f0acb19, OpenHCS 8d3bac264. Not shared-installed and not completion of the wider field cutover.

Owner and consumers

  • FieldInspection retains raw and resolved as FieldValue members. The two null-presence properties are deleted.
  • FieldValue is dataclass-declared. Unchanged python-introspect MemberFamily (main a9428c3) already owns tagged abstract-dataclass encoding/decoding. No new codec, wrapper, case roster or registry was added.
  • Shared bridge semantic DTO fields carry members, not nullable values plus two booleans. The four compact-presence re-derivations and redundant action-field overrides are deleted. Compact serialization uses the declaration-aware codec before selecting keys, preserving Value(None), empty/false/zero, Inherit() and Unset() tags even with previews.
  • Payload exclusion yields explicit absence for an excluded datum and retains directives; previews remain bounded display metadata. No exclusion fabricates literal null.
  • Field-list compaction maps concrete data through the member. OpenHCS help/rendering consume member behavior; the obsolete null-as-inheritance summary counters are deleted.
  • DataclassFieldAccess.is_config_type/is_container owns configuration classification: meaning members being dataclasses must not make them configuration containers. Extraction, reconstruction, structural leaves, history, context and form selection use that owner. Code-editor updates use it and canonical raw reads; duplicate nested recursion and three replaced/dead helper paths are deleted.

Source evidence

NRA SourceModule, module_syntax_index, build_class_family_index: 1,589 production/dependency modules, 9,923 class rows before/after, zero parse omissions. Evidence uses the producer, FormBridge, PyQt, OpenHCS, Toad, Core, current python-introspect and pycodify roots. Syntax/family evidence does not prove dynamic aliases, decorators, MRO or behavior.

Exact search after migration:

rg -n 'raw_value_is_none|resolved_value_is_none' across all five owned source and test roots: 0 hits, exit1, stderr empty. Original two inspection properties, two DTO fields and four re-derivations are gone.

Evidence root: /home/ts/.cache/agent-scratch/objectstate-declared-fields/; dto-members-{before,after}.json, dto-member-call-sites-before.json, dto-member-fixture-migrations.json, dto-null-flags-after.txt.

Confirmed behavior

Real Qt form/native typing, production Qt main-thread dispatcher, authenticated localhost ZMQ server/client, declaration-aware DTO decoding, mutation/catalog, reset, original-handle history undo, absence and view/server disposal pass. Explicit wire examples: {"Value":{"value":null}}, {"Value":{"value":""}}, {"Value":{"value":"None"}}, {"Inherit":{}}, {"Unset":{}}. Final journey also uses the existing metaclass-registry source required by OpenHCS. No provider or original saved input was used.

  • 66 distinct producer cases pass: 64 in the first batch and two old source-generation assertions corrected and confirmed separately. Their former None-as-inheritance expectations contradicted the declared contract; strict literal-null and explicit-empty-config assertions replace them. Initial failure output retained.
  • 43 focused FormBridge cases pass, including typed/compact member roundtrips, malformed-member rejection, code-editor updates and real ZMQ transport.
  • 68 focused Qt cases pass.

Receipts: dto-member-bridge-{journey,paired-final}.txt, dto-producer-tests-v1.txt, dto-codegen-correction.txt, dto-bridge-tests-v1.txt, dto-qt-tests-v1.txt.

Remaining application blocker

OpenHCS tests do not reach collection. The old installed metaclass-registry lacks testing; using the unchanged required source clears that import and exposes TypeError: LazyNapariDisplayConfig.colormap must be str; got Inherit during configuration startup. This wider lazy-validation cutover remains doctrine-owned under the existing unfinished field work. No skip, timeout increase, alternate test harness or installation was used. Receipts: dto-openhcs-{tests-v1,paired-tests-v1}.txt. The OpenHCS consumer source is pushed, not claimed fully application-verified.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Declaration-owned checkpoint (source-paired, not installed)

Pushed heads: ObjectState 93eae56; FormBridge b5d3af8; PyQt 8690060; OpenHCS f0c07c411. Dependency python-introspect ffcffaa (PR #25).

ValueDeclaration compiles annotations once. ParameterOwnerDeclaration owns parameters, field_types and init_field_names (one definition each); constructor and configuration owners share that implementation. FieldValue.of only preserves meaning members or boxes data; it does not classify runtime payloads. Named configuration access is absent on scalar leaves. Declared collection element types own traversal and serialization. DeclaredValue shares metadata/copy/serialization lifecycle between configuration and collection values.

InheritedDefault is the single frozen class-keyed default record; ValueDefault/FactoryDefault materialize it. own_default and inherited_default now index declared fields and raise KeyError for unknown names. Their direct resolver callers validate against the requested declaration; configuration_mro(field_name) filters ancestors by their declared fields before reading defaults. All touched production roots have zero _inherited_default, _resolve_type and __objectstate_rebuild__ references. UIParameterVisibilityPolicy owns field visibility metadata, keyed by the existing policy class. CompactFieldProjection is also its own metadata key; no string-key compatibility reader remains.

Text-line counts (published baseline -> checkpoint):

| production root | is_container | is_config_type | literal | None | getattr | get_base_type_for_lazy |
| --- | --- | --- | --- | --- | --- |
| ObjectState 1479884 | 27 -> 0 | 2 -> 0 | 94 -> 91 | 37 -> 16 | 46 -> 2 |
| FormBridge bdafb52 | 3 -> 0 | 6 -> 0 | 480 -> 468 | 18 -> 16 | 8 -> 0 |

The two remaining lazy callback-name lines are its definition and register_type_resolver registration; zero callers, imports or exports remain in the touched production family. The normalization wrapper/cache and per-caller fallback expressions are removed. Archived dirty-before normalization count was 45, now 2.

FormBridge FieldValue.of: published 3 -> 2; archived dirty-before 15 -> 2. get_base_type_for_lazy: 8 -> 0. metadata.get: 4 -> 2. Combined requested regex: published 15 -> 4; archived dirty-before 27 -> 4. The remaining FieldValue.of sites preserve DTO meaning after mapping JSON data, not payload kind. The remaining metadata.get sites read canonical runtime code-document tokens, not declaration metadata.

widget_creation_type consumers: WidgetCreationPipeline.init selected an enum by the string; it now calls param_info.creation_type(WidgetCreationType). ParameterFormManager._create_parameter_widget only logged it; it now logs the actual info class. All four string ClassVars are deleted.

NRA syntax/family evidence: 1,590 production/dependency modules, 9,953 classes, no parse errors. AST calls: ObjectState getattr 28 -> 13, FormBridge 17 -> 15; is_container/is_config_type calls zero, is_dataclass exactly one annotation compiler call. Dynamic resolution is not established by these syntax counts; the actual source-paired journey below checks the affected behavior.

Exact deleted Python type-name DTO declarations remain: source_type (1), object_state_path_type (2), raw_value_type (2), resolved_value_type (2), object_type (3), help_target_type (1). Genuine mime_type is retained. Deletion gates cover the exact declarations, not all *_type fields.

Verification: python-introspect public resolver/analyzer 64 passed; producer declaration/handle/inspection/scopeless/codegen/deletion cases 51 passed; bridge DTO/deletion cases 29 passed; Qt declared/numeric cases 66 passed. Actual source-paired native Qt input, main-thread dispatch, authenticated localhost ZMQ, DTO decode, reset, undo and disposal passed with null, empty string, text None, inheritance and absence. No provider and no installation.

Still unfinished: OpenHCS config startup reaches SourceBindingsConfig.post_init but attempts to iterate Inherit in its source-binding normalization. Earlier removed has_value reads in the shared normalization owner are repaired; the whole remaining post-init normalizer needs a directive-aware owner pass. The old test_subfield_semantics.py still imports deleted MISSING/string APIs and fails collection; this failure is retained, not skipped or xfailed. Full OpenHCS/app acceptance and #32/#46 cutover are not complete. doctrine-segment remains the implementation owner.

Dependency: python-introspect ffcffaa, draft PR #25. No shared runtime publication/restart performed.

@trissim

trissim commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Fresh direct-task checkpoint addressing the source-plan roster/C3 review; this does not resume the blocked P44 goal or claim final P44 acceptance.

Published source pairing:

Ownership and deletions:

  • _SourceBindingPlanBase iterates dataclasses.fields(self), indexes each resolved annotation, admits its raw member through ValueDeclaration, normalizes data through that declaration and validates the result. Inherit/Unset remain directives via member behavior, not flag tests.
  • SequenceDeclaration owns declared list/tuple shape conversion; NullableDeclaration composes it without interpreting payload shape. Object-annotated sequence payloads remain opaque.
  • Only actual extra behavior is field-declared under SourceFieldTransform: bindings uniqueness/coercion, grouping cleanup, metadata schema merge and stack components. Validated transforms consume validated input; coercing transforms validate their output. No string-name normalization roster remains.
  • Both normalization and annotation-validation mixins call super().__post_init__(). DataclassPostInit is their shared cooperative endpoint. Deleted SourceBindingsConfig.__post_init__, CompiledSourceBindingPlan.__post_init__, _normalize_field, _tuple_values, _validate_field_value, and obsolete forwarding helpers/imports.

NRA source evidence: 54 relevant production modules across ObjectState, FormBridge, PyQt, python-introspect and OpenHCS parsed; zero parse errors. Before/after source-plan roster calls: source_bindings.py 5→0, config.py 5→0. Explicit named-parent post-init calls: 2→0. Declaration, inheritance, write/check/call and consumer sites are retained at /home/ts/.cache/agent-scratch/objectstate-declared-fields/declared-source-plan-nra.json. Syntax is not proof of dynamic alias resolution; actual C3 is separately exercised below.

Verification:

  • 79 python-introspect focused tests passed, including getter-owned validation/error identity and a cooperative trailing preparation capability.
  • 57 ObjectState focused tests passed, including declaration shape normalization and opaque scalar payloads.
  • Seven direct source-paired application API checks passed: raw directives, both source-plan owners' normalization/rejection, compiled directive rejection, shared declarations and real PipelineConfig construction with inherited Napari colormap gray.
  • Additional real application API checks passed: a new declared field normalizes/validates with no roster edit, a field-declared transform executes, an additional C3 capability executes once after normalization, and compiled annotation validation still rejects directives. Actual MRO: CooperativePlan → CompiledSourceBindingPlan → SourceBindingDeclarationsMixin → _SourceBindingPlanBase → AnnotatedDataclassValidationMixin → TrailingInit → DataclassPostInit → ABC → object.
  • Added corresponding OpenHCS unit regressions; OpenHCS pytest itself remains gated by this checkout's previously reported unbuilt native extensions. No skip, gate bypass, installation, full-suite or full P44 claim. All three PRs remain drafts.

@trissim

trissim commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

P44 takeover checkpoint (not ready):

  • ObjectState 9c7f05a, FormBridge ed74d9e, PyQt da2449a pushed. Preserved predecessor work and the automatic pre-compaction checkpoint.
  • Deleted FieldValue.is_inherited and all 10 callers. Already-admitted members now own inheritance; FormBridge RawDisplayValue uses ConfigurationDeclaration.read_raw/own_default, including factory defaults. No compatibility API or flag reader added.
  • Source search across the three production roots: zero FieldValue.is_inherited or .raw_value_is_none, .resolved_value_is_none, .resolved_value_available, .has_value, .is_none, .is_missing, .is_container reads. Before sites: .scratch/p44/flag-sites-before.txt. AST ownership inventory: .scratch/p44/ast-before.json (no parse errors). This is not a claim that remaining container classifiers were deleted.
  • Six formerly failing subfield contracts now mutate through DottedFieldPath.bind(...).write(...); targeted subfields/declarations: 18 passed. Stale resolver and constructor-patcher tests now use resolve_declared_type and ValueDeclaration.construct; removed APIs were not restored.
  • Actual source-paired generated PyQt form on isolated Xvfb: inherited 77 distinct from literal None, backend updates the open form, native key input commits, reset has exactly one hook/publication, then disposal. Screenshot: /home/ts/.cache/agent-scratch/rts-results/p44-form.png.
  • Full ObjectState: 262 passed, 146 failed, 33 errors. FormBridge form/help/preview tests: 18 passed, 8 failed. Removed API consumers/test doubles and other failures remain; these are not accepted as baseline failures. Logs and exact per-repo SHAs: /home/ts/.cache/agent-scratch/rts-results/p44.json.
  • Remaining production ownership work includes FormBridge container conversion and PyQt literal/table classifiers. All three PRs remain draft. No installed package was changed.

This branch has not been deployed

No deployments
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.

1 participant