diff --git a/desktop/src/features/agents/AGENTS.md b/desktop/src/features/agents/AGENTS.md index f803ec5113..832908bf7f 100644 --- a/desktop/src/features/agents/AGENTS.md +++ b/desktop/src/features/agents/AGENTS.md @@ -207,7 +207,10 @@ with a TypeScript lookup table or an id comparison in a component. [the identity contract](../../../../docs/agent-profile-identity.md). Availability dots read relay presence, never a saved deployment receipt or runtime status. Failed/disconnected reads are unknown; lifecycle - actions retain their separate routing. See + actions retain their separate routing. Current exact-key Online/Away presence + suppresses Start for an inactive local record without granting Stop authority; + list/profile/member startup guards must not interpret Offline as proof of safe + startup. See [the availability contract](../../../../docs/agent-availability.md). 14. **Thinking effort has two surfaces: a local-only WRITE control and a read-only two-facts DISPLAY.** The write control is `EffortPickerField` diff --git a/desktop/src/features/agents/lib/useAgentAvailability.test.mjs b/desktop/src/features/agents/lib/useAgentAvailability.test.mjs index 6bf1b25959..f9b2df050a 100644 --- a/desktop/src/features/agents/lib/useAgentAvailability.test.mjs +++ b/desktop/src/features/agents/lib/useAgentAvailability.test.mjs @@ -89,7 +89,31 @@ for (const lifecycle of ["running", "stopped"]) { onStart() {}, }), ); - assert.equal(html.includes('data-testid="start"'), !isActive); - assert.equal(html.includes('data-testid="active"'), isActive); + assert.equal(html.includes('data-testid="start"'), false); + assert.equal(html.includes('data-testid="active"'), true); + }); +} + +for (const availability of ["online", "away"]) { + test(`stale restart and runtime error cannot hide stopped ${availability} presence`, () => { + const html = renderToStaticMarkup( + createElement(AgentRuntimeAvatarControl, { + activeTestId: "active", + startTestId: "start", + errorTestId: "error", + isActive: false, + isStarting: false, + requiresRestart: true, + errorLabel: "Previous startup failed", + availability, + label: "Agent", + onStart() {}, + }), + ); + assert.match(html, /data-testid="active"/); + assert.doesNotMatch( + html, + /data-testid="start"|data-testid="error"|