Skip to content

Make configuration contracts nominal and viewer-native - #92

Merged
trissim merged 7 commits into
mainfrom
codex/ui-config-napari-performance
Jul 30, 2026
Merged

Make configuration contracts nominal and viewer-native#92
trissim merged 7 commits into
mainfrom
codex/ui-config-napari-performance

Conversation

@trissim

@trissim trissim commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

OpenHCS 0.7.0 makes configuration declarations, generated forms, MCP reflection,
and viewer transport share the same nominal contracts. It removes public options
that had no working runtime effect, eliminates duplicated display and backend
payload models, and moves remaining specialization back to the declarations that
own it.

The release also improves the two user-facing performance boundaries reported in
the GUI: repeated configuration-form construction and large Napari ROI tables.

Configuration architecture

  • Closed configuration choices and registered-function choices remain enums from
    declaration through UI, schema generation, code round trips, compilation, and
    execution.
  • CellProfiler text conversion is limited to import/export setting boundaries.
    Repeated-choice module settings now retain enum identity through runtime binding.
  • Generic annotation validation rejects invalid worker counts, viewer ports, blank
    hosts and registry names, and non-positive Z spacing at the declaring type.
  • Napari and Fiji display configurations are concrete typed dataclasses that own
    their viewer wire projection.
  • PolyStore consumes its own ZarrConfig and the typed viewer display contract; it
    does not import OpenHCS configuration declarations.
  • Forwarding strategy shells, display payload mirrors, generated field-description
    factories, and compatibility-only coercion paths were removed.

Public configuration cleanup

The UI no longer advertises settings that were inert, misleading, or impossible
to select meaningfully:

  • visualization dtype
  • streaming batch size
  • Fiji executable path
  • experimental analysis-function injection
  • unused well-pattern fields
  • custom aggregation aliases
  • singleton database-type selection
  • ineffective CPU-mask toggles

Array conversion choices now come from ArrayBridge rather than a second OpenHCS
dtype model.

ObjectState and generated forms

  • ObjectState owns direct-child field topology and rebuilds that derived index after
    updates, checkpoints, and time travel.
  • Generated lazy and injected dataclasses preserve declaration docstrings, source
    metadata, field validation, and UI semantics.
  • Raw reconstruction preserves a registered lazy runtime type when an enclosing
    annotation names its concrete base. This keeps unresolved inheritance sentinels
    out of concrete validation while resolved reconstruction still normalizes through
    the registered base type.
  • PyQT-reactive consumes ObjectState-owned immutable topology instead of rediscovering
    nested configuration structure for every form.
  • Responsive form layout uses reusable construction metadata without caching live
    Qt objects, ObjectState instances, parents, or signals.

MCP diagnostics

  • Architecture-symbol lookup errors now state that the namespace is curated,
    provide live near matches, and point clients to architecture-topic discovery.
  • Invalid config patches report unknown nested fields and suggestions derived from
    the reflected dataclass authoring schema.
  • Synthesized configuration descriptions now expose the declaration rationale that
    ObjectState previously dropped.

Napari and ROI performance

  • The first-party ROI manager uses a virtual table backed by the native Shapes
    layer instead of eagerly rebuilding one widget per ROI.
  • ROI payloads are added to Napari Shapes in coherent chunks while preserving
    geometry, features, colors, and selection ownership.
  • Binding 4,097 ROIs in the focused benchmark improved from approximately 490 ms
    to 1.07 ms.
  • Napari streaming applies configured colormaps and component display semantics
    through the typed display contract.

Verification

  • ObjectState: 159 tests passed on the release candidate; its GitHub matrix passed
    Python 3.11, 3.12, and 3.13 on Linux, Windows, and macOS.
  • OpenHCS broad release suite: 680 passed.
  • CellProfiler nominal binding and repeated-row regressions: 109 passed.
  • UI/configuration caller migration suite: 176 passed.
  • Generated .cppipe ZMQ regressions: 3 passed.
  • Disk/Zarr pipeline configuration integrations: 2 passed.
  • Exhaustive configuration-consumer coverage gate: passed.
  • Configuration mirror/deletion gates: passed.
  • The full local official30 ZMQ run exercised all 30 cases and identified one
    parser-boundary enum defect; the corrected 24-step imaging-flow cytometry case
    then passed exact native-reference equivalence in isolation.
  • 0.7.0 wheel and sdist built, passed Twine checks, installed in a clean Python
    3.12 environment, exposed all eight console scripts, and included the Napari
    manifest and all 42 packaged knowledge assets.
  • The clean installed wheel with its MCP extra generated a synthetic plate,
    rendered the portable neurite preset, executed it through the packaged MCP
    and ZMQ runtime, and completed without importing the source checkout.
  • The final pushed release matrix passed all 35 executed checks with zero
    failures. It includes all 30 headless CellProfiler parity cases, real Fiji and
    Napari viewer smoke tests, installed-wheel integration, Python 3.11 and 3.13
    boundaries, Linux/macOS/Windows package installation, both desktop installer
    harnesses, OMERO, disk/Zarr, and ImageXpress/Opera Phenix combinations.

External package releases

  • python-introspect 0.1.7
  • ObjectState 1.0.22
  • PyQT-reactive 0.1.28
  • PolyStore 0.1.26

OpenHCS pins compatible minimum versions so older published OpenHCS releases do not
silently adopt the new infrastructure contracts.

trissim added 6 commits July 30, 2026 14:10
Replace closed string choices and generated display-config mirrors with owning enum/dataclass declarations, remove inert public options, and route processor dispatch through existing registry strategy mixins. Apply the typed viewer contracts through Napari and Fiji while virtualizing the first-party ROI table and chunking Shapes updates for large result sets. Add generated configuration-consumer and mirror-deletion gates plus focused CellProfiler, streaming, and ROI regressions.
Synchronize package, Codex plugin, MCP bundle, and registry metadata for the typed-configuration and viewer-performance release. Document the removed inert options, owner-derived MCP diagnostics, ObjectState form-construction improvements, and virtualized ROI table benchmarks.
Copilot AI review requested due to automatic review settings July 30, 2026 19:54

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.

@augmentcode

augmentcode Bot commented Jul 30, 2026

Copy link
Copy Markdown

👀 Human Input Needed
A pair-review briefing is ready for you.

→ Pair Review Briefing

@augmentcode augmentcode Bot 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.

Deep Code Review Agent🐛

Review completed with 1 suggestions.

Fix in Cosmos

return {}
if not is_dataclass(cls):
return dict(patch.values)
authoring_path = f"{ConfigPatch.__name__}.{ConfigPatch.values.__name__}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This constructs the diagnostic root from ConfigPatch.values.__name__, but values is a dataclass field with a default_factory, so the class has no values attribute at runtime. Any non-empty patch for a dataclass config will raise AttributeError before unknown-field validation can run, turning valid patches and the new diagnostics tests into generic config_patch_invalid failures.

Severity: high


🤖 Was this useful? React with 👍 or 👎

@trissim
trissim merged commit 035fa20 into main Jul 30, 2026
36 checks passed
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