Skip to content

feat(members): show the sessions a member is driving in its drawer - #8591

Merged
bolichen97 merged 1 commit into
mainfrom
feat/members-driving-sessions
Sep 5, 2026
Merged

feat(members): show the sessions a member is driving in its drawer#8591
bolichen97 merged 1 commit into
mainfrom
feat/members-driving-sessions

Conversation

@CrysisDeu

@CrysisDeu CrysisDeu commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

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):

  • one row per live worker: status dot whose precedence is the shared tabStatus contract (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)
  • ordering via the shared lastActivityEpoch (pages/chat/sessionOrder.ts) — no third spelling of the last_turn_ts || last_ts || created ladder
  • a row is a jump into that session (/chat?sid=…)
  • newest activity first; folded at 5 behind Show all (N) / Show less — the fold is keyed to the member, so switching members starts the next list folded
  • one-sentence empty state, shown only once the first WS slots snapshot has arrived (slotsLoaded); before that a skeleton, so a cold open never asserts "not driving" for a beat
  • new copy in all 13 catalogs (12 hand-translated + en-XA regenerated)

Data source (investigated first)

session_create already writes created_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 what authorize_target's member ownership boundary reads. session_send writes 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_fencedauthorize_target refuses not_creator), so a member can only session_send to sessions it created. For a member, the created set is the driven set. So:

  • No new driven_by field, no new endpoint, no transcript scraping. The one backend change is exposing created_by on the slot projection (slot_projection.py), which the already-subscribed WS slots frames carry.
  • The drawer filters dashboard.slots on created_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 same running / pending_approval / needs_input signals the sidebar dot reads.
  • A worker the member closes leaves the live slots and therefore the list, which is the honest reading of "driving right now".

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):

driving sessions folded

Expanded:

driving sessions expanded

Empty state (fixer):

driving sessions empty

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 commit 5389268, since removed from the branch.

Feature map

docs/feature-map/README.md Crew Members row updated with the drawer's driving-sessions surface, the slot_projection.py created_by source, and the GET /api/ws (slots) frame it reads.

Tests

  • Backend: test_member_session_control.py::TestCreatedByProjection (attributed slot reports the creator key; unattributed slot reports "" not absent); test_chat_slot_facade_contract.py key-order contract updated.
  • Frontend: 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.
  • Local gates: tsc -b, eslint, i18n:check (19 checks PASS vs origin/main), black, flake8. Test suites left to CI per the item's rules.

Scope

No refactor of the drawer; block added alongside existing sections. main currently carries inherited reds (Bundle Size Gate #8519, E2E #8581) unrelated to this change.

@CrysisDeu
CrysisDeu requested a review from a team September 4, 2026 23:12
@CrysisDeu
CrysisDeu requested a review from a team as a code owner September 4, 2026 23:12
@CrysisDeu
CrysisDeu requested a review from dwu96 September 4, 2026 23:12
@github-actions github-actions Bot added the readiness: checking Automated validation is still running label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5) — ✅ PASS

Design-level review of 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55 — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

All design checks passed: the fence claim is verified in session_control.py:160-198 (a member caller is unconditionally restricted to slots it created, so the "created == driven" equivalence is derived from existing enforcement, not asserted), the new field is additive with an "" default and a pinned contract test, the drawer reuses the shared tabStatus and lastActivityEpoch contracts instead of re-spelling them, and the disclosed trade-offs (live-only listing, no new endpoint) are reasonable calls. The extra files in the diff range (slack/gateway.py, kiro_cli.py) belong to main's #8396 picked up by GitHub's test merge, not this PR.

Design-Verdict: PASS

Derives "driven by" from the existing ownership-fence-backed created_by attribution instead of inventing new provenance — minimal, additive, and reversible.

[DESIGN-REVIEWED] 2a8c6a4

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review — ✅ human override accepted

Human judgment by @CrysisDeu overrides the GPT 5.6 finding for 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55; the recorded reason is authoritative for this commit.

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:
/ai-review override gpt 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55: <one-sentence reason>

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

First Principles Review (Fable 5) — 🟡 CONCERNS

Premise-level review of 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55 — why this exists and whether the shipped surface is the smallest honest version. Updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Verification is complete. All the shared mechanisms the description claims to reuse (tabStatus, lastActivityEpoch, slotsLoaded, existing needs_approval/needs_your_answer/drawer_working catalog keys) exist as claimed, created_by has exactly one real frontend consumer (the drawer filter), and the kiro-cli hunks in the patch match — by subject and content — commit 47d6f74b2 already merged to main as #8396.

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 ships

