Skip to main content

How it works

A plan is a flat list. Each line is one adapter op, filtered by environments:. Order is derived from references. Every value has a state (literal, resolved, pending, secret or kept), and the JSON output carries it explicitly so an agent never has to parse prose. Receipts live on an orphan git branch so CI runs, which start from nothing, can still see what the last run did. The store is an interface; local is the alternative, and a hosted one is where a control plane would plug in.

Verification without a cloud account

This repository was built and accepted entirely against a local fake cloud, because no real provider account was available during development.
  • packages/sim serves the API subsets the adapters use, with a chaos endpoint: latency, failing or hanging the next N requests matching a rule, 429 with Retry-After, lost responses after a successful write, pagination, Neon’s asynchronous operations, deployment lifecycles, and console-style drift (edit, delete, delete-and-recreate).
  • scenarios/ holds the acceptance scenarios: one YAML file per failure mode (anywhere under scenarios/, grouped by failure family such as mid-run failure, concurrency, drift, secrets, the deploy barrier and mistakes agents or humans make), each run end to end through the CLI by scenarios/runner.test.ts.
  • scenarios/journeys/ holds long system tests, one directory per dimension: among them a week of a team’s CI lifecycle, many actors at once on real git receipts (including SIGKILL mid-apply), providers misbehaving like real clouds, an agent driving Sponson only through MCP and JSON, humans editing consoles and refactoring plans, and every channel a secret could leak through (including the receipts branches’ history and PR comments).
  • property/ generates random plans, failures (including lost responses) and drift, and checks the invariants numbered at the top of property/engine.property.test.ts, among them that plan writes nothing and that nothing Sponson created survives a successful destroy, over hundreds of generated cases per run (SPONSON_PROPERTY_RUNS sets how many).
What the fake cannot prove is that the real APIs behave as assumed. The assumptions are numbered at the top of each provider’s routes file in packages/sim/src/routes/, each marked verified or unverified.
  • Checked against the published specifications (Vercel’s, Neon’s and Supabase’s Management API OpenAPI documents, Clerk’s Backend API OpenAPI and, for one list envelope, Clerk’s own SDKs; LaunchDarkly’s REST API reference): every HTTP call the adapters make (path, version, query parameters, request body, response fields read, statuses handled) and every assumption the specifications can settle. The check found and fixed real mismatches, among them Vercel’s deployment gitSource missing the required repository id and Neon connection strings hard-coded to a new project’s database and role names. docs/api-verification.md has the per-call tables, sources and dates.
  • Still needs a live run: what no specification states, such as how fast an env write reaches a deployment, which Neon requests answer 423 while a branch is created, whether a Neon branch being deleted still lists, which status Clerk gives a duplicate redirect URL, whether LaunchDarkly accepts re-adding a target its variation already serves, and how long a Supabase preview branch takes to come up. scenarios/contract.test.ts pins the critical ones: it runs against the sim by default and against the real APIs with pnpm test:live (see the file header for the required variables). It has not yet been run against real accounts.

Status

Format, engine, the built-in adapters and secret schemes, local and git-branch receipt stores, CLI, MCP server, GitHub Action, templates for GitLab CI/CD, CircleCI and Bitbucket Pipelines (run end to end in Docker against the fake cloud by scripts/try-ci-templates.sh: GitLab’s through gitlab-ci-local, CircleCI’s and Bitbucket’s job by job in their images with the hosts’ variables emulated; not yet run on the hosts themselves). Which providers are supported, and how to start with each: docs/providers.md. Not yet: LaunchDarkly rules (its individual targets are supported), a hosted approval inbox, garbage collection of scopes whose PR closed without the action running.