Files
PaperClipAI/ui/storybook/support/capability-gaps/environments.ts
T
DottaandPaperclip c8efdbfba4 test(storybook): add production examples for feature map UI gaps (#16196)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The feature map records the user-facing capabilities.
> - Storybook uses the same feature index.
> - Step 2 found 49 UI capabilities with no authored examples.
> - This pull request adds shipped-component examples with isolated
fixtures.
> - The catalog records each example's states and remaining production
checks.

## Linked Issues or Issue Description

Refs: #16167. The verification inventory is merged; this follow-up now
targets master.

## What Changed

- Add 37 suites and 257 scenarios for all 49 UI capabilities from the
step-2 inventory. Keep existing stories and IDs.
- Use shipped pages and components. Simulate API replies, sockets,
props, and callbacks at their boundaries.
- Activate story API fixtures before the application providers read
data. Block unregistered API mutations and restore owned storage/fetch
state.
- Add browser checks for rendering, declared play assertions, fixture
reset, and selected mobile/theme states. Update the catalog and
verification inventory.

## Verification

- `pnpm -r typecheck`: passed.
- `pnpm build`: passed.
- UI Vitest suite: 730 files and 8,208 tests passed. Fixture boundary
tests: 4 passed.
- Map/catalog checks, 27 generator/map tests, and token gates: passed.
- `pnpm build-storybook`: passed. All 2,248 previous built entry IDs
remain present.
- Pre-reconciliation static browser suite: 260 checks passed (257
scenarios, token fixture reset, and two mobile/theme cases). All
non-play stories assert an explicit subject state; 129 play functions
passed.
- `pnpm test:run` could not complete on this Mac. Embedded PostgreSQL
exhausted host shared-memory allocation. The run also reported
native-runner test timeouts. Only this task's verified runner was
stopped; other jobs and host settings were preserved.
- Reconciled onto merged master `252d9b5077`. The six draft stories and
new same-browser reset regression passed (7 checks); 16
draft-persistence tests and UI typecheck passed. Static merge
verification: 32 affected-subject/draft checks passed, including
same-browser reset. Rebuilt Storybook retains all 2,248 original IDs in
its 2,517-entry index. Four additional play-result checks passed:
visible onboarding reset, pending probe, filtered-empty runs, and
optimistic queued-response removal. UI typecheck and 27 catalog/map
tests also passed. Final static browser suite on
`3fab35df8d912935fa86ce0de7d32d07e2b5f4c3`: all 261 checks passed (257
scenarios plus fixture-reset and mobile checks). Latest head
`3fab35df8d912935fa86ce0de7d32d07e2b5f4c3`: all 55 CI/status checks
passed; the two optional Storybook workflow jobs were skipped. Greptile
5/5 with no unresolved threads.
- No pinned Linux visual-baseline comparison or real provider journey is
claimed.

## Risks

Fixtures can drift from production contracts. The catalog records
inspected sources and their fingerprints. Capability links provide
initial isolated UI coverage; they do not certify every recipe variant,
real permissions, persistence, or provider behavior.

The new examples expose existing UI limits. Plugin discovery failure
stays on Loading. Document and environment-list reads lack dedicated
failure feedback; Cases and Inbox fall back to empty views after errors.
Goal alignment has display views but no assignment control. These
findings remain visible in the inventory.

## Model Used

OpenAI GPT-6 via Codex. The exact runtime deployment ID and context
window are not exposed in this session. Used code generation, shell
execution, and browser verification.

## 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-10-13 13:24:09 -05:00

173 lines
5.2 KiB
TypeScript

import type { Environment, EnvironmentCapabilities } from "@paperclipai/shared";
import { prepareFixtureApi, type FixtureState } from "./api";
export const environment: Environment = {
id: "environment-gap",
name: "Release sandbox",
description: "Isolated release checks",
driver: "sandbox",
status: "active",
config: { provider: "daytona", reuseLease: true },
envVars: {},
metadata: null,
createdAt: new Date("2026-10-12"),
updatedAt: new Date("2026-10-12"),
};
const capabilities: EnvironmentCapabilities = {
adapters: [],
drivers: {
local: "supported",
ssh: "supported",
sandbox: "supported",
plugin: "unsupported",
},
sandboxProviders: {
fake: {
status: "unsupported",
supportsLoginPty: false,
supportsSavedProbe: false,
supportsUnsavedProbe: false,
supportsRunExecution: false,
supportsReusableLeases: false,
supportsInteractiveSetup: false,
interactiveSetupConnectionTypes: [],
supportsTemplateCapture: false,
supportsTemplateDelete: false,
},
daytona: {
status: "supported",
supportsLoginPty: true,
supportsSavedProbe: true,
supportsUnsavedProbe: true,
supportsRunExecution: true,
supportsReusableLeases: true,
supportsInteractiveSetup: true,
interactiveSetupConnectionTypes: ["ssh"],
supportsTemplateCapture: true,
supportsTemplateDelete: true,
displayName: "Daytona",
},
},
};
export function installEnvironmentFixture(
state: FixtureState = "ready",
image: "none" | "captured" | "failed" | "loading" | "denied" = "none",
unsupported = false,
) {
let current = { ...environment };
const template = {
id: "template-gap",
environmentId: environment.id,
provider: "daytona",
templateKind: "snapshot",
templateRef: "fixture-template",
sourceTemplateRef: null,
sourceEnvironmentConfigFingerprint: "fixture-fingerprint",
status: "active",
createdByUserId: "user-storybook",
createdByAgentId: null,
capturedAt: "2026-10-12T12:00:00Z",
lastUsedAt: null,
supersededByTemplateId: null,
metadata: null,
createdAt: "2026-10-12T12:00:00Z",
updatedAt: "2026-10-12T12:00:00Z",
};
return prepareFixtureApi(
[
{
path: "/api/instance/settings/experimental",
state: "ready",
read: () => ({
enableEnvironments: true,
enableManagedSandboxOnly: false,
}),
},
{
path: "/api/instance/settings",
state: "ready",
read: () => ({ defaultEnvironmentId: environment.id }),
},
{
path: "/api/companies/company-storybook/environments",
read: () => (state === "empty" ? [] : [current]),
},
{
path: "/api/companies/company-storybook/environments/capabilities",
read: () =>
unsupported
? {
...capabilities,
sandboxProviders: {
fake: {
status: "unsupported",
supportsLoginPty: false,
supportsSavedProbe: false,
supportsUnsavedProbe: false,
supportsRunExecution: false,
supportsReusableLeases: false,
supportsInteractiveSetup: false,
interactiveSetupConnectionTypes: [],
supportsTemplateCapture: false,
supportsTemplateDelete: false,
},
daytona: {
...capabilities.sandboxProviders.daytona,
status: "unsupported",
supportsSavedProbe: false,
supportsTemplateCapture: false,
},
},
}
: capabilities,
},
{
path: "/api/environments/environment-gap/secret-refs",
read: () => ({ refs: [] }),
},
{
path: "/api/environments/environment-gap",
method: "PATCH",
read: ({ body }) => {
current = { ...current, ...body };
return current;
},
},
{
path: "/api/environments/environment-gap/probe",
method: "POST",
read: () => ({
ok: true,
driver: "sandbox",
summary: "Provider connection succeeded.",
details: {},
}),
},
{
path: "/api/environments/environment-gap/custom-image-template",
read: () =>
image === "loading"
? new Promise<Response>(() => {})
: image === "denied"
? Response.json(
{
error: "You do not have permission to inspect this image.",
},
{ status: 403 },
)
: image === "failed"
? Response.json(
{ error: "Image metadata is unavailable." },
{ status: 503 },
)
: {
activeTemplate: image === "captured" ? template : null,
activeTemplateMatchesConfig: true,
activeSession: null,
latestSession: null,
},
},
],
state,
);
}