Intent: see which worker sessions a crew member is driving, from its drawer, and jump into them. ADDITION.

  1. Drawer block listing the member's live workers with status dots — justified
  2. Row click jumps into that session — justified
  3. Fold at 5 behind Show all/Show less, reset per member — justified
  4. Skeleton until the first slots frame, then an empty state — justified
  5. created_by exposed on the WS slot payload — justified; one consumer (MembersPage.tsx:202), plain field, not generalized
  6. New copy in 13 catalogs — justified (i18n invariant)
  7. Feature-map row updated — justified (docs invariant)
  8. Capture-script frames 06/06b/06c — justified, dev tooling
  9. kiro-cli spawns pinned off PATH (include_inherited_path on resolve_kiro_cli, _pinned_kiro_cli, 5s budget, two spawn sites, ~200 test lines) — undeclared, rides along, duplicate of main 47d6f74b2 (fix(gateway): pin both unattended kiro-cli spawns off PATH #8396)

Watch

  • Item 9 is byte-compatible with main (the clean test merge d4ea7c273 proves the hunks reconcile), so this looks like a stacked branch diffed against a stale base — harmless at merge, but the PR as reviewed ships a second, unexamined copy of a security change its description never mentions.
  • DRIVING_STATUS is a third spelling of the status→dot-class mapping: grep fill-warn finds the identical four class strings inline at SessionGridView.tsx:302 (2 production sites before, 3 after). A shared TabStatus→classes map is the general fix; larger than this change, so deferred.

Subtractions

  • Rebase onto main and drop the kiro_cli.py / slack/gateway.py / test_slack_gateway*.py hunks from this branch, so the PR's diff carries only the declared drawer feature.

[FIRST-PRINCIPLES-REVIEWED] 2a8c6a4

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review — ✅ no blocking findings

Reviewed 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55 — this comment is updated in place on each push.

Review details

No findings.

[OPUS-REVIEWED] 2a8c6a4

Verdict parsed from the review's SHA-scoped output markers for commit 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55.

False positive or not applicable? A repository writer can comment:
/ai-review override fable 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55: <one-sentence reason>

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

UX Review (Fable 5) — ✅ PASS

UX-level review of 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55 — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

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, aria-expanded on the fold toggle, and sr-only text for dot-only states.

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

  • driving_sessions: "Sessions it's driving" — sibling drawer headers are terse noun phrases ("Recent activity", "Wake sources") and every other membersPage string calls the member "this member"/"their", never "it"; rename to "Driving sessions" to match both the header shape and the product's voice.

[UX-REVIEWED] 2a8c6a4

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Sep 4, 2026
@CrysisDeu
CrysisDeu force-pushed the feat/members-driving-sessions branch 2 times, most recently from 7ed80b4 to 5c36d4d Compare September 4, 2026 23:30
@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Sep 4, 2026
@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Driving sessions is absent from the feature mapfixed in 5c36d4d

docs/feature-map/README.md Crew Members row now names the drawer's driving-sessions surface, its source (slot_projection.py created_by on the WS slots frames) and the GET /api/ws (slots) route it reads.

@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Colour-only status dotfixed in 5c36d4d

The two states parked on the user ("Needs approval", "Needs your answer") now render as visible coloured text beside the dot — the sidebar's own idiom; running/idle stay dot-only with the word in the row's hover title and an sr-only span. Every row carries title="<session title> · <status>", so a truncated title is readable on hover (this also covers the Suggestion). Tests pin both.

@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Re-spelled lastActivityEpoch and the tabStatus precedence chainfixed in 5c36d4d

Both Subtractions taken: the local slotActivityEpoch is deleted and the list sorts and stamps by lastActivityEpoch from pages/chat/sessionOrder.ts; the inline ternary is replaced by tabStatus(s, [], s.key) from lib/sessionTabs.ts, with a static DRIVING_STATUS map that only translates its verdict into dot class / label / spoken-or-not. The precedence order now has one owner.

@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Reset drivingExpanded when the active member changesfixed in 5c36d4d

The fold is now keyed to the member's slot key (drivingExpandedFor), so switching members starts the next list folded instead of inheriting the previous expansion. Covered by a new test.

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Sep 4, 2026
@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • DRIVING_STATUS.cls is a third status→colour vocabularyrebutted (holds, but disproportional here)

The dot sits inside the member drawer, whose own presence vocabulary is already green=working: the status line above it renders "Working" in text-ok and the roster's presence dot is green. TAB_STATUS_COLOR is the tab-strip palette, where running is var(--accent); adopting it would put a purple "running" dot two lines under a green "Working" in the same panel — trading a cross-surface split for an in-panel one. The row deliberately follows the sibling list-of-sessions-with-a-dot idiom (SessionGridView.tsx:302, the session picker), and the precedence ORDER — the part sessionTabs.ts calls the contract — is single-sourced through tabStatus. Folding the grid's inline ladder and this record into one exported map touches SessionGridView and is a standalone cleanup, not this PR's purpose. The text values on the unspoken entries stay so the record remains a total Record<TabStatus, …> with one uniform shape; three inert class strings cost nothing and keep the type honest.

@CrysisDeu
CrysisDeu force-pushed the feat/members-driving-sessions branch from 5c36d4d to 9156873 Compare September 5, 2026 00:12
@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Gate driving_none on slotsLoadedfixed in 9156873

The block now reads dashboard.slotsLoaded: with no driven sessions and no snapshot yet, it renders the same two-bar skeleton the Recent-activity section uses instead of the affirmative "Not driving any sessions right now." — so a cold open or WS reconnect never asserts a verdict for a beat before rows pop in. A new test pins skeleton-before-first-frame → empty-after-first-frame.

@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Sep 5, 2026
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.
@CrysisDeu
CrysisDeu force-pushed the feat/members-driving-sessions branch from 9156873 to 5389268 Compare September 5, 2026 00:25
@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Sep 5, 2026
@CrysisDeu
CrysisDeu force-pushed the feat/members-driving-sessions branch from 5389268 to 2a8c6a4 Compare September 5, 2026 00:26
@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • driving_sessions heading cold-reads as a noun phrasefixed in 2a8c6a4

Heading is now "Sessions it's driving" (verb sense unambiguous at first glance); the 11 hand translations were re-phrased the same way (e.g. zh-CN 它正在驱动的会话, de "Sitzungen, die es steuert", fr "Sessions qu'il pilote") and en-XA regenerated. Screenshots re-captured and re-pinned in the PR body.

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Sep 5, 2026
@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Version lookup adds a bounded wait to the gateway boot pathrebutted (does not hold: file not in this PR)

src/kiro_crew/slack/gateway.py is not part of this change. The PR's file list (GitHub files) is docs/feature-map/README.md, src/kiro_crew/dashboard/slot_projection.py, two test/ files, and website/** (MembersPage, types, i18n catalogs, capture script). Neither _pinned_kiro_cli nor _warn_if_kiro_cli_outdated is touched or referenced by this diff; the finding was raised against a different PR's diff.

@CrysisDeu

Copy link
Copy Markdown
Collaborator Author
  • Relative override can still execute through attacker-controlled PATHrebutted (does not hold: file not in this PR)

src/kiro_crew/slack/gateway.py:1534 and KIROCREW_KIRO_BIN resolution are not part of this change; no line of this PR's diff touches process spawning, PATH, or gateway.py. The PR adds a created_by field to the slot projection and a drawer block in MembersPage.tsx. The finding belongs to another PR's diff.

@CrysisDeu

Copy link
Copy Markdown
Collaborator Author

/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.

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Human judgment recorded

@CrysisDeu marked the gpt AI finding as false positive, not applicable, or explicitly accepted for 2a8c6a4ca8ba21ae7ab8282efdc37a4eaf8f2f55.

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.

This decision applies only to this commit. A new push requires a new judgment.

@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: passed Eligible automated validation passed for the current revision and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Sep 5, 2026
@bolichen97
bolichen97 enabled auto-merge (squash) September 5, 2026 06:47
@bolichen97
bolichen97 merged commit a405994 into main Sep 5, 2026
66 of 73 checks passed
@bolichen97
bolichen97 deleted the feat/members-driving-sessions branch September 5, 2026 06:53
@github-actions github-actions Bot removed the readiness: passed Eligible automated validation passed for the current revision label Sep 5, 2026
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.

3 participants