---
name: studio-config-units
description: Generate and manage ConfigUnit definitions for Studio AI platform — entity schemas, document types, chapters, orchestration, and definition sets. Use when creating or inspecting business document types (BRD, PRD, tech spec).
metadata:
  version: "0.1.21"
---

# studio-config-units

Generate complete ConfigUnit definitions for Studio AI platform. A ConfigUnit is the atomic deployment package that bundles an entity (data schema), document type (chapters + orchestration), and definition sets.

## Prerequisites

- Node.js >= 18
- `@ai-partner-x/aiko-studio-cli` installed globally:

```bash
npm install -g @ai-partner-x/aiko-studio-cli
```

## First-Time Setup

```bash
studio-cli login
```

Or for dev environments:

```bash
studio-cli login --api-base http://localhost:8080 --frontend http://localhost:5173
```

Check if already configured:

```bash
studio-cli config show 2>&1
```

If not configured, tell the user: "Please run `studio-cli login` to authenticate first."

## When to Use

Use this skill when you need to:
- Generate a new business document type (BRD, PRD, tech spec, etc.) for Studio AI
- Define the data model (entity + fields) and document structure (chapters + bindings) together
- Set up AI orchestration workflows (skeleton → creation → review)
- Review existing config unit definitions on the platform

## Core Concepts

### ConfigUnit

A ConfigUnit is the top-level container that aggregates:

| Component | Purpose |
|-----------|---------|
| `entity` | Data schema — fields, types, nested structures, relationships |
| `docType` | Document template — chapters, content bindings, orchestration nodes |
| `definitionSets` | Reusable standards/specs injected into AI prompts (optional) |

### Entity Fields

Each field has:
- `id` — **required for Studio admin JSON import** (UUID; every field and subField)
- `name` — Chinese display name
- `nameEn` — English identifier (used in code and API)
- `type` — `string`, `number`, `date`, `boolean`, `enum`, `object`, `array`, `ref`, `ref-array`
- `required` — whether mandatory
- `description` — AI generation context
- `enumValues` — (enum only) allowed values
- `subFields` — (object/array only) nested fields
- `refEntityId` — (ref/ref-array only) target entity UUID
- `referenceFields` — AI inference dependencies

> Note: `link` / `link-array` were the legacy names for `ref` / `ref-array` and have been retired from new content. Persisted legacy data with `type: "link"` is read-path tolerant (the deserializer normalizes to `ref`). Do not emit `link` in newly generated JSON.

### Document Type Chapters

Each chapter maps to an entity field and defines how content is rendered:
- `title` — chapter display title
- `entityFieldId` — bound entity field **UUID** (`""` when the chapter only aggregates multiple bindings)
- `dynamic` — if `true`, chapter expands per array item
- `titleFieldId` — (dynamic only) **subField UUID** used as dynamic title
- `contentBindings` — content blocks with `renderType`: `markdown`, `prototype`, `table`, `flowchart`, `sequence`, `er`, `gantt`, `mindmap`

### Orchestration Nodes

Define the AI-assisted document generation workflow:
- `skeleton` — derive document structure from prerequisites (e.g., BRD → PRD)
- `creation` — fill in detailed content for each chapter
- `resolution` — human review and refinement
- `loop` — iterative improvement cycles

### Inference Dependencies (referenceFields)

Fields can declare dependencies on other data for AI generation:
- `strategy: "inline"` — data injected directly into prompt (small, critical data)
- `strategy: "procedure"` — AI uses `read_entity` tool on demand (large data)
- `strategy: "link"` — follows `ref` / `ref-array` references to inject linked data

## UUID Generation (MANDATORY)

**CRITICAL: Never hand-craft UUIDs.** All `id` fields in generated JSON MUST use real UUIDs from `studio-cli uuid`.

Before generating any config unit JSON, batch-generate all needed UUIDs:

```bash
studio-cli uuid 30 --json
```

This outputs a JSON array of 30 valid v4 UUIDs. Assign them sequentially to entities, fields, subFields, chapters, contentBindings, nodes, etc.

Other usage patterns:

```bash
studio-cli uuid                   # single UUID
studio-cli uuid 10                # 10 UUIDs, one per line
studio-cli uuid 5 --prefix field  # labeled output for easy reference
```

**Why this matters:** Hand-crafted IDs like `ec11f041a-0000-...` have format errors (9-char first segment instead of 8) that cause database constraint violations.

## CLI Commands

### List config units

```bash
studio-cli config-units list --project-type-id <id> --format json
```

