feat(members): show the sessions a member is driving in its drawer - #8591
Conversation
Design Review (Fable 5) — ✅ PASSDesign-level review of All design checks passed: the fence claim is verified in Design-Verdict: PASS Derives "driven by" from the existing ownership-fence-backed [DESIGN-REVIEWED] 2a8c6a4 |
GPT 5.6 Review — ✅ human override acceptedHuman judgment by @CrysisDeu overrides the GPT 5.6 finding for This comment is updated in place on each push. The model was not re-run because an authorized human decision supersedes it. False positive or not applicable? A repository writer can comment: |
First Principles Review (Fable 5) — 🟡 CONCERNSPremise-level review of Verification is complete. All the shared mechanisms the description claims to reuse ( First-Principles-Verdict: CONCERNS ~270 lines of kiro-cli PATH-pinning ride along undeclared — they are main's already-merged #8396, not this feature. What this change shipsIntent: see which worker sessions a crew member is driving, from its drawer, and jump into them. ADDITION.
Watch
Subtractions
[FIRST-PRINCIPLES-REVIEWED] 2a8c6a4 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
UX Review (Fable 5) — ✅ PASSUX-level review of All evidence reviewed: the diff (frontend block, locale strings, tests), sibling drawer sections and ChatSidebar idiom for the status vocabulary. No image files are committed in this range (screenshots live in a removed temp commit), so lens 12 has no in-repo pixels to audit. The block reuses the sidebar's exact status labels and precedence, has skeleton/empty/list states, keyboard-reachable button rows, UX-Verdict: PASS Reuses the sidebar's status vocabulary, three-state loading discipline, and per-row drill-in; a first-time user reads it correctly at a glance. Suggestions
[UX-REVIEWED] 2a8c6a4 |
7ed80b4 to
5c36d4d
Compare
|
|
|
|
|
5c36d4d to
9156873
Compare
|
The Crew Members drawer showed a member's stats, activity, wake sources and configuration but not the worker sessions it opens via session_create and steers via session_send -- the user had to go hunting in the Sessions sidebar. Add a "Driving sessions" block: one row per live worker with the sidebar's status dot (approval > needs input > running > idle), title and last activity; a row jumps into that session; folded at five behind Show all; one-line empty state. Data source: `created_by` is already written at a worker's birth, persisted in the history meta line and rehydrated on restart, and a member caller is ownership-fenced to the slots it created (authorize_target), so the created set IS the driven set. Expose it on the slot projection and filter the already-subscribed WS slots frames on it -- no new endpoint, no separate driven_by field, no transcript scraping for the send-provenance prefix. Refs the Crew Members drawer surface; i18n keys added to all 13 catalogs.
9156873 to
5389268
Compare
5389268 to
2a8c6a4
Compare
|
|
|
|
/ai-review override gpt 2a8c6a4: Both findings cite src/kiro_crew/slack/gateway.py, which this PR does not modify (files: docs/feature-map/README.md, dashboard/slot_projection.py, two tests, website/** MembersPage + i18n); the lane reviewed another PR's diff. |
Human judgment recorded@CrysisDeu marked the gpt AI finding as false positive, not applicable, or explicitly accepted for
This decision applies only to this commit. A new push requires a new judgment. |
Summary
The Crew Members drawer showed a member's stats, recent activity, wake sources and configuration — but not the worker sessions it is actually driving. A member (e.g. a conductor) dispatches its real work through
session_create/session_send, and the only way to see those workers was to go hunting in the Sessions sidebar.This adds a Sessions it's driving block to the drawer (between the stat cards and Recent activity):
tabStatuscontract (lib/sessionTabs.ts: permission › question › running › idle); the two states parked on the user ("Needs approval", "Needs your answer") are also spoken as visible text, matching the sidebar; every row carries a hover title (full session title · status)lastActivityEpoch(pages/chat/sessionOrder.ts) — no third spelling of thelast_turn_ts || last_ts || createdladder/chat?sid=…)slotssnapshot has arrived (slotsLoaded); before that a skeleton, so a cold open never asserts "not driving" for a beatData source (investigated first)
session_createalready writescreated_by= the caller's slot key on the new slot at birth, persists it in the history meta line (both save paths) and rehydrates it on restart (both restore paths) — it is whatauthorize_target's member ownership boundary reads.session_sendwrites no durable marker; it only prefixes the injected prompt with[sent by session … via session_send].The key observation: a member caller is ownership-fenced (
_caller_is_ownership_fenced→authorize_targetrefusesnot_creator), so a member can onlysession_sendto sessions it created. For a member, the created set is the driven set. So:driven_byfield, no new endpoint, no transcript scraping. The one backend change is exposingcreated_byon the slot projection (slot_projection.py), which the already-subscribed WSslotsframes carry.dashboard.slotsoncreated_by === <member DM slot key>(member-<slug>, taken from the thread endpoint's returned key, falling back to the roster binding). Live status comes for free from the same frames — the samerunning/pending_approval/needs_inputsignals the sidebar dot reads.Trade-off noted: workers that exist only on disk (gateway restarted, slot not rehydrated) are not listed until they come back live. That matches "driving" semantics; a history-backed list would need a sessions join the drawer does not have today.
Screenshots
Folded (radar: approval, running, needs-input, idle rows; scribe's worker correctly absent):
Expanded:
Empty state (fixer):
Captured with the extended
website/scripts/capture-members-page.mjs(frames 06/06b/06c self-assert row count, status order, exclusion of the other member's worker, toggle label and empty copy before writing). Screenshots pinned to temp commit5389268, since removed from the branch.Feature map
docs/feature-map/README.mdCrew Members row updated with the drawer's driving-sessions surface, theslot_projection.pycreated_bysource, and theGET /api/ws(slots) frame it reads.Tests
test_member_session_control.py::TestCreatedByProjection(attributed slot reports the creator key; unattributed slot reports""not absent);test_chat_slot_facade_contract.pykey-order contract updated.MembersPage.test.tsx— empty state (foreign + unattributed slots excluded), list ordering + status mapping (approval outranks running), row navigation, fold/expand at 5, live removal when a worker closes, visible text for the parked states + hover title, per-member fold reset, skeleton-before-first-frame.tsc -b, eslint,i18n:check(19 checks PASS vsorigin/main), black, flake8. Test suites left to CI per the item's rules.Scope
No refactor of the drawer; block added alongside existing sections.
maincurrently carries inherited reds (Bundle Size Gate #8519, E2E #8581) unrelated to this change.