Files
Aron PrinsandClaude Opus 5.5 ee9de7fb26 Screenshots: recapture all for v2026.1106.0 (#174)
Recaptures every docs screenshot against `v2026.1106.0` (`d69631b0`).
196 of 278 were stale, and some contradicted the text, such as the
removed **Run with provider trace** button and the old roster tabs.

## What changed

- **Images:** 276 of 276 captured in both themes; 271 PNGs changed.
Every registry entry is stamped `v2026.1106.0`.
- **Pipeline:** `seed.mjs`, `capture.mjs`, `routes.mjs`, `config.mjs`
and `github-review-fixture.mjs` now match this release's UI. No targets
were dropped.
- **Caption:** `experimental/file-viewer.md` now describes what its
image shows.

## Check these

- **Staged state:** the budget banner is removed in the browser on
`dashboard/dashboard-overview`, `experimental/server-info` and
`onboarding/sidebar-new-company-button`. The budget pages keep their
real incidents. The seed also turns off hard stops outside the Budget
Demo agents, and marks agents stuck in `verifying` as ready, so demo
pages aren't paused.
- **`experimental/file-viewer-browse`:** opening the task **Files** tab
crashed the app at the tag on the seeded instance (`Maximum update depth
exceeded` in `SidePanelTabs`), so the image shows a file open in its
side panel instead. `file-viewer.md` still lists `g f` as an entry
point.

## Review coverage

All 140 light images were checked at contact-sheet size, so fine text
wasn't readable that way. 44 images from the final run, 24 light and 20
dark, were opened at full size. The remaining dark images weren't
viewed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-07 16:41:26 +01:00

84 lines
6.4 KiB
JavaScript

/**
* Browser-only demo responses for the real GitHub setup components.
* No GitHub request, credential, installation, review, or agent run is created.
* Ordinary company/navigation reads still use the isolated screenshot instance.
*/
export async function installGitHubReviewFixture(page, ids, stage) {
if (!ids.companyId || !ids.agentId) throw new Error("Seed the screenshot instance first");
const now = "2026-09-22T12:00:00.000Z";
const endpointId = "github-review-docs-demo";
const endpoint = {
id: endpointId, companyId: ids.companyId, connectionId: "demo-bot-connection",
provider: "github", publicId: "demo-public-id",
// The wizard stages are drafts; repositories and prompts live on the
// connected bot's Access and Settings tabs since v2026.1106.0.
status: stage === "connect" || stage === "identity" ? "verifying" : "active",
deploymentMode: "direct", assignedAgentId: ids.agentId,
assignedAgentName: "Storybook Bot", sponsorUserId: null,
providerAccountId: "1000", providerAccountLabel: "acme",
botExternalId: "1001", botUsername: "acme-storybook[bot]", botLabel: "Storybook Bot",
allowDirectMessages: false, allowGroupChats: false, allowUnlinkedPeople: false,
replyMode: "subscribed", capabilities: {},
setup: {
step: "provider_setup", webhookUrl: "https://paperclip.example.com/api/chat-webhooks/demo-public-id/github",
webhookVerifiedAt: now, webhookSecretConfigured: true,
github: { stage, appSlug: stage === "connect" ? null : "acme-storybook", installationUrl: "https://github.com/apps/acme-storybook/installations/new", managementUrl: "https://github.com/settings/installations/1000" },
},
healthMessage: null, lastActivityAt: now, lastPublicationAt: null,
activatedAt: null, createdAt: now, updatedAt: now,
};
const events = ["opened", "synchronize", "reopened", "ready_for_review", "mention", "comment"];
const configuration = { revision: 1, configuration: {
version: 1, toolsEnabled: true, responsibleUserId: "local-board", memberAccess: "all_linked", people: [], repositories: {},
defaults: {
invocation: "linked_authors", events, reviewDrafts: false, reviewBotAuthors: false,
includeAuthors: [], excludeAuthors: [], targetBranches: [], excludedBranches: [], requiredLabels: [], excludedLabels: [], ignoredPaths: [],
instructions: "Generate and build stories for the changed UI. Open the rendered pages. Require visible, case-sensitive oogabooga from the product UI; do not inject it into test fixtures. Submit the exact head, evidence, and honest coverage. Complete and matching: 5/5. Complete without a match: 3/5. Build or browser failure: incomplete.",
prompts: Object.fromEntries(events.map(event => [event, event === "opened" ? "Run the Storybook acceptance review for this new PR using the configured review instructions. Submit an assessment for its current head commit." : "Follow the configured review instructions and use the supplied event context."])),
findingCategories: ["correctness", "accessibility"], minimumCommentSeverity: "warning",
publishSummary: true, publishInline: true, allowApprove: false, allowRequestChanges: false, ratingThreshold: 5,
},
}};
const resources = ["acme/storybook-demo", "acme/design-system"].map((name, index) => ({
id: `demo-repository-${index}`, companyId: ids.companyId, endpointId,
type: "repository", providerResourceId: String(2000 + index), label: name,
detail: "Private repository", providerUrl: `https://github.com/${name}`,
availability: "available", enabled: index === 0, createdAt: now, updatedAt: now,
}));
const send = (route, data) => route.fulfill({status: 200, contentType: "application/json", body: JSON.stringify(data)});
await page.route("**/api/**", async route => {
const path = new URL(route.request().url()).pathname;
if (path === "/api/announcements/current") return send(route, null);
if (path === "/api/instance/settings/experimental") {
// Merge onto the instance's real flags: replacing them dropped every other
// gated surface (Decisions, Status) from the sidebar in these shots.
const response = await route.fetch();
const flags = response.ok() ? await response.json() : {};
return send(route, { ...flags, enableChatConnectors: true, enableGitHubReviewBots: true, enableIsolatedWorkspaces: true });
}
if (path === `/api/companies/${ids.companyId}/agents`) {
const response = await route.fetch();
const agents = await response.json();
return send(route, agents.map(agent => agent.id === ids.agentId ? { ...agent, name: "Storybook Bot", permissions: { ...agent.permissions, trustPreset: "low_trust_review" } } : agent));
}
if (path === `/api/chat-endpoints/${endpointId}`) return send(route, endpoint);
if (path === `/api/chat-endpoints/${endpointId}/resources`) return send(route, {resources});
// GitHubChatSetup renders from this wizard state, not from setup.github.stage.
if (path === `/api/chat-endpoints/${endpointId}/github/setup`) return send(route, stage === "identity"
? { endpointId, state: "identity", identityMethod: "existing_connection" }
: { endpointId, state: "create" });
if (path === `/api/chat-endpoints/${endpointId}/github/repositories`) return send(route, {
items: resources, nextOffset: null, totalCount: resources.length,
enabledCount: resources.filter(resource => resource.enabled).length, availableCount: resources.length,
});
if (path === `/api/chat-endpoints/${endpointId}/github/registration`) return send(route, { registrationUrl: "https://github.com/settings/apps/new", expiresAt: new Date(Date.now() + 600000).toISOString(), manifest: {} });
if (path === `/api/chat-endpoints/${endpointId}/github/configuration`) return send(route, configuration);
if (path === `/api/chat-endpoints/${endpointId}/github/personal-connections`) return send(route, [{ connectionId: "demo-personal", name: "My GitHub", login: "octocat", enabled: true, status: "active" }]);
if (path === `/api/chat-endpoints/${endpointId}/github/identity`) return send(route, { githubUserId: "42", login: "octocat", connectionId: "demo-personal", avatarUrl: null });
if (path === `/api/chat-endpoints/${endpointId}/github/repositories/refresh`) return send(route, resources);
if (path.startsWith(`/api/chat-endpoints/${endpointId}/`)) return send(route, []);
// fallback (not continue) so capture.mjs context-level handlers still run.
return route.fallback();
});
}