### Get config unit details

```bash
studio-cli config-units get <unit-id> --project-type-id <id> --format json
```

### Get full snapshot (entity + docType + definitions)

```bash
studio-cli config-units full <unit-id> --project-type-id <id> --format json
```

### Supporting commands

```bash
studio-cli project-types list --format json     # find project type IDs
studio-cli config-units full <id> --project-type-id <id> --format json  # inspect entity + docType schema
```

## Generate ConfigUnit JSON

When asked to generate a config unit, output JSON matching `ConfigUnitFullDTO`. **Canonical skill source lives in this repo under `studio-cli/skills/studio-config-units/`** (bundled with `@ai-partner-x/aiko-studio-cli`). Install into an IDE with `studio-cli install-skills` only — there is no separate sync command.

### 管理端「JSON 导入」契约（必读）

与 `studio-ai` 里部分 **e2e fixture** 不同：配置单元设计器里的导入是 `JSON.parse` 后直写表单，**必须**满足下列约束，否则会在保存/脏值检测时报错，或章节绑定丢失。

| 区域 | 要求 |
|------|------|
| **`entity.id`** | 实体根 `id`（UUID） |
| **`entity.fields[]` / `subFields[]`** | **每一项必须有 `id`（UUID）**。缺少时前端会对 `undefined` 调用 `.startsWith`，例如：`Cannot read properties of undefined (reading 'startsWith')`。 |
| **`refEntityId`** | 无引用时写 `""`（与 `EntityFieldConfig` 一致） |
| **`docType.id`** | 文档类型 `id`（UUID） |
| **`chapters[]`** | 每章有 `id`；`entityFieldId` 为绑定的实体字段 **UUID**，多绑定并列的「综述」类章节用 `entityFieldId: ""` |
| **`contentBindings[]`** | 每项有 `id`；**`entityFieldId` 必须为对应字段的 UUID** |
| **`dynamic: true`** | `titleFieldId` 为**子字段 UUID**（展示用标题），不得用 `titleFieldNameEn` |
| **`docType.systemPrompt`** | **强烈推荐**。为空则编译系统提示词时不会出现 `## 文档类型规范`，管理端「文档类型提示词」也无内容可展示。 |
| **`entityFieldNameEn`** | **不要用**：导入链路不识别，会导致 `entityFieldId` 为空、绑定失效 |

参考完整范例：仓库内 `.aiko-studio/schema/urs.json`（已按上述契约编写）。

### Complete JSON Schema（结构示意）

下列片段演示字段名与嵌套；生成真实文件时须为 **entity / 每个 field / 每个 subField / docType / 每章 / 每 binding / 每 node** 分配 `studio-cli uuid` 产出的 UUID，并补齐 `systemPrompt` 等上表项。

