LearnNewsExamplesServices
Frontmatter
id17305
titleFleet runtime status asserts 'stopped' for agents it never launched
stateClosed
labels
bugaiagent-os
assigneesneo-opus-grace
createdAtAug 17, 2026, 6:31 PM
updatedAtAug 17, 2026, 9:15 PM
githubUrlhttps://github.com/neomjs/neo/issues/17305
authorneo-fable-clio
commentsCount2
parentIssue14560
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 17, 2026, 9:15 PM

Fleet runtime status asserts 'stopped' for agents it never launched

Closed Backlog/active-chunk-17 bugaiagent-os
neo-fable-clio
neo-fable-clio commented on Aug 17, 2026, 6:31 PM

Context

Caught live by the operator during the #17271 L1 witnessed run (2026-08-17, "did i miss the window?"): every card in the live-roster cockpit renders benched / offline — nine of nine, header tally 9 benched / offline · 0 external harness — while the SAME rows carry participationStatus: 'active' and, for the in-turn agent, presence: {state: 'fresh', confidence: 'observed'}. A card asserting "benched / offline" and "fresh" simultaneously contradicts itself on its own surface.

Observation vs inference separated: the store rows, header tally, and card labels are observed (Neural Link inspect_store receipts on #17271); the mechanism below is code-read, cited by line.

The Problem

ai/services/fleet/FleetManager.mjs:187-206fleetRuntimeStatus() passes lifecycle.status(agent.id) straight through:

  • For an agent the fleet never launched (no pid, no startedAt, no exitCode), lifecycle answers state: 'stopped'; the mapper only downgrades confidence to 'inferred' and ships the state.
  • The method's own doc promises: "a row is observed when a process record backs it and inferred otherwise — the state is never invented." But stopped for a never-started, non-fleet-managed process IS an invented state: never-launched ≠ stopped.

Display-side is contract-correct and NOT the bug: apps/agentos/CARD-CONTRACT.md:13 reserves off → "benched / offline" for "a process Fleet manages and knows to be stopped" (echoed by sourceHealth.mjs:272), explicitly forbids benched / offline as "a false participation verdict" for unobserved rows, and already carries the honest unobserved vocabulary — the resolver just never receives it for wired rows, because the server asserts a session state it has no record for.

Effect: the entire external-harness fleet (the ONLY topology in production use today — all nine maintainers run under their own harnesses) renders as operator-benched. The one distinction the fleet's own registry could refute (participationStatus: 'active' sits on the same row) is contradicted by a fabricated lifecycle verdict. The pre-live sample path renders unobserved correctly — going live makes the display LESS honest, inverting the #17271 credibility goal.

The Architectural Reality

  • Truth law (fleetPresenceStateAdapter doc, same file family): "a liveness tier a deployment cannot emit produces ABSENCE OF SIGNAL, never a verdict." The runtime axis violates it for the no-record case.
  • The observed flag at FleetManager.mjs:192 already computes exactly the needed distinction (status.state !== 'stopped' || status.pid != null || status.startedAt != null || status.exitCode != null) — the row just doesn't use it for the STATE, only for confidence.
  • Wire consumers: cockpit roster DTO → resolveFleetDisplayState (shared with the HealthBar tally) — fixing the producer heals card text, dot, and header counts together.

The Fix

In fleetRuntimeStatus(): when NO process record backs the agent (the existing observed === false branch), emit the honest absence state (unobserved — reusing the CARD-CONTRACT vocabulary; alternatively a dedicated external if the display ladder wants the finer word) instead of passing through lifecycle's stopped. A REAL stopped record (fleet started it; it exited or was stopped) keeps stopped/off semantics — that is precisely the "operator-benched participation fact" the contract names. Verify resolveFleetDisplayState + HealthBar tally + header buckets restore the external harness/unobserved counts.

Acceptance Criteria

  • A registered agent with no fleet lifecycle record reports a runtime state distinct from stopped (absence of signal, not a verdict); the doc sentence "the state is never invented" becomes true.
  • A fleet-launched agent that exited/was stopped still reports stopped (real record, unchanged semantics).
  • Cockpit cards for external-harness agents render unobserved (or the chosen external word) — never benched / offline; header tally restores the external/unobserved bucket (red→green witness against today's 9 benched / offline state).
  • Unit coverage on the mapper: no-record vs real-stopped-record rows.

Out of Scope

Richer idle/wedged/rate-limited states (the named watchdog-signals follow-up) · presence axis (correct today) · card visual hierarchy (#17303 / #17264 own chips and anatomy).

Related

Epic #14560 (parent) · #17271 (origin L1 run, receipts) · CARD-CONTRACT.md (display authority) · #17303 (row anatomy sibling)

Live latest-open sweep: latest 10 checked 2026-08-17T16:30Z, no equivalent; A2A claim window clean (newest claim 13:54, unrelated scope).

Origin Session ID: 7ee47ccf-d1c7-469d-a75e-15cebf3b5ea5

Retrieval Hint: query_raw_memories("fleet runtime stopped never launched false benched offline verdict external harness")

tobiu referenced in commit 8ba810b - "fix(ai): the fleet reports absence of signal for agents it never launched (#17305) (#17308) on Aug 17, 2026, 9:15 PM
tobiu closed this issue on Aug 17, 2026, 9:15 PM