Files
com_r35157_nenjim-hubd-impl…/openspec/specs/nenjim-process-manager/spec.md
T

101 lines
7.4 KiB
Markdown

# nenjim-process-manager Specification
## Purpose
TBD - created by archiving change 79-integrate-process-manager-runtime-status. Update Purpose after archive.
## Requirements
### Requirement: Process Manager is a Hub-managed process
`com.r35157.nenjim.npm.NenjimProcessManager` SHALL extend the canonical `NenjimProcess` and SHALL add no public refresh, polling, event, start, stop, or query operation. `NenjimProcessManagerImpl` SHALL require and retain its owning non-null `NenjimHub` as the sole source of displayed process status and the non-null shared `JavaFxRuntimeService` as the sole JavaFX Application Thread submission path.
#### Scenario: Process Manager is used through the common lifecycle
- **WHEN** the registered Process Manager is resolved through `NenjimProcess`
- **THEN** its inherited no-argument `start()` is the only public lifecycle operation used by the Hub
#### Scenario: Owning Hub is required
- **WHEN** reference Process Manager construction receives a null Hub
- **THEN** construction fails with `NullPointerException` before startup
#### Scenario: JavaFX runtime service is required
- **WHEN** reference Process Manager construction receives a null JavaFX runtime service
- **THEN** construction fails with `NullPointerException` before startup
#### Scenario: Public API remains minimal
- **WHEN** a consumer examines `NenjimProcessManager`
- **THEN** it exposes no Process Manager-specific refresh, polling, event, stop, status, or query method
### Requirement: Process Manager polls immediately on one non-blocking worker
On its accepted startup attempt, the Process Manager SHALL request the existing window through its injected already-started `JavaFxRuntimeService` without initializing or starting JavaFX, then start exactly one dedicated background polling loop. The loop SHALL request `NenjimHub.getStartedProcessIds()` immediately and again after each normal three-second interval. Polling work SHALL not execute on the JavaFX Application Thread, and the worker SHALL be a daemon that does not prevent JVM termination.
#### Scenario: JavaFX prerequisite is unavailable
- **WHEN** Process Manager startup submits its window before the injected JavaFX runtime service has started successfully
- **THEN** service rejection propagates as Process Manager startup failure and no polling worker starts
#### Scenario: First snapshot is immediate
- **WHEN** Process Manager startup schedules its JavaFX window and starts its polling worker
- **THEN** the worker requests a Hub snapshot before waiting for the first three-second interval
#### Scenario: Polling continues at the required interval
- **WHEN** one polling attempt completes without interruption
- **THEN** the same worker waits three seconds and performs the next attempt
#### Scenario: Polling is not JavaFX work
- **WHEN** the Hub snapshot is queried and mapped
- **THEN** that work runs on the dedicated background polling thread rather than the JavaFX Application Thread
#### Scenario: Worker does not own JVM lifetime
- **WHEN** only the Process Manager polling worker would otherwise keep the JVM alive
- **THEN** its daemon status permits normal JVM termination
### Requirement: Successful snapshots replace the JavaFX list exactly
Each successful poll SHALL map every returned `NenjimComponentId` to its exact `value()` string in Hub-provided order and SHALL publish that complete point-in-time list through the injected `JavaFxRuntimeService`. Every JavaFX control mutation SHALL execute on the JavaFX Application Thread, and publication SHALL replace the complete displayed list rather than infer additions or removals. The existing title, dimensions, and multiple-selection behavior MAY remain unchanged, and no hardcoded process rows SHALL remain.
#### Scenario: Ordered ID values are displayed
- **WHEN** the Hub returns an ordered snapshot of component IDs
- **THEN** the JavaFX list is replaced with the corresponding `value()` strings in the same order
#### Scenario: A later snapshot removes an ID
- **WHEN** a successful later snapshot omits an ID present in the previously displayed snapshot
- **THEN** complete replacement removes that string without the Process Manager maintaining authoritative lifecycle state
#### Scenario: Process Manager eventually displays itself
- **WHEN** the Hub records `nenjim.process-manager.default` after its `start()` returns successfully
- **THEN** a later successful poll displays that ID in the position supplied by the Hub
#### Scenario: JavaFX controls remain thread-confined
- **WHEN** the window is created or a successful snapshot is published
- **THEN** all JavaFX control creation and mutation is submitted through the retained runtime service for execution on the JavaFX Application Thread
### Requirement: Polling failures preserve the last successful view
A polling failure SHALL be logged clearly, SHALL enqueue no invented or partial replacement, SHALL not terminate the JavaFX application thread, and SHALL leave the last successfully displayed snapshot visible. The background loop SHALL retry after the next normal three-second interval. If background waiting is interrupted, the worker SHALL restore its interrupted status and terminate the polling loop cleanly. Synchronous failures from the Process Manager's `start()` SHALL remain ordinary fail-fast Hub process-start failures.
#### Scenario: Hub polling fails
- **WHEN** obtaining or mapping a Hub snapshot throws a runtime failure
- **THEN** the failure is logged, the displayed list is unchanged, and the worker retries after the normal interval
#### Scenario: JavaFX publication fails
- **WHEN** publishing a successfully polled snapshot fails on the JavaFX application thread
- **THEN** the failure is logged without deliberately terminating that application thread or publishing invented fallback data
#### Scenario: Polling worker is interrupted
- **WHEN** the background worker is interrupted while waiting for its next poll
- **THEN** it restores its interrupted status and exits without another polling attempt
#### Scenario: Initial process start fails
- **WHEN** a synchronous failure prevents `NenjimProcessManager.start()` from completing
- **THEN** the failure propagates through the Hub, the Process Manager ID is not recorded, and no later Hub process is started
### Requirement: Displayed IDs are startup milestones only
The Process Manager list SHALL mean exactly the component IDs in the latest successfully published `NenjimHub.getStartedProcessIds()` snapshot. It SHALL make no claim about current health, worker activity, or continued liveness and SHALL add no names, aliases, metadata, timestamps, controls, icons, colours, history, or persistence. Polling SHALL be treated as a temporary internal observation mechanism without specifying Hub events as delivered functionality.
#### Scenario: Consumer interprets a displayed ID
- **WHEN** a component ID appears in the Process Manager list
- **THEN** it means that the Hub recorded a successful return from that process's `start()` and does not guarantee current health or liveness
#### Scenario: Presentation remains limited to IDs
- **WHEN** the Process Manager renders a Hub snapshot
- **THEN** every row contains only the exact component-ID value with no translated name or additional process metadata
#### Scenario: Event functionality remains absent
- **WHEN** the delivered Process Manager implementation is inspected
- **THEN** it observes the Hub by polling and exposes no event type, subscription, or push-update contract