103 KiB
| title | type | status | date | docs | scope | provenance | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PLAN — Eje agéntico ($agent) · track del agente como tal | process / plan de ejecución | v2.2 — D-AG.1/D-AG.2 + bloque §3 + ⚖️1/⚖️2/⚖️3 FIRMADOS (2026-07-21). F0 desbloqueada. | 2026-07-21 |
|
ESTE track = el agente como tal (motor, protocolo, contratos, ciclo, semántica, superficies propias). La integración en palabras (4 ejes F-B, provenance en su modelo, puertas mudas, transact, concurrencia espacial) pertenece al TRACK DE PALABRAS, que consume el contrato definido aquí. | Ids entre corchetes = origen: N* (propuesta propia) · G* (Gemini) · C* (ChatGPT) · F* (Fable) · Z* (z.ai). Detalle y veredictos en el triage. |
PLAN — Eje agéntico ($agent)
§1 · Tesis y principios (doctrina, no negociable sin re-firma)
- Es un eje, no un componente: motor (art) + contrato de participación por componente + registro + superficies propias. Instancia el patrón de eje ortogonal existente (motor + módulo-por-componente + wiring + canon + guard).
- Regla de oro: el agente actúa por la MISMA API pública del provider; la
ruta de llamada no se bifurca, pero la concreción semántica depende del
actor (eventos polimórficos
allowedFamilies→{family:'delegate', verb:'act'}cuando el actor es el agente). Puerta ausente ⇒ se promociona al componente; nunca bypass. - Actor-agnóstico (libro cap. 29): macro, regla, workflow o LLM — todos son «otro actor». Nada del eje depende de un proveedor LLM concreto.
- Degradación total: con el eje ausente, todo componente funciona al 100%. Fila §0 de contratos mínimos obligatoria en F0.
- Presupuestos cliente = cortesía de UX, no frontera de seguridad [F4a]: la frontera vive donde vive la credencial (proxy/backend). Se declara así de honesto en la doctrina.
§2 · Decisiones FIRMADAS (2026-07-21, vinculantes)
| D | Decisión |
|---|---|
| D-AG.1a | Arte agent · $agent · EngineAgent (puro) + ActiveAgent (reactivo, contrato ActiveEngine) |
| D-AG.1b | Factory feature-scoped defineActiveAgent(...) a nivel app (patrón auth/session); NADA en ActiveUix v1; promoción a accessor uix.agent con el consumidor canónico (precedente scene-D4) |
| D-AG.1c | Adaptadores de proveedor en $agent/adapters/* fuera del barrel (precedente $logger/adapters); ScriptedAgentTransport determinista first-class (tests sin mocks, demos estáticas) |
| D-AG.2a | Protocolo de eventos PROPIO espejo de AG-UI (5 categorías: run · deltas · tool-calls · estado · custom), nombres alineados con el canon; AG-UI = baseline de paridad (patrón ethereal) |
| D-AG.2b | El streaming lo posee cada adaptador (fetch+ReadableStream/SSE local); $http/$connection intactos |
| D-AG.2c | Estado = snapshot-por-turno v1; categoría snapshot/delta RESERVADA tipada; JSON Patch en la generalización |
Enmiendas menores a D-AG.2 aceptadas en triage (no alteran lo firmado, se firman con el bloque §3): dirección tipada del canal de estado [F7], mapeo wire de review/elicitación como confirmation-tool [F3e], versionado de protocolo y manifiestos en el handshake del run [F12].
§3 · Decisiones A FIRMAR (consolidadas del triage)
Cada bloque es una decisión firmable. ⚖️ marca las bifurcaciones con alternativas reales donde hace falta TU elección; el resto lleva la forma recomendada ya consensuada por la revisión cruzada.
D-AG.3 — Modelo de dominio y sesión [N1 · G1 · C1 · C3 · F2]
- La escalera, documentada:
ActiveAgent= sesión (larga vida, contexto entre runs — «hazlo otra vez en la sección 2») →Run= delegación (presupuesto, autorización, agrupado de undo, devolución de control) →Turn= coordinación →CapabilityCall= mutación (lo único que toca el mundo). Conversation = superficie opcional que encadena runs. - Run degenerado: una sola call auto-autorizada (macro/regla/workflow — el caso no-IA del libro) es un Run válido y barato.
initiative[C3]:'user' | 'system' | 'scheduled'en la identidad del Run, viajando en el contexto de actor de cada call. Alimenta política (D-AG.7), a11y y audit. El verbo de entrada la insinúa (offer-first = iniciativa del sistema).- Reservas (huecos declarados, no construidos):
parentRunId(sub-runs / agente-como-capacidad / A2A) [C6]; identidad de usuario en el vocabulario de actor (multiusuario, llega conconnection) [F12]. - ✅ Modo ambiental (always-on) [F2a·G1·C6] — FIRMADO ⚖️1: fuera del eje
v1, RESERVADO CON NOMBRE:
Subscription/watcher que emitedelegate.offer; micro-runs coalescidos = diseño futuro (F5). Deja constancia para que no crezca un segundo sistema de agencia paralelo por la puerta de atrás.
D-AG.4 — Máquina de estados del run [N2 · C2 · G4 · G5 · F3]
- Estados = verbos
delegate, como custodia del control, no fases cognitivas [C2]: el ciclo plan→tool→plan del modelo vive DENTRO deacting. reviewingre-entrante desdeacting[C2·F3a] (aprobaciones parciales/incrementales).- La autorización fija alcance [F3a]:
authorizedderiva del plan un allowlist de capacidades + presupuesto; un act fuera de alcance ⇒escalateautomático a re-review (ni fallo ni silencio). Sin esto, la review es teatro. returnedcon outcome tipado [F3b·G4]:completed | partial | rolled-back | aborted | error, conreason(p. ej.superseded— la premisa cambió por mutación externa;budget-exhausted;killed). Política de fallo a mitad de secuencia — FIRMADO ⚖️3: rollback a inicio-de-run por defecto (el usuario autorizó el plan entero, no la mitad; reversión vía historia nativa); una capacidad puede DECLARAR en su manifiesto que admite cierre parcial cuando tenga sentido.escalated: no terminal;reasontipado (elicitation | insufficient-scope | budget-exhausted | out-of-plan) [F3d]; timeout → auto-return (escalada abandonada) [G5].- Pausa sin verbo nuevo [F3c]: pausa =
returncon contexto reanudable; reanudar = run nuevo encadenado en la sesión (coincide con elresumede AG-UI — la mecánica wire y nuestra semántica convergen). - Interrupción del usuario =
returninmediato, jamás error. - Kill switch global [F12]: primitiva del motor (
disable()) → todos los runsreturned(aborted). Cubre «agente presente pero desactivado YA».
D-AG.5 — Tool-loop y presupuestos [N3 · G2 · G3 · F4]
- Loop en
EngineAgent, cliente, v1; portabilidad a servidor como requisito explícito del núcleo (sin DOM, sin runes en el Engine) [F1c]. - Acts secuenciales v1. Fallos tipados → verbos (recuperable→retry acotado
· alcance→
escalate· abortado→return); claseunknown-capability(tool alucinada) devuelta como tool-result para auto-corrección, acotada por presupuesto [F4c]. - Presupuestos first-class: máx. acts/run · máx. turns · timeout
(uix.timers) · tokens/contexto con política de truncado local
(FIFO + resumen) [G3·Z2] ·
AbortSignalen cada capacidad. Agotamiento ⇒escalate, jamás silencio. (Los guards de orca NO alcanzan este loop — verificado.) - Idempotencia [G2·Z3]: dedupe por
toolCallIden la puerta de capacidad; reintento tras timeout de red devuelve el resultado cacheado, nunca re-ejecuta. - Topología de credenciales [F4a]: adapter-proxy hacia el backend del app como topología de primera clase documentada; directo-a-proveedor desde el navegador = footgun señalado a gritos.
D-AG.6 — Contrato de capacidades y reads [D-AG.3 previa · G7 · G11 · C5 · F1a · F4c · F5a · F9]
- 6a Hogar: contrato estructural en el arte (
AgentCapability/AgentRead: ids string, args Standard-Schema vía sium, handler opaco — patrón MotionDom/SceneDom); los manifiestos uix (src/uix/agent/components/{x}.ts) lo satisfacen tipando contra la API del provider. El handler opaco da location-transparency gratis (reserva distribuida) [C6]. - 6b Proyección model-facing: emisor sium→JSON Schema +
descriptionobligatoria por read/act/arg. Límites de tamaño por arg en el contrato [F4c]. - 6c Instancias y contexto — push→pull [F9·G11]: índice siempre presente
(id estable + tipo + etiqueta + resumen de una línea, jerárquico — valida el
parentId de CopilotKit) + reads profundos como capacidad pull
(
read(instanceId)) + priorización por foco/viewport (señal UIX-nativa)- ambigüedad de direccionado ⇒ elicitación, no heurística.
availablereactivo por act +capabilities-changedentre turnos; call pendiente contra capacidad revocada ⇒ fallo tipado → escalate [C13a].
- ambigüedad de direccionado ⇒ elicitación, no heurística.
- 6d Resultados: tipados con sium; los RESULTADOS de reads/acts con contenido de terceros son tan no-confiables como un documento importado (misma doctrina de origen) [F4c].
- 6e Traits [C5]: annotations para el razonador (coste, latencia, estabilidad, staleness) — precedente MCP tool annotations.
- 6f OCC [G7·F8d]: cada read exporta
_version; cada act la exige; mismatch ⇒StateStaleErrorrecuperable (re-read → re-plan). - 6g Altitud [C4]: capacidades = mutaciones MECÁNICAS del mundo, pocas y a
la altura correcta (
replaceRange, no 12 micro-inserts). Operaciones semánticas (summarize,translate) = cognición del modelo; «skills» agent-side reutilizables (equivalente MCP prompts) = tier RESERVADO. - 6h Tiers de madurez del manifiesto [F1a]:
reads-only→acts reversibles→acts completos; el guard audita el tier declarado; los ~110 componentes entran incrementalmente sin gatear el eje. - 6i Reversibilidad POR-EFECTO [F5a]: no por-capacidad; efectos externos (enviar/publicar/notificar) = irreversibles por definición; la autoridad de reversión es la historia nativa del componente (nunca compensación de orca).
D-AG.7 — Autorización, consentimiento y política [N5 · G8 · G9 · C3 · F5 · F8]
- Tres niveles (
suggest | review | auto), resolución estilo prefs (app = techo, usuario ajusta por debajo, la capacidad exige MÁS control, nunca menos), deny-overrides; irreversible ⇒ review SIEMPRE. - Riesgo dinámico por payload [G9]: el manifiesto declara clasificador de
riesgo sobre args;
autoescala areviewpor invocación. - Origen del contexto en la resolución [F8b — la unificación]: cada read
lleva etiqueta de origen (
authored-by-user | imported | third-party | other-participant); cualquier origen no-confiable en el turno BAJA el techo (⇒review, osuggestpara capacidades sensibles). §7.1 del informe deja de ser amenaza abierta: es una fila más de esta resolución. initiativeafecta techos [C3]: iniciativa autónoma (system/scheduled) ⇒ defaults más estrictos que la pedida por el usuario.- Autorización vinculada al estado, no a la prosa [F8d]: la review computa contra fingerprint F de los reads relevantes; la autorización se liga a F + TTL; deriva ⇒ recomputar diff (idéntico → re-aprobación automática opcional; distinto → re-review). Cierra TOCTOU (§7.2 del informe).
- Fatiga de aprobación [F5b]: grants persistentes («siempre permitir X») con TTL y alcance explícito (sesión/componente/tipo de act); la review muestra el cambio concreto propuesto en el dominio del app, nunca prosa (enmendado 2026-07-22 — el contenido de la review es del APP; ver doctrina «The review surface» en agent.md §7).
capabilities-changed⇒ re-gate de grants [F5c].- perm solo para scopes que tocan servidor (aplicado en el proxy/tool-loop server-side); el caso base es política local sin dependencia de perm.
reads= sujetos de permiso simétricos aacts(consentimiento de qué viaja al modelo; componentes sensibles no registran reads).
D-AG.8 — Semántica, actor y a11y [N6 · G6 · G12 · F1b · F6 · F11]
- El motor NO emite (art sin DOM); expone el run como estado reactivo. Las
superficies declaran el ciclo en sus morfos (
delegate-*;sustain-processinges de Aura, stateBound, limpiado al cerrar). Los componentes actuados concretandelegate.actvíaallowedFamiliescon contexto de actor. - Acuñación del actor [F6b]: el contexto de run es un token opaco emitido solo por el motor por CapabilityCall — no un literal construible; el guard verifica que nadie en el canon fabrica actores a mano.
- ✅ Propagación causal del actor [G6·F6a] — FIRMADO ⚖️2: híbrido (d).
El actor es un token opaco acuñado solo por el motor (F6b), llevado como
UN slot reservado en el envelope causal que el framework ya propaga
(
OrcaEventMetaen la vía orca; el bagcontextdel envelope de bus en la vía bus), heredado profundidad-a-profundidad igual quetraceIdya lo hace, y leído por sema SÍNCRONAMENTE vía un campoactor?: ActorTokenenTriggerOptions → SemanticSignal(verificado: legible antes del primerawaitdeEngineSemantic.emitparapre/coincident). AsyncContext/ALS (la cadenaals.tsde orca) es auto-relleno oportunista, NUNCA la garantía — en navegador degrada a root, que sema no tolera. Esto COMPARTE el primitivo de propagación con la traza OTel de D-AG.9 (run=trace, CapabilityCall=span, actor=baggage) sin bifurcar la agencia (⚖️1). La hipótesis OTel-baggage se confirma, corregida por el caveat browser-await: la fiabilidad viene del envelope explícito; lo ambiental es azúcar. Enmiendas vinculantes del stress-test:- Justificación corregida: explícito gana a ambiental por integridad de
AUDIT / provenance de efectos secundarios (WAL D-AG.9 + traza OTel),
NO por anuncio síncrono per-emit — el anuncio va COALESCIDO POR PLAN por
Aura (WCAG 4.1.3), nunca per-act, y
data-actores pintura derivada del MODELO (eidos lee el estado reactivo del run). Sema leesignal.messageverbatim y NO resuelve el token de actor. - Hogar del tipo: el tipo branded
ActorTokenvive en una hoja bajo orca Y agent ($libso arte-hoja) para evitar el ciclo orca→agent; la autoridad de acuñar/resolver queda enEngineAgent. La vía bus lleva el actor en el bagcontextsin tipar → su defensa anti-forja es el lint deagent-check(D-AG.11), no el sistema de tipos. - «Ya propaga» corregido: el contexto causal NO cruza hoy la
suscripción bus→orca (solo
payload), nipublishCausedBy(solo causation/correlation), niwithOptionalEnvelopeFields; inclusotraceIdse re-enraiza ahí. El retrofit es acotado y presupuestado en ~6 costuras:OrcaEventMeta.actor,OrcaALSContext.actor, forwarding dectx.emit, copia enbuildChildEnvelope, forwarding debusEnvelope.context.actoren la suscripción, ypublishCausedBy+withOptionalEnvelopeFieldscon merge del padre. - Garantía acotada + fasing: la garantía síncrona/autoritativa se
entrega para el puente A→B autorado explícitamente que hila
opts.actor. Agente-mueve-componente-de-stock por la API pública NO tiene call-site → en navegador (ALS muerto) resuelve al sentinelUSERbranded = best-effort, fuera de v1, NO se cierra con plumbing pervasivo en providers. La atribución IN-SCOPE viaja por eldata-actorderivado del modelo (sin hilaropts.actor); la baggage del envelope es específicamente para efectos secundarios out-of-scope + audit. F1 construye SOLO el primitivo (ActorToken branded + sentinel USER + registro privado + guard anti-forja +actor?en TriggerOptions leído en el prepare-loop de emit). El retrofit de propagación (enmienda 3) se DIFIERE a la fase con un consumidor real de cascada async out-of-scope (F3+), gateado por el drift-check del guard (ambiental nunca es el único portador en un puente cross-componente).
- Justificación corregida: explícito gana a ambiental por integridad de
AUDIT / provenance de efectos secundarios (WAL D-AG.9 + traza OTel),
NO por anuncio síncrono per-emit — el anuncio va COALESCIDO POR PLAN por
Aura (WCAG 4.1.3), nunca per-act, y
- Run sin superficie = prohibido por encima de suggest [F1b]: autonomía >
suggestexige superficie de presencia registrada (Aura mínima); el motor rehúsa (o advierte) al entrar enactingsin ella. Verificable. - Write-scope declarado [G10]: el run declara su alcance de escritura (componente | parte | rango); hold y pintura aplican solo a ese scope. (Materialización por componente → track palabras.)
- Contrato a11y del eje [F11·G12·Z11]:
- UNA live region
politepropiedad de Aura; anuncios atribuidos («Agente: …») y coalescidos por lote/plan — jamás por delta ni por act individual (WCAG 4.1.3). - No-robo-de-foco como invariante del MOTOR (WCAG 3.2.1/3.2.2), no cortesía de cada superficie.
aria-busyen la región mutándose durante streaming; anuncio de completitud al cerrar.- Elicitaciones posponibles, no modales por defecto (WCAG 2.2.4).
- Salida global por teclado (doctrina Esc): cancelar/return alcanzable
sin ratón. Aura
reduce: 'static-frame', jamáshide. Oportunidad §8.3: nadie tiene este patrón — documentarlo es fijarlo.
- UNA live region
D-AG.9 — Persistencia, audit y observabilidad [N8 · F10 · F12]
- v1: sesión en memoria (
snapshot()) + journal write-ahead mínimo por run vía$storage(sessionStorage vale): autorizaciones + acts aplicados; detección de runs huérfanos al recargar [F12]. (Orca no puede ser store — verificado.) - Puerto de trazas con forma OTel GenAI [F10]: run = trace, CapabilityCall
= span — el puerto se define YA, el vehículo de almacenamiento llega
después. Responde §7.3 del informe. Comparte el primitivo de propagación
con el actor (⚖️2, D-AG.8): un solo carrier de contexto causal, cargas
distintas (traza = export async/tolerante a pérdida; actor = lectura
síncrona/autoritativa). En el borde de export se emite una etiqueta
no-autoritativa (
'agent') para observabilidad; el token resoluble nunca se serializa (anti-forja F6b). - Persistencia de conversaciones/historial entre sesiones: adapter
$storageopcional, diferida con hueco.
D-AG.10 — i18n del agente [F12 · cruce con eje langs]
identity/system-context lleva el locale efectivo (prefs.language); el
idioma en que el agente responde y en que se ANUNCIA (live region, superficies de review del app)
sigue el eje langs como cualquier superficie. Los textos del eje (anuncios,
estados) = catálogos langs/components/ normales.
D-AG.11 — Guard mecánico agent-check [F1a · F5a · F6b · F12 · crítica previa]
Nace CON el árbol de manifiestos (no después). Audita: manifiesto ↔ API pública real (drift tipado) · tier de madurez declarado [F1a] · veracidad de reversibilidad por-efecto (review-always para APIs de reemplazo destructivo) [F5a] · calidad model-facing (descriptions no vacías, args descritos, clases de fallo declaradas — determina si el modelo usa bien las capacidades) [F12] · anti-falsificación de actor (ningún sitio del canon construye contextos a mano) [F6b] · no-bypass (todo act mapea a puerta emisora).
§4 · Secuencia de fases
Regla heredada del precedente blocks/scene: decisiones firmadas ANTES de código; guard en la misma fase que crea la superficie que vigila; doctrina con gate propio.
| Fase | Contenido | Verifica / guard |
|---|---|---|
| F0 · Doctrina ✅ (doc) | docs/architecture/agent.md ESCRITA + registrada en el índice: capítulo comparativo (matriz 6 refs + bibliografía de seguridad) · tesis+principios · dominio+máquina de estados · contrato de participación · fila §0 · actor primitivo (⚖️2) · autorización · a11y · amenazas. Corrección: la fila §0 vive en la DOCTRINA (§4 del doc), no en src/uix/contracts.ts — el agente es un arte APP-level (D-AG.1b), no una capa UIX; su degradación se verifica en la suite del arte (arts:check) cuando F1 cree arts/agent, no en el boundary-test de UIX |
docs:check ✅ 0/0 · (degradación → arts:check en F1) |
| F1 · Motor mínimo ✅ (2026-07-21) | ENTREGADO — src/libs/actor (ActorToken branded + sentinel USER_ACTOR) · src/arts/agent (24º arte, alias $agent): EngineAgent (máquina D-AG.4 completa — suggest/review/auto, escalated con reason+timeout, returned outcome-tipado, cancelled pre-autorización, kill switch, autorización journaled incluso auto; loop D-AG.5 — acts secuenciales, fallos→verbos, unknown-capability acotado, idempotencia por callId, presupuestos acts/turns/wall-clock, AbortSignal; techo por origen no-confiable F8b; acuñación de actor con registro privado WeakMap — forjados resuelven a null) + ActiveAgent (sesión reactiva, contrato ActiveEngine, activeRun para Aura) + puerto AgentTransport + protocolo v1 (protocol.ts: 5 categorías + dirección tipada + reservas state/elicitación + versionado) + ScriptedAgentTransport ($agent/adapters/scripted, fuera del barrel) + journal WAL (memory + webStorage, detección de huérfanos) + puerto de trazas OTel (run=trace, call=span, label no-autoritativa) + emisor sium→JSON Schema (toJsonSchema, nota de promoción a $sium al 2º consumidor) + costura actor? en TriggerOptions→SemanticSignal (runtime copia verbatim; sema no resuelve) + defineActiveAgent (service-factory app-level D-AG.1b: adapta el ActiveTimers del core al puerto AgentTimersPort + logger del core — cero setTimeout a pelo en runtime; tests con puerto manual determinista + flush settle() nombrado). |
✅ suite 18/18 · ✅ arts:check 0/0 (24 arts) · ✅ portabilidad (Engine sin DOM/runes) · ✅ anti-forja testeado · ✅ sema 178/178 · check: 0 errores propios |
| F2 · Piloto palabras | ESTE track entrega: capacidad tipada contra la API de palabras + OCC (_version) + write-scope + journal. El TRACK PALABRAS entrega su lado (4 ejes F-B firmados allí, puertas mudas promocionadas, api.transact, concurrencia espacial). Corre contra ScriptedAgentTransport |
run end-to-end en demo estática · un run = un undo · Playwright |
| F3 · Semántica + superficies ✅ CERRADA (2026-07-22) | allowedFamilies delegate en el 1er componente actuado (→ REUBICADO a F2: su hogar natural es el piloto, el primer componente actuado real) · Aura (dueña de sustain-processing; live region; reduce static-frame) · aura.ts — EL PRIMER morfo del repo con eventos familia delegate (delegate-offer · delegate-escalate untilAction · delegate-return, los tres con requiresLiveRegion) + sustain-processing stateBound (dueña Aura, target indicator) + 5 partes (provider/indicator/status/region role=status aria-live=polite aria-atomic/cancel trigger) + texts (estados + anuncios atribuidos «Agent: …») + expression: 'family-default' (el perfil bajo de delegate es decisión firmada de capa 1; la modulación por intent de §F6 es visual → eidos/scene). Verificado: morfo:vocabulary limpio (solo WARN preexistente de cropper) · esquemas 114/114. Gotcha de convención: la clave de stateRef debe ser un VALOR representativo del vocabulario declarado (precedente progress/file-upload), no un nombre conceptual. Fase 2 soma ✅ (2026-07-21): soma/components/aura/ completo — provider raíz con puerto estructural AuraAgentSource (duck-type de ActiveAgent; soma NO importa $agent — degradación total: sin agente = idle válido), watcher de transiciones en constructor ($effect + untrack, cero write-loops), mapeo custody-of-control (authorized→acting; terminales→idle), sustain-processing stateBound con clearSignal al salir + guard de carrera (si el run avanzó antes de resolver el emit), delegate-escalate untilAction + clear en resolución, delegate-return = anuncio único consolidado atribuido en la Region PROPIA (role=status/polite/atomic — sin doble anuncio por la vía compartida), cancel() = salida global (disabled en idle, aria-label langs) + 5 wrappers + types + exports + README + catálogo langs/components/aura.ts (es/en) registrado + barrel soma. Test 6/6 con EngineSemantic({visual:false}) REAL (la degradación explícita del §0) — prueba emits/persistencias/clears de verdad; contracts sweep verde (solo los 2 fallos AJENOS preexistentes); svelte-check 0 errores propios. Fases 4–5 eidos+recipe ✅ (2026-07-21): eidos/components/aura/ completo — root <Aura> (data-size responsive sm/md/lg) · <Aura.Indicator> = el orb: aurora $scene real montada con el patrón de ciudadanía del pack (engine por superficie DOM WeakMap — eidos NO importa $packs, frontera dura), params modulados por estado según §F6 (velocidad/amplitud/hue: idle .35/.45 neutral → acting 1.2/1 primary → escalated 1.7/1.15 threat; reviewing risk — mapeo canon de intents), colores vía eidos.resolveToken('--color-{role}-solid') (jamás getComputedStyle), fallback = gradiente radial CSS del recipe (ES el render bajo reduced-motion static-frame del engine / SSR / effect off — la presencia nunca desaparece) · <Aura.Cancel> compone <Button> vía child/asChild (defaults diferidos al Button canónico — regla de la casa, sin ghost/neutral hardcodeado) · Status/Region passthrough · recipe aura.css sin @keyframes (R-4.5: el movimiento es del scene) + región sr-only + tokens aura en base.ts (orb-size por talla, tinte por estado en slots de rol re-tintables por tema). Gates: generate:eidos-css ✓ · api-contract+lint+visual-attrs+generated-css 25/25 · recipe-css-contract 30/30 · eidos-lint aura CERO inválidos · check 0 errores propios. Fase 6 demo ✅ + VERIFICADA (2026-07-21): web/routes/uix/components/aura/+page.svelte — v2 9 pestañas con harness compartido (SystemAxes/MotionPanel/SemaPanel/DemoTrace); la demo compone el MOTOR REAL (createActiveAgent + transporte con COMPUERTAS deterministas — botones «Model responds»/«Act completes», cero timers, cero estados falseados); drivers del ciclo completo (auto/review/suggest × user/system, run irreversible→escalada, authorize/reject, approve/deny, Stop = el Cancel del componente). Verificación: consola 0 errores · ciclo COMPLETO conducido en vivo (planned→acting→returned→idle con «Agente: terminó — control devuelto» atribuido y en es; escalada con stamp data-event-family="delegate" PERSISTENTE untilAction → deny → stamp delegate-return en hold → auto-limpieza a null — primera estampa delegate del ecosistema verificada en DOM); review path (reviewing espera→authorize→acting); computed styles decisivos (orb 20/28px por talla, tinte neutral→primary oklch(0.56 0.18 306)→threat oklch(0.63 0.19 23), opacity .5 idle); pixel-check en Chrome REAL con capturas: página entera + orb en acting con la AURORA WEBGL PINTANDO dentro del canvas (27×27 DPR-ajustado), Cancel = Button real (data-button, asChild); Region role=status/polite con el anuncio; screenshot del pane cuelga (limitación documentada §13 de la guía — vía sancionada usada); smoke scoped PASS (gotcha: MSYS_NO_PATHCONV=1 para SMOKE_SCOPE en Git Bash); check 0 errores propios. Corrección de tamaño (2026-07-21, señalada por el usuario): los orb-size iniciales (14/20/28px) eran INVENTADOS — violación de «never improvise» + magic numbers. Corregido con derivación canónica: --aura-orb-size-{k}: var(--avatar-size-{k}) (sm 32 / md 40 / lg 48) — Avatar = la primitiva de disco de presencia/identidad; un tema que retoca avatares retoca el orb. Verificado en navegador (32/40/48 computados + look real). Promoción uix.scene (D4) ✅ EJECUTADA (2026-07-21): defineEngineScene (service-factories, espejo de motion, junto a dom) · defineUixServices la registra · superficie ActiveUix (standalone crea con dom real / undefined con dom disabled; attach lee app.scene ?? fallback con ownsScene; getter; dispose en orden events→scene→motion; types con doc) · contracts.ts (fila + publicSurface) + expectativa del boundary-test · ActiveEidos.scene accessor · el indicator PREFIERE eidos.scene (presupuesto global) con WeakMap fallback fuera del árbol · scene/README + arts/README actualizados (el pack conserva sus engines propios — packs no consumen uix). Gotcha del guard: exportar la clase provider en el barrel soma exige indirection internals.ts (literal provider.svelte prohibido en exports.ts — precedente calendar). Gates: contracts 67/69 (2 fallos AJENOS conocidos) · arts:check 24 · check 0 propios · navegador: canvas montado por la vía compartida tras reload. Fases 7–8 ✅ (2026-07-22) — AURA COMPLETA (0–8), component:audit PASS: README eidos con comparativa (5 refs — thinking-indicators/CopilotKit/Vercel useChat.status/presencia colaborativa Figma-Docs/assistant-ui; paisaje escaso reconocido, §8.3 «nadie tiene esto») + Decisiones + excepción R-1.5 documentada (único focusable = Cancel, focus del Button) + Gaps con disposición (diferir×3/descartar). Fixes del audit: opacity 0.5→var(--opacity-50) (R-4.2); apg: 'none — …' en el morfo (A-1.4). Gates: component:audit PASS 1/0/0 (2 warnings heurísticos D-1.5/D-4.3 = falsos positivos por usar el harness compartido DemoTrace/SemaPanel, bajo umbral) · morfo:vocabulary limpio · eidos-lint aura 0 inválidos · recipe-contract verde. Primer componente del eje agéntico cerrado de punta a punta. Commit F1+F3(0–6): 6be7195f0. F3 CERRADA (2026-07-22): review resuelta como doctrina (sin componente nuevo — split framework/app en agent.md §7) y allowedFamilies reubicada a F2. Commit fases 7–8: 2c175c5d9. Siguiente: F4 por la vía del chat (2º consumidor no gateado: participante con provenance por modelo de mensaje + composer como entrada de delegación + manifiestos + agent-check) · F2 piloto palabras cuando su track firme los 4 ejes. |
component:audit de ambas · morfo-check · axe/SR pass del contrato a11y |
| F4 · Generalización | Árbol src/uix/agent/components/ + registro por instancia (índice push→pull) + agent-check (D-AG.11) + 2º consumidor (chat agéntico: participante + redactor + slot de actividad de tool) + elicitación materializada (Form.AutoFields) + promoción uix.agent (cierra D-AG.1b) |
agent-check verde · 2 manifiestos reales (dueños firmados §5b: form + table/tree-grid) · fila §0 attach |
| F4a · Marco de integración APP ✅ (2026-07-22) | Auditoría completa del track (encargo del usuario: divergencias + marco independiente del componente). Divergencias CAZADAS y CORREGIDAS (4 firmadas sin implementar): initiative→techo (C3: system/scheduled clampa auto→review) · presupuesto de contexto D-AG.5 (maxContextBytes, FIFO-trim byte-based, el goal sobrevive; resumen diferido) · tope por-arg F4c (maxArgBytes→invalid-args tipado) · schema de resultado D-AG.6d (result? Standard-Schema; mismatch = recoverable, no cuenta como act). Divergencias ESTRUCTURALES resueltas: integración bus (patrón session EXACTO: el arte posee el vocabulario agent.* en consts + bus-helpers tipados publican con bus INYECTADO; defineActiveAgent cablea core.bus; source='agent', correlationId=runId = la costura causal ligera sin el retrofit de 6 costuras) · orca app-land (el APP registra acciones sobre agent.run.closed/escalated — invariante intacto; probado con orca REAL) · página del arte /active/docs/agnt (convención de la casa que faltaba: sección Delegation en nav, artículo + playground VIVO con los 4 motores puros reales compuestos en página — bus log en vivo, journal WAL, contador orca, kill switch reactivo, compuertas deterministas). Gates: agent 26/26 (integration.test: spine motor→bus→orca real + los 4 fixes) · smoke agnt PASS · check 0 propios · verificado en pane + Chrome real (ciclo completo, orca archiva, kill oculta drivers). Divergencias DIFERIDAS con disposición: resumen semántico de contexto (F5) · superseded producido por OCC (F2, lado componente) · wiring identity.locale←prefs (F4 con uix.agent) · journal por defecto en factory (app decide vehículo). Auditoría de conformidad bus/orca ✅ (2026-07-22, pregunta del usuario): contraste punto-a-punto contra los README de ambos — conforme en 12/13 (module-events consts+types+bus-helpers = patrón documentado literal · envelope correlationId · Rule 5 payloads planos clonables · eventos-como-constantes · module→bus/action→ctx.emit · artifacts-no-consumen-orca · Rule 7 N/A a module events). 1 no-conformidad real corregida: goal (contenido del usuario) viajaba en AgentRunBusPayload — viola higiene de credenciales del bus («pasa correlationId y que el suscriptor resuelva del módulo») y §Events de orca («no unnecessary private data — la acción resuelve del módulo al ejecutar»). Fix: payload = SOLO metadata; el suscriptor resuelve vía App.agent.run(runId) (testeado en el spine con orca real: 'goal' in payload === false + resolución del módulo). Página agnt documenta la higiene + recomendación configureEvent('agent.run.state', { queuePolicy: ORCA_QUEUE_REPLACE_QUEUED }) (evento frecuente → doctrina de colas de orca; constante verificada). Carril de INICIATIVA documentado (2026-07-22, pregunta del usuario «¿el bus como eje?»): el bus es eje en TRES direcciones — observar (vocabulario agent.*) · reaccionar (orca) · iniciar (hecho de dominio → acción orca → App.agent.start({initiative:'system'}) → clamp auto→review por construcción); lo que NO es: vehículo de la delegación (capacidades=handlers no clonables, turnos=request/response del protocolo, contenido en el módulo). Sección «The bus as the initiative axis» + ejemplo en la página. Adaptador REAL openai-chat (2026-07-22): $agent/adapters/openai-chat (fuera del barrel, D-AG.1c) — dialecto OpenAI chat-completions (Ollama/llama.cpp/LM Studio/proxy), SSE→protocolo v1, sanitización de nombres con puntos (ida y vuelta), re-pairing de tool_calls al reproducir el transcript (el motor no anota los tool_calls del assistant — memoria por callId en el adaptador), fetch inyectable. Fix cazado en vivo: Ollama reutiliza index:0 para TODAS las calls del stream → call nueva se detecta por id distinto (no por index), call-end por call arrancada; sin el fix los args se concatenaban (JSON inválido → invalid-args en motor + 400 en replay). Tests 4 (protocolo+nombres · spine motor-sobre-cable con re-pairing verificado en el body del turno 2 · index-reuse split · transport-error close) = agent 30/30. Demo viva en la página agnt contra qwen3-coder:30b REAL (Ollama 11434; el 8080 del usuario es Open WebUI, API keys off): capacidades doc.set-title/append-line (reversibles, sium) + doc.clear (irreversible→escalada), read snapshot-por-turno del doc, streaming en vivo, controles authorize/escalation. Ciclo entero verificado en navegador: planned→authorized→acting→returned(completed,done), 3 acts, 2 turnos, doc mutado («Notas activeUIX» + 2 líneas), respuesta final en es (identity.locale), rastro completo en bus (opened/state×4/act.applied×3/closed, correlationId=run-1), CORS preflight 204, consola 0. GOTCHAS: pane oculto no dispara clicks reales (click sintético como sonda) · sesión paralela regenerando rutas mata runs en vuelo (full reload) · CPU inference 30B ≈ 2-3 min/turno. Aura como superficie de presencia de la demo real ✅ (2026-07-22, corrección del usuario): el feedback de «¿está pensando?» NO se improvisa con chips — ES Aura (para eso se construyó). La sección real de la página agnt bootea un uix standalone mínimo (createActiveUix({langs sium+secs, defaultLocale es}) + setActiveUix + Soma.create() + ActiveEidos.create({applyDom, modeSource→tema del shell}) + eidos/index.css) — legítimo: un APP compone AMBOS tiers, la demo ES el app. Motor llama → createActiveAgent (mismas opciones: bus+journal; activeRun reactivo = AuraAgentSource; stream vía .engine.onEvent) y <Aura {agent}><Indicator/><Status/><Region/><Cancel> montada; los botones authorize/escalation quedan como afordancias app-level (doctrina §7: Aura da estados+cancel, la review es del app). Verificado sobre el run real: idle «Inactivo» → planned «Propone un plan» (langs es resuelto) → … → returned con announcement en Region «Agente: terminó — control devuelto» + doc mutado + answer es; Cancel=Button disabled-en-idle; consola 0. Gotcha entorno: canvas 300×150 sin dimensionar en pane oculto (rAF congelado — el orb pinta en Chrome visible; pixel-verificado en F3). Presencia perceptible + superficie radial ✅ (2026-07-22, diseño del usuario): Aura.Indicator default pasa al efecto orb de $scene (anillo vivo con ruido + luz orbitando — el aurora-banda leía estático a 32-48px; el usuario eligió el orb existente tras descartar mi halo inventado, que nació sin verificación visual — lección re-aprendida: Chrome real ANTES de enseñar). Modulación §F6: estado→energía (forceHoverState/hoverIntensity/rotateOnHover) + rol→delta de hue OKLCH ($color.safeParseColor). aurora queda variante (commit d008605fa). Patrón «Aura al centro de un OnionMenu» (trigger snippet = orb; sectores contextuales reviewing→Authorize/Reject · escalated→Approve/Deny · activo→Stop; auto-open con RE-ASERCIÓN mientras la custodia espera — un cierre externo re-abre) vivo en agnt §Real model + documentado en README de aura. E2E verificado en Chrome real contra qwen: la escalada real abre el anillo (orb ROJO al centro, Approve teal / Deny) → Deny → returned(aborted, user-cancel) + announcement + documento INTACTO. |
agent suite 30/30 · smoke · check |
| F5 · Reservas (cada una con gate propio, ninguna en v1) | deltas JSON Patch · skills semánticas (6g) · modo ambiental (si D-AG.3 lo firma dentro) · sub-runs/A2A · multiusuario · svrs/agent (solo si un consumidor real exige autoridad de servidor — respeta «transport app-land») |
— |
§5 · D-AG.12 — el contrato como REFERENCIA ✅ FIRMADA (2026-07-23)
Pregunta original del usuario (2026-07-22): «¿es el mejor diseño o podemos ir más allá y establecer una referencia?». Firmada tras investigación a fondo el 2026-07-23 (precedente externo verificado a esa fecha, no de memoria).
D-AG.12a — la spec y su conformance
Se extrae de docs/architecture/agent.md una especificación normativa —
«el contrato de delegación», en docs/spec/ — con:
- lenguaje RFC-2119 e IDs de requisito estables (
AG-1…n), - escalera de estabilidad por sección:
stable | provisional | reserved, - versionado por fecha (patrón MCP: la fecha marca el último cambio incompatible),
- la doctrina se queda como el PORQUÉ; la spec es el QUÉ.
Conformance en DOS vehículos, no uno (la distinción es la que evita que «suite de conformance» sea retórica — un lint del propio repo no acredita a nadie):
| Estrato | Vehículo | Naturaleza |
|---|---|---|
| Wire protocol v1 | kit de fixtures (semilla: ScriptedAgentTransport) |
PORTABLE — un tercero lo corre contra SU implementación |
| Contrato de participación | agent-check (D-AG.11) |
lint del repo sobre manifiestos |
Ambos citan IDs de requisito en sus fallos. Sin eso la suite no acredita.
Estado inicial: DRAFT. La spec se escribe ANTES de F4b para que F4b se construya CONTRA ella (spec-first), no después para describir lo que salió.
D-AG.12b — las dos reclamaciones de frontera
Se nombran en la spec con marcador de estado explícito (claimed vs
shipped), porque hoy ninguna está materializada:
- contexto por atención — reads push→pull priorizadas por focus/viewport
(señal UIX-nativa; F4). Hoy
claimed. - delegación como transacción — run = grupo de undo + OCC + write-scope +
superseded(⚖️3 + F2). Hoyclaimed.
Gate de promoción a 1.0 / «referencia»
≥2 FORMAS DE DOMINIO distintas, no «2º consumidor» (corrección firmada el
2026-07-23; ver §5b) + las dos claims con estado shipped + kit de fixtures
en verde. Precedente externo que lo respalda: MCP ya no promueve a Final
sin escenario en la suite (SEP-2484) y opera lifecycle formal
Active→Deprecated→Removed con ventana de 12 meses; AG-UI se volvió
referencia por ADOPCIÓN (AWS Bedrock AgentCore, Microsoft Agent Framework),
no por publicar suite. Conclusión: la spec se escribe antes para gobernar; el
título de referencia se gana después, con consumidores y claims reales.
Posición honesta que la spec DEBE declarar: acts secuenciales v1 ·
cliente-first con portabilidad exigida (svrs/agent diferido a consumidor
real) · generalidad en prueba.
§5b · Quién prueba el eje — FIRMADO (2026-07-23)
El gate de F4 pedía «2 manifiestos reales» sin asignar dueños. Esto rellena ese hueco; no enmienda nada firmado.
Criterio (el que sustituye a «el que esté disponible»):
El probador debe ser aquel cuyo manifiesto sea el más difícil de expresar — un formato lo decide su caso peor, no su caso fácil.
Aplicado, y con una razón que no es de conveniencia sino de anatomía del
propio contrato: los args de una capacidad SON schemas (sium →
toJsonSchema, F1 construido) y un run ES una transacción sobre un conjunto
de ediciones. Esquema y conjunto son las dos formas de las que el contrato
está hecho:
| Dueño | Forma | Qué fuerza a resolver |
|---|---|---|
form |
esquema | Args tipados vía sium + validación + write-scope por campo. Es el ÚNICO componente cuyo manifiesto el motor ya sabe escribir: agente→componente (args contra campos) y componente→agente (elicitación) son la misma proyección en los dos sentidos |
table / tree-grid |
conjunto | Actos sobre selección de N filas, OCC por fila, batch como transacción, superseded real. La claim «delegación como transacción» solo aguanta carga aquí; sobre texto es casi trivial |
Chat y palabras son CONSUMIDORES, no jueces. Chat entra por lo que solo
él da (provenance por modelo de mensaje · slot de actividad de tool · vista
conversacional de un run); palabras es un actuado más cuando su gate abra.
Ninguno decide el formato del manifiesto ni el gate de la spec. Riesgo que
esto evita, y que era real: chat y palabras son ambos texto lineal, así
que un manifiesto probado solo ahí asumiría texto en silencio (rango como
selección, ediciones secuenciales, args string) y el caso peor aparecería
tarde. Dato del inventario al firmar: 170 morfos, 0 declaran capacidad
delegate.
Corolario firmado — la elicitación NO depende de superficie conversacional.
Una pregunta tipada es un formulario en contexto: Form.AutoFields (ya
previsto en F4) la materializa, descartable y no-modal, que es justo lo que
exige el contrato a11y (WCAG 2.2.4). La nota del protocolo v1
(«materializes with the conversation surface») describía UNA opción, no una
necesidad; corregida en protocol.ts.
La entrada de delegación — patrón, no componente
Materializar el encargo (goal + contexto visible + autoridad) es un patrón con pieles, montado en app-land con piezas del framework — mismo veredicto que la review-card: el framework da estados, afordancias y piezas; el APP da el contenido en su dominio. Lo que el servicio aporta —reads priorizadas por atención— llega cuando exista (F4). Descartado explícitamente una entrada global siempre-disponible: roza el modo ambiental, que está FIRMADO FUERA (⚖️1) y no se recupera por la puerta de atrás.
§5 · Bifurcaciones que requieren TU elección (⚖️)
| # | Decisión | Estado |
|---|---|---|
| ⚖️1 | Modo ambiental (D-AG.3) | ✅ FIRMADO: fuera-reservado-con-nombre |
| ⚖️2 | Propagación causal del actor (D-AG.8) | ✅ FIRMADO: híbrido — token opaco de actor como baggage del envelope causal (comparte primitivo con la traza OTel); F1 solo el primitivo, retrofit ~6 costuras diferido a F3+ |
| ⚖️3 | Fallo a mitad de secuencia (D-AG.4) | ✅ FIRMADO: rollback-a-inicio default; parcial por-capacidad |
| §3 | D-AG.3–D-AG.11 (forma recomendada) | ✅ FIRMADO EN BLOQUE (2026-07-21) |
§6 · Qué NO entra en este track
Los 4 ejes de F-B de palabras, la provenance en el modelo del documento
(Block.origin), las puertas mudas del provider, api.transact y la
materialización del write-scope → track palabras. La doctrina de
data-actor como pintura derivada del modelo queda enunciada aquí
(D-AG.8/triage) y materializada allí.