brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
manage-engagement-bufferManage an engagement buffer that ingests, prioritizes, rate-limits, deduplicates, and tracks state for incoming engagement items across platforms. Generates periodic digests and enforces cooldown periods. Composes with du-dum: du-dum sets the observation/action cadence, this skill manages the queue between beats.
Independent GitHub snapshot · Automated classification · Original documentation governs
Ingerir, deduplicar, priorizar y limitar la tasa de items entrantes de engagement entre plataformas, luego entregar un digest compacto al reloj de acción. El buffer se sienta entre las señales crudas de plataforma y la acción deliberada: absorbe ráfagas, fusiona duplicados, hace cumplir cooldowns y asegura que el agente actúa en los items de mayor valor primero. Sin un buffer, un agente autónomo o procesa items en orden de llegada (perdiendo los urgentes enterrados en ruido) o intenta todo a la vez (alcanzando límites de tasa y pareciendo spammer).
Esta habilidad compone con du-dum: du-dum decide cuándo observar y actuar; esta habilidad decide qué merece acción. El buffer es la cola que acumula entre los beats de du-dum.
buffer_path — ruta al archivo buffer JSONLplatform_config — límites de tasa por plataforma y configuraciones de cooldowndigest_size — número de items top en el digest (predeterminado: 5)ttl_hours — tiempo de vida para items no actuados (predeterminado: 48)cooldown_minutes — cooldown por hilo después de la acción (predeterminado: 60)Diseñar la estructura del item de engagement. Cada item en el buffer es una sola línea JSON con estos campos:
{
"id": "gh-notif-20260408-001",
"source": "github:pjt222/agent-almanac",
"timestamp": "2026-04-08T09:15:00Z",
"content_summary": "PR #218 review requested by contributor",
"priority": 4,
"state": "new",
"dedup_key": "github:pjt222/agent-almanac:pr-218:contributor-name",
"thread_id": "pr-218",
"ttl_hours": 48
}
Definiciones de campos:
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador único (prefijo de fuente + fecha + secuencia) |
source | string | Plataforma y canal (github:repo, slack:channel, email:inbox) |
timestamp | ISO 8601 | Cuándo se ingirió el item |
content_summary | string | Descripción de una línea del item de engagement |
priority | int 1-5 | Prioridad compuesta (ver Paso 4) |
state | enum | new, acknowledged, acted, cooldown, merged, expired |
dedup_key | string | Clave compuesta: source + thread + author |
thread_id | string | Identificador del hilo de conversación para rastreo de cooldown |
ttl_hours | int | Horas hasta que el item expire si no es actuado (predeterminado: 48) |
Almacenar como un archivo JSON Lines (un objeto JSON por línea). Este formato soporta escrituras append-only, procesamiento línea-por-línea y poda fácil reescribiendo sin las líneas expiradas.
Esperado: Un archivo buffer JSONL inicializado en buffer_path con el schema documentado en un comentario o encabezado complementario. El schema es lo suficientemente estable para soportar todos los pasos descendentes.
En caso de fallo: Si el archivo buffer no se puede crear (permisos, problemas de ruta), recurrir a una lista en memoria para el ciclo actual y loggear el error de sistema de archivos. No descartar items silenciosamente — bufferarlos en algún lado, incluso temporalmente.
Aceptar items de adaptadores de plataforma y añadirlos al buffer con asignaciones iniciales de prioridad.
Asignación de prioridad por tipo de item:
| Tipo | Prioridad | Razón |
|---|---|---|
| Mención directa (@agent) | 5 | Alguien pidió atención explícitamente |
| Solicitud de revisión | 4 | Bloqueando el trabajo de alguien más |
| Reply en hilo rastreado | 3 | Conversación activa en la que el agente participa |
| Notificación (asignado, suscrito) | 2 | Informativo, puede requerir acción |
| Broadcast (release, anuncio) | 1 | Solo conciencia, raramente accionable |
Para cada item entrante:
state a newtimestamp al tiempo UTC actualdedup_key desde source + thread + author# Pseudocode: ingest from GitHub adapter
for notification in github_adapter.fetch():
item = build_item(notification)
item.priority = priority_by_type(notification.reason)
item.state = "new"
append_jsonl(buffer_path, item)
log("ingested {item.id} priority={item.priority}")
Esperado: Items nuevos aparecen en el archivo buffer con prioridades correctas y state=new. Cada adaptador produce items bien formados independientemente — los fallos del adaptador no bloquean otros adaptadores.
En caso de fallo: Si un adaptador de plataforma falla (auth expiró, rate limited, red caída), loggear el fallo y saltar esa fuente para este ciclo. No limpiar items existentes del buffer — items obsoletos de un fetch exitoso anterior son mejores que un buffer vacío.
Escanear el buffer por items que comparten el mismo dedup_key dentro de una ventana configurable (predeterminado: 24 horas). Mantener la instancia de mayor prioridad y marcar las otras como merged.
dedup_keystate=mergedthread_id con diferentes autores dentro de 1 hora indica una ráfaga de actividad — consolidar en un solo item con un conteo de participantes añadido a content_summary# Dedup logic
groups = group_by(buffer, "dedup_key", window_hours=24)
for key, items in groups:
if len(items) > 1:
keeper = max(items, key=lambda i: (i.priority, i.timestamp))
for item in items:
if item.id != keeper.id:
item.state = "merged"
# Thread burst detection
thread_groups = group_by(buffer, "thread_id", window_hours=1)
for thread_id, items in thread_groups:
active_items = [i for i in items if i.state == "new"]
if len(active_items) >= 3:
keeper = max(active_items, key=lambda i: i.priority)
keeper.content_summary += f" ({len(active_items)} participants)"
for item in active_items:
if item.id != keeper.id:
item.state = "merged"
Esperado: El buffer no contiene entradas duplicadas de dedup_key dentro de la ventana. Las ráfagas de hilo se colapsan en items únicos con conteos de participantes. Los items merged permanecen en el archivo (para auditoría) pero son excluidos del procesamiento descendente.
En caso de fallo: Si la deduplicación produce merges inesperados (items distintos legítimos compartiendo una clave), estrechar la ventana de dedup o refinar la construcción de la clave. Añadir un hash de contenido al dedup key puede distinguir items que comparten source + thread + author pero tienen contenido genuinamente diferente.
Re-ordenar el buffer por puntaje compuesto incorporando decaimiento por recencia y escalación.
Fórmula de puntaje compuesto:
score = base_priority * recency_weight * escalation_factor
recency_weight = 0.9 ^ hours_since_ingestion
escalation_factor = 1.0 + (resubmission_count * 0.2)
# Cap effective priority at 5
effective_priority = min(5, score)
Comportamiento:
3 * 1.0 * 1.0 = 3.03 * 0.43 * 1.0 = 1.29 (decayó por debajo de items de prioridad-2)2 * 1.0 * 1.4 = 2.8 (escalado cerca de prioridad-3)Ordenar todos los items state=new por effective_priority descendente. Este orden ordenado es lo que el digest (Paso 6) presenta a du-dum.
Esperado: El buffer está ordenado por puntaje compuesto. Items frescos de alta prioridad están en el top. Items viejos han decaído. Items reenviados han escalado. Ningún item excede la prioridad 5.
En caso de fallo: Si la fórmula de puntaje produce rankings poco intuitivos (p. ej., un item de prioridad-2 de 1 hora rankea por encima de un item fresco de prioridad-3), ajustar la tasa de decaimiento. Un decaimiento de 0.95 por hora es más suave; 0.85 por hora es más agresivo. Sintonizar para que coincida con el tempo de engagement.
Prevenir que el agente sobre-engaje haciendo cumplir límites de escritura por plataforma y cooldowns por hilo.
Límites de tasa por plataforma (configurable vía platform_config):
| Plataforma | Límite predeterminado | Ventana |
|---|---|---|
| Comentarios GitHub | 1 por 20 segundos | rolling |
| Reviews GitHub | 3 por hora | rolling |
| Mensajes Slack | 1 por 10 segundos | rolling |
| Replies de email | 5 por hora | rolling |
Cooldown por hilo: Después de que el agente actúe en un hilo, ese hilo entra en cooldown por cooldown_minutes (predeterminado: 60). Durante el cooldown, los nuevos items para ese hilo son ingeridos pero no surgen en el digest.
Backoff de error: Al recibir una respuesta 429/rate-limit de cualquier plataforma, doblar el cooldown para esa plataforma. Resetear al predeterminado después de una acción exitosa.
# Rate limit check before action
def can_act(platform, thread_id):
if rate_limit_exceeded(platform):
return False, "rate limited"
if thread_in_cooldown(thread_id):
return False, "thread cooldown active"
return True, "clear"
# After action
def record_action(platform, thread_id):
increment_rate_counter(platform)
set_cooldown(thread_id, cooldown_minutes)
# After rate-limit error
def handle_rate_error(platform):
current_cooldown = get_platform_cooldown(platform)
set_platform_cooldown(platform, current_cooldown * 2)
Esperado: El agente nunca excede los límites de tasa de plataforma. Los hilos tienen períodos de cooldown forzados. Los errores de rate-limit disparan backoff automático. El buffer acumula items durante el cooldown sin perderlos.
En caso de fallo: Si los límites de tasa se alcanzan a pesar del cumplimiento (skew de reloj, agentes concurrentes), aumentar el margen de seguridad — establecer límites al 80% del límite real de la plataforma. Si los cooldowns son demasiado agresivos (perdiendo hilos sensibles al tiempo), reducir cooldown_minutes para hilos de alta prioridad solamente.
Producir un resumen compacto para el beat de acción de du-dum. El digest es el punto de entrega: du-dum lee esto, no el buffer crudo.
Contenidos del digest:
state=newdigest_size)# Engagement Digest — 2026-04-08T12:00:00Z
## Pending: 12 items
### Top 5 by Priority
| # | Priority | Source | Summary | Age |
|---|----------|--------|---------|-----|
| 1 | 5.0 | github:pr-218 | Review requested by contributor | 2h |
| 2 | 4.2 | github:issue-99 | Maintainer question (escalated) | 6h |
| 3 | 3.0 | slack:dev | Build failure alert | 1h |
| 4 | 2.8 | github:pr-215 | CI check feedback (3 participants) | 3h |
| 5 | 2.1 | email:inbox | Collaboration inquiry | 8h |
### Expiring Soon
- github:issue-85 — 4h remaining (TTL 48h, ingested 44h ago)
### Cooldowns Active
- pr-210: 22 min remaining
- issue-92: 45 min remaining
### Buffer Health
- Total items: 47 | New: 12 | Merged: 18 | Acted: 11 | Expired: 6
Escribir el digest a una ruta conocida (p. ej., buffer_path.digest.md) que el reloj de acción de du-dum lee.
Esperado: Un digest bajo 50 líneas que du-dum puede parsear en una lectura. El digest contiene suficiente información para decidir sobre qué actuar, pero no el buffer completo. Si nada está pendiente, el digest lo dice claramente.
En caso de fallo: Si el digest crece más allá de 50 líneas, reducir digest_size o resumir las secciones de expirando/cooldown más agresivamente. El digest es un resumen — si se acerca al tamaño del buffer, ha perdido su propósito.
Después de que du-dum procese items del digest, actualizar sus estados y mantener el rastro de auditoría.
Máquina de estado:
new → acknowledged → acted → cooldown → expired
↑ │
└───── (re-ingested) ───┘
merged → (terminal, no further transitions)
expired → (terminal, archived)
Para cada transición de estado:
state del item en el archivo buffer{"item_id": "...", "from": "new", "to": "acknowledged", "timestamp": "...", "reason": "du-dum digest pickup"}Retención y poda:
state=acted o state=expired mayores a 7 días (configurable)buffer_path.archive.jsonl), no eliminandostate=merged mayores a 24 horas (han servido su propósito de dedup)# End-of-cycle maintenance
for item in buffer:
if item.state == "new" and age_hours(item) > item.ttl_hours:
transition(item, "expired", reason="TTL exceeded")
if item.state in ("acted", "expired") and age_days(item) > retention_days:
archive(item)
if item.state == "merged" and age_hours(item) > 24:
archive(item)
rewrite_buffer(buffer_path, active_items_only)
Esperado: Cada transición de estado se loggea con un timestamp y razón. El archivo buffer contiene solo items activos (new, acknowledged, cooldown). Los items archivados se preservan separadamente para auditoría. El buffer no crece sin límite.
En caso de fallo: Si el archivo buffer se vuelve corrupto durante la reescritura (escritura parcial, crash), restaurar desde el respaldo pre-reescritura. Siempre escribir a un archivo temporal y renombrar atómicamente — nunca reescribir en el lugar. Si el archivo crece demasiado grande, comprimirlo o rotarlo mensualmente.
du-dum — patrón de cadencia con el que este buffer compone; du-dum decide cuándo observar y actuar, esta habilidad decide qué merece acciónmanage-token-budget — contabilidad de costos; el buffer respeta restricciones de presupuesto de tokens al dimensionar digests y limitar throughput de accióncircuit-breaker-pattern — manejo de fallos para adaptadores de plataforma alimentando el buffer; cuando el circuito de un adaptador se abre, la ingestión degrada elegantementecoordinate-reasoning — señales estigmérgicas entre buffer y sistemas de acción; el archivo buffer mismo es un artefacto estigmérgicoforage-resources — descubrimiento de nuevas fuentes de engagement para alimentar a los adaptadores de ingestión del buffer