```json
{
  "entity": {
    "id": "<entity-uuid>",
    "name": "实体中文名",
    "nameEn": "EntityNameEn",
    "description": "实体用途描述",
    "fields": [
      {
        "id": "<field-uuid>",
        "name": "字段中文名",
        "nameEn": "fieldNameEn",
        "type": "string",
        "required": true,
        "description": "字段用途描述",
        "enumValues": [],
        "refEntityId": "",
        "subFields": []
      },
      {
        "id": "<field-uuid>",
        "name": "优先级",
        "nameEn": "priority",
        "type": "enum",
        "required": true,
        "description": "功能优先级",
        "enumValues": ["P0-必须", "P1-重要", "P2-期望"],
        "refEntityId": "",
        "subFields": []
      },
      {
        "id": "<field-uuid>",
        "name": "功能模块",
        "nameEn": "features",
        "type": "array",
        "required": true,
        "description": "功能模块列表",
        "enumValues": [],
        "refEntityId": "",
        "subFields": [
          {
            "id": "<subfield-uuid>",
            "name": "模块名称",
            "nameEn": "name",
            "type": "string",
            "required": true,
            "description": "模块名称",
            "enumValues": [],
            "refEntityId": "",
            "subFields": []
          },
          {
            "id": "<subfield-uuid>",
            "name": "业务逻辑",
            "nameEn": "logic",
            "type": "string",
            "required": true,
            "description": "业务逻辑描述",
            "enumValues": [],
            "refEntityId": "",
            "subFields": [],
            "referenceFields": [
              {
                "fieldId": "<source-field-uuid>",
                "entityId": "<source-entity-uuid-or-null>",
                "required": true,
                "strategy": "inline",
                "instruction": "参考设计规范中的交互标准"
              }
            ]
          },
          {
            "id": "<subfield-uuid>",
            "name": "原型",
            "nameEn": "prototype",
            "type": "string",
            "required": false,
            "description": "HTML 交互原型",
            "enumValues": [],
            "refEntityId": "",
            "subFields": []
          }
        ],
        "referenceFields": []
      },
      {
        "id": "<field-uuid>",
        "name": "关联BRD",
        "nameEn": "linkedBrd",
        "type": "ref",
        "required": false,
        "description": "关联的BRD文档",
        "enumValues": [],
        "refEntityId": "<target-entity-uuid>",
        "subFields": []
      }
    ]
  },
  "docType": {
    "id": "<doctype-uuid>",
    "name": "文档中文名",
    "icon": "file-text",
    "description": "文档用途描述",
    "contentMode": "structured",
    "systemPrompt": "文档类型级提示词（三层架构第二层）：角色、风格、编号规则、与 TOC 的配合方式等。",
    "prerequisites": [
      {
        "docTypeId": "<prerequisite-doc-type-uuid>",
        "required": true
      }
    ],
    "chapters": [
      {
        "id": "<chapter-uuid>",
        "title": "1. 概述章节",
        "entityFieldId": "<field-uuid>",
        "optional": false,
        "dynamic": false,
        "sortOrder": 0,
        "description": "章节描述",
        "contentBindings": [
          {
            "id": "<binding-uuid>",
            "label": "内容块标签",
            "entityFieldId": "<field-uuid>",
            "renderType": "markdown",
            "sortOrder": 0,
            "description": "AI 生成指引",
            "referenceFields": []
          }
        ],
        "subChapters": []
      },
      {
        "id": "<chapter-uuid>",
        "title": "2. 动态章节",
        "entityFieldId": "<array-field-uuid>",
        "titleFieldId": "<name-sub-field-uuid>",
        "optional": false,
        "dynamic": true,
        "sortOrder": 1,
        "description": "按数组字段动态展开",
        "contentBindings": [
          {
            "id": "<binding-uuid>",
            "label": "业务逻辑",
            "entityFieldId": "<sub-field-uuid>",
            "renderType": "markdown",
            "sortOrder": 0,
            "description": "模块的业务逻辑描述",
            "referenceFields": []
          },
          {
            "id": "<binding-uuid>",
            "label": "原型设计",
            "entityFieldId": "<sub-field-uuid>",
            "renderType": "prototype",
            "sortOrder": 1,
            "description": "模块的原型 HTML",
            "referenceFields": []
          }
        ],
        "subChapters": []
      }
    ],
    "nodes": [
      {
        "id": "<node-uuid>",
        "type": "skeleton",
        "title": "骨架推演",
        "description": "基于前置文档推导文档骨架",
        "required": true,
        "sortOrder": 0,
        "nodeSystemPrompt": "你是...",
        "feedback": {
          "activationMessage": "正在推演骨架...",
          "completionMessage": "骨架推演完成",
          "inputPlaceholder": "描述你的需求..."
        }
      },
      {
        "id": "<node-uuid>",
        "type": "creation",
        "title": "内容生成",
        "description": "逐章节生成详细内容",
        "required": true,
        "sortOrder": 1,
        "nodeSystemPrompt": "你是...",
        "feedback": {
          "activationMessage": "正在生成内容...",
          "completionMessage": "内容生成完成",
          "inputPlaceholder": "补充需求细节..."
        }
      },
      {
        "id": "<node-uuid>",
        "type": "resolution",
        "title": "文档评审",
        "description": "评审完整性和一致性",
        "required": true,
        "sortOrder": 2,
        "nodeSystemPrompt": "你是...",
        "feedback": {
          "activationMessage": "开始评审...",
          "completionMessage": "评审完成",
          "inputPlaceholder": "输入评审意见..."
        }
      }
    ]
  }
}
```

### Generation Rules

**UUID Rules (MUST follow):**
1. Run `studio-cli uuid <count> --json` FIRST to generate all UUIDs needed
2. Every `id` slot MUST use a UUID from the generated batch — NEVER hand-craft IDs
3. Count needed UUIDs: 1 entity + **every** field + **every** subField (recursive) + 1 docType + each chapter + each contentBinding + each orchestration node + definitionSet objects if any + extras

