Files
paperclip/ui/src/pages/TeamCatalog.fixtures.ts
T
Dotta fff3832a01 [codex] Add teams catalog extraction (#7550)
Fixes #7551

## Thinking Path

> - Paperclip is the control plane for AI-agent companies, and reusable
company/team setup is part of making those companies faster to launch.
> - The teams catalog work introduces app-shipped team templates that
can be browsed, previewed, and installed into a company.
> - Catalog installation crosses several contracts: bundled package
contents, shared API types, server import/install behavior, CLI
workflows, and the board UI.
> - Agents also need a safe path through catalog installs: scoped
company selection, explicit source policy, approval fallback for agent
creation, and preserved catalog provenance.
> - This pull request extracts the completed teams catalog branch into
one reviewable PR on top of `public-gh/master`.
> - The benefit is a reusable teams catalog foundation with server, CLI,
package, docs, and hidden UI surfaces kept in sync.

## What Changed

- Added the `@paperclipai/teams-catalog` package with bundled/optional
team definitions, generated manifest, validators, catalog builder tests,
and migration notes.
- Added shared teams catalog types/validators plus server routes and
services for listing, previewing, and installing catalog teams.
- Integrated catalog install with company portability, skill/source
policy checks, provenance metadata, origin hashes, target-manager
reparenting, and installed/out-of-date detection.
- Added CLI `teams` commands and agent-safe company selection behavior,
including `company current` and approval fallback for forbidden
agent-run installs.
- Added hidden Team Catalog UI/API/query surfaces, Storybook fixtures,
and targeted UI tests while keeping the UI route out of primary
navigation.
- Added docs for CLI/company/teams catalog behavior and removed
generated screenshot artifacts from the PR diff.

## Verification

- `pnpm exec vitest run cli/src/__tests__/company.test.ts
cli/src/__tests__/teams.test.ts
packages/teams-catalog/src/catalog-builder.test.ts
packages/teams-catalog/src/shipped-catalog.test.ts
server/src/__tests__/agent-permissions-service.test.ts
server/src/__tests__/company-portability.test.ts
server/src/__tests__/company-skills-service.test.ts
server/src/__tests__/teams-catalog-routes.test.ts
server/src/__tests__/teams-catalog-service.test.ts
server/src/__tests__/teams-catalog-install-no-overrides.test.ts
ui/src/lib/company-routes.test.ts ui/src/pages/TeamCard.test.tsx
ui/src/pages/TeamCatalog.test.tsx
ui/src/pages/useInstallTeamCatalogEntry.test.tsx`
- `pnpm --filter @paperclipai/shared typecheck && pnpm --filter
@paperclipai/teams-catalog typecheck && pnpm --filter paperclipai
typecheck && pnpm --filter @paperclipai/server typecheck && pnpm
--filter @paperclipai/ui typecheck`
- Confirmed branch is rebased onto `public-gh/master` (`78dc3625a`) and
`public-gh/master` is an ancestor of `HEAD`.
- Confirmed PR diff excludes `pnpm-lock.yaml`, `.github/workflows/*`,
generated screenshot images, and screenshot helper scripts.

## Risks

- Medium review surface: this crosses package generation, shared
contracts, server install behavior, CLI, docs, and hidden UI code.
- Catalog install behavior creates agents/projects/tasks/skills and must
keep company scoping, permissions, source policy, and provenance checks
strict.
- `pnpm-lock.yaml` is intentionally excluded per repo policy;
CI/default-branch automation owns lockfile refresh.
- The Team Catalog UI is included but hidden from primary navigation, so
future enablement should re-check visual QA before exposure.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
>
> ROADMAP checked: this aligns with reusable companies/templates and
plugin-adjacent onboarding work. This PR packages work already developed
on the Paperclip task branch for review.

## Model Used

- OpenAI Codex, GPT-5 series coding agent in this Paperclip session;
exact runtime context window was not exposed. Used shell, git, `gh`, and
local test/typecheck tooling.

## 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots, or documented why screenshots are intentionally omitted
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 12:55:49 -05:00

167 lines
6.8 KiB
TypeScript

import type {
CatalogTeam,
CatalogTeamSkillPreparation,
InstalledCatalogTeam,
} from "@paperclipai/shared";
// ---------------------------------------------------------------------------
// Shared Team Catalog fixtures.
//
// Used by both the Storybook stories (ui/storybook/stories/team-catalog.stories.tsx)
// and the in-app /design-guide showcase so the two surfaces stay in sync.
// ---------------------------------------------------------------------------
export const sampleTeam: CatalogTeam = {
id: "paperclipai:bundled:company-defaults:core-exec-team",
key: "paperclipai/bundled/company-defaults/core-exec-team",
kind: "bundled",
category: "company-defaults",
slug: "core-exec-team",
name: "Core Exec Team",
description:
"A starter executive team: a CEO who manages a CTO and a CMO, plus a launch project and a weekly standup routine. Installs ready-to-run agents you can customize.",
path: "catalog/bundled/company-defaults/core-exec-team",
entrypoint: "TEAM.md",
schema: "agentcompanies/v1",
defaultInstall: true,
recommendedForCompanyTypes: ["company-root"],
tags: ["exec", "starter"],
counts: {
agents: 3,
projects: 1,
tasks: 1,
routines: 1,
localSkills: 1,
catalogSkills: 1,
externalSkillSources: 1,
},
rootAgentSlugs: ["ceo"],
agentSlugs: ["ceo", "cto", "cmo"],
projectSlugs: ["launch"],
requiredSkills: [
{ type: "catalog", ref: "engineering/code-review", agentSlugs: ["cto"], resolved: true, catalogSkillKey: "engineering/code-review" },
{ type: "github", ref: "acme/growth-playbook@v1.2.0", agentSlugs: ["cmo"], resolved: false, sourceRef: "v1.2.0" },
],
envInputs: [
{ key: "OPENAI_API_KEY", agentSlug: "cto", projectSlug: null, kind: "secret", requirement: "required" },
{ key: "DEFAULT_TIMEZONE", agentSlug: null, projectSlug: "launch", kind: "plain", requirement: "optional" },
],
sourceRefs: [
{ type: "github", ref: "acme/growth-playbook@v1.2.0", pinned: true },
{ type: "url", ref: "https://example.com/policies/brand.md", pinned: false },
],
files: [
{ path: "TEAM.md", kind: "team", sizeBytes: 2144, sha256: "a1" },
{ path: "README.md", kind: "readme", sizeBytes: 980, sha256: "a2" },
{ path: "agents/ceo/AGENTS.md", kind: "agent", sizeBytes: 1200, sha256: "a3" },
{ path: "agents/cto/AGENTS.md", kind: "agent", sizeBytes: 1100, sha256: "a4" },
{ path: "agents/cmo/AGENTS.md", kind: "agent", sizeBytes: 1050, sha256: "a5" },
{ path: "projects/launch/PROJECT.md", kind: "project", sizeBytes: 640, sha256: "a6" },
],
trustLevel: "external_sources",
compatibility: "compatible",
contentHash: "sha256:deadbeefdeadbeefdeadbeefdeadbeef",
packageName: "@paperclipai/teams-catalog",
packageVersion: "0.1.0",
};
export const optionalTeam: CatalogTeam = {
...sampleTeam,
id: "paperclipai:optional:software-development:platform-pod",
key: "paperclipai/optional/software-development/platform-pod",
kind: "optional",
category: "software-development",
slug: "platform-pod",
name: "Platform Engineering Pod",
description: "An optional platform pod with a tech lead and two engineers.",
recommendedForCompanyTypes: [],
counts: { ...sampleTeam.counts, agents: 4, routines: 2 },
rootAgentSlugs: ["tech-lead"],
agentSlugs: ["tech-lead", "eng-1", "eng-2", "sre"],
trustLevel: "markdown_only",
sourceRefs: [],
};
export const warnTeam: CatalogTeam = {
...sampleTeam,
id: "paperclipai:optional:research:lab-with-local-source",
slug: "lab-with-local-source",
name: "Research Lab (local source)",
kind: "optional",
category: "research",
trustLevel: "scripts_executables",
sourceRefs: [
{ type: "url", ref: "https://example.com/unpinned.md", pinned: false },
{ type: "local_path", ref: "/Users/dev/skills/secret-sauce", pinned: false },
],
};
// Server-computed installed-team state (PAP-10256). Drives the `INSTALLED · N`
// group, the per-row out-of-date badge, and the detail header chip. Shared by
// the Storybook stories and /design-guide showcase so they stay in sync.
export const outOfDateInstalledState: InstalledCatalogTeam = {
catalogId: sampleTeam.id,
catalogKey: sampleTeam.key,
present: true,
currentContentHash: sampleTeam.contentHash,
installedOriginHashes: ["sha256:0000older0000older0000older"],
agentCount: 3,
outOfDate: true,
};
export const currentInstalledState: InstalledCatalogTeam = {
...outOfDateInstalledState,
installedOriginHashes: [sampleTeam.contentHash],
outOfDate: false,
};
export const sampleSkillPreparations: CatalogTeamSkillPreparation[] = [
{ type: "catalog", ref: "engineering/code-review", agentSlugs: ["cto"], action: "already_in_package", catalogSkillId: "skill-1", catalogSkillKey: "engineering/code-review", sourceLocator: null, sourceRef: null, reason: null },
{ type: "github", ref: "acme/growth-playbook@v1.2.0", agentSlugs: ["cmo"], action: "external_import_required", catalogSkillId: null, catalogSkillKey: null, sourceLocator: "github.com/acme/growth-playbook", sourceRef: "v1.2.0", reason: "Resolved from GitHub at install time" },
];
// Onboarding "Pick a starter team" grid (design §6): `defaultInstall` bundled
// teams restricted to markdown_only/assets trust. Shared by the TeamCard
// Storybook fixture and the /design-guide showcase so they stay in sync.
export const onboardingTeams: CatalogTeam[] = [
{
...sampleTeam,
trustLevel: "markdown_only",
sourceRefs: [],
requiredSkills: [],
counts: { ...sampleTeam.counts, localSkills: 0, catalogSkills: 0, externalSkillSources: 0 },
},
{
...sampleTeam,
id: "paperclipai:bundled:company-defaults:growth-pod",
key: "paperclipai/bundled/company-defaults/growth-pod",
slug: "growth-pod",
name: "Growth Pod",
description:
"A lean growth squad: a head of growth managing a content marketer and a data analyst, wired to a launch project and a weekly metrics routine.",
tags: ["growth", "marketing", "starter"],
counts: { agents: 3, projects: 1, tasks: 0, routines: 1, localSkills: 0, catalogSkills: 0, externalSkillSources: 0 },
rootAgentSlugs: ["head-of-growth"],
agentSlugs: ["head-of-growth", "content-marketer", "data-analyst"],
trustLevel: "assets",
sourceRefs: [],
requiredSkills: [],
},
{
...sampleTeam,
id: "paperclipai:bundled:company-defaults:support-pod",
key: "paperclipai/bundled/company-defaults/support-pod",
slug: "support-pod",
name: "Support Pod",
description: "A two-person support desk with a lead and an agent, plus a triage routine.",
tags: ["support", "ops"],
counts: { agents: 2, projects: 0, tasks: 0, routines: 1, localSkills: 0, catalogSkills: 0, externalSkillSources: 0 },
rootAgentSlugs: ["support-lead"],
agentSlugs: ["support-lead", "support-agent"],
projectSlugs: [],
trustLevel: "markdown_only",
sourceRefs: [],
requiredSkills: [],
},
];