> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oktolabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture & mockups

> Reference for the 17 MCP tools that capture system architecture (entities, interfaces, diagrams) and screen mockups across ideations, refinements, specs, and cards — including the validate-then-write authoring loop and the spec-to-card propagation snapshots.

# Architecture & mockups

Pulse exposes **17 of its 216 MCP tools** for visual design artifacts:

* **12 architecture-design tools** (`server.py:6824–7503`) — structured system designs with entities, interfaces, and diagrams (Excalidraw, Mermaid, draw\.io, SVG, PNG).
* **5 screen-mockup tools** (`server.py:9436–9710`) — HTML+Tailwind page mockups, modals, drawers, popovers, and panels.

Both artifact types attach to **any pipeline entity** — ideation, refinement, spec, or card — and both have a dedicated copy tool that takes a deep-copy snapshot from a spec onto a card so an implementer's context is self-contained.

Source-of-truth citations: `okto-pulse-feature-inventory.md:378–410` and `:429–445`.

***

## When to use which

| Artifact                | Captures                                                                                    | Authoring tools                                                                                      |
| ----------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Architecture Design** | Services, modules, databases, queues, events, runtime boundaries, API contracts, data flows | Schema-validated payload (`entities` + `interfaces` + `diagrams`), with optional Excalidraw imports. |
| **Screen mockup**       | A single page, modal, drawer, popover, or panel rendered as sanitized HTML+Tailwind.        | Free-form HTML; supports text annotations from reviewers.                                            |

Use **architecture designs** to encode runtime topology and ownership boundaries that downstream cards must respect. Use **screen mockups** for visual UI references the implementer renders against. They are independent — one spec can have both.

***

## Architecture designs

### Authoring loop

The architecture model is critiqued by the server before it accepts a write. Skip the validation step and you get rejected with contextual paths like `entities[0].name` or `diagrams[0].adapter_payload.elements[2].linkedEntityId` — fix the cited field and retry.

The recommended loop for non-trivial payloads:

<Steps>
  <Step title="Fetch the schema once per session">
    `okto_pulse_get_architecture_design_schema` returns allowed enums, entity/interface contracts, Excalidraw adapter rules, bad and good examples, and a complete minimal payload.

    ```text theme={null}
    Input:
      board_id: "brd_abc123"

    Output (truncated):
    {
      "success": true,
      "schema": {
        "entity_types": ["web_app", "mobile_app", "api", "service", "database",
                         "queue", "topic", "external_system", ...],
        "interface_directions": ["source_to_target", "target_to_source",
                                 "bidirectional", "none"],
        "connection_types": ["direct", "elbow"],
        ...
      }
    }
    ```
  </Step>

  <Step title="Dry-run critique">
    `okto_pulse_validate_architecture_design_payload` (`server.py:6933`) runs the same critique the create/update path runs but persists nothing. It returns:

    * `valid` — whether the payload would be rejected
    * `issues` — blocking errors with JSON paths
    * `warnings` — non-blocking gaps that hurt downstream clarity
    * `suggested_fixes` — concrete corrections for common mistakes
    * `summary` — counts of entities, interfaces, diagrams, elements, links

    Pass `parent_type` + `parent_id` for create-mode validation. Pass `design_id` (and only the fields you intend to change) for update-mode — omitted fields are merged from the existing design before critique.
  </Step>

  <Step title="Persist after `valid: true`">
    Call `okto_pulse_add_architecture_design` (`server.py:7049`) or `okto_pulse_update_architecture_design` (`server.py:7207`) with the same payload. Warnings are not blockers, but each one usually marks a detail a downstream implementer or validator would otherwise have to guess.
  </Step>
</Steps>

<Warning>
  **Specs are locked once validation passes.** Attempting to add or update an architecture design on a spec whose current validation `outcome == "success"` returns `"Spec is locked because validation passed. Move it back to draft or approved to edit architecture."` Move the spec back to `draft` or `approved` first.
</Warning>

