---
stage: models
requires: components
outputs: "{wiki_dir}/models.md"
version: 2.1.0
estimated_tokens: 2000

guardrails:
  enforcement: active
  allowed_tools:
    - civyk-repoix
    - Read
    - Grep
    - Glob
    - Bash
  forbidden_actions:
    - "Delete any files"
    - "Modify any source files"
  read_only: true
---
# Stage 9: Data Models

Generate data model documentation covering entities, relationships, validation rules, and ER diagrams using Mermaid.

## Prerequisites

- Stage 08 completed (or skipped if no API)
- Mode: `{REPOIX_MODE}` (if "cli", convert MCP calls per AGENTS.md)
- Discovery cache loaded: LIMITS, COMPONENT_SUFFIXES, COMPONENT_PREFIXES

## Critical Rules

| Rule | Action |
|------|--------|
| API required | **MUST** verify {wiki_dir}/api.md exists (or stage skipped) |
| Search before skip | **MUST** search for models before deciding to skip |
| Mermaid only | **MUST** use Mermaid ER diagrams (no ASCII) |
| Skip if none | **MAY** skip if no models found (stateless apps) |

---

{{include:ai-cache-enforcement.md}}

{{include:understand-fast-path.md}}

---

**Anti-pattern (DO NOT):**

```text
User --+-- Order
       |
       +-- Profile
```

**Correct pattern:**

```mermaid
erDiagram
    User ||--o{ Order : places
    User ||--|| Profile : has
```

---

## Step 1: Verify Previous Stage

```bash
civyk-hatch deepwiki-update-state verify-stage --stage=09-models --wiki-dir={wiki_dir}
```

---

## Step 2: Find Model Definitions

**Load discovered patterns from discovery_cache:**

```bash
civyk-hatch deepwiki-update-state show --wiki-dir={wiki_dir}
# Extract: LIMITS = discovery_cache.project_size.limits
# Extract: COMPONENT_SUFFIXES = discovery_cache.file_patterns.component_patterns.suffixes
# Extract: COMPONENT_PREFIXES = discovery_cache.file_patterns.component_patterns.prefixes
```

**MUST search using YOUR DISCOVERED patterns (iterate over your actual COMPONENT_SUFFIXES):**

```text
# MANDATORY: For EACH suffix in YOUR COMPONENT_SUFFIXES that relates to data/models:
# Example if COMPONENT_SUFFIXES = ["Dto", "Entity", "Model", "Schema", "Repository", "Request", "Response"]:
search(action="symbols", query="%Dto", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="%Entity", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="%Model", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="%Schema", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="%Repository", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="%Request", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="%Response", kind="class", limit=LIMITS.symbols)
# ... continue for ALL data-related suffixes in YOUR discovered COMPONENT_SUFFIXES

# MANDATORY: For EACH prefix in YOUR COMPONENT_PREFIXES:
# Example if COMPONENT_PREFIXES = ["Base", "Abstract", "I"]:
search(action="symbols", query="Base%", kind="class", limit=LIMITS.symbols)
search(action="symbols", query="Abstract%", kind="class", limit=LIMITS.symbols)
# ... continue for ALL prefixes in YOUR discovered COMPONENT_PREFIXES
```

**[!] CRITICAL:** The patterns above are examples. You **MUST** use YOUR actual discovered COMPONENT_SUFFIXES and COMPONENT_PREFIXES from enumerate-index output, not these examples.

**ORM-specific patterns (language detection from PRIMARY_LANGUAGE):**

```text
# Java/Kotlin
search(action="code", query="@Entity|@Table|@Column", is_regex=true, source_only=true, limit=LIMITS.code)
# Python
search(action="code", query="models.Model|mongoose.Schema", is_regex=true, source_only=true, limit=LIMITS.code)
# Go/Rust
search(action="code", query="gorm.Model|#\\[derive.*Serialize", is_regex=true, source_only=true, limit=LIMITS.code)

# Model directories
files(pattern="**/models/**", include_stats=true, limit=LIMITS.files)
files(pattern="**/entities/**", include_stats=true, limit=LIMITS.files)
```

---

## Step 3: Explore Type Hierarchies

For each model class:

```text
# Get full hierarchy
symbol(action="hierarchy", fqn="<model_class>", direction="both", depth=5)

# Find all references
symbol(action="references", fqn="<model_class>")

# Get all fields
file(action="symbols", path="<model_file>", include_private=true, kinds=["property", "field", "method"])

# Find similar models and duplicate patterns
symbol(action="similar", fqn="<model_class>", similarity_threshold=0.6, limit=20)
quality(action="duplicates", source_only=true, similarity_threshold=0.6, limit=30)

# Read implementation
# Read file: <model_file>
# -> Extract fields with types
# -> Note validation constraints
# -> Identify relationships (ForeignKey, ManyToMany)

# Get imports
file(action="imports", path="<model_file>")

# Find tests
file(action="related", path="<model_file>", relationship_types=["test"])
```

---

## Step 4: Generate Documentation

Write `{wiki_dir}/models.md` using this template:

{{include:wiki/model-template.md}}

**Fill placeholders with:** Models summary, entities table, entity details (fields, types, constraints), Mermaid ER diagrams, validation rules, migration notes.

---

## Step 5: Complete Stage

```bash
civyk-hatch deepwiki-update-state stage --stage=09-models --status=completed --artifacts="{wiki_dir}/models.md" --wiki-dir={wiki_dir}
```

---

## Output Format

```text
===========================================================
  STAGE COMPLETE: 09-models

  Generated: {wiki_dir}/models.md
  Entities: {count}
  Relationships: {count}

  Next: Run {next_command}
===========================================================
```

---

## Edge Cases

| Scenario | Action |
|----------|--------|
| No ORM/models found | Skip stage (stateless app) |
| Multiple ORMs | Document each separately |
| NoSQL/Document store | Use document schema format |
| No relationships | Skip ER diagram |

---

## Next Stage

Run `{next_command}` - CLI auto-detects current stage and emits next prompt.
