UI completion pass + accountability & benchmarking
UI (daily-drivable now): - Board: dnd-kit drag-and-drop between columns; click a card → task detail drawer (Sheet) with status, member assignee picker, send-to-AI-seat dispatch, description/artifact, parent/children navigation; seat-triad assignee chips (AI indigo monogram / human slate). - Cartable page (the personal pending slice), Members & invitations page (invite + copy join token; V1 sends no email), Review inbox now shows a word-level diff of your edits vs the proposal (lib/diff.ts, LCS), Org chart page (React Flow: org → teams → seats in the human/open/AI triad). Nav reordered; nothing left "soon". Accountability & benchmarking: - Identity: GET /members (directory + org role) and GET /invitations (with join token, inviter-only) — the directory also resolves names client-side everywhere. - OrgBoard: work_item_transitions recorded on every status change (AddWorkItemTransitions migration); GET /performance — per assignee (human and AI on the same scale): pending by column, done, worked hours (time in InProgress), avg cycle time (start of work → done), plus the unassigned-pending count. Owner-level capability. - Performance page: benchmark table merging board metrics with AI trust metrics (approval rate + edit distance from analytics); flags work with no one accountable. Verified: build green; ArchitectureTests 8/8; IntegrationTests 43/43 (new: directory, invitations list + Member 403s, transition-derived worked-hours/cycle-time, unassigned count); client npm build green (TS strict). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { Label } from '@/components/ui/label'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { api } from '@/lib/api'
|
||||
import { diffWords } from '@/lib/diff'
|
||||
import { useAuth } from '@/store/auth'
|
||||
|
||||
interface ReviewItem {
|
||||
@@ -156,6 +157,27 @@ function ReviewCard({ item, onDecided }: { item: ReviewItem; onDecided: (id: str
|
||||
/>
|
||||
</div>
|
||||
|
||||
{content !== item.content && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label>Your edits (vs the proposal)</Label>
|
||||
<div className="max-h-40 overflow-auto whitespace-pre-wrap rounded-lg border bg-muted/40 p-3 text-xs leading-relaxed">
|
||||
{diffWords(item.content, content).map((segment, i) =>
|
||||
segment.kind === 'same' ? (
|
||||
<span key={i}>{segment.text}</span>
|
||||
) : segment.kind === 'removed' ? (
|
||||
<del key={i} className="rounded bg-destructive/15 text-destructive">
|
||||
{segment.text}
|
||||
</del>
|
||||
) : (
|
||||
<ins key={i} className="rounded bg-seat-ai/15 font-medium text-primary no-underline">
|
||||
{segment.text}
|
||||
</ins>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor={`children-${item.id}`}>Child tasks (one per line)</Label>
|
||||
<Textarea
|
||||
|
||||
Reference in New Issue
Block a user