Files
PaperClipAI/ui/src/components/StatusBadge.test.tsx
T
DottaandPaperclip 841742fc1a [codex] Graduate experimental conference room defaults (#8628)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The board UI has been graduating experimental conference-room task
experiences into the default issue and onboarding flows
> - Several task UI improvements were still coupled to the Conference
Room Chat experimental flag even though they are useful outside chat
itself
> - That coupling meant disabling chat also reverted unrelated defaults
such as work-mode labels, task status colors, team creation copy, and
the graduated issue thread
> - This pull request keeps chat-specific gating scoped to chat while
making the graduated task UI the default experience
> - The benefit is that operators can use the newer task workflows
without needing to enable the separate chat experiment

## Linked Issues or Issue Description

No public GitHub issue exists for this exact change.

### Problem or motivation

The Conference Room Chat experimental flag was controlling unrelated
task UI defaults, which made non-chat workflows regress when chat was
disabled.

### Proposed solution

Remove that flag from task-thread, work-mode, onboarding, status, and
team-creation presentation paths while leaving chat-specific behavior
separately gated.

### Alternatives considered

Keeping the flag as a broad umbrella until chat graduates would avoid a
behavior change, but it keeps unrelated UI improvements hidden behind
the wrong capability switch.

### Roadmap alignment

Checked `ROADMAP.md`; this is focused graduation/polish for existing UI
surfaces rather than a new roadmap-level core feature.

Related search:

- Searched open PRs and issues for `conference room chat experimental
flag`: no matches.
- Searched open PRs and issues for `graduated issue thread`: no matches.

## What Changed

- Removes Conference Room Chat flag branching from task-thread
rendering, work-mode labels, task status colors, and team creation copy.
- Makes the onboarding completion path create/reuse an onboarding
project, create the first assigned task, and send the user to the
dashboard instead of chat.
- Deletes the legacy onboarding wizard and classic task-thread files now
that the graduated flow is the default.
- Updates focused UI tests and affected E2E specs for the default task
experience.
- Adds a user-visible onboarding error if restored state is missing the
company or agent required for launch.

## Verification

- `pnpm run preflight:workspace-links && pnpm exec vitest run
ui/src/components/NewIssueDialog.test.tsx
ui/src/components/OnboardingWizardVariant.test.tsx
ui/src/components/RunChatSurface.test.tsx
ui/src/components/SidebarCompanyMenu.test.tsx
ui/src/components/StatusBadge.test.tsx ui/src/lib/agent-order.test.ts
ui/src/lib/onboarding-launch.test.ts ui/src/lib/work-mode-meta.test.ts
ui/src/pages/IssueDetail.test.tsx`
- `pnpm --filter @paperclipai/ui typecheck`
- `npx playwright test --config tests/e2e/playwright.config.ts --list
tests/e2e/conference-room-typing-intro.spec.ts
tests/e2e/planning-mode-visual-verification.spec.ts`
- Attempted targeted Playwright execution locally, but this host is
missing Chromium system libraries (`libatk1.0-0t64`, `libatspi2.0-0t64`,
`libxcomposite1`, `libxdamage1`, `libxfixes3`, `libxrandr2`, `libgbm1`,
`libasound2t64`). CI runs the specs in the proper Actions environment.

## Risks

- Medium UI behavior risk: this intentionally changes the default
experience for users who have not enabled Conference Room Chat.
- Medium onboarding risk: completion now creates/reuses a project and
creates the first task instead of only navigating.
- Low migration risk: no database schema or migration changes are
included.
- The PR avoids `pnpm-lock.yaml` and `.github/workflows` changes.

## Model Used

OpenAI Codex, GPT-5-class coding model, tool-enabled local repository
workflow with shell, git, and test execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-25 11:52:36 -05:00

73 lines
3.0 KiB
TypeScript

// @vitest-environment node
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vitest";
import { AgentStatusBadge, IssueStatusBadge, StatusBadge } from "./StatusBadge";
import { agentStatusVar, taskStatusVar } from "../lib/status-colors";
/**
* Issue/task status chips carry the unified glyph and are recolored from the
* `--status-task-*` base hue via the `.status-chip` color-mix helper.
*/
describe("IssueStatusBadge", () => {
it("wires each issue status to its --status-task-* base hue, with a glyph", () => {
for (const [status, cssVar] of Object.entries(taskStatusVar)) {
const html = renderToStaticMarkup(<IssueStatusBadge status={status} />);
expect(html).toContain("status-chip");
expect(html).toContain("border");
expect(html).toContain(`var(${cssVar})`);
expect(html).toContain('viewBox="0 0 24 24"'); // unified glyph
}
});
it("points in_progress at the blue liveness var and todo at the amber var", () => {
expect(renderToStaticMarkup(<IssueStatusBadge status="in_progress" />)).toContain("var(--status-task-in_progress)");
expect(renderToStaticMarkup(<IssueStatusBadge status="todo" />)).toContain("var(--status-task-todo)");
});
it("sentence-cases the label and uses regular weight", () => {
const html = renderToStaticMarkup(<IssueStatusBadge status="in_review" />);
expect(html).toContain("In review");
expect(html).not.toContain("In Review"); // sentence case, not title case
expect(html).toContain("font-normal");
expect(html).not.toContain("font-medium");
});
it("strikes through cancelled chips", () => {
expect(renderToStaticMarkup(<IssueStatusBadge status="cancelled" />)).toContain("line-through");
});
it("falls back to the backlog (gray) var for unknown statuses", () => {
expect(renderToStaticMarkup(<IssueStatusBadge status="mystery" />)).toContain("var(--status-task-backlog)");
});
it("renders task chips without depending on the chat flag", () => {
const html = renderToStaticMarkup(<IssueStatusBadge status="todo" />);
expect(html).toContain("status-chip");
expect(html).toContain('viewBox="0 0 24 24"');
expect(html).toContain("Todo");
});
});
/** Agent chips recolor from the `--status-agent-*` base hues. */
describe("AgentStatusBadge", () => {
it("wires each agent status to its --status-agent-* base hue via status-chip", () => {
for (const [status, cssVar] of Object.entries(agentStatusVar)) {
const html = renderToStaticMarkup(<AgentStatusBadge status={status} />);
expect(html).toContain("status-chip");
expect(html).toContain(`var(${cssVar})`);
}
});
it('renders "active" as the idle label', () => {
expect(renderToStaticMarkup(<AgentStatusBadge status="active" />)).toContain("idle");
});
});
describe("StatusBadge", () => {
it("uses the graduated brand hues", () => {
expect(renderToStaticMarkup(<StatusBadge status="todo" />)).toContain("bg-amber-100");
expect(renderToStaticMarkup(<StatusBadge status="in_progress" />)).toContain("bg-blue-100");
});
});