Skip to content

Engine management stays responsive and shuts down reliably - #41

Merged
JaredP94 merged 5 commits into
mainfrom
fix/engine-manager-batch
Nov 3, 2026
Merged

JaredP94 merged 5 commits into
mainfrom
fix/engine-manager-batch

Conversation

@JaredP94

@JaredP94 JaredP94 commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Description

Engine status no longer holds the lifecycle lock during slow readiness/identity probes. Delayed observations cannot undo a start, stop, or port change, and a model inventory sweep that exceeds its budget returns HTTP 503 so peers retain their last-good lists.

Install verification, opaque commands, and oMLX disk-image copying now report stages without invented percentages. Real download progress remains visible; desktop (local and remote) and TUI render unmeasured stages sensibly.

Local non-loopback bind overrides require the persisted, live-read engine_allow_lan_bind opt-in (default false). Remote starts remain loopback-only. Shutdown callers join one concurrent engine sweep, and cancellation cannot skip daemon cleanup just because the start CLI had not returned yet.

References: NVIDIA#84, NVIDIA#180, NVIDIA#13, NVIDIA#81, NVIDIA/Personal-AI-Router@27b342a, and NVIDIA/Personal-AI-Router@72d5605.

Scope

The original five focused implementation commits cover:

  1. Shared bounded passive status probes, lifecycle revisions, stale-result rejection, and deadline-bound HTTP model inventory.
  2. Optional unmeasured install percentages, desktop projections, TUI rendering, progress tests and documentation.
  3. Live LAN-bind permission in node-settings with a narrow read-only worker/broker relay. This fork does not have upstream's engine-settings subsystem, so only this permission read is relayed. Internal notifications are documented and excluded from renderer delivery.
  4. One joined shutdown sweep, preserving concurrent engine stops and retries of failed actionable process/command stops.
  5. Deterministic detached-daemon cancellation regression, correct cleanup after an executed CLI exits unsuccessfully, readiness-phase synchronization, and crash-report synchronization.

Three signed-off review follow-up commits:

Version decision relative to v0.8.0: node-settings 3.1.0 → 3.2.0 for the additive setting; reuse existing unreleased engine-manager 1.4.0, broker 2.5.0 and TUI 1.2.1 bumps. The follow-up engine changes are test-only. No changelog/release-asset changes.

Validation

Fresh worktree from origin/fix/engine-manager-batch; its own npm ci --no-audit --no-fund, no dependency symlink. macOS arm64, isolated temporary fixtures only; no real engine installation/uninstallation or user engine/configuration paths modified.

Current follow-up verification:

  • Engine-manager status/cancellation group: go test -race -count=100 -run '^(TestStatus|TestStartDoesNotWaitForPassiveProbe|TestModelsResult_CanceledCaller)' ./... — passed.
  • Detached-daemon cases: go test -race -count=20 -run '^TestStopAllStopsDetachedCommandDaemon' ./... — passed, including a fresh run after all temporary fault injections were removed.
  • Engine-manager full go test -race -count=1 ./... — passed (126s). Full GOMAXPROCS=2 go test -count=1 ./... — passed (125s). The unconstrained normal run failed; see the complete list below. These passes do not prove those failures pre-existing.
  • Node-settings and TUI: full go test -count=1 ./... — passed. Broker standalone full go test -vet=off -count=1 ./... — passed.
  • Engine-manager, node-settings and TUI: gofmt -l . clean; native go vet ./..., GOOS=linux go vet ./..., and GOOS=windows go vet ./... — passed.
  • With the temporary PR Isolate cross-process tests, fix the failing broker tests, and add CI #42 merge: broker formatting, native/Linux/Windows vet, full go test -count=1 ./..., and permission-relay go test -race -count=20 -run '^TestEngineSettingReadRelay$' ./... — passed. The merge was aborted afterward; no integration commit is pushed.
  • Expected standalone prerequisite: after dropping the competing cancellation edit, this branch alone has the original broker vet warning at supervisor.go:538/:523 about cancellation ownership. PR Isolate cross-process tests, fix the failing broker tests, and add CI #42 resolves it. This is not reported as a passing standalone vet gate.
  • Desktop: typecheck, lint (zero warnings), unit tests (78 files / 769 tests), dead-code check, and service-contracts check — passed.
  • SPDX: 1,225 checked, zero missing; git diff --check clean.