### Tool reference

| Tool                                                | Line | Purpose                                                                                                                                                         |
| --------------------------------------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `okto_pulse_get_architecture_design_schema`         | 6905 | Returns the JSON schema, examples, and enums. Call once per session.                                                                                            |
| `okto_pulse_validate_architecture_design_payload`   | 6933 | Dry-run critique. Returns `valid`, `issues`, `warnings`, `suggested_fixes`, `summary`. Persists nothing.                                                        |
| `okto_pulse_list_architecture_designs`              | 6824 | List designs for an `ideation` / `refinement` / `spec` / `card`. Pass `include_payloads="true"` to embed diagram bytes (heavier, requires `render` permission). |
| `okto_pulse_get_architecture_design`                | 6870 | Get one design by ID. `include_payloads` honored as above.                                                                                                      |
| `okto_pulse_add_architecture_design`                | 7049 | Create a design with `title`, `global_description`, and any of `entities` / `interfaces` / `diagrams` (JSON arrays or native lists).                            |
| `okto_pulse_update_architecture_design`             | 7207 | Partial update. Omitted fields are left unchanged. `change_summary` is recorded on the new version.                                                             |
| `okto_pulse_delete_architecture_design`             | 7298 | Hard delete.                                                                                                                                                    |
| `okto_pulse_import_excalidraw_architecture_diagram` | 7329 | Import an Excalidraw JSON scene. Pass `replace_diagram_id` to overwrite an existing diagram, or omit to append.                                                 |
| `okto_pulse_dump_architecture_diagram`              | 7408 | Load a diagram payload through its adapter and return the raw payload plus an adapter-formatted dump string.                                                    |
| `okto_pulse_copy_architecture_to_card`              | 7460 | Deep-copy snapshot from spec → card. Empty `design_ids` copies all.                                                                                             |
| `okto_pulse_archive_tree`                           | 6733 | Cascading soft-delete of an entity and its descendants.                                                                                                         |
| `okto_pulse_restore_tree`                           | 6777 | Reverse of `archive_tree`.                                                                                                                                      |

### Payload anatomy

`okto_pulse_add_architecture_design` accepts three structured arrays.

#### `entities` — runtime boundaries

Categorical `entity_type` plus a concrete `name`. The API rejects payloads where `name` duplicates `entity_type` after normalization (e.g. `name="API"`, `entity_type="api"`) because ownership and task boundaries become ambiguous.

```json theme={null}
[
  {
    "id": "entity-web-app",
    "name": "Customer Portal",
    "entity_type": "web_app",
    "responsibility": "Collects checkout input and displays order status.",
    "technologies": ["React", "Vite"]
  },
  {
    "id": "entity-checkout-api",
    "name": "Checkout API",
    "entity_type": "api",
    "responsibility": "Validates checkout commands and orchestrates payment authorization.",
    "technologies": ["FastAPI", "SQLAlchemy"]
  },
  {
    "id": "entity-orders-db",
    "name": "Orders DB",
    "entity_type": "database",
    "responsibility": "Persists orders, payment state, and idempotency keys.",
    "technologies": ["PostgreSQL"]
  }
]
```

#### `interfaces` — contracts on the wire

`endpoint` is optional but recommended (API path, RPC method, event name, queue name). `direction` must be one of `source_to_target`, `target_to_source`, `bidirectional`, `none`.

Interfaces do not own source/target — diagram connections do, via `sourceElementId` / `targetElementId`.

```json theme={null}
[
  {
    "id": "interface-create-order",
    "name": "Create order",
    "endpoint": "POST /orders",
    "description": "Customer Portal sends a checkout request to Checkout API.",
    "direction": "source_to_target",
    "protocol": "REST",
    "contract_type": "OpenAPI",
    "request_schema": {"type": "object", "required": ["cart_id"]},
    "response_schema": {"type": "object", "required": ["order_id"]}
  }
]
```

#### `diagrams` — visualization

