# Formato de seeds para el dataset de entrenamiento (Fase 2)

Referencia común para escribir `data/raw/seeds/<bucket>.jsonl`. Cada linea es un JSON
independiente (JSONL, `ensure_ascii=False`), con esta forma:

```json
{
  "messages": [
    {"role": "system", "content": "..."},
    {"role": "user", "content": "..."},
    {"role": "assistant", "content": "", "reasoning_content": "...", "tool_calls": [
      {"id": "call_1", "type": "function", "function": {"name": "tool_name", "arguments": {"param": "valor"}}}
    ]},
    {"role": "tool", "tool_call_id": "call_1", "name": "tool_name", "content": "resultado o error como texto plano"},
    {"role": "assistant", "content": "respuesta final visible al usuario", "reasoning_content": "razonamiento del turno final"}
  ],
  "tools": [ /* subset de definiciones de tools realmente usadas en este ejemplo, mismo formato que data/schemas/*.json: {name, description, parameters} */ ],
  "meta": {"bucket": "nombre-del-bucket"}
}
```

## Reglas de formato (obligatorias, no negociables)

- **`tool_calls.function.arguments` es SIEMPRE un dict JSON**, nunca un string, nunca XML
  escrito a mano (`<tool_call><function=...>`). El chat template real de produccion usa
  XML tipo Hermes, pero eso lo genera `apply_chat_template` automaticamente a partir de
  este formato dict — nunca lo escribimos nosotros. Ver `06_validate_dataset.py`.
- **`reasoning_content` es un campo separado**, nunca metas `<think>...</think>` dentro de
  `content`. Todo turno `assistant` (tenga o no `tool_calls`) debe traer `reasoning_content`
  con el razonamiento real de ese turno (puede ser breve, pero debe existir y ser genuino,
  no un placeholder vacio).
- El primer turno `assistant` de una trayectoria con tool calling debe traer
  `"content": ""` (el contenido visible va vacio cuando hay `tool_calls`; el texto que el
  usuario ve al final va en el ULTIMO turno assistant, sin `tool_calls`).
- Cada `tool` message necesita `tool_call_id` que matchee el `id` del `tool_calls` que lo
  origino, y `name` con el nombre exacto de la tool.
- Si un ejemplo no usa ninguna tool (bucket de negativos, o parte de skills/errores que no
  llama nada), omite el campo `tools` o dejalo `[]`, y no incluyas ningun turno `tool`.
- `tools` en cada ejemplo es un ARRAY con las definiciones REALES tomadas de
  `data/schemas/{penpot,gitea,github-personal,docmost,atlassian}.json` — copia el objeto
  `{name, description, parameters}` tal cual (podes recortar la `description` si es muy
  larga, pero el `parameters` JSON Schema no se inventa ni se simplifica).
- **Nunca inventes tools o parametros que no existen en los schemas reales.** Si dudas,
  Lee el `.json` correspondiente antes de escribir el ejemplo.
- `system` message es opcional (usalo cuando el ejemplo necesita contexto de skill/tarea
  para tener sentido), pero no es obligatorio en todos los ejemplos.
- Cada linea debe ser JSON valido de una sola linea (sin saltos de linea reales dentro del
  string — usa `\n` escapado si el contenido necesita multi-linea, como reportes de Docmost).
- No repitas la misma pregunta/situacion literal entre ejemplos del mismo bucket — variar
  shapes/valores/nombres/escenarios reales (`05_build_dataset.py` variará aún más para
  llegar al volumen final; los seeds deben ser ya diversos, no clones).

## Prohibicion absoluta

- **La skill `spark-ssh` esta held-out**: cero menciones, cero ejemplos que la nombren o
  la usen, en NINGUN bucket. `05_build_dataset.py` va a hacer un `assert` de esto sobre
  todos los seeds combinados — si tu bucket la menciona, el build fallara.

## Fuentes de verdad (leer antes de escribir, no inventar reglas)

- `data/schemas/*.json` — definiciones reales de tools (154 combinadas).
- `data/schemas/PENPOT_DEPLOYMENT_NOTES.md` — reglas de gating de Penpot (`import_image`
  ausente, `export_shape` sin `filePath`).
- `data/raw/sanitized/skills/*/SKILL.md` — 5 skills reales, ya sanitizadas (usar esta
  copia, no la original de `~/.claude/skills/`).
- `data/raw/sanitized/agents/*.md` — 7 agentes reales, ya sanitizados.
- `data/raw/sanitized/plans/*.md` — 66 planes reales, ya sanitizados (útil para estilo de
  reportes, ejemplos de tablas Docmost, incidentes reales para el bucket de errores).

## Ejemplo completo (Docmost, formato de tabla GFM correcto)

```json
{"messages": [{"role": "user", "content": "Actualiza la tabla de progreso de mi pagina de Docmost (pageId abc-123) con: Fase 1 completada, Fase 2 en proceso."}, {"role": "assistant", "content": "", "reasoning_content": "Necesito usar update_page con markdown de tabla GFM: encabezado, fila separadora |---|, y cada fila de datos en su propia linea real -- sin la fila separadora Docmost colapsa la tabla en un parrafo ilegible.", "tool_calls": [{"id": "call_1", "type": "function", "function": {"name": "update_page", "arguments": {"pageId": "abc-123", "content": "| Fase | Estado |\\n| --- | --- |\\n| Fase 1 | Completada |\\n| Fase 2 | En proceso |\\n"}}}]}, {"role": "tool", "tool_call_id": "call_1", "name": "update_page", "content": "{\"success\": true}"}, {"role": "assistant", "content": "Listo, actualice la tabla de progreso: Fase 1 completada, Fase 2 en proceso.", "reasoning_content": "La tool confirmo exito, informo al usuario en una linea."}], "tools": [{"name": "update_page", "description": "Update an existing page's content or properties", "parameters": {"type": "object", "properties": {"pageId": {"type": "string"}, "content": {"type": "string"}}, "required": ["pageId", "content"]}}], "meta": {"bucket": "otros_mcps"}}
```