Regression/failure-path evidence for the follow-ups:

  • Temporarily reacquiring the lifecycle lock in the passive probe made the revised Start test fail specifically at “Start waited for a passive readiness probe.” Restoring production code passed the 100-repeat race group.
  • Temporarily disabling executed-CLI cleanup made the before-CLI-exit regression fail because the stop marker was absent. Restoring it passed the detached-daemon race stress.
  • Injecting a fatal assertion after daemon startup but before explicit StopAll failed as intended; process inspection found zero surviving fixture control-CLI processes. The injection was removed before final checks.
Observed unconstrained normal-suite failures (not asserted to be pre-existing)

The failed run included loopback connection/readiness timeouts and the following test failures. No production probe was weakened and no test was removed. A subsequent full constrained normal run and a full race run passed; neither establishes baseline causality.

  • TestStopReclaimsOurOrphanOnManagedPort
  • TestStopDoesNotReclaimSameExternalImage
  • TestStopDeclinesForeignListenerWithActionableError
  • TestStopRejectsAdoptedProcessEngine
  • TestStopReconcilesAdoptedProcessAfterExternalStop
  • TestStopKeepsAdoptedProcessRunningWhileEndpointIsUnhealthy
  • TestCommandStopFailureSucceedsWhenEndpointIsConfirmedDown
  • TestCommandStopFailureRestartsHealthMonitoring
  • TestCommandStopReportsStoppedOnlyAfterEndpointCloses
  • TestRunOpInstallAutostart
  • TestLMStudioDeleteModelRemovePath
  • TestDeleteModelRestartAfterBouncesRunningEngine
  • TestDeleteModelWithoutRestartAfterDoesNotBounce
  • TestDeleteModelRestartFailureFailsTheAction
  • TestModelLifecycle
  • TestModelSurface_PinGateIsUnconditional
  • TestModels
  • TestModelsResult
  • TestModelsResultLoaded
  • TestModelsResultNoLoadedActionOmitsKey
  • TestSweepLoadedSeedsThenEmitsOnChange
  • TestInstallFlowReportsOnlyMeasurablePercents
  • TestPullEngineErrorBecomesRPCError (local and peer-endpoint)

The review's other non-blocking observations required no production changes: revision fencing/shared-probe cancellation/shutdown joining, model deadlines, optional progress propagation, live-read fail-closed permission, and version decisions remain as reviewed. Timing failures are recorded rather than labeled pre-existing without evidence.

Limits: Linux/Windows vet is static/compile coverage, not runtime certification. Live-engine, multi-node, and the separate services/tests suite were not run. A fresh optional second-model review attempt timed out; it is not counted as approval.

Risk

  • Merge ordering: PR Isolate cross-process tests, fix the failing broker tests, and add CI #42 must land first to provide broker cancellation ownership and its tests.
  • Passive UI status during a lifecycle operation is its current snapshot, not a wait for completion; explicit port checks and model sweeps wait within their budgets.
  • LAN permission applies to per-call local overrides, not operator-authored manifest commands. Enabling it exposes a third-party engine API without adding authentication. Revocation affects subsequent starts, not existing listeners. No desktop toggle is added; documented node-settings JSON-RPC methods are the operator surface.
  • An executed control CLI can detach a daemon before exiting unsuccessfully; cleanup uses its official bounded stop command. Failed spawns do not authorize cleanup.
  • Unmeasured install percent is absent; matched consumers render the stage instead of retaining the preceding download percentage.

Checklist

  • I have read the Contributing Guidelines.
  • Every commit is signed off, with upstream co-authorship where ported.
  • Both blocking review findings have focused fixes and regression/failure-path evidence.
  • The broker overlap is removed; PR Isolate cross-process tests, fix the failing broker tests, and add CI #42 integration is verified and its merge-first prerequisite is explicit.
  • Relevant documentation is updated; generated service contracts check passes.
  • Changed files and commit messages checked for private data and unintended generated artifacts.
  • Validation commands, limitations, observed failures, and the standalone broker prerequisite are recorded accurately.
  • Affected component version decisions and user-visible outcomes are documented.

@JaredP94

JaredP94 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

