Repository navigation
feat(dashboard): readiness stamp on the agents list and the fleet grid (abilityai/trinity-enterprise#527) - #3038
Conversation
…d (trinity-enterprise#527 rider)
Operator ruling 2026-09-24 (ent#560's closure): readiness is a
role-companion property, and the owner's stamp should be visible on
the agents list and the fleet grid, not only on the role card.
- GET /api/agents attaches readiness {status, changed_at, source} from
one batched read (get_role_readiness_for_agents, the display-label
pattern, no N+1). An unstamped agent carries null and shows nothing:
whether it is a companion is in its template.yaml, which a list must
not read, so there is no guessed calibrating. The list says what and
when, never who; the owner-scoped role card keeps the person.
- One predicate for both surfaces (utils/readinessBadge.js), with the
role card's words and variants (ready = success, calibrating =
warning, dot). The tooltip names a rollout stamp and what calibrating
holds back.
- The list places it after the pressure badge (documented order
updated) on both layouts; the grid tile places it after the runtime
badge.
Tests: 7 backend (real DB + the endpoint), 6 helper, 3 mounted tile
(2 red without the tile change). Full vitest and ratchets green.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Live check (local instance, 37 agents, SQLite): this branch's diff was applied to a running stack (backend with API.
UI. 2 themes × 2 views × 4 agents, found by
On the grid tile the badge sits after the runtime icon. In the list it goes on the secondary line under the name. Both themes read correctly. The two test stamps ( |
/review ReportBranch:
Execution coverage (Step 2.5)
No source-text assertions in the changed tests. Critical findingsNone. Informational findings[I1] Staleness: a readiness flip does not reach an open dashboard until a reload (confidence 8/10) const hasChanges =
newAgents.length !== agents.value.length ||
!newAgents.every(a => currentAgentNames.has(a.name))
if (hasChanges) { agents.value = newAgents … }An owner who marks a companion ready in the Workspace keeps seeing [I2] Test gap: the list rows are not mounted (confidence 7/10) [I3] Doc staleness: the list badge contract (confidence 9/10) Clean categories
Summary
🤖 Generated with Claude Code |
AndriiPasternak31
left a comment
There was a problem hiding this comment.
The backend side is right: one batched, parameterised read, no new endpoint, changed_by dropped before it leaves the DB layer, and the field rides the existing get_accessible_agents scope. My main concern is the calibrating tooltip. It claims a pause that the role card deliberately refuses to claim. Two of your own /review findings are also still open on this head, since the PR is a single commit. None of this blocks, but I'd fix 1–3 before merge.
-
[should-fix]
src/frontend/src/utils/readinessBadge.js:31: the calibrating tooltip always says "its scheduled brief is paused until its owner marks it ready". The role card only says this when_brief_held()is true (src/backend/client_portal/role_card.py:334-352), meaning the agent has an enabled seat-delivery schedule and autonomy is on. The comment there spells out why: with autonomy off, "paused until you mark it ready" would promise a flip that starts nothing. Scenario: an owner stamps a companioncalibratingthat has no Workspace-delivery schedule, or whose autonomy is off. The role card shows no pause line, but the list and grid tooltip says its brief is paused. The owner marks it ready and nothing happens. This is the list-vs-card disagreement that the file header says the shared predicate exists to prevent. Fix: the list rows already carryautonomy_enabled, so suppress the clause when that is false. For the schedule half, either add a batchedbrief_heldbool next toreadiness(one query overagent_schedulesfor the sameagent_names), or drop the clause and let the role card own that sentence. -
[should-fix]
docs/memory/feature-flows/dashboard-list-view.md:100and:225-228(your /review I3, still open). D14 is the contract for the row's meta strip: "a future badge goes here in that order or it does not go in the row". The component comment now readsslug · pressure · readiness · runtime · tags · +N, but the flow doc still saysslug · pressure · runtime · tags · +N. The next person adding a badge will follow the doc and lose the order. Update both places, and add one line todashboard-grid-view.mdfor the nameline badge (after runtime, before SYSTEM/SKILL RUNNER). -
[should-fix]
src/frontend/src/stores/network.js:1383-1397(your /review I1, still open). The 30s poll only replacesagents.valuewhen the set of names changes, and a readiness flip emits no WS event. A dashboard left open in another tab keeps showingcalibratingafter the owner marks the agent ready in the Workspace, until a reload. Remounting the Dashboard refetches, so this only hits an already-open tab. That is still the case where an operator watches the fleet.tagshas the same gap already, but this PR adds a field that is expected to change. Fix: on each poll, patchreadinessin place for rows already present, with no node rebuild. Pin it with a small vitest over the poll body. -
[nit]
src/frontend/tests/unit/readinessOnGrid.spec.js:4-6(your I2). The header says the list rows "are covered by the shared helper's spec", but the helper spec covers the words, not the placement. Dropping the badge fromrow-secondary-mdor mistypingagent.readinessin one row would still ship green. A mount ofAgentListPanelwith one stamped and one unstamped agent, asserting onereadiness-badgeper stamped row, would close this. Otherwise, reword the comment so it doesn't overclaim. -
[nit]
src/frontend/src/utils/readinessBadge.js:27-29: the rollout tooltip reads "Ready — carried over when the readiness gate shipped since 2026-09-24 (UTC)". Here "since" attaches to "shipped". The role card puts the date first ("since … · carried over when the readiness gate shipped"). Use "Ready since 2026-09-24 (UTC) — carried over when the readiness gate shipped", and update the assertion inreadinessBadge.spec.js.
What I checked
- Read the diff, the ent#527 role card (
role_card.py,PortalAgentRole.vue), the rollout seed migration,agent_cleanup.py(the stamp cascades on delete and follows a rename, so no stale badge on a recreated name), andstores/network.jsfetch/poll. The field travels on the agent object, so all modes see it throughvisibleAgents. - Design contract:
BaseBadgewith semantic variants only. No raw palette classes or loading gates added. The badge sits inside the D14lg/mdstrip only,flex-shrink-0. On the tile it is shorter than the name line, so tile rhythm doesn't move. - Auth/disclosure: no new route, and the stamp is visible only on agents the caller can already list. Non-owner viewers already see the status on the role card; the list omits who flipped it.
- Frontend on a clean
npm ci:npm run test:unitgives 177 files / 3689 tests passed, including the colour and loading-gate ratchets.npm run buildpasses. - Backend:
test_ent527_readiness_on_lists.py,test_ent527_role_card.py,test_ent689_readiness_gate.pyandtest_2889_readiness_classifier.pygive 142 passed. The display-label and cleanup tests give 35 passed. gh pr checks 3038: all required checks green (pytest, e2e, schema-parity, pg-migrations, CodeQL).
…ne is held PR #3038 review item 1: the list/grid calibrating tooltip always said "its scheduled brief is paused until its owner marks it ready", while the role card says so only when _brief_held() is true (an enabled seat-delivery schedule AND autonomy on). With autonomy off or no Workspace-delivery schedule the owner would mark it ready and nothing would start. - services/role_readiness_gate: is_seat_delivery_schedule + brief_is_held, the one predicate; role_card._brief_held now uses it. - GET /api/agents attaches brief_held next to readiness: one batched, projected read over agent_schedules (get_workspace_delivery_schedules_for_agents), only for calibrating stamps with autonomy on; fail-soft to no claim. - readinessBadge(readiness, briefHeld): the pause clause only when held, otherwise "not yet marked ready by its owner". Tile and list pass agent.brief_held. - Nit: ready tooltips put the date first, as the role card does ("Ready since … (UTC) — carried over when the readiness gate shipped"). - Nit: AgentListPanel is now mounted in the spec — one badge per stamped row on both the lg and md secondary lines, none on the unstamped row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…board PR #3038 review item 3: the 30s poll replaced agents only when the set of names changed, and a readiness flip emits no WS event, so an open tab kept showing calibrating until a reload. On an unchanged name set the poll now patches readiness and brief_held on the rows already present (only when the value changed) — no row replacement, no node rebuild. Pinned by a vitest over the real poll body (fake timers, same row objects, same nodes). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rid nameline PR #3038 review item 2: dashboard-list-view.md (diagram and the D14 secondary-line contract) now reads slug · pressure · readiness · runtime · tags · +N; dashboard-grid-view.md gains the nameline badge order (runtime · readiness · SYSTEM / SKILL RUNNER) and the brief_held tooltip rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @AndriiPasternak31. All five items are addressed in three commits on top of
Verification
🤖 Generated with Claude Code |
Resolve tests/registry.json: dev's file plus this branch's ent#527 entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve tests/registry.json: dev's file plus this branch's entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve tests/registry.json: dev's file plus this branch's ent#527 entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
obasilakis
left a comment
There was a problem hiding this comment.
Approving. Reviewed and validated: all five review items addressed; new backend/frontend tests pass locally and each fix has a test that goes red with the fix reverted; full CI green on b9461fb including regression diff.
Non-blocking: get_role_readiness_for_agents in list_agents_endpoint is unguarded, so a failed read 500s the whole list — same as the display-label read beside it.
…echanical, per the merge-train note on the PR get_role_readiness_for_agents was the one unguarded decoration read on GET /api/agents: a DB fault 500'd the whole list. Degrade to no stamp (briefs_held_for_list already degrades to no pause), plus a test that drives the endpoint with the read raising. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
merge-train: two commits pushed to this branch (mechanical, before assembling the train):
Other validation notes, not blocking: the PR body's Changes list predates the follow-up commits ( |
…ss-on-lists # Conflicts: # tests/registry.json
Summary
Rider on abilityai/trinity-enterprise#527, from the operator ruling of 2026-09-24 (ent#560's closure): readiness is a role-companion property, and the agents list and fleet grid should show the readiness stamp, not only the role card.
GET /api/agentsattachesreadiness: {status, changed_at, source}per agent.db.get_role_readiness_for_agents, following the display-label pattern, so there is no N+1 on the fleet's hottest endpoint.nulland shows nothing — never a guessedcalibrating. Whether an agent is a companion at all is in its template.yaml, which a list must not read.changed_byis an email or the ent#689 rollout sentinel. The role card is owner-scoped and keeps the person.utils/readinessBadge.js, is used by both surfaces. It carries the role card's words and variants:ready= success,calibrating= warning, each with a dot. The tooltip names a rollout stamp ("carried over when the readiness gate shipped") and what calibrating holds back ("its scheduled brief is paused…").Changes
src/backend/db/role_readiness.py:get_role_readiness_for_agentssrc/backend/database.py: the facade methodsrc/backend/routers/agents.py: attachesreadinessinlist_agents_endpointsrc/frontend/src/utils/readinessBadge.js: the new shared predicatesrc/frontend/src/components/AgentListPanel.vue,AgentTile.vue: render itdocs/memory/requirements/core-agent.md§5.36: the riderTest plan
tests/unit/test_ent527_readiness_on_lists.py(7), on a real DB:Nonewhen unstampedreadinessBadge.spec.js(6),readinessOnGrid.spec.js(3, mounts the real tile; 2 are red without the tile change)npm run build; 282 related backend testsRelated to abilityai/trinity-enterprise#527. That issue closes at release.
🤖 Generated with Claude Code