**Entity Rules:**
1. **Admin JSON import:** Every `entity.fields[]` and nested `subFields[]` entry MUST have `id` (UUID). Include `refEntityId: ""` when unused. Skipping `id` breaks the entity editor (`fieldToConfig` / `.startsWith`).
2. Every field must have `name`, `nameEn`, `type`, `required`
3. `description` is strongly recommended — it becomes AI generation context
4. `enumValues` is required when `type` is `enum` (use `[]` otherwise)
5. `subFields` is required when `type` is `array` or `object`
6. `refEntityId` is for `ref` / `ref-array` types (use UUIDs from existing entities)
7. `referenceFields` can be added to any field (including subFields) for AI inference dependencies
8. `referenceFields[].entityId` can be null when referencing a field within the same entity

**DocType Rules:**
1. **Admin JSON import:** Chapters and `contentBindings` use **`entityFieldId` / `titleFieldId` (UUIDs)**. Do not use `entityFieldNameEn` — the import path does not remap it.
2. Each chapter and each binding SHOULD have its own `id` (UUID). Dynamic chapters: `titleFieldId` = UUID of the title subfield (e.g. `name` / `title`), not the English name string alone.
3. **Document layer prompt:** Set `docType.systemPrompt` so the compiled system prompt includes `## 文档类型规范` and the admin UI can show “文档类型提示词”.
4. `prerequisites[].docTypeId` must reference existing doc type UUIDs
5. Chapter `entityFieldId` must reference a field from the ConfigUnit entity (or `""` for a multi-binding “overview” chapter)
6. For dynamic chapters (`dynamic: true`), `entityFieldId` must point to an `array` type field
7. Content binding `renderType` determines rendering:
   - `auto` — smart rendering: frontend auto-detects content type; AI can use `:::type` fences to explicitly mark blocks (see **Auto Render Mode** below)
   - `markdown` — general text (can also embed ` ```plantuml ` code blocks for server-rendered PlantUML diagrams)
   - `prototype` — HTML prototype (rendered in iframe)
   - `table` — Markdown table syntax (`| col | col |`)
   - `flowchart` — Mermaid flowchart (`graph TD` / `flowchart LR`)
   - `sequence` — Mermaid sequence diagram (`sequenceDiagram`)
   - `er` — Mermaid ER diagram (`erDiagram`)
   - `gantt` — Mermaid Gantt chart (`gantt`)
   - `mindmap` — Mermaid mind map (`mindmap`)
8. Binding-level `referenceFields` override entity field defaults

**PlantUML Diagram Pattern:**

For complex diagrams (swimlane activity diagrams, state machines, deployment diagrams), use PlantUML instead of Mermaid. The pattern is:

1. Set the content binding `renderType` to `"markdown"` (not a special type)
2. In the field `description`, instruct the AI to generate ` ```plantuml ` fenced code blocks within the Markdown content
3. The frontend automatically detects PlantUML code blocks and renders them via the server-side PlantUML service

Example field description for a flowchart field:
```
"description": "Must include: 1) swimlane activity diagram (multi-role collaboration); 2) state machine diagram (core object state transitions). Use ```plantuml``` code blocks, with a Markdown heading before each diagram."
```

Example `nodeSystemPrompt` PlantUML instructions:
```
- Swimlane activity diagrams: use |RoleName| syntax for lanes
- State machines: use `state "DisplayName" as s1` syntax, `[*]` for start/end
- Each PlantUML statement MUST be on its own line (use \\n in JSON strings)
- Never put more than 15 nodes in a single diagram; split into multiple diagrams if needed
```

**PlantUML Linter Auto-Fix (built-in):**

The system includes a `PlantUmlValidationHook` that automatically validates all PlantUML code blocks after `write_entity` calls:

- **Layer 1 (auto-fix):** Simple syntax errors (missing semicolons, missing newlines, literal `\\n`) are automatically corrected and written back to the database. The AI is unaware of these fixes.
- **Layer 2 (AI-driven fix):** Complex errors that cannot be auto-fixed are reported back to the AI via `plantuml_errors` in the tool result. The AI must then use `write_entity` with `old_text`/`new_text` to fix the problematic code blocks.

When writing `nodeSystemPrompt` for nodes that generate PlantUML, include format requirements (one statement per line, proper syntax) to minimize Layer 2 errors.

**Auto Render Mode (`renderType: "auto"`):**

Use `renderType: "auto"` when a field may contain mixed content types (text + diagrams + prototypes + tables). The frontend applies a three-tier resolution:

1. **`:::type` fences (AI explicit):** AI wraps content blocks in `:::type` ... `:::` fences
2. **Auto-detection:** HTML content → iframe; JSON array → table; ` ```plantuml ` / ` ```mermaid ` code blocks → diagram
3. **Fallback:** plain Markdown rendering

Supported fence types: `prototype` (or `html`), `table`, `plantuml`, `mermaid`

Example AI output for an `auto` field:
```
## Feature Overview

This module handles user authentication.

:::prototype
<html>
<body>
  <h1>Login Page</h1>
  <form><input placeholder="Email"/><button>Login</button></form>
</body>
</html>
:::

## Flow Diagram

` ` `plantuml
@startuml
participant "Frontend" as U
participant "Backend" as S
U -> S: POST /login
S --> U: 200 OK + JWT
@enduml
` ` `
```

When to use `auto` vs specific `renderType`:
- Use `auto` when AI-generated content may mix multiple types in a single field
- Use specific types (`markdown`, `prototype`, `table`) when the field always contains one type

**Orchestration Rules:**
1. Node `type`: `skeleton` (derive structure), `creation` (fill content), `resolution` (review), `loop` (iterate)
2. `nodeSystemPrompt` should be detailed and role-specific
3. `feedback` messages guide the user through the workflow
4. Nodes execute in `sortOrder` sequence; `required: true` nodes cannot be skipped

## Output Directory

All generated config unit JSON files **MUST** be written to the workspace directory:

```
.aiko-studio/schema/
```

File naming convention: `<nameEn-lowercase>.json` (e.g. `brd.json`, `prd.json`, `tech-spec.json`)

Before writing, ensure the directory exists:

```bash
mkdir -p .aiko-studio/schema
```

Example output path:

```
.aiko-studio/schema/brd.json
.aiko-studio/schema/prd.json
.aiko-studio/schema/design-system.json
```

## Workflow

### Generate a new config unit

1. Ask the user what business document they want to create (BRD, PRD, tech spec, etc.)
2. Query existing config units for reference (optional, if platform is running):
   ```bash
   studio-cli config-units list --project-type-id <id> --format json
   ```
3. If the new document depends on an existing one, read its schema from `.aiko-studio/schema/` or fetch from platform:
   ```bash
   studio-cli config-units full <id> --project-type-id <id> --format json
   ```
4. Design the entity schema (fields, types, subFields)
5. Design chapters that map to entity fields
6. Design orchestration nodes for the AI generation workflow
7. **Count all `id` slots** (entity + fields + subFields + docType + chapters + bindings + nodes + definitionSets + etc.) and batch-generate UUIDs:
   ```bash
   studio-cli uuid <total-count> --json
   ```
8. Assemble the JSON using the generated UUIDs and **管理端「JSON 导入」契约** (every field/subField `id`, chapter/binding `entityFieldId` UUIDs, `docType.systemPrompt`, no `entityFieldNameEn`)
9. **Write to `.aiko-studio/schema/<name>.json`** using the Write tool
10. Paste the JSON into the platform frontend to import

### Inspect an existing config unit

```bash
studio-cli config-units full <id> --project-type-id <id> --format json
```

### Cross-reference entities for linking

When generating a config unit that depends on another (e.g. PRD depends on BRD):

1. Read the dependency's JSON from `.aiko-studio/schema/<name>.json`
2. Extract entity field UUIDs for `referenceFields[].entityId/fieldId`
3. Extract doc type UUID for `prerequisites[].docTypeId`

Or query the platform:

```bash
studio-cli config-units full <unit-id> --project-type-id <id> --format json
```

## Real-World Examples

Reference fixtures are available at:
- `studio-ai/src/lib/e2e-pipeline-fixtures/brd.json` — BRD config unit (entity + docType)
- `studio-ai/src/lib/e2e-pipeline-fixtures/prd-detailed.json` — PRD config unit with full orchestration

These are **e2e / pipeline** JSON: they may omit per-field `id` or use `entityFieldNameEn` where the test harness normalizes them. **Do not copy that shape for Studio admin 「JSON 导入」** — follow **管理端「JSON 导入」契约** above or export a live unit via `studio-cli config-units full … --format json`.

Workspace example aligned with admin import: `.aiko-studio/schema/urs.json`.

## Safety Rules

- Generated JSON files go to `.aiko-studio/schema/` — never overwrite without user confirmation if the file already exists
- The CLI is strictly read-only — it cannot modify any platform data
- Never expose the API Key in logs, commits, or user-visible output
- All UUIDs for cross-references must come from existing entities/fields — read from `.aiko-studio/schema/` or query via the CLI
- When querying the platform, use `--format json` for parseable output