Addressed both blocking findings in 2f78b8c and b5cee58:

  1. The status/locking test now observes lifecycle entry while the passive probe remains blocked, then waits for real startup separately. The entire requested status/cancellation group passed -race -count=100; reintroducing the passive lifecycle lock fails the entry assertion.
  2. Detached fixtures register unconditional executor cleanup immediately after construction and poll readiness within the existing bounded helper. Both daemon cases passed -race -count=20; an injected fatal before explicit shutdown left zero fixture CLI processes.

For the non-blocking overlap, 8fd4080 removes this branch's competing broker cancellation edit. PR #42 must merge first. A temporary merge was conflict-free, retained #42's helper/tests, and passed broker native/Linux/Windows vet, full tests and relay race stress. No #42 implementation was duplicated in this branch.

The PR description now records all observed unconstrained normal-suite failures by name, without claiming they are pre-existing. Full engine-manager race and GOMAXPROCS=2 normal suites passed, as did desktop gates, node-settings/TUI tests, formatting and headers. Standalone broker vet still requires #42; this prerequisite is explicit rather than reported as green. Other non-blocking production/contract/version observations needed no additional runtime changes.

JaredP94 and others added 5 commits November 3, 2026 09:04
Adapt NVIDIA#180 to share bounded status observations and discard them after lifecycle or health changes. Slow readiness no longer blocks start, stop, or port changes. Model sweeps include status and operation waits in their deadline and return HTTP 503 on timeout so peers retain their last-good lists.

Preserve the fork's CLI detection, capability snapshots, and concurrent engine shutdown. The existing unreleased engine-manager 1.4.0 bump already covers this fix relative to v0.8.0.

Co-authored-by: Kaylee Lubick <klubick@nvidia.com>
Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Adapt NVIDIA/Personal-AI-Router@27b342a: omit percentages for verification, opaque install commands, and the fork's oMLX disk-image copy. Keep measured download progress and terminal outcomes. Desktop clears the previous percentage for both local and remote install stages; the TUI displays stages and failure reasons without fabricated numbers.

The broker and remote stream relay optional progress fields verbatim. Regenerate the service contract and document the omission rule. Existing unreleased engine-manager 1.4.0 and TUI 1.2.1 bumps cover these fixes relative to v0.8.0.

Co-authored-by: ckelseynv <143756939+ckelseynv@users.noreply.github.com>
Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Adapt NVIDIA#81 with a narrow read-only permission relay for this fork, which has no upstream engine-settings subsystem. Local non-loopback bind overrides require engine_allow_lan_bind, default false, read from node-settings for every request and denied on errors or timeout. Remote starts remain loopback-only.

Add persistent typed get/set methods and regressions for denial, revocation, malformed replies, persistence and relay failures. Make existing broker probe cancellation ownership explicit to Go vet, with no behavior change. Bump node-settings to 3.2.0 for the additive setting; existing unreleased engine-manager and broker minor bumps cover their changes relative to v0.8.0.

Co-authored-by: Mallikh Kalkere <mkalkere@users.noreply.github.com>
Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Port NVIDIA/Personal-AI-Router@72d5605: prepare-shutdown and EOF must wait for one sweep rather than probing foreign listeners twice. Preserve this fork's concurrent engine stops and retry only failed process or command stops that can succeed on a later call.

Cover sweep deduplication using lifecycle revisions rather than elapsed-time ratios, concurrent joining, and retry after a failed stop command. The existing unreleased engine-manager 1.4.0 bump covers this fix relative to v0.8.0.

Co-authored-by: Terve <ntervalon@nvidia.com>
Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
The detached-daemon test observed a marker written before the start CLI exited. Shutdown could cancel the CLI before cmd.Wait returned, leaving the successful-command flag unset and skipping the official stop command despite a live detached daemon.

Preserve command exit errors and clean up commands that actually executed, including canceled or nonzero exits, while excluding spawn failures. Synchronize the original readiness-phase test on a real readiness request and add a deterministic cancellation-before-CLI-exit regression. Also wait for the crash report itself in the separate watcher test instead of racing its earlier stopped-state publication.

The detached cases pass -race -count=20 in simultaneous processes with broker relay load. Existing unreleased engine-manager 1.4.0 covers this fix relative to v0.8.0.

Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
@JaredP94
JaredP94 force-pushed the fix/engine-manager-batch branch from 8fd4080 to b3dda21 Compare November 3, 2026 07:07
@JaredP94
JaredP94 merged commit 454d5c5 into main Nov 3, 2026
11 of 12 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.

1 participant