// @bun
import{CodeBlock as a}from"@contractspec/lib.design-system";import r from"@contractspec/lib.ui-link";import{ChevronRight as o}from"lucide-react";import{jsx as e,jsxs as t}from"react/jsx-runtime";function l(){return t("div",{className:"space-y-8",children:[t("div",{className:"space-y-3",children:[e("h1",{className:"font-bold text-4xl",children:"Build a first module bundle"}),e("p",{className:"text-lg text-muted-foreground",children:"Define one bundle spec, resolve it for a real route and preference profile, then render the resulting surface plan through the React host layer."})]}),t("div",{className:"card-subtle space-y-4 p-6",children:[e("h2",{className:"font-bold text-2xl",children:"What you'll build"}),t("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[e("li",{children:"One `ModuleBundleSpec` with a route and workbench surface."}),e("li",{children:"One `ResolvedSurfacePlan` from `resolveBundle`."}),e("li",{children:"One React host using `BundleProvider` and `BundleRenderer`."})]})]}),t("div",{className:"space-y-6",children:[t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"1) Define the bundle spec"}),e("p",{className:"text-muted-foreground text-sm",children:"The bundle spec is the durable contract. It owns route selection, surface shape, layouts, data recipes, and verification coverage for all seven preference dimensions."}),e(a,{language:"typescript",filename:"src/bundles/support.workbench.bundle.ts",code:`import { defineModuleBundle } from "@contractspec/lib.surface-runtime/spec/define-module-bundle";

export const SupportWorkbenchBundle = defineModuleBundle({
  meta: {
    key: "support.workbench",
    version: "0.1.0",
    title: "Support Workbench",
  },
  routes: [
    {
      routeId: "support-ticket",
      path: "/operate/support/tickets/:ticketId",
      defaultSurface: "ticket-workbench",
    },
  ],
  surfaces: {
    "ticket-workbench": {
      surfaceId: "ticket-workbench",
      kind: "workbench",
      slots: [
        { slotId: "primary", role: "primary", accepts: ["entity-section"], cardinality: "many" },
        { slotId: "assistant", role: "assistant", accepts: ["assistant-panel"], cardinality: "many", mutableByAi: true, mutableByUser: true },
      ],
      layouts: [
        { layoutId: "balanced", title: "Balanced", root: { type: "slot", slotId: "primary" } },
      ],
      data: [
        { recipeId: "ticket-core", source: { kind: "entity", entityType: "support.ticket" }, hydrateInto: "ticket" },
      ],
      verification: {
        dimensions: {
          guidance: "Surface can reveal walkthrough or inline help states.",
          density: "Layout supports compact and balanced detail modes.",
          dataDepth: "Resolver can hydrate summary or detailed ticket context.",
          control: "Advanced actions stay policy-gated.",
          media: "Surface supports text-first and hybrid assist modes.",
          pace: "Transitions and confirmations adapt to operator pace.",
          narrative: "Summary and evidence ordering stay explicit.",
        },
      },
    },
  },
});`}),e("p",{className:"text-muted-foreground text-sm",children:"Expected output: `defineModuleBundle` validates the route, surface, and verification dimensions at runtime."})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"2) Resolve the plan"}),e("p",{className:"text-muted-foreground text-sm",children:"Resolve against a real route, device, and preference profile. This is where the runtime chooses the surface, layout, bindings, and audit reasons."}),e(a,{language:"typescript",filename:"src/runtime/resolve-support-workbench.ts",code:`import { resolveBundle } from "@contractspec/lib.surface-runtime/runtime/resolve-bundle";

export const supportWorkbenchPlan = await resolveBundle(
  SupportWorkbenchBundle,
  {
    tenantId: "tenant_demo",
    workspaceId: "workspace_ops",
    actorId: "user_42",
    route: "/operate/support/tickets/123",
    params: { ticketId: "123" },
    query: {},
    device: "desktop",
    locale: "en",
    preferences: {
      guidance: "hints",
      density: "compact",
      dataDepth: "detailed",
      control: "advanced",
      media: "hybrid",
      pace: "balanced",
      narrative: "top-down",
    },
    capabilities: ["tickets.read", "tickets.update"],
  }
);`}),e("p",{className:"text-muted-foreground text-sm",children:"Expected output: a `ResolvedSurfacePlan` with `bundleKey`, `surfaceId`, `layoutId`, `bindings`, `adaptation`, and audit reasons."})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"3) Render the plan"}),e("p",{className:"text-muted-foreground text-sm",children:"The host app renders the resolved plan, not the raw spec. That keeps layout selection, overlays, and AI proposals downstream of the declared bundle contract."}),e(a,{language:"tsx",filename:"src/app/support/SurfaceHost.tsx",code:`import { BundleProvider, BundleRenderer } from "@contractspec/lib.surface-runtime/react";

export function SurfaceHost() {
  return (
    <BundleProvider plan={supportWorkbenchPlan}>
      <BundleRenderer assistantSlotId="assistant" />
    </BundleProvider>
  );
}`}),e("p",{className:"text-muted-foreground text-sm",children:"Expected output: the route renders according to the resolved layout root and slot plan instead of bespoke page assembly."})]}),t("div",{className:"card-subtle space-y-3 p-6",children:[e("h3",{className:"font-semibold text-lg",children:"Verification checks"}),t("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[e("li",{children:"The resolved `surfaceId` matches the route you expected."}),e("li",{children:"The `layoutId` is stable for the active view and preferences."}),e("li",{children:"The plan carries audit reasons and all seven adaptation dimensions."}),e("li",{children:"Assistant or overlay work stays within declared slots."})]})]})]}),t("div",{className:"flex items-center gap-4 pt-4",children:[t(r,{href:"/docs/specs/module-bundles",className:"btn-primary",children:["Back to module bundles ",e(o,{size:16})]}),e(r,{href:"/docs/specs/overlays",className:"btn-ghost",children:"Next: overlays"})]})]})}export{l as GuideFirstModuleBundlePage};
