# Details Edit Protocol

This document describes the WebSocket message protocol for reading and editing the `details` field of category items (indicators, strategies, research scripts) from the web client.

## Background

Every category item stored in the sandbox has a `details` field: a full markdown description of the implementation with enough detail that another coding agent could reproduce the code from it alone. The web client can display this field, allow the user to edit it in plain text, and submit the revised version — the gateway then diffs the old vs new details and instructs the appropriate subagent to update the Python code accordingly.

The `details` field is intentionally **filtered out of the workspace `_types` stores** (see `mcp-tool-wrapper.ts:filterTypeStoreState`) because it can be several kilobytes of markdown. The read/update protocol below provides direct, on-demand access.

---

## Message Flow

### 1. Read Details

**Client → Server**
```json
{
  "type": "read_details",
  "category": "indicator" | "strategy" | "research",
  "name": "My Indicator Name"
}
```

**Server → Client (success)**
```json
{
  "type": "details_data",
  "category": "indicator",
  "name": "My Indicator Name",
  "details": "## My Indicator\n\nFull markdown description..."
}
```

**Server → Client (error)**
```json
{
  "type": "details_error",
  "category": "indicator",
  "name": "My Indicator Name",
  "error": "Item not found or has no details"
}
```

---

### 2. Submit Updated Details

**Client → Server**
```json
{
  "type": "update_details",
  "category": "indicator" | "strategy" | "research",
  "name": "My Indicator Name",
  "details": "## My Indicator\n\nRevised full markdown description..."
}
```

The gateway will:
1. Read the current `details` from the sandbox via `PythonRead`
2. Compute a unified diff between the old and new text
3. If no changes are detected, reply immediately with `details_updated` (success)
4. Otherwise, invoke the appropriate subagent (indicator / strategy / research) with instructions to update the Python code according to the diff, and also persist the new `details` text

**While the subagent is running**, the server streams progress events using the same event types as normal agent interactions:

```json
{ "type": "subagent_chunk",    "agentName": "indicator", "content": "Reading current implementation..." }
{ "type": "subagent_tool_call", "agentName": "indicator", "toolName": "PythonRead",  "label": "PythonRead" }
{ "type": "subagent_tool_call", "agentName": "indicator", "toolName": "PythonEdit",  "label": "PythonEdit" }
{ "type": "subagent_chunk",    "agentName": "indicator", "content": "Applied patch. Validation passed." }
```

**Server → Client (completion)**
```json
{
  "type": "details_updated",
  "category": "indicator",
  "name": "My Indicator Name",
  "success": true
}
```
or on failure:
```json
{
  "type": "details_updated",
  "category": "indicator",
  "name": "My Indicator Name",
  "success": false,
  "error": "Failed to update details"
}
```

---

## Workspace Sync After Update

When the subagent calls `PythonEdit`, the sandbox returns a `_workspace_sync` payload in the MCP response. The gateway automatically applies this to the `{category}_types` workspace store and sends a WebSocket `patch` message to the client (the normal workspace sync path). The client should listen for these patches to refresh any UI that displays list metadata (name, description).

The `details` field itself is **not** in the workspace store — the client must call `read_details` again if it needs the refreshed details text after an update.

---

## Implementation Notes

| Component | File | Responsibility |
|---|---|---|
| WebSocket routing | `src/channels/websocket-handler.ts` | Parse `read_details` / `update_details`, stream subagent events, send `details_data` / `details_updated` |
| Harness methods | `src/harness/agent-harness.ts` | `readDetails()`, `streamDetailsUpdate()` |
| Diff utility | `src/harness/agent-harness.ts` | `buildUnifiedDiff()`, `computeLCS()` (module-level helpers) |
| Instruction builder | `src/harness/agent-harness.ts` | `buildDetailsUpdateInstruction()` |
| Details filter | `src/tools/mcp/mcp-tool-wrapper.ts` | `filterTypeStoreState()` — strips `details` before workspace sync |