Excalidraw is first-class. Edges link to interfaces via `linkedInterfaceIds` (one connector can carry several contracts). `connectionType` accepts only `"direct"` and `"elbow"` — `"curved"` is rejected.

```json theme={null}
[
  {
    "id": "diagram-runtime-context",
    "title": "Runtime context",
    "diagram_type": "context",
    "format": "excalidraw_json",
    "adapter_payload": {
      "type": "excalidraw",
      "version": 2,
      "elements": [],
      "appState": {},
      "files": {}
    }
  }
]
```

### Excalidraw round-trip

Authoring agents can ship a complete Excalidraw scene without touching the structured arrays first.

```text theme={null}
Input to okto_pulse_import_excalidraw_architecture_diagram:
  board_id: "brd_abc123"
  design_id: "ad_7f3a"
  title: "Runtime context (v2)"
  payload_json: { "type": "excalidraw", "elements": [...], "appState": {...} }
  diagram_type: "context"

Output:
{
  "success": true,
  "architecture_design": {
    "id": "ad_7f3a",
    "version": 4,
    "diagrams": [
      { "id": "dg_91", "title": "Runtime context (v2)",
        "format": "excalidraw_json", "diagram_type": "context", ... }
    ],
    ...
  }
}
```

To export, pair `okto_pulse_dump_architecture_diagram` with the diagram ID — it loads the payload through its adapter and returns both the raw payload and an adapter-formatted `dump` string.

***

## Screen mockups

### Tool reference

| Tool                              | Line | Purpose                                                                                                                                                                |
| --------------------------------- | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `okto_pulse_add_screen_mockup`    | 9436 | Add a screen to any entity. `screen_type` ∈ `page` / `modal` / `drawer` / `popover` / `panel`. Script tags and `on*` event attributes are stripped before persistence. |
| `okto_pulse_update_screen_mockup` | 9502 | Partial update — empty strings mean "no change".                                                                                                                       |
| `okto_pulse_annotate_mockup`      | 9561 | Append a reviewer annotation (text + `author_id`) to an existing screen.                                                                                               |
| `okto_pulse_list_screen_mockups`  | 9620 | Paginated list. `screen_type` filter optional; `limit` capped at 200.                                                                                                  |
| `okto_pulse_delete_screen_mockup` | 9667 | Remove one mockup.                                                                                                                                                     |

### `entity_type` is universal

All five screen-mockup tools accept `entity_type` ∈ `spec` / `ideation` / `refinement` / `card` (default `spec`). The same shape works whether you are sketching a page during ideation discovery, locking it on a spec, or attaching the final reference to an implementation card.

### Authoring example

```text theme={null}
Input to okto_pulse_add_screen_mockup:
  board_id:    "brd_abc123"
  entity_id:   "spec_XYZ"
  entity_type: "spec"
  title:       "Checkout — payment step"
  screen_type: "page"
  description: "Shown after cart review when the user clicks Pay."
  html_content: "<div class='p-6 max-w-md mx-auto bg-white rounded-xl shadow'>...</div>"

Output:
{
  "success": true,
  "entity_type": "spec",
  "screen": {
    "id": "sm_a1b2c3d4",
    "title": "Checkout — payment step",
    "description": "Shown after cart review when the user clicks Pay.",
    "screen_type": "page",
    "html_content": "<div class=\"p-6 max-w-md mx-auto bg-white rounded-xl shadow\">...</div>",
    "annotations": [],
    "order": 0
  }
}
```

<Note>
  The HTML sanitizer drops `<script>` blocks and any `on*` event attribute (`onclick`, `onload`, etc.). Style classes, inline `style` attributes, and Tailwind utilities pass through untouched.
</Note>

### Annotations

Reviewers add design notes without editing the HTML. Each annotation gets a stable `id` and records the `author_id`.

