132 lines
15 KiB
Markdown
132 lines
15 KiB
Markdown
# NeitzelFXDesigner initial project contract
|
||
|
||
Status: accepted architecture consolidated from decision rounds Q1–Q15 on 2026-11-12. Module names and configuration 1.0 fields are implemented by bootstrap work packages 3–4. Public preview Java signatures remain provisional; the draft wire codec and limits now have regression coverage. This document refines roadmap stage 1, not the complete product specification.
|
||
|
||
Decision provenance: [accepted workspace decisions](provenance.md). Execution order: [repository bootstrap plan](repository-bootstrap-plan.md). Existing authoring, preview, binding, generation and host requirements remain in the [broader roadmap context](provenance.md#broader-roadmap).
|
||
|
||
## Project and scope
|
||
|
||
- Repository: **NeitzelFXDesigner**; application name: **Neitzel FX Designer**.
|
||
- Remote: `ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git`.
|
||
- Canonical independent checkout: `/Volumes/PlanckSSD/KI/java/NeitzelFXDesigner`, alongside NeitzelLib in the canonical Java workspace. The research worktree is not its permanent checkout.
|
||
- Initial default branch: `main`. The initial repository bootstrap establishes this branch; the earlier consolidation found no advertised remote refs.
|
||
- The Component builder fix belongs to NeitzelLib. Designer/tooling code belongs to NeitzelFXDesigner. Application fixtures depend on library artifacts, never copied NeitzelLib sources.
|
||
- First milestone: one real Component and sample Model through Build and Refresh, successful-build capture, metadata discovery and target-runtime rendering in both minimal hosts. Include classpath and module-path fixtures and failure diagnostics.
|
||
- Full binding/generation UI, general projection editing, production handoff, packaging and wider qualification retain their later roadmap gates. Minimal hosts are not feature-complete releases.
|
||
|
||
## Modules and dependency direction
|
||
|
||
The artifact names below are established by work package 3. See [implemented boundaries and baselines](module-host-boundaries.md); the broader responsibilities remain the target architecture.
|
||
|
||
| Module/directory | Responsibility | Boundary |
|
||
| --- | --- | --- |
|
||
| `designer-contracts` | Configuration types/schema, wire envelopes, metadata DTOs and capability definitions | No Kit, IntelliJ or application classes; schema/protocol versions are independently tracked |
|
||
| `designer-core` | Application contexts, build/snapshot orchestration, validation, document edit intents and worker sessions | Depends on contracts; obtains host services through interfaces, not host implementations |
|
||
| `designer-kit-ui` | Shared canvas, hierarchy, inspector and later binding/generation panels | Depends on core and pinned Kit/JavaFX; no IntelliJ API |
|
||
| `designer-standalone` | Native application entry point, documents/undo, menus, navigation and lifecycle | Adapts core/UI to standalone services |
|
||
| `designer-intellij` | FXML editor, IDE Documents/commands, project/build/navigation integration and focus | Adapts the same core/UI; qualify build and packaging against the selected IDE SDK |
|
||
| `designer-preview-api` | Typed example descriptors and fresh preview-session lifecycle | Small project-facing artifact; no Kit or IntelliJ dependency |
|
||
| `designer-target-tools` | Discovery and NeitzelLib loading/rendering adapter in the application runtime | Uses contracts/preview API and target-compatible library dependencies; never execute application classes in a host |
|
||
| `integration-fixtures/` | Real classpath and module-path Maven applications, examples and failure cases | Same scenarios consumed by both hosts; normal artifact dependencies |
|
||
|
||
Shared contracts may be Java artifacts without implying identical JDK/JavaFX versions in hosts and workers. Select bytecode/API baselines per module from the supported target fixtures; verify that application-facing artifacts load on the oldest initial target before publishing them. The IntelliJ packaging toolchain must be pinned and tested; a Maven reactor for shared artifacts does not assume that ordinary Maven JAR packaging produces a supported plugin.
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
S[Standalone adapter] --> U[Shared Kit UI]
|
||
I[IntelliJ adapter] --> U
|
||
U --> C[Shared designer core]
|
||
S --> C
|
||
I --> C
|
||
C --> K[Configuration / protocol / metadata contracts]
|
||
C -->|Dedicated local IPC| W[Target-runtime tooling]
|
||
W --> K
|
||
W --> P[Preview API]
|
||
A[Application examples] --> P
|
||
W --> N[NeitzelLib and application runtime]
|
||
```
|
||
|
||
Each host owns its own engine/UI instances. The authoritative document and undo history belong to the active host. Kit remains a projection. This diagram describes dependencies and process boundaries, not shared mutable state across hosts.
|
||
|
||
## Shared application configuration
|
||
|
||
`neitzel-fx-designer.json` lives at the application's Maven reactor root. It contains a schema version and named application contexts. A context selects an application module, Maven profiles, classpath/module-path launch mode, preview sources/module and examples. Relative paths resolve from the configuration location, never the process working directory. Validate modules and paths against the selected reactor. Obtain dependency graphs and ordinary source/resource roots from Maven rather than maintaining competing lists.
|
||
|
||
Configuration 1.0 is now executable; see the [schemas and validation contract](configuration-and-protocol.md). The following example is valid input, with Java requirements defaulting to 21:
|
||
|
||
```json
|
||
{
|
||
"schemaVersion": "1.0",
|
||
"contexts": {
|
||
"desktop": {
|
||
"applicationModule": "app",
|
||
"mavenProfiles": ["designer-preview"],
|
||
"launchMode": "classpath",
|
||
"buildRuntime": "build-java",
|
||
"targetRuntime": "application-java",
|
||
"preview": {
|
||
"sourceSet": "module",
|
||
"module": "preview",
|
||
"provider": "example.preview.PersonExamples",
|
||
"defaultExample": "person.standard"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
The schema covers `test` preview sources in the application module, module-path entry/access settings and runtime requirements. Example IDs belong to provider descriptors; configuration selects a default and may select/filter descriptors rather than duplicating their metadata. A provider class name identifies a typed implementation, not an arbitrary reflective factory method. Provider registration/descriptor extraction must be validated against the library before the public API is frozen.
|
||
|
||
Select the context automatically when exactly one matches. Otherwise ask, show the active context and remember the choice locally. Opening a Component from a parent inherits that context. Shared source documents retain one host-owned draft even when usable in multiple contexts.
|
||
|
||
Local settings hold installed JDK mappings, absolute machine paths and remembered context/UI preferences. Shared runtime names refer to required build and target runtimes; resolve, display and validate those roles separately. Application JavaFX comes from Maven. A missing/incompatible target requests setup; never silently substitute the designer's or IDE's JVM. No automatic configuration migration. Unsupported schema/capabilities disable the affected tool with diagnostics while ordinary source editing remains available.
|
||
|
||
## Build and snapshot contract
|
||
|
||
1. Resolve the selected context and required reactor dependencies, including configured preview sources. Prefer the Maven wrapper; expose the plan, command/output and cancellation. Avoid unrelated applications unless dependency resolution requires them.
|
||
2. Identify known unsaved Java, Maven and designer-configuration inputs affecting the build. Offer **Save affected files and build** or **Cancel**, listing the affected files. Do not implicitly build older disk versions. Account for IDE autosave; another process's unsaved buffers are not observable.
|
||
3. Capture the relevant input identity/revision manifest and execute the build with the selected build runtime. FXML-only draft edits have separate revisions and need not trigger Java compilation.
|
||
4. After success, stage a consistent snapshot of compiled outputs, generated metadata, resources and resolved dependency content/identities into an ignored designer cache. Do not hand workers mutable `target` paths or mutable dependency outputs. Copy or content-address artifacts; a snapshot must not change if later builds overwrite their inputs.
|
||
5. Verify inputs/output capture remained consistent throughout the operation. A fingerprint at only one instant is insufficient. Detected changes, capture failures, cancellation or failed builds prevent activation. Publish a complete manifest/snapshot atomically, never a partially populated directory.
|
||
6. Activate the successful snapshot, refresh discovery and restart affected preview sessions. A manifest identifies context, build inputs, artifacts/digests, runtime requirements and tool contracts. Discovery and rendering use the same build identity.
|
||
7. Retain the last usable successful snapshot after failure, mark retained derived results outdated, and require explicit **Preview with last successful build**. An outdated build is not silently promoted to current.
|
||
|
||
Cache contents are local, ignored and reconstructible. Active workers retain their snapshots until stopped; eviction must not remove in-use artifacts. Numerical retention limits are operational defaults, not a new authoring decision.
|
||
|
||
FXML previews overlay the owning host's current parent and open Component drafts onto the selected build snapshot. Document revisions and snapshot identity remain distinct; source edits must not silently change a worker's captured input. Reject obsolete results using host-owned revision ordering, not numeric assumptions about IDE modification stamps. Resources outside the supported draft-overlay mechanism remain part of explicit resource/build freshness validation.
|
||
|
||
## Discovery and preview API
|
||
|
||
Metadata listing must not construct Models or invoke Controller methods. Separate example descriptors (stable IDs, display labels, compatible Model/View information and declared capabilities) from runtime construction. Generated descriptor metadata or equivalent non-constructing discovery must be tested; calling arbitrary provider initialization merely to list examples does not satisfy this boundary.
|
||
|
||
Selecting an example creates a fresh owned preview session with its Model graph and explicitly configured services. Provide readiness and cleanup hooks. Ordinary examples become ready after load/CSS/layout; asynchronous examples signal readiness subject to cancellation/timeout. Construction, services, Controller actions and cleanup execute only in the target JVM. Verify the adapter against NeitzelLib's actual injection/loading lifecycle before publishing Java signatures.
|
||
|
||
A parent rendering snapshot shares its Model graph across embedded Components; standalone Component preview selects its own example. Interactive preview has its own JVM/session. Bounded graceful cleanup precedes forced worker termination when necessary; cleanup callbacks cannot be guaranteed after process death, so host-side lifecycle ownership remains required.
|
||
|
||
## Versions and communication
|
||
|
||
Track configuration schema, wire/metadata contracts and preview API compatibility independently from product releases. Major changes represent breaking contracts; additive features use declared optional capabilities. Equal product versions alone are not proof of compatibility. Verify discovery and rendering independently so one unavailable capability does not unnecessarily disable the other.
|
||
|
||
Use a dedicated loopback-only socket with a per-launch random token and version/capability handshake for worker messages. Standard output/error remain captured application logs and cannot carry protocol framing. Do not log tokens. Bind the session to the launched worker and reject messages before authentication/negotiation. Use explicit bounded framing, validate lengths and resource limits before allocation, correlate requests/replies and define cancellation/error outcomes. Encoding, limits and negotiation are now defined by the [executable draft wire contract](configuration-and-protocol.md#draft-wire-protocol-10); transport integration remains later work.
|
||
|
||
Every applicable request/result identifies its worker session, request, context and build snapshot; rendering also identifies document revisions and requested size. Obsolete results cannot mutate current document/UI state. Diagnostics identify operation and available source origin while preserving editing.
|
||
|
||
Keep the proven reserved owner-lifetime channel for worker cleanup independent of FX responsiveness. The independently owning standalone editor must survive IDE death; it does not use the preview-worker death rule. Production host-to-host handoff remains a separate protocol/gate; choosing a worker socket does not silently choose its production transport.
|
||
|
||
## Library prerequisite and acceptance
|
||
|
||
Integrate and test the Component builder fix separately in NeitzelLib, preserve unrelated work, and establish the first released artifact containing it. Declare the resulting supported minimum/capability in designer metadata. Older unsupported versions receive diagnostics, not a hidden adapter. Until release, development fixtures may pin a clearly identified installed snapshot; a SNAPSHOT name alone does not establish fix provenance. The corrected source on main declares `de.neitzel.lib:fx:1.0-SNAPSHOT` with Java 21 / JavaFX 21.0.7. The fix and tested local artifact identity are recorded in [runtime provenance](runtime/neitzellib-baseline.md). No corrected minimum released version is asserted.
|
||
|
||
Accept the first milestone only when both minimal hosts use the same core/UI/fixtures and demonstrate:
|
||
|
||
- Constructor-only Components accept custom/inherited FXML attributes after initialization; invalid values fail; Model identity/write-back survive without an adapter.
|
||
- Classpath and module-path applications build, discover and render through their selected runtimes; missing module access is diagnosed rather than repaired with silent broad opens.
|
||
- Build scope and explicit save choices are observable; failed/cancelled/stale builds preserve documents and do not publish a current snapshot.
|
||
- Subsequent builds cannot mutate a running worker's snapshot; active snapshot cleanup is safe.
|
||
- FXML draft updates render without Java recompilation and stale responses are ignored.
|
||
- Missing/incompatible runtime/schema/protocol/capability failures are actionable and limited to affected tools.
|
||
- Listing examples performs no Model/Controller construction; selecting an example produces fresh state and honors readiness/cleanup.
|
||
- Console output cannot corrupt worker messages; owner death, cancellation and timeout terminate workers.
|
||
|
||
These are acceptance requirements, not newly passed tests. Broader product behavior remains governed by the existing roadmap.
|