OSS-first docs

These docs teach the open system first: contracts, generated surfaces, runtimes, governance, and incremental adoption. Studio shows up as the operating layer on top, not as the source of truth.

Host the Builder workbench

Use the reusable Builder workbench as the desktop control surface for snapshot loading, guided authoring, preview, readiness, export, and mobile review handoff.

What you'll build

  • A workspace snapshot fetch path.
  • A `BuilderWorkbench` host with action callbacks.
  • Runtime-mode aware preview/export controls plus mobile review links.

1) Fetch the workspace snapshot

The web shell already exposes a query path for the current Builder workspace snapshot. Your host should load it first, then refresh it after each successful command.

builder-workbench-controller.ts
export async function fetchBuilderSnapshot(workspaceId: string) {
  const response = await fetch(
    `/api/operate/builder/queries/builder.workspace.snapshot?workspaceId=${encodeURIComponent(workspaceId)}`,
    { cache: "no-store" }
  );
  if (!response.ok) {
    throw new Error("Failed to fetch Builder workspace snapshot.");
  }
  const payload = await response.json() as {
    ok: boolean;
    result: BuilderWorkspaceSnapshot;
  };
  if (!payload.ok) {
    throw new Error("Builder workspace snapshot query returned an error.");
  }
  return payload.result;
}

Expected output: one `BuilderWorkspaceSnapshot` containing workspace, plan, providers, runtime targets, preview, export, mobile review state, and the operator posture needed for local trust, lease, and comparison status.

2) Host the workbench and refresh on action

The simplest host pattern is local state plus a small action wrapper that executes one Builder command and then refreshes the snapshot.

BuilderWorkbenchHost.tsx
import {
  BuilderWorkbench,
  useBuilderWorkbenchState,
} from "@contractspec/module.builder-workbench/presentation";

const { snapshot, setSnapshot, promptDraft, setPromptDraft } =
  useBuilderWorkbenchState({
    workspace: initialSnapshot.workspace,
    initialSnapshot,
  });

async function runAction(commandKey: string, payload?: Record<string, unknown>) {
  await executeBuilderCommand({ commandKey, workspaceId, payload });
  setSnapshot(await fetchBuilderSnapshot(workspaceId));
}

<BuilderWorkbench
  snapshot={snapshot}
  promptDraft={promptDraft}
  onPromptDraftChange={setPromptDraft}
  onCapturePrompt={() =>
    runAction("builder.channel.receiveInbound", createPromptEnvelope(workspaceId, promptDraft))
  }
  onGenerateBlueprint={() => runAction("builder.blueprint.generate")}
  onCompilePlan={() => runAction("builder.plan.compile")}
  onCreatePreview={() => runAction("builder.preview.create", { runtimeMode: "hybrid" })}
  onRunReadiness={() => runAction("builder.preview.runHarness")}
  onPrepareExport={() => runAction("builder.export.prepare", { runtimeMode: "hybrid" })}
  onApproveExport={() => runAction("builder.export.approve")}
  onExecuteExport={() => runAction("builder.export.execute")}
  selectedExportRuntimeMode="hybrid"
/>;

Expected output: each successful action leaves the host with a fresh snapshot and keeps the workbench tabs aligned with current runtime state.

3) Persist Builder defaults in workspace config

The host should agree with the CLI and setup flows on the same control-plane defaults. For local or hybrid setups, keep the Builder API base URL, token env var, and local runtime metadata in `.contractsrc.json`.

.contractsrc.json
{
  "builder": {
    "enabled": true,
    "runtimeMode": "local",
    "bootstrapPreset": "local_daemon_mvp",
    "api": {
      "baseUrl": "https://api.contractspec.io",
      "controlPlaneTokenEnvVar": "CONTROL_PLANE_API_TOKEN"
    },
    "localRuntime": {
      "runtimeId": "rt_local_daemon",
      "grantedTo": "local:operator",
      "providerIds": ["provider.codex", "provider.local.model"]
    }
  }
}

4) Bootstrap providers and routing policy explicitly

Builder v3 treats provider routing as policy, not heuristic. Use the workspace bootstrap command as the single managed-first setup path instead of orchestrating provider registration in the app shell.

builder-bootstrap.ts
await executeBuilderCommand({
  commandKey: "builder.workspace.bootstrap",
  workspaceId,
  payload: {
    preset: "managed_mvp",
    includeLocalHelperProvider: true,
  },
});

Common command keys

  • builder.workspace.bootstrap
  • builder.channel.receiveInbound
  • builder.blueprint.generate
  • builder.plan.compile
  • builder.preview.create
  • builder.preview.runHarness
  • builder.export.prepare
  • builder.export.approve
  • builder.export.execute

Snapshot-backed operator details

  • local runtime trust and lease details
  • channel-action posture for mobile/operator follow-up
  • comparison posture and export readiness from the shared snapshot

5) Keep runtime mode explicit

Preview and export flows are runtime-mode aware. The host chooses between `managed`, `local`, and `hybrid` and passes that choice into preview or export commands instead of hiding it behind provider selection heuristics.

runtime-mode
const [selectedExportRuntimeMode, setSelectedExportRuntimeMode] =
  React.useState(resolveBuilderExportRuntimeMode(initialSnapshot));

await executeBuilderCommand({
  commandKey: "builder.preview.create",
  workspaceId,
  payload: {
    runtimeMode: selectedExportRuntimeMode,
  },
	});

6) Link mobile review flows

When a patch proposal, approval ticket, or incident needs operator follow-up away from the desktop workbench, deep-link into the mobile review route instead of inventing a separate data model.

mobile-review-path.ts
export function buildBuilderMobileReviewPath(
  workspaceId: string,
  cardId: string
) {
  return `/operate/builder/workspaces/${encodeURIComponent(workspaceId)}/mobile-review/${encodeURIComponent(cardId)}`;
}

Expected output: the same Builder workspace state stays visible from desktop workbench and mobile review surfaces.

7) Keep Connect adjacent, not embedded

Builder owns the authoring control plane. When Builder delegates into coding repositories, enable Connect in those target workspaces for context packs, mutation verification, replay, and review packets, but do not replace Builder contracts with Connect artifacts.

connect-init.sh
contractspec connect init --scope workspace