# Schema $ref Resolution Issue

**Status:** Bug in Symbols
**Affects:** ConeIdentifier and any other enum types with $ref
**Date:** 2025-12-16

## Problem

Symbols is not resolving `$ref` references when displaying schemas. This causes enum types like `ConeIdentifier` to show only the description without type information.

## Example

**What Symbols shows:**
```json
{
  "params": {
    "properties": {
      "identifier": {
        "description": "Cone identifier (provide either name or id)"
      },
      "prompt": {
        "type": "string"
      }
    }
  }
}
```

**What Substrate actually sends:**
```json
{
  "params": {
    "properties": {
      "identifier": {
        "$ref": "#/$defs/ConeIdentifier",
        "description": "Cone identifier (provide either name or id)"
      },
      "prompt": {
        "type": "string"
      }
    }
  }
}
```

**The actual ConeIdentifier definition (in `$defs`):**
```json
{
  "$defs": {
    "ConeIdentifier": {
      "description": "Identifier for a cone - either by name or UUID",
      "oneOf": [
        {
          "properties": {
            "by_name": {
              "properties": {
                "name": {
                  "description": "Cone name (supports partial matching)",
                  "type": "string"
                }
              },
              "required": ["name"],
              "type": "object"
            }
          },
          "required": ["by_name"],
          "type": "object"
        },
        {
          "properties": {
            "by_id": {
              "properties": {
                "id": {
                  "description": "Cone UUID",
                  "format": "uuid",
                  "type": "string"
                }
              },
              "required": ["id"],
              "type": "object"
            }
          },
          "required": ["by_id"],
          "type": "object"
        }
      ]
    }
  }
}
```

## Root Cause

Symbols' schema display/CLI generation doesn't follow `$ref` pointers to inline the referenced type definitions.

## Expected Behavior

When displaying a schema with `$ref`, Symbols should:

1. Look up the reference path (e.g., `#/$defs/ConeIdentifier`)
2. Replace the `$ref` with the actual type definition
3. Display the full type information including `oneOf` variants

## Suggested Fix

In the schema processing code, add a function to resolve refs:

```haskell
resolveRef :: Value -> Value -> Value
resolveRef rootSchema schemaNode =
  case schemaNode ^? key "$ref" . _String of
    Just refPath ->
      let resolved = followRefPath rootSchema refPath
      in mergeWithDescription schemaNode resolved
    Nothing -> schemaNode

followRefPath :: Value -> Text -> Value
followRefPath root path =
  -- Parse "#/$defs/ConeIdentifier" -> ["$defs", "ConeIdentifier"]
  let parts = T.splitOn "/" (T.drop 2 path)  -- drop "#/"
  in foldl' (\v p -> v ^?! key p) root parts

mergeWithDescription :: Value -> Value -> Value
mergeWithDescription original resolved =
  -- Keep description from original if present, merge with resolved
  case original ^? key "description" of
    Just desc -> resolved & _Object . at "description" ?~ desc
    Nothing -> resolved
```

Or in a more imperative style:

```python
def resolve_refs(schema, root_schema=None):
    if root_schema is None:
        root_schema = schema

    if isinstance(schema, dict):
        if "$ref" in schema:
            ref_path = schema["$ref"]  # e.g., "#/$defs/ConeIdentifier"
            resolved = follow_ref(root_schema, ref_path)
            # Preserve description if present
            if "description" in schema:
                resolved = {**resolved, "description": schema["description"]}
            return resolve_refs(resolved, root_schema)
        else:
            return {k: resolve_refs(v, root_schema) for k, v in schema.items()}
    elif isinstance(schema, list):
        return [resolve_refs(item, root_schema) for item in schema]
    else:
        return schema

def follow_ref(schema, ref_path):
    # "#/$defs/ConeIdentifier" -> ["$defs", "ConeIdentifier"]
    parts = ref_path.lstrip("#/").split("/")
    result = schema
    for part in parts:
        result = result[part]
    return result
```

## Verification

Run this test to see the actual schema from Substrate:

```bash
cargo test --test rpc_integration test_cone_identifier_schema -- --nocapture
```

Output shows the complete ConeIdentifier definition with `oneOf` and both variants.

## Impact

Without this fix:
- Users can't see what values are valid for `identifier` field
- CLI can't generate proper argument parsing for enum types
- Documentation is incomplete

## Related

- ConeIdentifier is a tagged enum used in: `cone_get`, `cone_delete`, `cone_chat`, `cone_set_head`
- Same issue would affect any future enum types with `$ref`