```text theme={null}
Input to okto_pulse_annotate_mockup:
  board_id:  "brd_abc123"
  entity_id: "spec_XYZ"
  screen_id: "sm_a1b2c3d4"
  text:      "Show the saved-card option above the new-card form by default."

Output:
{
  "success": true,
  "annotation": {
    "id": "an_e5f6g7h8",
    "text": "Show the saved-card option above the new-card form by default.",
    "author_id": "agent_ux_lead"
  }
}
```

***

## Spec → card propagation

When a sprint slices a spec into implementation cards, attach the relevant architecture and mockup context to each card so the implementer's view is self-contained. Two tools snapshot from the spec onto the card.

| Tool                                   | Line | What it copies                                                                                                                |
| -------------------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------- |
| `okto_pulse_copy_architecture_to_card` | 7460 | Architecture designs as deep-copy snapshots (preserves provenance to the source spec). Empty `design_ids` copies all.         |
| `okto_pulse_copy_mockups_to_card`      | 7504 | Screen mockups onto `card.screen_mockups`. Empty `screen_ids` copies all. Existing mockups on the card are preserved (by ID). |

Both tools accept multi-value IDs as a native list (`["scr_a", "scr_b"]`), a JSON string, or pipe-separated. Comma-only input is rejected — see `okto_pulse.core.mcp.helpers.coerce_to_list_str` (`okto-pulse-feature-inventory.md:395`).

```text theme={null}
Input to okto_pulse_copy_mockups_to_card:
  board_id: "brd_abc123"
  spec_id:  "spec_XYZ"
  card_id:  "card_001"
  screen_ids: ["sm_a1b2c3d4"]

Output:
{
  "success": true,
  "copied": 1,
  "total_on_card": 1
}
```

This is the **mandatory card-level attachment pattern** — agents reading `okto_pulse_get_task_context` see the architecture and mockups inline rather than chasing pointers back to the spec.

***

## Permissions

All architecture and mockup tools resolve through the granular permission registry (`server.py:_mcp_check_architecture_permission` and `Permissions.SPECS_UPDATE`). The actions checked per call:

| Tool family                                   | Permission action                        |
| --------------------------------------------- | ---------------------------------------- |
| `list` / `get` (without payloads)             | `read` on parent type                    |
| `list` / `get` (with `include_payloads=true`) | `render` on parent type                  |
| `add` / `update` / `import`                   | `create` / `edit` on parent type         |
| `delete`                                      | `delete` on parent type                  |
| `copy_*_to_card`                              | dedicated `architecture_copy` permission |
| Screen mockups (all writes)                   | `Permissions.SPECS_UPDATE`               |

A blocked call returns `{"error": "FORBIDDEN", "message": "...", ...}` — flip the agent's permission preset in **Board → Agents → Edit**.

See [Permissions](/concepts/pipeline) for the preset reference.

***

## Errors

Architecture and mockup writes return the standard MCP error envelope:

```json theme={null}
{
  "error": "VALIDATION_ERROR",
  "message": "entities[0].name duplicates entity_type after normalization.",
  "detail": {"path": "entities[0].name", "value": "api"}
}
```

Common codes for this domain:

| Code               | Meaning                                     | Most common cause                                                                                                    |
| ------------------ | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `VALIDATION_ERROR` | Payload rejected by critique                | Skipped the dry-run; check `entities[*].name`, `interfaces[*].direction`, `diagrams[*].adapter_payload.elements[*]`. |
| `CONFLICT`         | Spec is locked                              | Validation `outcome=success` — move spec back to `draft` or `approved`.                                              |
| `NOT_FOUND`        | Wrong board                                 | Design or screen exists on a different board.                                                                        |
| `FORBIDDEN`        | Permission preset doesn't allow this action | See permission table above.                                                                                          |

***

## Next steps

<CardGroup cols={2}>
  <Card title="MCP reference index" href="/reference/mcp">
    All 216 tools across 8 domains.
  </Card>

  <Card title="ADLC pipeline" href="/concepts/sdlc-flow">
    Where architecture and mockups attach in the ideation → spec → card flow.
  </Card>
</CardGroup>
