Plan de refactorización de streaming unificado del runtime

Objetivo

Entregar una pipeline de streaming compartida para main, subagent y acp de modo que todos los runtimes obtengan comportamiento idéntico de coalescencia, fragmentación, orden de entrega y recuperación ante fallos.

Por qué existe esto

  • El comportamiento actual está dividido en múltiples rutas de modelado específicas por runtime.
  • Los bugs de formateo/coalescencia pueden corregirse en una ruta pero permanecer en otras.
  • La consistencia de entrega, supresión de duplicados y semántica de recuperación son más difíciles de razonar.

Arquitectura objetivo

Pipeline única, adaptadores específicos por runtime:

  1. Los adaptadores de runtime emiten solo eventos canónicos.
  2. El ensamblador de stream compartido coalece y finaliza eventos de texto/herramienta/estado.
  3. El proyector de canal compartido aplica fragmentación/formateo específico del canal una sola vez.
  4. El ledger de entrega compartido aplica semántica de envío/replay idempotente.
  5. El adaptador de canal saliente ejecuta envíos y registra puntos de control de entrega.

Contrato de eventos canónicos:

  • turn_started
  • text_delta
  • block_final
  • tool_started
  • tool_finished
  • status
  • turn_completed
  • turn_failed
  • turn_cancelled

Flujos de trabajo

1) Contrato de streaming canónico

  • Definir esquema estricto de eventos + validación en core.
  • Agregar tests de contrato de adaptador para garantizar que cada runtime emite eventos compatibles.
  • Rechazar eventos malformados del runtime temprano y mostrar diagnósticos estructurados.

2) Procesador de stream compartido

  • Reemplazar la lógica de coalescencia/proyector específica por runtime con un solo procesador.
  • El procesador gestiona el buffering de deltas de texto, flush por inactividad, división por tamaño máximo y flush de completado.
  • Mover la resolución de configuración ACP/main/subagent a un solo helper para prevenir divergencias.

3) Proyección de canal compartida

  • Mantener los adaptadores de canal simples: aceptan bloques finalizados y envían.
  • Mover las particularidades de fragmentación de Discord solo al proyector de canal.
  • Mantener la pipeline agnóstica al canal antes de la proyección.

4) Ledger de entrega + replay

  • Agregar IDs de entrega por turno/fragmento.
  • Registrar puntos de control antes y después del envío físico.
  • Al reiniciar, reenviar fragmentos pendientes de forma idempotente y evitar duplicados.

5) Migración y transición

  • Fase 1: modo shadow (la nueva pipeline calcula la salida pero la ruta antigua envía; comparar).
  • Fase 2: transición runtime por runtime (acp, luego subagent, luego main o al revés según riesgo).
  • Fase 3: eliminar código legacy de streaming específico por runtime.

No objetivos

  • Sin cambios al modelo de políticas/permisos ACP en esta refactorización.
  • Sin expansión de funcionalidades específicas del canal fuera de correcciones de compatibilidad de proyección.
  • Sin rediseño de transporte/backend (el contrato del plugin acpx permanece tal cual a menos que sea necesario para paridad de eventos).

Riesgos y mitigaciones

  • Riesgo: regresiones de comportamiento en las rutas existentes main/subagent. Mitigación: modo shadow con comparación + tests de contrato de adaptador + tests e2e de canal.
  • Riesgo: envíos duplicados durante recuperación ante fallos. Mitigación: IDs de entrega durables + replay idempotente en el adaptador de entrega.
  • Riesgo: los adaptadores de runtime divergen de nuevo. Mitigación: suite de tests de contrato compartida requerida para todos los adaptadores.

Criterios de aceptación

  • Todos los runtimes pasan los tests de contrato de streaming compartidos.
  • ACP/main/subagent de Discord producen comportamiento equivalente de espaciado/fragmentación para deltas pequeños.
  • El replay ante fallo/reinicio no envía fragmentos duplicados para el mismo ID de entrega.
  • La ruta legacy del proyector/coalescencia ACP es eliminada.
  • La resolución de configuración de streaming es compartida e independiente del runtime.