{
 "slug": "penpot",
 "name": "Penpot",
 "url": "https://penpot.app",
 "domain": "penpot.app",
 "category": "design",
 "category_name": "Design",
 "tested_at": "2026-10-06",
 "run": "20261006T025636Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261006T025636Z",
   "date": "2026-10-06",
   "level": 3,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 3,
 "level_name": "Does the work",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 1,
  "tries": 1,
  "self_start": true
 },
 "badges": [
  "agent-can-leave"
 ],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up by email"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "part",
   "text": "Work done: 57% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "card_checkout"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes its account",
   "left": "deleted"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "yes",
   "text": "Docs agents can read: llms.txt, an OpenAPI and an MCP server",
   "have": [
    "llms_txt",
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up by email",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "part",
   "text": "Work done: 57% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "card_checkout",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes its account",
   "left": "deleted",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "email_signup",
   "label": "Sign-up by email",
   "routes": [],
   "minutes": 16.2,
   "core": "4/7"
  }
 ],
 "minutes": 16.2,
 "next": {
  "to": 4,
  "text": "Next: do 80% of the core work (now 57%)"
 },
 "stop": null,
 "core": "4/7",
 "scores": {
  "coverage": 61,
  "reliability": 92,
  "resilience": null,
  "setup": 90,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 90,
  "security": "private",
  "standards": [
   {
    "standard": "MCP",
    "state": "behind",
    "behind": 1,
    "value": "2025-11-25"
   },
   {
    "standard": "MCP discovery",
    "state": "behind",
    "behind": null,
    "value": "legacy"
   },
   {
    "standard": "OpenAPI",
    "state": "behind",
    "behind": 2,
    "value": "3.0.0"
   }
  ]
 },
 "reliability_method": "first-try",
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": 57,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": "59d395064c20",
  "kb_version": "2",
  "identity": null
 },
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": "claude-opus-5-5",
  "driver": 2,
  "signed": true,
  "inbox": [
   "agentdrives.com"
  ],
  "robots": "start"
 },
 "same_level_drives": 1,
 "drives": 1,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": null,
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "home",
   "at": "2026-10-12"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "Integration guide, MCP guide, auto-generated RPC docs /api/_doc and OpenAPI /api/main/doc/openapi.json (3.0.0, 149 paths), penpot.app/llms.txt"
  },
  "signup": {
   "status": "headless",
   "note": "prepare-register-profile + register-profile RPCs (documented in /api/_doc); no CAPTCHA"
  },
  "verify": {
   "status": "headless",
   "note": "verification mail arrived about 13 min after sign-up (after a resend and a first check at ~11 min found nothing); verify-token RPC activated the account. The cause of the delay is unknown and may be on either side."
  },
  "credentials": {
   "status": "headless",
   "note": "create-access-token RPC with the login session; MCP key via create-access-token type mcp",
   "via": ""
  },
  "first_call": {
   "status": "headless",
   "note": "get-profile with Authorization: Token on /api/main/methods/. The integration guide's curl path /api/rpc/command/get-profile gets a Cloudflare managed challenge (403 cf-mitigated: challenge)."
  },
  "first_action": {
   "status": "headless",
   "note": "create-project and create-file RPCs, read back with get-project-files"
  },
  "pay": {
   "status": "browser",
   "grade": "P1",
   "rails": [
    "in-app subscription page (checkout not observed)"
   ],
   "rail_ids": [
    "other"
   ],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "free tier",
   "note": "No 402, x402, MPP, UCP or billing write API; not in the x402 Bazaar or mpp.dev. Subscription page offers Unlimited $7/user/month and Enterprise $25 with a 14-day free trial button; after CONTINUE we could not see the checkout or whether a card is needed."
  },
  "cancel": {
   "status": "n/a",
   "grade": "n/a",
   "note": "Nothing to cancel: our agent used the free plan.",
   "docs_note": "no plan or trial was started; the account stayed on the free Professional plan",
   "nothing": "free_plan"
  },
  "delete": {
   "status": "headless",
   "note": "delete-profile RPC -> 204 for both accounts; login then fails with wrong-credentials and the old token resolves to Anonymous User",
   "left": "deleted",
   "account": true
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-06",
  "source": "drive",
  "options": [],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": null,
   "card_required": null,
   "free_plan": true
  },
  "owner_fixes": [
   {
    "title": "Accept x402 or MPP on your API",
    "how": "Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card."
   },
   {
    "title": "List your plans on Stripe Projects",
    "how": "Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev)."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": false,
  "sdk": false,
  "mcp": "official",
  "llms_txt": true,
  "webhooks": true,
  "sandbox": false
 },
 "surface_notes": {
  "api": "RPC over HTTP POST, 153 commands in /api/_doc; JSON or Transit",
  "openapi": "3.0.0, 149 paths without a leading '/', update-file schema ~1 MB inline",
  "mcp": "official remote MCP, 4 tools, needs an open Penpot tab with the plugin"
 },
 "can_do": [
  "Sign up, verify the email, get an access token and delete the account, all via the API",
  "Create projects and files and move files between projects",
  "Draw and edit boards and shapes with update-file change operations",
  "Create a main component and a linked copy",
  "Comment on a design, reply and resolve",
  "Create a team, invite a member, have them join and change their role",
  "Share a file as a library and link it into another file",
  "Start a file from a built-in template",
  "Export a file as .penpot and import it into another team",
  "Create a view-only share link",
  "Through the MCP server with a Penpot tab open: edit shapes, get CSS for a shape and export a board as PNG"
 ],
 "cannot_do": [
  {
   "what": "Use the MCP server headless",
   "why": "every tool runs through the plugin in an open Penpot browser tab"
  },
  {
   "what": "Set prototype interactions with plain JSON",
   "why": "update-file returns a 500 assertion error; only Transit-encoded keywords are accepted"
  },
  {
   "what": "Propagate a design-token change to the shapes using it via the API",
   "why": "the backend stores the new value but leaves the shapes' fills unchanged"
  },
  {
   "what": "Export a board to PNG/SVG via the REST API",
   "why": "no documented export command; only the MCP tool or the UI"
  },
  {
   "what": "Buy or start a paid plan headless",
   "why": "no billing API or agent payment rail; upgrade is in the web app"
  }
 ],
 "blockers": [
  "MCP requires a live browser tab running the Penpot plugin",
  "Cloudflare challenge on the /api/rpc/command/ path shown in the integration guide"
 ],
 "tips_for_owner": [
  "Unblock the documented API path for agents",
  "Run MCP tools without an open tab",
  "Accept plain JSON in update-file",
  "Apply token changes to the shapes using them",
  "Return clear 4xx errors",
  "Add a billing API for upgrades",
  "Publish a current, valid OpenAPI"
 ],
 "tips_for_agents": [
  "Call https://design.penpot.app/api/main/methods/<command> with 'Authorization: Token <token>' and 'Accept: application/json'; the /api/rpc/command/ path from the guide may get a Cloudflare challenge",
  "Sign up via prepare-register-profile + register-profile, then verify-token with the token from the mail (it can take ~15 min)",
  "For update-file send application/transit+json when values must be keywords; give every shape full geometry; read revn/vern from get-file first",
  "export-binfile, import-binfile and clone-template reply as SSE: take the result from the 'end' event; omit the 'version' form field on multipart imports",
  "MCP: create-access-token {type:'mcp'}, enable MCP once under Your account > Integrations, keep a Penpot tab open on the file"
 ],
 "selfhost": {
  "install": {
   "status": "skipped",
   "minutes": 0,
   "note": "no docker in the drive sandbox; Penpot has an official Docker self-host edition (penpot.app/self-host)"
  }
 },
 "summary": "An agent can get through Penpot's whole access ladder headless with the documented RPC API: sign up, verify, token, first design, delete account. It can drive most design work through low-level update-file changes, comments, teams, libraries, templates and .penpot export/import. The official MCP server works but needs a live browser tab running the Penpot plugin; prototype interactions need Transit encoding, and token changes do not reach the shapes.",
 "wall": "AI design tools need an open browser tab",
 "plan_scope": "free plan",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Penpot is a free, open design and prototyping tool with a documented API. Our agent could sign up, verify its email, get an access token, build and edit a design, invite teammates, export files, and delete its account entirely on its own, no browser needed for most steps. The main thing it couldn't do alone was use Penpot's AI integration (MCP), which only works while a Penpot tab with the plugin is open in a browser.",
  "can_do": [
   "Sign up, confirm the email, and get login credentials without a person's help",
   "Create and edit a design, add comments, build a team, and share files, all through the API",
   "Export a whole design project and re-import it into another account",
   "Delete the account completely, confirmed by the old login no longer working",
   "Use Penpot's built-in AI design tools, but only while a browser tab with the plugin stays open"
  ],
  "cannot_do": [
   {
    "what": "Use the AI (MCP) design tools without a browser open",
    "why": "the AI tools only run through a live browser tab with Penpot's plugin connected"
   },
   {
    "what": "Export a design to an image file through the API alone",
    "why": "there is no documented way to do this outside the app or the browser-based AI tool"
   },
   {
    "what": "Automatically update a design wherever a shared color/style value changes",
    "why": "the system saved the new value but did not update the shapes using it"
   },
   {
    "what": "Sign up for or cancel a paid plan without using the website",
    "why": "there is no way to buy or manage a subscription through the API"
   }
  ]
 },
 "plan_gated": [
  {
   "capability": "Admin Console and SSO",
   "plan": "Enterprise",
   "evidence": "Subscription page: Enterprise $25/org member/month lists SAML/SSO, Audit Trail, plugin whitelisting"
  },
  {
   "capability": "SCIM and plugin allowlist",
   "plan": "Enterprise",
   "evidence": "Subscription page: Enterprise $25/org member/month lists SAML/SSO, Audit Trail, plugin whitelisting"
  },
  {
   "capability": "Audit logs",
   "plan": "Enterprise",
   "evidence": "Subscription page: Enterprise $25/org member/month lists SAML/SSO, Audit Trail, plugin whitelisting"
  }
 ],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Design",
   "capability": "Create and edit vector designs on a board/canvas",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": "design/editing tools (e.g. create/update shapes)",
    "cli": null,
    "ui": "Workspace editor"
   },
   "check": "Open the file in Penpot and see the new/edited shape persisted on the board",
   "source": "https://penpot.app/design; https://help.penpot.app/user-guide/design-systems/"
  },
  {
   "id": "cap-02",
   "group": "Design",
   "capability": "Build interactive prototypes with connections, flows and animations between boards",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace, Prototype tab"
   },
   "check": "Open View mode and confirm interaction (navigate/open overlay/close overlay) fires as configured",
   "source": "https://help.penpot.app/user-guide/prototyping-testing/prototyping/"
  },
  {
   "id": "cap-03",
   "group": "Design",
   "capability": "Create reusable components and variants (design system assets)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Assets panel, Libraries"
   },
   "check": "Instantiate the component elsewhere and confirm it links back to the main component",
   "source": "https://help.penpot.app/user-guide/design-systems/"
  },
  {
   "id": "cap-04",
   "group": "Design",
   "capability": "Define and sync design tokens (color, spacing, typography) across a file",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Assets panel, Design Tokens"
   },
   "check": "Change a token value and confirm every element referencing it updates",
   "source": "https://help.penpot.app/user-guide/design-systems/"
  },
  {
   "id": "cap-05",
   "group": "Dev handoff",
   "capability": "Inspect a design to get code, CSS, measurements and properties for developer handoff",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Inspect mode (Workspace and View mode)"
   },
   "check": "Switch to Inspect mode on a layer and read the generated CSS/code and measurements",
   "source": "https://help.penpot.app/user-guide/dev-tools/; https://penpot.app/code"
  },
  {
   "id": "cap-06",
   "group": "Collaboration",
   "capability": "Co-edit a file with teammates in real time",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace (multi-cursor presence)"
   },
   "check": "Two accounts open the same file and each sees the other's live cursor and edits",
   "source": "https://penpot.app/collaboration; https://penpot.app/"
  },
  {
   "id": "cap-07",
   "group": "Collaboration",
   "capability": "Comment on designs and reply to feedback threads",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace/View mode, Comments"
   },
   "check": "Add a comment, then GET the file/comments view and see it listed with author and timestamp",
   "source": "https://help.penpot.app/user-guide/account-teams/"
  },
  {
   "id": "cap-09",
   "group": "Design systems",
   "capability": "Organize reusable assets, styles and components into shareable Libraries",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Assets panel, Libraries"
   },
   "check": "Attach a library to another file and confirm its shared components appear in the assets panel",
   "source": "https://help.penpot.app/user-guide/design-systems/"
  },
  {
   "id": "cap-10",
   "group": "Templates",
   "capability": "Start a file from a community template in the Libraries & Templates hub",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "penpot.app/libraries-templates (PenpotHub)"
   },
   "check": "Duplicate a template and see a new project file populated with its content",
   "source": "https://penpot.app/libraries-templates"
  },
  {
   "id": "cap-11",
   "group": "Import/export",
   "capability": "Export layers/boards to image or vector file formats",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace, layer export panel"
   },
   "check": "Trigger export on a layer and confirm a downloaded file matches the selected format/size",
   "source": "https://help.penpot.app/user-guide/export-import/"
  },
  {
   "id": "cap-12",
   "group": "Import/export",
   "capability": "Export and import whole .penpot files (including migrating from Figma)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard, file menu"
   },
   "check": "Export a file, re-import it into another team, and confirm boards/components match the original",
   "source": "https://help.penpot.app/user-guide/export-import/; https://help.penpot.app/user-guide/first-steps/"
  },
  {
   "id": "cap-13",
   "group": "Extensibility",
   "capability": "Install and run plugins that extend editor functionality inside a file",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "Plugins API (in-file JS API)",
    "mcp": null,
    "cli": null,
    "ui": "Plugin Manager (install from PenpotHub or by URL)"
   },
   "check": "Install a plugin and confirm it appears and runs in the plugin panel within the file",
   "source": "https://help.penpot.app/user-guide/plugins-integrations/; https://help.penpot.app/plugins/"
  },
  {
   "id": "cap-14",
   "group": "Extensibility",
   "capability": "Build a custom plugin against the Penpot Plugins API and deploy it",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "Plugins API (JS, manifest-based)",
    "mcp": null,
    "cli": null,
    "ui": "Plugins developer docs"
   },
   "check": "Load the plugin manifest URL in a file and confirm its UI panel registers and its API calls mutate the file",
   "source": "https://help.penpot.app/plugins/"
  },
  {
   "id": "cap-15",
   "group": "Integrations",
   "capability": "Register outbound webhooks on a team that fire on file/comment/library events",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "Team webhooks (configured via app, not documented as public REST write API)",
    "mcp": null,
    "cli": null,
    "ui": "Team settings > Webhooks"
   },
   "check": "Create a webhook, trigger the event (e.g. create a file), and confirm the receiving endpoint gets the POST payload",
   "source": "https://help.penpot.app/technical-guide/integration/"
  },
  {
   "id": "cap-16",
   "group": "Integrations",
   "capability": "Generate and use personal access tokens to authenticate API/integration calls",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "",
    "mcp": null,
    "cli": null,
    "ui": "Your account > Access tokens"
   },
   "check": "Call an authenticated endpoint with the generated token and confirm it succeeds in place of password auth",
   "source": "https://help.penpot.app/technical-guide/integration/"
  },
  {
   "id": "cap-17",
   "group": "Organization",
   "capability": "Organize work into projects and files within a team",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard"
   },
   "check": "Create a project and move a file into it; confirm the dashboard reflects the new grouping",
   "source": "https://help.penpot.app/user-guide/account-teams/"
  },
  {
   "id": "cap-18",
   "group": "Collaboration",
   "capability": "Create a team, invite members, and assign roles",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard > Teams"
   },
   "check": "Invite a member and confirm they appear in the team member list with the assigned role",
   "source": "https://help.penpot.app/user-guide/account-teams/"
  },
  {
   "id": "cap-19",
   "group": "Sharing",
   "capability": "Share a file/prototype via a view-only link and test it in View mode",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace share menu, View mode"
   },
   "check": "Open the generated share link in an incognito session and confirm the design/prototype renders read-only",
   "source": "https://help.penpot.app/user-guide/prototyping-testing/prototyping/"
  },
  {
   "id": "cap-20",
   "group": "Deployment",
   "capability": "Self-host the full Penpot platform on your own infrastructure",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "docker compose (self-host install)",
    "ui": null
   },
   "check": "Run the documented docker install and reach the self-hosted instance's login page",
   "source": "https://penpot.app/self-host; https://help.penpot.app/technical-guide/getting-started/"
  },
  {
   "id": "cap-21",
   "group": "Admin",
   "capability": "Manage organizations, Admin Console and SSO for an Enterprise deployment",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Enterprise Admin Console"
   },
   "check": "Configure SSO in the Admin Console and confirm a member can log in via the SSO provider",
   "source": "https://help.penpot.app/user-guide/account-teams/; https://penpot.app/pricing"
  },
  {
   "id": "cap-22",
   "group": "Admin",
   "capability": "Enforce SCIM provisioning and a plugin allowlist (Enterprise governance controls)",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": "SCIM",
    "mcp": null,
    "cli": null,
    "ui": "Enterprise Admin Console"
   },
   "check": "Provision a user via SCIM and confirm their Penpot account is created/deactivated accordingly",
   "source": "https://penpot.app/pricing"
  },
  {
   "id": "cap-23",
   "group": "Admin",
   "capability": "Review audit logs of account/team activity",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Enterprise Admin Console"
   },
   "check": "Perform a tracked action (e.g. member removal) and confirm it appears in the audit log",
   "source": "https://penpot.app/pricing"
  },
  {
   "id": "cap-24",
   "group": "Admin",
   "capability": "Manage personal account settings and profile",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Your account settings"
   },
   "check": "Change a profile field and confirm it persists after reload",
   "source": "https://help.penpot.app/user-guide/account-teams/"
  }
 ],
 "attempts": [
  {
   "t": "01:30",
   "cap": "docs",
   "capability": "Find docs",
   "task": "Find API, MCP and integration docs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "help.penpot.app/technical-guide/integration (access tokens, webhooks, curl example), help.penpot.app/mcp/ (remote MCP at design.penpot.app/mcp/stream?userToken=), auto-generated RPC docs at design.penpot.app/api/_doc -> /api/main/doc (153 commands with param schemas), penpot.app/llms.txt 200 text/plain",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "01:30",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Register account headless via documented RPC prepare-register-profile + register-profile",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /api/main/methods/prepare-register-profile -> 200 {token}; POST register-profile {token} -> 200 {id:7eed092c-..., email:the agent's inbox}. No CAPTCHA, no bot check met. Both commands are listed in /api/main/doc.",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "03:40",
   "cap": "discovery",
   "capability": "MCP discovery",
   "task": "POST server/discover (2026-07-28) to design.penpot.app/mcp/stream",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "server/discover -> HTTP 400 JSON-RPC -32000 'Bad Request: Server not initialized' (legacy). initialize offering 2026-07-28 -> 200 SSE protocolVersion 2025-11-25, serverInfo penpot 1.0.0, Mcp-Session-Id issued. tools/list without auth -> 4 tools: execute_code, high_level_overview, penpot_api_info, export_shape. tools/call without userToken -> 'No userToken found in session context. Multi-user mode requires authentication.'",
   "notes": "",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "03:40",
   "cap": "discovery",
   "capability": "Agent discovery files",
   "task": "Probe ai-catalog, agent-card, server-card, PRM, auth.md, robots, markdown",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "penpot.app/.well-known/ai-catalog.json, agent-card.json, agent.json, mcp/server-card.json, ucp: 404 (nginx). design.penpot.app/mcp/stream/server-card -> 406. design.penpot.app/.well-known/oauth-protected-resource -> SPA HTML 200 (not JSON); path-suffixed variant 301 -> /404. auth.md, SKILL.md 404. penpot.app/robots.txt: no Content-Usage/Content-signal lines; User-agent * Disallow /api/ etc. design.penpot.app/robots.txt: User-agent * Disallow /api/ /js/ /uploads/. penpot.app/llms.txt 200 (links llms-full.txt on penpot.dev); help.penpot.app/llms.txt 404.",
   "notes": ""
  },
  {
   "t": "12:52",
   "cap": "verify",
   "capability": "Verify email",
   "task": "Receive Penpot verification mail and click link",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "register-profile 200 at 02:58:09Z; re-sent via second prepare-register-profile+register-profile at 03:03Z (200, same profile id). inbox read the agent's inbox polled 02:58-03:13Z: 'no mail for the agent's inbox'. Inbox itself receives mail (earlier mails from other services present with --all). Mail not received; the cause may be on either side.",
   "notes": "mail not received after ~15 min and one resend; cause may be on either side (Penpot sending or our inbox routing)",
   "quality": {
    "error_legibility": "silent"
   }
  },
  {
   "t": "12:52",
   "cap": "first_call",
   "capability": "Log in",
   "task": "login-with-password before verification",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "POST /api/main/methods/login-with-password -> 400 {\"type\":\"validation\",\"code\":\"wrong-credentials\"} with the password just registered (account not yet verified)",
   "notes": "error says wrong-credentials rather than 'email not verified': misleading",
   "quality": {
    "error_legibility": "vague",
    "recoverable": "no"
   }
  },
  {
   "t": "14:38",
   "cap": "verify",
   "capability": "Verify email",
   "task": "Receive Penpot verification mail and verify via documented verify-token RPC",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Mail 'Verify your Penpot account' from no-reply@penpot.app (Date 03:10:59Z, token iat 02:58:09Z = first registration) read from inbox at ~03:16Z; POST /api/main/methods/verify-token {token} -> 200, then login-with-password -> 200 isActive:true",
   "notes": "mail took ~13 min from sign-up to its Date header; arrived after the first 10-min check (logged as failed above). Cause of the delay unknown, may be on either side.",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "16:12",
   "cap": "credentials",
   "capability": "Get API credentials",
   "task": "Create personal access token via documented create-access-token RPC",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /api/main/methods/create-access-token {name, expiration:'720h'} with session cookie -> 200 {id, token, expiresAt 2026-11-05}. First tries with expiration '30d' and 'P30D' -> 400 params-validation (explain names :expiration and schema duration; OpenAPI says only format: duration).",
   "notes": "",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "yes",
    "docs_match": "match",
    "verify_route": "yes"
   }
  },
  {
   "t": "16:12",
   "cap": "first_call",
   "capability": "First authenticated API call",
   "task": "GET get-profile with Authorization: Token",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /api/main/methods/get-profile with 'Authorization: Token ••••' -> 200 profile id 7eed092c-... email the agent's inbox",
   "notes": "",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "16:12",
   "cap": "first_call",
   "capability": "First authenticated API call (integration guide path)",
   "task": "curl example from integration guide: GET /api/rpc/command/get-profile with token",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "GET and POST https://design.penpot.app/api/rpc/command/get-profile -> HTTP 403 cf-mitigated: challenge, 'Just a moment...' Cloudflare managed challenge, for our Web Bot Auth signed agent. The /api/main/methods/ path (the one in /api/_doc and OpenAPI servers) is not challenged.",
   "notes": "the exact curl from help.penpot.app/technical-guide/integration does not work for our signed agent",
   "quality": {
    "error_legibility": "vague",
    "recoverable": "yes"
   }
  },
  {
   "t": "16:33",
   "cap": "first_action",
   "capability": "First real action",
   "task": "Create a project and a design file in our team",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-project -> 200 id [id]; create-file -> 200 id [id] revn 0",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "17:17",
   "cap": "cap-01",
   "capability": "Create and edit vector designs",
   "task": "Add a board 'Home' with a rounded rect, then recolor and rename the rect",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "update-file add-obj (frame+rect) -> 200; mod-obj set fills/name -> 200; get-file revn 2 shows rect [id] name 'Primary Button' fills #E5484D inside board 'Home'",
   "notes": "update-file takes raw change ops with full geometry (selrect, points, transform); the OpenAPI schema for it is ~1 MB inline. Works, but an agent must construct internal file model.",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match",
    "idempotent": "no"
   }
  },
  {
   "t": "17:44",
   "cap": "cap-02",
   "capability": "Build interactive prototypes",
   "task": "Add board 'Details', click->navigate interaction with dissolve on the button, and a flow starting at 'Home'",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "update-file with JSON body: mod-obj set interactions -> HTTP 500 {type:server-error, code:assertion, explain: action-type must be one of #{:navigate ...}, value \"navigate\"} (JSON strings are not decoded to keywords inside set ops). Same change sent as application/transit+json with keywords -> 200; set-flow -> 200. get-file shows interactions [{eventType click, actionType navigate, destination Details}] and flow 'Main flow' startingFrame Home.",
   "notes": "Writing works, but only with Transit encoding (not described in the API docs). View-mode firing checked separately in the browser.",
   "quality": {
    "error_legibility": "vague",
    "recoverable": "yes",
    "docs_match": "drift",
    "verify_route": "yes"
   }
  },
  {
   "t": "17:55",
   "cap": "cap-07",
   "capability": "Comment on designs and reply",
   "task": "Open a comment thread on board 'Home', reply to it, resolve it, then list",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-comment-thread -> 200 id [id] seqn 1; create-comment -> 200; get-comments -> 2 comments with our ownerId and createdAt; get-comment-threads -> countComments 2; update-comment-thread-status isResolved -> 200",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "22:08",
   "cap": "cap-03",
   "capability": "Create reusable components",
   "task": "Make a 'Chip' main component and place a linked copy on board 'Home'",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "update-file (transit) add-obj main frame with componentId/mainInstance + add-component + add-obj copy with shapeRef -> 200. get-file: data.components has Chip (mainInstanceId [id]); copy [id] has componentId, componentFile, shapeRef -> main. Workspace in browser renders the main 'Chip' with the component icon and the copy in 'Home' (shots/008.png).",
   "notes": "the API has no 'instantiate component' call: the agent builds the copy shape tree and refs by hand",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "22:08",
   "cap": "cap-04",
   "capability": "Define and sync design tokens",
   "task": "Create token set 'brand' with color.primary, apply it to the button fill, then change the token value",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "set-token-set + set-token -> 200; get-file tokensLib shows brand.color.primary; mod-obj applied-tokens {fill: color.primary} -> 200; set-token value #E5484D -> #00AA55 -> 200 and tokensLib shows #00AA55, but the rect fills stay #E5484D in get-file and in the workspace render (shots/008.png). Token propagation to shapes is not done by the backend.",
   "notes": "defining tokens works headless; the 'sync to every element' part did not happen via the API",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match",
    "error_legibility": "silent"
   }
  },
  {
   "t": "23:22",
   "cap": "cap-02",
   "capability": "Build interactive prototypes",
   "task": "Check the API-made interaction fires in View mode",
   "route": "browser",
   "documented": true,
   "result": "partial",
   "verified": false,
   "evidence": "View mode (share link, section=interactions) shows flow 'Main flow' starting at Home and renders the button (shots/013.png); two clicks on the button in our agent's browser did not navigate to 'Details' (shots/015.png). Interaction is stored (get-file) but firing was not confirmed.",
   "notes": "could be our click or a missing attribute in the hand-built interaction; not confirmed either way",
   "quality": {
    "verify_route": "yes"
   }
  },
  {
   "t": "23:22",
   "cap": "cap-19",
   "capability": "Share a view-only link",
   "task": "Create a share link for Page 1 and open it without a session",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-share-link -> 200 id [id]; anonymous get-view-only-bundle {fileId, shareId} -> 200 permissions type share-link canRead true isLogged false; the /#/view?...&share-id= URL renders the board in View mode (shots/013.png)",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "23:50",
   "cap": "cap-15",
   "capability": "Register outbound webhooks",
   "task": "Register a team webhook and read it back; delivery not tested",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "create-webhook to a URL that does not answer 2xx -> HTTP 500 {type: server-error, code: webhook-validation} (a validation error sent as 500); with https://agentdrives.com/ (our own site, answers 200) isActive:false -> 200 id [id]; get-webhooks lists it. Delivery not tested: we have no webhook receiver of our own in this drive and did not use a third-party catcher.",
   "notes": "get-webhooks returns uri as a parsed object, create returns a string",
   "quality": {
    "error_legibility": "vague",
    "recoverable": "yes",
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "24:36",
   "cap": "cap-18",
   "capability": "Create a team, invite members, assign roles",
   "task": "Create a team, invite our second inbox as editor, accept as that user, promote to admin",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-team -> 200 [id]; create-team-invitations [the agent's inbox, our own inbox] role editor -> 200; invitation mail arrived; invitee signed up via prepare-register-profile with invitationToken, verified, verify-token(invitation) -> 200 state created; get-team-members lists an inbox canEdit; update-team-member-role admin -> 204; get-team-members shows isAdmin true",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "24:36",
   "cap": "cap-09",
   "capability": "Organize assets into shareable libraries",
   "task": "Publish the test file as a shared library and link it into a second file",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "set-file-shared isShared true -> 200; get-team-shared-files lists 'AgentDrives Test File'; create-file consumer [id]; link-file-to-library -> 200; get-file-libraries(consumer) returns 'AgentDrives Test File' (which holds component Chip)",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "24:42",
   "cap": "cap-17",
   "capability": "Organize work into projects and files",
   "task": "Create a second project, move a file into it, rename the project",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-project -> 200 [id]; move-files [consumer file] -> 204; get-project-files on new project lists 'AgentDrives Consumer File'; rename-project -> 204; get-projects shows 'AgentDrives Archive (renamed)'",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "24:47",
   "cap": "cap-24",
   "capability": "Manage personal account settings",
   "task": "Set profile language to en and read it back",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "get-profile before: lang ''; update-profile {fullname, lang en, theme default} -> 200; get-profile -> lang en",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "24:56",
   "cap": "cap-10",
   "capability": "Start a file from a template",
   "task": "Clone the built-in 'wireframing-kit' template into our project",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "get-builtin-templates -> 10+ ids; clone-template {projectId, templateId wireframing-kit} -> 200 SSE progress (import v1/metadata..sobjects) then end; get-project-files lists 'Wireframing kit v1.1' [id]; get-file-summary shows 66 components",
   "notes": "covers the built-in templates offered in-app; the penpot.app/libraries-templates hub items were not tried",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "25:42",
   "cap": "cap-12",
   "capability": "Export and import whole .penpot files",
   "task": "Export the test file as .penpot and re-import it into the second team",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "export-binfile {fileId, version 3} -> SSE, end event carries asset URI; download -> 200 application/zip 20165 bytes, 22 entries; import-binfile multipart into team 2 Drafts: with version=3 as a form field -> 400 params-validation (version must be integer 1|3, multipart gives string), without it -> SSE end with new file id [id]; get-file on it shows boards Home/Details, Primary Button, Chip main+copy and component Chip",
   "notes": "get-project-files answered Transit when the request had no Accept: application/json (content negotiation by Accept)",
   "quality": {
    "verify_route": "yes",
    "docs_match": "drift",
    "error_legibility": "clear",
    "recoverable": "yes"
   }
  },
  {
   "t": "29:03",
   "cap": "credentials",
   "capability": "Get MCP key",
   "task": "Create the MCP key via create-access-token type mcp and enable MCP",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-access-token {name, type: mcp} -> 200 type mcp; get-current-mcp-token -> token; Integrations page lists key 'agentdrives-mcp'. Enabling the MCP Server status was done in the browser (Your account > Integrations toggle; no documented API for the toggle).",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "29:03",
   "cap": "cap-01",
   "capability": "Create and edit vector designs (MCP)",
   "task": "Via remote MCP execute_code add a text and a circle to board 'Details', read back via API",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "remote MCP https://design.penpot.app/mcp/stream?userToken=•••• with the Penpot tab open in our agent's browser and plugin connected (File > MCP server, auto-connected after enabling): execute_code list shapes -> 8 names; execute_code createText+createEllipse appended to Details -> ids; get-file via REST shows 'MCP Text' (text) and 'MCP Circle' (circle) under 'Details'. Without an open tab: 'No Penpot instance connected for user token.'",
   "notes": "MCP needs a live browser tab running the plugin: a headless agent alone cannot use it",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match",
    "error_legibility": "clear"
   }
  },
  {
   "t": "29:03",
   "cap": "cap-11",
   "capability": "Export layers/boards to image",
   "task": "Export board 'Home' as PNG via the MCP export_shape tool",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "export_shape {shapeId Home, format png} -> MCP image content, decoded PNG 1815 bytes, 400x300, shows the red button and the yellow chip (export_home.png)",
   "notes": "needs the Penpot tab open with the MCP plugin connected",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "29:03",
   "cap": "cap-05",
   "capability": "Inspect a design for code/CSS handoff",
   "task": "Get CSS and measurements for 'Primary Button'",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "execute_code penpot.generateStyle([shape],{type:'css'}) -> CSS with left 40px, top 40px, width 160px, height 48px, background #E5484DFF, 8px radii; matches the values set via the API",
   "notes": "via the MCP server / Plugins API generateStyle; also needs the open tab. The REST API gives raw geometry (get-file) but no CSS.",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "29:10",
   "cap": "cap-16",
   "capability": "Personal access tokens",
   "task": "Generate a token and use it in place of the password",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "create-access-token -> token; every later call in this drive (create-project, update-file, comments, teams, export/import) used 'Authorization: Token ••••' with no cookie; get-access-tokens lists it",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "32:18",
   "cap": "pay",
   "capability": "Pay step",
   "task": "Probe agent payment rails and the upgrade path without paying",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "No 402 anywhere: x402./mpp./agents.penpot.app do not resolve; /.well-known/ucp -> 301 /404 (design) and 404 (penpot.app); OpenAPI has no x-payment-info; not found in the x402 Bazaar or mpp.dev/api/services. Billing API: only read calls (get-subscription-usage -> editors list; profile.subscription null). In the app, Your account > Subscription offers Unlimited $7/user/month and Enterprise $25 with 'TRY IT FREE FOR 14 DAYS'; the Unlimited button opens 'Apply Unlimited (trial)' with an editors count and CONTINUE; after CONTINUE our agent's browser came back to the subscriptions page, still Professional, and we could not see where checkout happens or whether a card is asked.",
   "notes": "checkout provider and card requirement unknown",
   "route_detail": "browser for the subscription page"
  },
  {
   "t": "32:45",
   "cap": "cleanup",
   "capability": "Clean up created data",
   "task": "Delete webhook, share link, MCP key, files, projects, second team",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "delete-webhook 204 (get-webhooks -> []), delete-share-link 204, delete-access-token 204, delete-file x4 204, delete-project x2 204, delete-team 204 (get-teams -> only Default). get-projects still listed the two deleted projects right after (soft delete, Penpot keeps deleted items recoverable for a period).",
   "notes": "",
   "quality": {
    "verify_route": "yes"
   }
  },
  {
   "t": "32:45",
   "cap": "cancel",
   "capability": "Cancel plan",
   "task": "No paid plan or trial was started",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": true,
   "evidence": "Account stayed on the free Professional plan (subscription page shows Professional; profile.subscription null); nothing to cancel",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "delete",
   "capability": "Delete account and data",
   "task": "Delete both accounts via the documented delete-profile RPC",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "delete-profile -> 204 for the invitee (session cookie) and for the main account (Authorization: Token). Afterwards login-with-password -> 400 wrong-credentials for both; get-profile with the old token -> 200 Anonymous User (token no longer valid).",
   "notes": "",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "32:45",
   "cap": "cap-06",
   "capability": "Co-edit a file in real time",
   "task": "Two accounts editing one file live",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "Not tried: needs two live browser sessions at once; we had a second account (team invitee) but no time left in the drive budget.",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "cap-13",
   "capability": "Install and run plugins",
   "task": "Install a plugin in a file",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "Not tried separately for lack of time. The MCP server itself runs as a Penpot plugin in the open tab (File > MCP server), which did load and run in our agent's browser (MCP attempt).",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "cap-14",
   "capability": "Build a custom plugin",
   "task": "Load a custom plugin manifest",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "Not tried for lack of time; Plugins API used indirectly through MCP execute_code (penpot.createText, generateStyle).",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "cap-21",
   "capability": "Admin Console and SSO (Enterprise)",
   "task": "Enterprise feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Subscription page: Enterprise $25/org member/month lists 'Native SAML/SSO and full Audit Trail logging', 'Granular plugin whitelisting'; our account is on the free Professional plan",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "cap-22",
   "capability": "SCIM and plugin allowlist (Enterprise)",
   "task": "Enterprise feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Subscription page: Enterprise $25/org member/month lists 'Native SAML/SSO and full Audit Trail logging', 'Granular plugin whitelisting'; our account is on the free Professional plan",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "cap-23",
   "capability": "Audit logs (Enterprise)",
   "task": "Enterprise feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Subscription page: Enterprise $25/org member/month lists 'Native SAML/SSO and full Audit Trail logging', 'Granular plugin whitelisting'; our account is on the free Professional plan",
   "notes": ""
  },
  {
   "t": "32:45",
   "cap": "cap-20",
   "capability": "Self-host Penpot",
   "task": "Docker install",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "no docker in the drive sandbox",
   "notes": ""
  }
 ],
 "stale": false,
 "icon": "/logos/penpot.png",
 "monitored": false,
 "verdict": "L3 · Does the work: our agent gets in on its own and makes its first design call. Sign-up needed no CAPTCHA; the verification mail arrived late, after a resend, for reasons unknown. The documented curl path for the first call hit a Cloudflare managed challenge, but our agent found a working RPC endpoint and got through to create a project and file, reading both back. Pricing showed Unlimited and Enterprise plans with a trial button, but checkout stayed hidden after continuing, so paying is unconfirmed. Account deletion worked cleanly, with no plan ever started.",
 "page": "https://agentdrives.com/tools/penpot?via=api"
}