var s=Object.defineProperty;var l=(t)=>t;function c(t,r){this[t]=l.bind(null,r)}var u=(t,r)=>{for(var i in r)s(t,i,{get:r[i],enumerable:!0,configurable:!0,set:c.bind(r,i)})};var m=(t,r)=>()=>(t&&(r=t(t=0)),r);import{CodeBlock as n}from"@contractspec/lib.design-system";import o from"@contractspec/lib.ui-link";import{jsx as e,jsxs as a}from"react/jsx-runtime";var d=["declared routes, surfaces, layouts, slots, actions, and data recipes","entity registries and field renderers for relation-heavy workbenches","preference-aware adaptation across guidance, density, data depth, control, media, pace, and narrative","auditable overlays and bounded AI patch proposals instead of free-form JSX generation"],p=["Define one `ModuleBundleSpec` with `defineModuleBundle` and keep the route and surface map explicit.","Resolve the bundle with `resolveBundle` for a real user, route, device, and preference profile.","Render the plan through `BundleProvider` and `BundleRenderer` so the UI stays downstream of the resolved spec.","Add overlays, policy hooks, planner proposals, and telemetry only after the base route resolves cleanly.","Pilot one dense domain first, such as a PM or operations workbench, before expanding the abstraction across the app."];function v(){return a("div",{className:"space-y-10",children:[a("section",{className:"space-y-3",children:[e("p",{className:"editorial-kicker",children:"Spec pack"}),e("h1",{className:"font-serif text-4xl tracking-[-0.04em] md:text-5xl",children:"Module bundles turn surface composition into a typed ContractSpec runtime instead of a pile of bespoke page code."}),a("p",{className:"max-w-3xl text-lg text-muted-foreground leading-8",children:["The implemented package is"," ",e("code",{children:"@contractspec/lib.surface-runtime"}),". It lets you define a bundle spec once, resolve it into a personalized surface plan, then render that plan through React without letting AI or per-route custom code bypass the declared system boundary."]})]}),a("section",{className:"editorial-proof-strip",children:[a("div",{className:"editorial-stat",children:[e("span",{className:"editorial-label",children:"Runtime promise"}),e("span",{className:"editorial-stat-value",children:"bundle spec → resolved surface plan"})]}),e("p",{className:"max-w-2xl text-muted-foreground text-sm leading-7",children:"The bundle spec owns what can render, where it can render, which preferences matter, and how overlays and AI proposals stay bounded."})]}),e("section",{className:"grid gap-4 md:grid-cols-2",children:d.map((t)=>a("article",{className:"editorial-panel space-y-3",children:[e("h2",{className:"font-semibold text-xl",children:"Bundle capability"}),e("p",{className:"text-muted-foreground text-sm leading-7",children:t})]},t))}),a("section",{className:"editorial-panel space-y-5",children:[a("div",{className:"space-y-2",children:[e("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"1) Define the bundle"}),e("p",{className:"text-muted-foreground text-sm leading-7",children:"Start with a typed route and one surface. The runtime validates that you declared routes, surfaces, and verification coverage for all seven preference dimensions."})]}),e(n,{language:"typescript",filename:"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" }],
      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.",
        },
      },
    },
  },
});`})]}),a("section",{className:"editorial-panel space-y-5",children:[a("div",{className:"space-y-2",children:[e("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"2) Resolve and render the plan"}),e("p",{className:"text-muted-foreground text-sm leading-7",children:"The app renders the resolved plan, not the raw spec. That keeps layout choice, data hydration, overlays, and AI proposals auditable."})]}),e(n,{language:"tsx",filename:"SurfaceHost.tsx",code:`import { BundleProvider, BundleRenderer } from "@contractspec/lib.surface-runtime/react";
import { resolveBundle } from "@contractspec/lib.surface-runtime/runtime/resolve-bundle";

const plan = 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"],
});

export function SurfaceHost() {
  return (
    <BundleProvider plan={plan}>
      <BundleRenderer assistantSlotId="assistant" />
    </BundleProvider>
  );
}`})]}),a("section",{className:"grid gap-5 lg:grid-cols-2",children:[a("article",{className:"editorial-panel space-y-4",children:[e("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"Adoption loop"}),e("ol",{className:"list-inside list-decimal space-y-3 text-muted-foreground text-sm leading-7",children:p.map((t)=>e("li",{children:t},t))})]}),a("article",{className:"editorial-panel space-y-4",children:[e("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"Guardrails that matter"}),a("ul",{className:"editorial-list",children:[a("li",{children:[e("span",{className:"editorial-list-marker"}),e("span",{children:"Do not stuff this behavior back into `lib.ui-kit`."})]}),a("li",{children:[e("span",{className:"editorial-list-marker"}),e("span",{children:"Do not let AI invent undeclared components or mutate raw DOM state."})]}),a("li",{children:[e("span",{className:"editorial-list-marker"}),e("span",{children:"Keep third-party UI libraries behind adapter subpaths only."})]}),a("li",{children:[e("span",{className:"editorial-list-marker"}),e("span",{children:"Every surface still needs explicit verification coverage for the seven preference dimensions."})]})]})]})]}),a("section",{className:"editorial-panel space-y-4",children:[e("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"Continue with overlays and runtime architecture"}),e("p",{className:"text-muted-foreground text-sm leading-7",children:"Once the bundle resolves deterministically, move into safe customization and the wider architecture that surrounds it."}),a("div",{className:"flex flex-wrap gap-3",children:[e(o,{href:"/docs/specs/overlays",className:"btn-primary",children:"Overlays"}),e(o,{href:"/docs/architecture",className:"btn-ghost",children:"Architecture overview"})]})]})]})}export{v as SpecsModuleBundlesPage};
