diff --git a/DECISION-SHEET.md b/DECISION-SHEET.md index e7c45d48e8a..ca81d448a2b 100644 --- a/DECISION-SHEET.md +++ b/DECISION-SHEET.md @@ -53,6 +53,12 @@ User rulings from the tune-session gallery review; all intentionally visible, sn 3. **Systematic cyan→status-blue liveness sweep** (~50 sites / 20 files; supersedes r1's "Live family left" note per user ruling): running-status tones (CommentThread, interrupt-handoff, runRetryState, AgentDetail run chip + status maps), live dots/pings (AgentDetail, OnboardingChat, ArtifactsPanel generating, ActiveAgentsPanel, IssueDetail Live pill, RunTranscriptView, IssueRunLedger live chip, DesignGuide sample), Live surfaces (LiveRunWidget theme, ActiveAgentsPanel Live-now box, AgentDetail live-card border), scheduled-retry family (IssueScheduledRetryCard, runRetryState, IssueRunLedger retry-pending), externalObjectStatus icon/badge `running` (now shares blue with `open`; liveness pulse differentiates — flagged), timeline "now" marker `#2dd4bf`→`#2563eb` (1.5px line vs `#5b9bf6` delegated bars, shape differentiates — flagged), and the liveness glow shadow tokens `--shadow-extract-1/11/14` value-edited `rgba(6,182,212,0.08)`→`rgba(37,99,235,0.08)` (kept-token VALUES changed, call sites unchanged). Deliberately LEFT (non-liveness cyan, one-line reasons): xterm terminal cursor (CompanyEnvironments — terminal chrome); `on_demand` invocation-source chips (AgentDetail x2 + DesignGuide sample — source tag, not liveness); CompanySkills "Includes assets" chip (content-type tag); CompanyImport renamed-file mono text x2 (rename annotation); BlockedReasonChip `recovery_required` (blocked-reason category); IssueRunLedger "Advanced" outcome + "Silence snoozed" tones (outcome/pause semantics, not live); UxLab decorative gradients (B1 allowlisted decoration). +## Gallery feedback round 3 (preset-tune session, Jul 6) — executed + +1+2. **Toggle unification** — hunt found exactly ONE second switch implementation: `ToggleField` in agent-config-primitives.tsx (hand-rolled h-5 w-9 pill, `bg-green-600` track — the "other green"). It now renders the canonical `ToggleSwitch` (3da1bbcc5 capsule, on = `var(--status-task-done)`), same props/behavior/testid. All other named suspects (AgentConfigForm, Instance*Settings, RoutineDetail, PipelineSettings, story fixtures) already used ToggleSwitch; remaining `bg-green-600` hits are buttons, not tracks. Every switch now renders the one capsule + one green. +3. **Agent-status chips → canonical colors** ("Org snippets and quick scan identity" = StatusBadge in control-plane-surfaces story): `statusBadge` agent keys now route through `brandChipBadge` families (bordered brand chips): running → blue, idle → GRAY (was yellow tint), paused → amber, **active → green (no canonical agent status exists — user-ruled mapping to the brand green/done family)**; error already rides the shared run-status red. brandChipBadge block moved above statusBadge in status-colors.ts (declaration order). Org.tsx's hand-rolled status-dot ternary now routes through `agentStatusDot` (same hues + gains the blue running dot). Left: Companies.tsx company-status chip (company entity, not agent), AgentConfigForm "current" model tag (not a status). +4. **Dark-text-on-light-wash sweep** — the flagged BudgetPolicyCard banner was already fixed in round 2 (screenshot predated it). Systematic sweep (bare `text-{red,amber,emerald,sky,green,yellow,cyan}-{50..300}` without dark: protection): **58 sites fixed across 14 files** (Dashboard budget alert, BudgetPolicyCard remaining-amount, AgentConfigForm banners x3, AgentDetail banners/chips x9, ProjectDetail x3, CompanyAccess, IssueDocumentsSection x6, RoutineHistoryTab x11, DocumentDiffModal x2, PipelineItemBodyDocument x2, RoutineSaveBar, DocumentFrameHeader, OutputFileTile x3, CompanySkills x10) — pattern: 50→950, 100→900, 200→800, 300→700 in light + original behind `dark:`, opacity suffixes preserved. Verified-safe leftovers: InviteLanding x4 (dark-styled standalone page), SidebarNavItem badge + DocumentAnnotationLayer tail + DevRestartBanner (solid dark/colored bg or dark:-protected). + ## Verification status (this review) - `pnpm check:token-gates` — re-run independently: 3/3 CLEAN (468 files, 31 allowlist entries). diff --git a/ui/src/components/AgentConfigForm.tsx b/ui/src/components/AgentConfigForm.tsx index dd1042d50e2..5a0204f26ec 100644 --- a/ui/src/components/AgentConfigForm.tsx +++ b/ui/src/components/AgentConfigForm.tsx @@ -1012,7 +1012,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) { }} /> -
+
Prompt template is replayed on every heartbeat. Keep it compact and dynamic to avoid recurring token cost and cache churn.
@@ -1041,7 +1041,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) { {kubernetesEnvironment.name} · Kubernetes sandbox
) : ( -
+
This instance requires the Kubernetes sandbox, but no managed Kubernetes environment is available for this company yet. Configure one before creating agents; execution will not fall back to local. @@ -1353,7 +1353,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) { }} /> -
+
Bootstrap prompt is legacy and will be removed in a future release. Consider moving this content into the agent's prompt template or instructions file instead.
diff --git a/ui/src/components/BudgetPolicyCard.tsx b/ui/src/components/BudgetPolicyCard.tsx index 619da97eddf..d392ff0c0e2 100644 --- a/ui/src/components/BudgetPolicyCard.tsx +++ b/ui/src/components/BudgetPolicyCard.tsx @@ -166,9 +166,9 @@ export function BudgetPolicyCard({ className={cn( "inline-flex items-center gap-2 text-(length:--text-micro) uppercase tracking-(--tracking-caps)", summary.status === "hard_stop" - ? "text-red-300" + ? "text-red-700 dark:text-red-300" : summary.status === "warning" - ? "text-amber-200" + ? "text-amber-800 dark:text-amber-200" : "text-muted-foreground", )} > diff --git a/ui/src/components/DocumentDiffModal.tsx b/ui/src/components/DocumentDiffModal.tsx index 59c0be705f8..b9543c3ee4c 100644 --- a/ui/src/components/DocumentDiffModal.tsx +++ b/ui/src/components/DocumentDiffModal.tsx @@ -73,8 +73,8 @@ export function DocumentDiffModal({ const lineClassesByKind: Record = { context: "bg-transparent", - removed: "bg-red-500/10 text-red-100", - added: "bg-green-500/10 text-green-100", + removed: "bg-red-500/10 text-red-900 dark:text-red-100", + added: "bg-green-500/10 text-green-900 dark:text-green-100", }; const markerByKind: Record = { diff --git a/ui/src/components/DocumentFrameHeader.tsx b/ui/src/components/DocumentFrameHeader.tsx index 91d09ab0aff..1aaa052c0d1 100644 --- a/ui/src/components/DocumentFrameHeader.tsx +++ b/ui/src/components/DocumentFrameHeader.tsx @@ -92,7 +92,7 @@ export function DocumentFrameHeader({ size="sm" className={cn( "h-auto px-1.5 py-0 text-(length:--text-micro) font-normal text-muted-foreground hover:text-foreground", - revisionMenu.historicalPreview && "text-amber-300 hover:text-amber-200", + revisionMenu.historicalPreview && "text-amber-700 hover:text-amber-800 dark:text-amber-300 dark:hover:text-amber-200", )} > rev {revisionMenu.displayedRevisionNumber} diff --git a/ui/src/components/IssueDocumentsSection.tsx b/ui/src/components/IssueDocumentsSection.tsx index ce51108a981..42688138dc6 100644 --- a/ui/src/components/IssueDocumentsSection.tsx +++ b/ui/src/components/IssueDocumentsSection.tsx @@ -964,7 +964,7 @@ export function IssueDocumentsSection({ size="icon-xs" className={cn( "text-muted-foreground transition-colors", - isLocked && "text-amber-300 hover:text-amber-200", + isLocked && "text-amber-700 hover:text-amber-800 dark:text-amber-300 dark:hover:text-amber-200", )} title={isLocked ? "Unlock document" : "Lock document"} aria-label={isLocked ? `Unlock ${doc.key} document` : `Lock ${doc.key} document`} @@ -974,7 +974,7 @@ export function IssueDocumentsSection({ {isLocked ? : } ) : isLocked ? ( - + ) : null} @@ -1063,7 +1063,7 @@ export function IssueDocumentsSection({
-

+

Viewing revision {selectedHistoricalRevision.revisionNumber}

@@ -1100,7 +1100,7 @@ export function IssueDocumentsSection({

-

Out of date

+

Out of date

This document changed while you were editing. Your local draft is preserved and autosave is paused.

@@ -1220,9 +1220,9 @@ export function IssueDocumentsSection({
-

+

Viewing revision {selectedHistoricalRevision.revisionNumber}

@@ -415,7 +415,7 @@ export function PipelineItemBodyDocument({ /> ) : null} actionsSlot={editing ? ( - ● Editing · unsaved + ● Editing · unsaved ) : ( + checked={checked} + onCheckedChange={onChange} + />

); } diff --git a/ui/src/components/issue-output/OutputFileTile.tsx b/ui/src/components/issue-output/OutputFileTile.tsx index 366b1311fbd..66227961679 100644 --- a/ui/src/components/issue-output/OutputFileTile.tsx +++ b/ui/src/components/issue-output/OutputFileTile.tsx @@ -3,9 +3,9 @@ import { getOutputFileGlyph, type OutputFileTone } from "@/lib/issue-output"; const TONE_CLASSES: Record = { video: "bg-indigo-500/15 text-indigo-300", - pdf: "bg-red-500/15 text-red-300", - zip: "bg-amber-500/15 text-amber-300", - image: "bg-emerald-500/15 text-emerald-300", + pdf: "bg-red-500/15 text-red-700 dark:text-red-300", + zip: "bg-amber-500/15 text-amber-700 dark:text-amber-300", + image: "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300", bin: "bg-muted text-muted-foreground", }; diff --git a/ui/src/lib/status-colors.ts b/ui/src/lib/status-colors.ts index 309f3a0434f..42a7de40c85 100644 --- a/ui/src/lib/status-colors.ts +++ b/ui/src/lib/status-colors.ts @@ -42,17 +42,42 @@ export const issueStatusText: Record = { export const issueStatusTextDefault = "text-muted-foreground"; +// --------------------------------------------------------------------------- +// Brand `.task-chip` status palette (PAP-75 / status-reference.html) +// +// Colour-named, 1px border, light + dark — values straight from paperclip.ing +// `brand.css`. Shared by the agents section (PAP-80) and the All Projects page +// (PAP-91); PAP-99 brings it to issue/task status chips, adding `violet` for +// `in_review`. +// --------------------------------------------------------------------------- + +export type BrandChipColor = "gray" | "blue" | "amber" | "green" | "violet" | "red"; + +export const brandChipBadge: Record = { + gray: "bg-[#F5F3F0] text-[#52585D] border-[#A8AEB2] dark:bg-[#6e696024] dark:text-[#9A958A] dark:border-[#9e958a73]", + blue: "bg-[#DBEAFE] text-[#1D4ED8] border-[#2563EB] dark:bg-[#2563eb2e] dark:text-[#2563EB] dark:border-[#2563eb73]", + amber: "bg-[#FEF3C7] text-[#B45309] border-[#F59E0B] dark:bg-[#f59e0b24] dark:text-[#F59E0B] dark:border-[#f59e0b73]", + green: "bg-[#DCFCE7] text-[#188A3C] border-[#22C55E] dark:bg-[#22c55e1f] dark:text-[#22C55E] dark:border-[#22c55e73]", + violet: "bg-[#EDE9FE] text-[#5B21B6] border-[#7C3AED] dark:bg-[#7c3aed2e] dark:text-[#7C3AED] dark:border-[#7c3aed73]", + red: "bg-[#FEE2E2] text-[#991B1B] border-[#DC2626] dark:bg-[#dc26262e] dark:text-[#DC2626] dark:border-[#dc262673]", +}; + // --------------------------------------------------------------------------- // Badge colors — used by StatusBadge for all entity types // --------------------------------------------------------------------------- export const statusBadge: Record = { // Agent statuses - active: "bg-green-100 text-green-700 dark:bg-green-900/50 dark:text-green-300", - running: "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300", // Gallery feedback r1: running = status blue (matches in_progress liveness), not cyan. + // Gallery feedback r3: agent chips route through the brand chip families + // (bordered .task-chip recipes) instead of ad-hoc tints. NOTE: `active` has + // no canonical agent status — user-ruled mapping to the brand GREEN family; + // `idle` is the gray family (was a yellow/amber tint); `error` rides the + // shared run-status red entry below. + active: `border ${brandChipBadge.green}`, + running: `border ${brandChipBadge.blue}`, // r1 made this blue; r3 routes through brandChipBadge.blue. scheduled_retry: "bg-sky-100 text-sky-700 dark:bg-sky-900/50 dark:text-sky-300", - paused: "bg-orange-100 text-orange-700 dark:bg-orange-900/50 dark:text-orange-300", - idle: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/50 dark:text-yellow-300", + paused: `border ${brandChipBadge.amber}`, + idle: `border ${brandChipBadge.gray}`, archived: "bg-muted text-muted-foreground", // Goal statuses @@ -126,25 +151,6 @@ export const agentStatusMotion: Record = { error: "hb-blink", }; -// --------------------------------------------------------------------------- -// Brand `.task-chip` status palette (PAP-75 / status-reference.html) -// -// Colour-named, 1px border, light + dark — values straight from paperclip.ing -// `brand.css`. Shared by the agents section (PAP-80) and the All Projects page -// (PAP-91); PAP-99 brings it to issue/task status chips, adding `violet` for -// `in_review`. -// --------------------------------------------------------------------------- - -export type BrandChipColor = "gray" | "blue" | "amber" | "green" | "violet" | "red"; - -export const brandChipBadge: Record = { - gray: "bg-[#F5F3F0] text-[#52585D] border-[#A8AEB2] dark:bg-[#6e696024] dark:text-[#9A958A] dark:border-[#9e958a73]", - blue: "bg-[#DBEAFE] text-[#1D4ED8] border-[#2563EB] dark:bg-[#2563eb2e] dark:text-[#2563EB] dark:border-[#2563eb73]", - amber: "bg-[#FEF3C7] text-[#B45309] border-[#F59E0B] dark:bg-[#f59e0b24] dark:text-[#F59E0B] dark:border-[#f59e0b73]", - green: "bg-[#DCFCE7] text-[#188A3C] border-[#22C55E] dark:bg-[#22c55e1f] dark:text-[#22C55E] dark:border-[#22c55e73]", - violet: "bg-[#EDE9FE] text-[#5B21B6] border-[#7C3AED] dark:bg-[#7c3aed2e] dark:text-[#7C3AED] dark:border-[#7c3aed73]", - red: "bg-[#FEE2E2] text-[#991B1B] border-[#DC2626] dark:bg-[#dc26262e] dark:text-[#DC2626] dark:border-[#dc262673]", -}; /** * Brand blue TEXT pair (the text hues of `brandChipBadge.blue`) for non-chip diff --git a/ui/src/pages/AgentDetail.tsx b/ui/src/pages/AgentDetail.tsx index b83f6e43128..bc838024bfd 100644 --- a/ui/src/pages/AgentDetail.tsx +++ b/ui/src/pages/AgentDetail.tsx @@ -963,7 +963,7 @@ export function AgentDetail() { return (
{showLeftAgentNotice ? ( -
+

You left this agent. It no longer appears in your sidebar.

@@ -988,7 +988,7 @@ export function AgentDetail() { />
) : null} {hasInvalidOrgChain ? ( -
+

Invalid reporting chain

-

+

{agent.name} cannot accept tasks or start runs until its reporting chain is repaired.

-

+

{formatOrgChainHealthPath(agent)}

{agent.orgChainHealth?.repairGuidance ? ( -

{agent.orgChainHealth.repairGuidance}

+

{agent.orgChainHealth.repairGuidance}

) : ( -

+

Assign this agent to an active manager/root, or explicitly pause or terminate the affected agent/subtree.

)} @@ -2156,7 +2156,7 @@ function PromptsTab({ {(bundle?.warnings ?? []).length > 0 && (
{(bundle?.warnings ?? []).map((warning) => ( -
+
{warning}
))} @@ -2435,7 +2435,7 @@ function PromptsTab({ return ( - + virtual file diff --git a/ui/src/pages/CompanyAccess.tsx b/ui/src/pages/CompanyAccess.tsx index be09b51b9ce..24ef4b60619 100644 --- a/ui/src/pages/CompanyAccess.tsx +++ b/ui/src/pages/CompanyAccess.tsx @@ -249,7 +249,7 @@ export function CompanyAccess() {
{access && !access.currentUserRole && ( -
+
This account can manage access here through instance-admin privileges, but it does not currently hold an active company membership.
)} diff --git a/ui/src/pages/CompanySkills.tsx b/ui/src/pages/CompanySkills.tsx index 95f310effcd..1d023705d4f 100644 --- a/ui/src/pages/CompanySkills.tsx +++ b/ui/src/pages/CompanySkills.tsx @@ -422,13 +422,13 @@ function TrustChip({ level }: { level: CompanySkillTrustLevel }) { icon: Folder, label: "Includes assets", tooltip: "Ships images, fonts, or other non-script files.", - className: "border-cyan-500/30 bg-cyan-500/10 text-cyan-200", + className: "border-cyan-500/30 bg-cyan-500/10 text-cyan-800 dark:text-cyan-200", }, scripts_executables: { icon: AlertTriangle, label: "Includes scripts", tooltip: "Ships executable scripts. Review before installing.", - className: "border-amber-500/40 bg-amber-500/10 text-amber-200", + className: "border-amber-500/40 bg-amber-500/10 text-amber-800 dark:text-amber-200", }, } as const; const config = map[level] ?? map.markdown_only; @@ -453,7 +453,7 @@ function CompatChip({ compatibility }: { compatibility: CompanySkillCompatibilit icon: HelpCircle, label: "Unknown format", tooltip: "Paperclip could not validate this skill as Agent Skills markdown. Install at your own risk.", - className: "border-yellow-500/40 bg-yellow-500/10 text-yellow-200", + className: "border-yellow-500/40 bg-yellow-500/10 text-yellow-800 dark:text-yellow-200", }, invalid: { icon: XOctagon, @@ -864,7 +864,7 @@ function SkillCard({ card, onOpen }: { card: DiscoveryCard; onOpen: (card: Disco
{card.installed ? ( - + Installed ) : null} @@ -1727,7 +1727,7 @@ function CatalogDetailPane({ ); } else if (hashOutOfSync) { cta = ( - @@ -1770,7 +1770,7 @@ function CatalogDetailPane({ {hashOutOfSync ? ( - + @@ -1908,7 +1908,7 @@ function InstallPreviewDialog({ {skill.trustLevel === "markdown_only" ? ( Safe ) : skill.trustLevel === "scripts_executables" ? ( - Review required + Review required ) : ( Non-script assets )} @@ -1952,7 +1952,7 @@ function InstallPreviewDialog({
{conflict ? ( -
+
An existing skill with key {conflict.key} is installed ( {conflict.sourceLabel ?? conflict.sourceType}). Installing will {defaultAction === "update" ? "overwrite the catalog content" : "replace the existing skill"}.
@@ -2456,8 +2456,8 @@ function SkillVersionDiffDialog({ ); const lineClassesByKind: Record = { context: "bg-transparent", - removed: "bg-red-500/10 text-red-100", - added: "bg-green-500/10 text-green-100", + removed: "bg-red-500/10 text-red-900 dark:text-red-100", + added: "bg-green-500/10 text-green-900 dark:text-green-100", }; const markerByKind: Record = { context: " ", diff --git a/ui/src/pages/Dashboard.tsx b/ui/src/pages/Dashboard.tsx index 4c78a1e32c2..68a0a9cca74 100644 --- a/ui/src/pages/Dashboard.tsx +++ b/ui/src/pages/Dashboard.tsx @@ -221,17 +221,17 @@ export function Dashboard() { {data.budgets.activeIncidents > 0 ? (
- +
-

+

{data.budgets.activeIncidents} active budget incident{data.budgets.activeIncidents === 1 ? "" : "s"}

-

+

{data.budgets.pausedAgents} agents paused · {data.budgets.pausedProjects} projects paused · {data.budgets.pendingApprovals} pending budget approvals

- + Open budgets
diff --git a/ui/src/pages/Org.tsx b/ui/src/pages/Org.tsx index 2cbc1816438..1cd2b8a9748 100644 --- a/ui/src/pages/Org.tsx +++ b/ui/src/pages/Org.tsx @@ -10,6 +10,7 @@ import { EmptyState } from "../components/EmptyState"; import { PageSkeleton } from "../components/PageSkeleton"; import { ChevronRight, GitBranch } from "lucide-react"; import { cn } from "../lib/utils"; +import { agentStatusDot, agentStatusDotDefault } from "../lib/status-colors"; function OrgTree({ nodes, @@ -67,15 +68,9 @@ function OrgTreeNode({ {node.name} diff --git a/ui/src/pages/ProjectDetail.tsx b/ui/src/pages/ProjectDetail.tsx index 2be189a9d17..b9265a52fe4 100644 --- a/ui/src/pages/ProjectDetail.tsx +++ b/ui/src/pages/ProjectDetail.tsx @@ -729,7 +729,7 @@ export function ProjectDetail() { return (
{showLeftProjectNotice ? ( -
+

You left this project. It no longer appears in your sidebar.

@@ -754,7 +754,7 @@ export function ProjectDetail() { />