Repository navigation
Conversation
Puerto Sandbox (exec/execWithNetwork/putFile/getFile, AutoCloseable) + DockerSandbox sobre el CLI docker vía ProcessBuilder (cero deps nuevas, misma filosofía "solo JDK" que los providers HTTP). Contenedor durmiente (sleep infinity), --memory/--cpus/--pids-limit, --read-only root + --tmpfs /tmp + HOME dentro del workspace (pnpm/next necesitan escribir cache), usuario no root, --rm. Sin red por defecto; execWithNetwork es la única vía con red (connect/disconnect con try/finally, SIEMPRE se desconecta incluso si el comando falla, timea o lanza). Timeout mata el contenedor entero (defensa en profundidad ante comandos colgados/comprometidos), no solo el proceso. Hallazgo verificado con Docker real: --network none en `docker run` impide reconectar red después (Docker lo rechaza) — el contenedor nace en bridge y start() lo desconecta de inmediato, comportamiento verificado idéntico a --network none pero reconectable. 25 tests (20 unit con ProcessRunner inyectado + 5 integración @tag integration/@EnabledIfDockerAvailable, ejecutados de verdad contra Docker real con alpine:3). Módulo completo: 91 tests, 0 failures, 1 skip preexistente (MimoLiveTest, sin API key).
…tenedor run_command/write_file/read_file/list_files/install_deps como @FluxorTool sobre un Sandbox activo. install_deps es la ÚNICA con execWithNetwork; el resto siempre exec sin red. Los fallos de comando (ExecResult) y de transferencia de fichero (SandboxException en putFile/getFile) se devuelven como datos en el resultado, nunca como excepción — el modelo los lee y corrige en el siguiente turno. Hallazgo: SchemaExtractor sabe anotar Optional<T> como no-requerido en el schema, pero ToolRegistry no puede bindear un Optional<T> SUMINISTRADO (el ObjectMapper compartido no registra jackson-datatype-jdk8). Sin nueva dependencia ni tocar ToolRegistry/Json (fuera de alcance): parámetros opcionales (timeoutSeconds, path/recursive) usan Long/String/Boolean nullable con default manual, documentado en el Javadoc de la clase. README del SDK documenta el uso, los defaults de seguridad y la advertencia de cadena de suministro (el sandbox aísla la ejecución, no audita el artefacto resultante). 12 tests nuevos con Sandbox fake. Módulo completo: 103 tests, 0 failures, 1 skip preexistente (MimoLiveTest, sin API key).
Port conceptual de AgenticMod (src/types/harness.ts:18-23,89) al SDK Java como
StepMod: la unión discriminada {id,name,type,config} de TS se colapsa en dos
hooks por interfaz (onRequest cubre pre_process/system_override/tool_provider;
onResponseText cubre post_process), usando el sistema de tipos como
discriminador en vez de un tag de string.
ModOverlay es la novedad "on-demand": colección efímera de mods por step
(forStep) o para todo el flow (forAll), con resolve(stepId) determinista
(forAll primero, luego específicos) — capacidad que no existe 1:1 en la IDE
(AgenticFlow no tiene mods propios), pero requerida por el caso de uso de
microajustes por prospecto en runtime.
5 builtins en mod/builtin/: SystemPromptMod (antepone/añade, análogo a
system_override), AppendGuidelineMod (conveniencia sobre SystemPromptMod
APPEND — la instancia mobile-first de #19), ForbidToolsMod (análogo a
runtime.blockTools), ProvideToolsMod (análogo a tool_provider/
runtime.attachTools; reutiliza ToolRegistry sobre ForkJoinPool.commonPool()
para no crear un pool dedicado por mod efímero) y RegexPostProcessMod.
Divergencia deliberada del TS: en el motor actual de la IDE, post_process NO
transforma la respuesta — solo inyecta un hint de texto antes de la llamada
(context-builder.ts buildPostProcessHint) y confía en que el modelo se
autoaplique la instrucción. onResponseText aquí es una transformación
mecánica real aplicada tras la respuesta, más fuerte que el comportamiento
TS actual, tal como exige el contrato del plan.
10/10 tests verdes (ModOverlayTest): orden de resolución, no-leak entre
steps, los 3 builtin con lógica no trivial (SystemPromptMod prepend/append/
inserción cuando no hay system previo, ForbidToolsMod no-op cuando no hay
match, RegexPostProcessMod).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ae85cHWqsJGWAFvD74dAHZ
StepExecutor.executeStep/executeStepText ganan un overload con ModOverlay (patrón idéntico al ya usado para DagTelemetry: overloads previos delegan al más completo con ModOverlay.EMPTY, cero cambio para callers existentes). onRequest se aplica en runToolLoop justo antes de provider.complete — es decir en cada turno del tool loop Y en cada intento de retry de schema (runToolLoop se reconstruye desde el history base, nunca desde una versión ya "moddeada", así que un mod no se acumula entre turnos); onResponseText se aplica sobre el texto crudo antes de extractJson/parse/validate, para que un post-process pueda rescatar un intento que si no fallaría el schema. ModContext reutiliza step.context() (el mapa que ya rellenan FlowExecution.withContext + los resultados de padres en el DAG) — cero plumbing nuevo para "config/estado del prospecto". ProvideToolsMod requiere una vía de despacho real, no solo de anuncio en el request: StepExecutor.invokeTool cae a los ProvideToolsMod del overlay resuelto cuando el nombre no está en el ToolRegistry compartido del step, así una tool on-demand es invocable de verdad, no solo visible para el modelo. FlowExecution.withMods(ModOverlay) — decisión donde el plan daba margen: el overlay debe llegar a StepExecutor incluso para el caso ad-hoc de un único step (FlowExecution siempre pasa por FlowExecutor.execute), así que FlowExecutor también gana el overload con ModOverlay (mismo patrón de delegación), no solo los 3 ficheros que enumeraba el plan — necesario para que "FlowExecution guarda el overlay y lo propaga por step" sea cierto para cualquier flow, no solo si StepExecutor se llamara directamente. StepConfig gana el campo opaco `mods` (JsonNode) con el mismo patrón de constructores compat que contract/model: el nuevo ctor de 8 args es el canónico, el de 7 (pre-mods) y el de 5 (pre-contract/model) siguen compilando y comportándose igual. withParentResults ahora preserva node.mods() en la copia "efectiva" del step, igual que ya hacía con contract/model. 8 tests nuevos (StepModExecutionTest): guía inyectada llega al request capturado; ForbidTools vacía el tools[] del request; post-process arregla JSON inválido ANTES de validar (0 reintentos consumidos); mismo mod aplicado a un step de texto; sin overlay el LlmRequest es estructuralmente idéntico (record equality) entre el path pre-mods (2/3-arg) y el nuevo con ModOverlay.EMPTY; un StepMod contador prueba que onRequest se reinvoca en cada intento de retry (2 llamadas para 2 intentos); ProvideToolsMod anunciado Y despachado de extremo a extremo; FlowExecution.withMods propagado a través de FlowExecutor hasta StepExecutor con FluxorRuntime real. Suite completa del SDK: 121 tests, 0 fallos, 1 skip preexistente (MimoLiveTest) — 103 baseline (#17) + 10 (Task 1) + 8 (Task 2). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ae85cHWqsJGWAFvD74dAHZ
Añade la sección "Mods (on-demand overlay)" al README del SDK, mismo estilo y nivel de detalle que la sección "Sandbox" ya existente: ejemplo de uso de ModOverlay/withMods, contrato de StepMod, los 5 builtins y la garantía de no-regresión (sin overlay, el pipeline es idéntico al de antes de mods). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ae85cHWqsJGWAFvD74dAHZ
…— inicio de la adopcion Declara la dependencia por coordenada (nombre+version, nunca vendorizada) hacia el motor cerrado de canvas/chrome de Javadaba (ADR 0003, javadaba-web Core): .npmrc con el scope @javadaba apuntando a GitHub Packages, dependencia en package.json y un smoke test que fija que Vitest resuelve el paquete. El registro aun no tiene la version publicada (Task 9 Step 3, pendiente de autorizacion + token); mientras tanto se consume via `npm link` en local (bitacora en docs/superpowers/backlog/2026-07-17-daba-engine-registro-privado.md, gitignored por convencion de este repo — artefacto de planificacion de agentes, no producto). Anadido resolve.dedupe: ['react','react-dom'] en vite.renderer y vitest config: un paquete enlazado resuelve su propio node_modules/react (via symlink a la ruta real) si no se fuerza una copia unica.
…a/daba-engine Adopcion del motor de canvas/chrome propietario (plan #20, javadaba-web Core), Task 10 -- las piezas "hoja" (sin dependencia del sustrato de camara, que sigue pendiente en Task 12): - HUD: HudWidgetLayer conserva su shell (WidgetWrapper, close button, drag/ resize por mouse, testids exactos) pero la matematica de snap/clamp/ colocacion anti-solape ahora es un adaptador fino (logic/hud-widget-policy.ts) sobre @javadaba/daba-engine/core/hud-grid -- logic/hud-grid.ts (188 LOC + su test) queda borrado. La SAFE_ZONE reservada (ExpandInspectorButton) se pliega en la lista `others` del motor en vez de su opcion `safeZone` (semantica opuesta: el motor CONFINA a esa zona, Fluxor necesita EVITARLA) -- resuelto sin tocar el motor. - Tutoriales: TutorialEngine.tsx pasa a ser un wrapper fino sobre el TutorialEngine del motor (maquina de estados + tracking rAF del target + salto por timeout), conservando el 100% del look de Fluxor (fondo sketchbook + doodles + anillo de color por escenario + BrutalistTutorialCard) via los nuevos renderBackdrop/renderCard(...,targetRect) del motor. - Menus contextuales: las 3 implementaciones custom (CanvasContextMenu.tsx, WindowContextMenu.tsx, el inline de NodeTree.tsx) se consolidan en providers declarativos sobre el ContextMenu unico del motor, con data-testid/labelColor passthrough para conservar selectores e2e existentes (canvas-ctx-*, ctx-menu-*, nodetree-ctx-*). - index.css/index.tsx: tokens --daba-* mapeados a la paleta oscura actual de Fluxor (iso-visual) + import de tokens.css/engine.css del motor. Gaps de contrato reales encontrados y resueltos EN EL MOTOR (interface-first, 3 commits en javadaba-web Core, ver su CHANGELOG): TutorialEngine.renderCard gana targetRect + renderBackdrop; ContextMenu gana testId/labelColor passthrough + previene el contextmenu nativo en su backdrop. Verificado: tsc --noEmit limpio, npm test 1582/1582 (-34 del hud-grid.test.ts borrado), npm run lint 0 errores (269 warnings preexistentes). e2e (Playwright+Electron) NO se pudo ejecutar en este sandbox -- Electron no abre ventana aqui (reproducido identico en el commit previo a este Task, no es una regresion); verificado en su lugar por revision manual exhaustiva de los data-testid/selectores que e2e/*.spec.ts espera.
…ton + DabaCanvas pan/pan-layer
Task 12 (Cortes 1-3, adoption plan #20): canvasPan/canvasZoom en desktop-store
pasan a ser un espejo de la camara de @javadaba/daba-engine en vez de estado
propio. engine-bridge.ts es el singleton de modulo que hidrata el EngineStore
desde el desktop-store ya persistido, refleja los cambios del motor de vuelta
al espejo (onChange crudo, sin reentrancia) y parchea setCanvasPan/
setCanvasZoom/_pushCameraToEngine sobre el store ya construido (desktop-store.ts
no puede importar este fichero sin crear un ciclo — el mismo tipo que ya evita
con harness-store). switchBoard y la rama activa de deleteBoard empujan la
camara del tablero entrante al motor; duplicateBoard no (nunca toca la camara
activa). navigateToWindow (usado por Dock.tsx) tambien se corrige: hacia un
set() crudo de canvasPan que hubiera desincronizado el espejo del motor.
SeamlessCanvas.tsx monta <EngineProvider store={engineStore}><DabaCanvas> en
vez de su propio root+pan-layer: pan por boton medio (shouldHandleBackgroundGesture,
button===1 solo — sin Alt-drag, Fluxor nunca lo tuvo) y la pan-layer (transform
CSS) pasan al motor; marquee, ctrl/cmd+wheel zoom (paso fijo, sin ancla al
cursor) y el menu contextual de fondo (via onBackgroundContextMenu) siguen
siendo dominio de Fluxor. rootProps conserva testid/aria/data-*/handlers de
raton exactos sobre el root del motor; panLayerClassName="desktop-pan-layer"
mantiene los selectores de los e2e existentes. DesktopCanvasBg pasa a
overlay con z-index:-1 (antes hermano ANTES de la pan-layer por orden DOM;
ahora el overlay del motor siempre pinta despues). CanvasContainerBridge
expone el nodo real del motor (useDabaCanvasContext) para el ResizeObserver
de canvasSize y el listener nativo de wheel (no sintetico, necesita
preventDefault real). index.css: el selector de will-change durante zoom pasa
de compuesto (.desktop-pan-layer[data-zooming]) a descendiente
(.desktop-canvas[data-zooming] .desktop-pan-layer), ya que data-zooming solo
puede ir en el root ahora — esto tambien revive [data-zooming]
.desktop-window-shell{transition:none}, su intencion original.
MentalGraphCanvas.tsx no requiere cambios: ya lee canvasPan/canvasZoom del
espejo y escribe via setCanvasPan/setCanvasZoom (ahora delegadas), no set()
crudo.
DesktopWindow.tsx: ni una linea (Opcion A — espejo, no CanvasItem controlado).
SnapGuides/calculateSnapGuides/activeSnapGuides: sin cambios (deuda registrada,
desviacion del plan original justificada por iso-behavior).
Motor: vendorizado via npm link contra javadaba-web@31416c4 (fix: pan por
boton-medio ya no exige gesto sobre el fondo del canvas).
Tests: 12 nuevos en engine-bridge.test.ts (hidratacion, propagacion motor->
espejo, delegacion accion->motor, ida-y-vuelta sin reentrancia, flujo
switchBoard/deleteBoard/duplicateBoard). 1594/1594 unit verdes. e2e:
dock-fixed-on-pan 4/4, desktop.spec.ts Canvas Panning and Zoom 6/6 (ctrl+scroll
flaky conocido, verde en retry). Suite completa: 287 passed/29 failed/1
flaky/6 skipped — los 29 fallos son exactamente el baseline preexistente.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Toggle "Snap to grid" en SettingsModal (default OFF, preset de tamano de celda 16/24/32 px, default 24) espejado uno-a-uno en engine-bridge.ts hacia snap.grid del motor (fluxorWindowGridSpec — NO DEFAULT_GRID_SPEC, que es la rejilla de iconos de web-os). DesktopWindow y MentalGraphCanvas cuantizan la posicion SOLO en el commit del drag (via resolveSnap del motor, guides.enabled=false): las guias de alineacion de Fluxor mandan primero (calculateSnapGuides intacto); si ninguna magnetizo y el toggle esta ON, cuantiza a rejilla. Resize y moveSelectedWindows sin tocar. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…ado sobre daba-engine (Task 13, Fase 2) NodeTree/SideBar sobre <ComponentsPanel> e InspectorPanel sobre <SideToolbar> (motor), completando la adopcion iniciada en Task 12 (camara) y continuada en Fase 1 (snap-to-grid). NodeTree conserva solo datos/decoracion de dominio (grupos 1:1 con los 8 de hoy, renderRow por kind, rename/locate/context-menu); el shell (headers, hover, rename in-place, empty state) es ahora del motor. engine-bridge.ts gana tres espejos nuevos, todos documentados in-line: - engine.items: windows/grids/mental-nodes(mental|step|flow)/attachables, ids namespaced kind:id. Cache por-id de EngineItem MUTADO in-place para geometria/label (nunca dispara setState) y solo notifica al motor en altas/bajas — SideToolbar suscribe TODO state.items sin acotar a la seleccion, y MentalGraphCanvas commitea posicion en cada frame de un drag; sin este patron, cualquier drag de un nodo NO seleccionado reconciliaria el Inspector entero (regresion que InspectorPanel.test.tsx ya vigilaba con un Profiler antes de esta tarea). Los lectores (locate(), seed de rename) leen en el momento del click sobre la MISMA referencia mutada, asi que siguen frescos sin necesitar notificacion. - engine.selection: unidireccional desde selectedMentalNodeIds (nunca selectedWindowIds — el Inspector sigue ignorando seleccion de ventanas). - hover/collapse bidireccionales: engine.hoveredItemId <-> hoveredWindowId (solo ventanas; grids/mental/step/frame leen el hover del motor directamente, ya estan dentro de su EngineProvider) y engine.chrome.panels.sideToolbar <-> settings.showInspector (persistencia sin cambios). Mismo patron de reentrancia que la camara (Task 12): raw set() en el onChange del motor, nunca la accion publica envuelta. Highlight unificado: MentalNode/StepNode/FrameNode leen engine.hoveredItemId directamente (data-daba-highlighted + outline var(--daba-highlight)) — antes solo las ventanas lo tenian. Tokens --daba-accent/--daba-highlight/--daba-accent-contrast/--daba-radius-lg/ --daba-marquee-* mapeados al azul de marca en :root. ExpandInspectorButton.tsx borrado; su rol lo cubre el boton colapsado de SideToolbar (CSS lo reposiciona fixed al mismo rincon via .inspector-side-toolbar.daba-side-toolbar__expand, ya que ese boton no tiene prop de testid/posicion propia). Contenido interactivo anidado dentro de renderRow (chips de rol/mod/flow, child-windows de un grid, StepRows de un flow) hace stopPropagation en click/dblclick/contextmenu para no disparar ademas el locate()/context-menu de la fila padre del motor — antes eran filas hermanas sin bubbling que gestionar. Cubierto por NodeTree.nestedRowIsolation.test.tsx. centerViewportOn (NodeTree.tsx) pasa a delegar en el centerOn del motor (viewport lazy = innerWidth-280/innerHeight-60, sin insets) en vez de reimplementar la formula — verificado con valores dorados contra la formula antigua en NodeTree.locateViewport.test.tsx (desviacion respecto al plan original, que esperaba cero referencias a centerViewportOn; anotado para Task 14 por el orquestador). Gates: unit 105/105 archivos, 1652/1652 tests; lint 0 errores (262 warnings preexistentes, ninguno nuevo); tsc 0 errores; e2e diferencial limpio (287 passed / 29 failed — exactamente la lista permitida / 1 flaky en retry / 6 skipped). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…arcial) Cierre parcial del barrido del satélite (Task 14 Step 1): - hud-grid.ts → hud-widget-policy.ts: actualiza las últimas referencias-comentario a la ruta nueva (Dock, HudWidgetLayer, desktop-store, desktop-store.test). El único hit de "hud-grid" que queda es el comentario histórico de desktop-store.ts que apunta al core/hud-grid del motor (intencional). - index.css: retira el chrome muerto del inspector (.inspector-header/-label/-collapse-btn/-body) que Task 13 Fase 2 movió al SideToolbar del motor; reescribe el comentario de --daba-accent (los tokens SÍ están mapeados en :root vía tokens.css del motor — la regla del motor resolvía a azul, no a valor inválido; el override mantiene el morado de mental-mode). - Dock.tsx: siembra startPos.current con el origen del drag en onAttachDragStart — sin ello el ghost del attachable quedaba clavado arriba-izquierda (solo el delta lo movía en vez de seguir al cursor). - desktop.spec.ts: aclara el comentario del test grid skippeado. Pendiente para cerrar Task 14 (detalle en la bitácora satélite docs/superpowers/backlog/2026-07-17-daba-engine-registro-privado.md): Step 1 restante — migración diferida de guías (SnapGuides)/ DottedBackground/centerViewportOn al motor (Task 12-bis); Step 2 — consolidación del motor 0.2.0 (vendor tarball y/o publicación al registro npm privado, acción del humano con credenciales); Step 3 — suite e2e 14/14 verde (entrelazado con la deuda e2e legacy #4 del backlog de producto); Step 4 — commits finales (Core CHANGELOG + satélite). Task 15 (docs/gobernanza del workspace) pendiente. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…ing + body sections Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
… runState Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…ged + runState param Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…inimal bento shell Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Ports STATUS_CONFIG/PRIORITY_CONFIG verbatim from the frozen reference (shapes, order, colors, icon set) onto the project's LucideIcon name-based lookup (no lucide-react dependency here). Labels are EN by default per the task doc's resolved decision #2 (IDE-wide text consistency), centralized in this one table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Ports the reference's 2-7 sided polygon indicator (line/triangle/square/ pentagon/hexagon/heptagon) verbatim — same viewBox, points, strokeWidth. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Ports the "Epic: X" pill verbatim as its own component; returns null when epic is absent (F0 spec §1.1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Ports the reference's per-card JSX verbatim (drag-info block, status shape + badge + EpicBadge + title + excerpt + tags, created/updated metadata, desktop + mobile variants). excerpt is derived from description's first non-blank line (not persisted, F0 spec §1.3); dates format ISO-8601 to the reference's DD-MMM-YYYY. Adds a minimal isSelected ring (multi-select behavior preserved from the deleted kanban widget; not in the reference) and a runStateOverlay slot reserved for F4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…order Single SortableContext (no more 4 columns) wrapping the reference's filteredAndSortedCards derivation (status.order primary, card.order secondary — F0 spec §1.1) and empty state, ported verbatim. DnD behavior layer (PointerSensor+KeyboardSensor, meta/shift multi-select scoped to same status, reorder persisted via updateBacklogCards) reconstructed from the deleted BacklogKanbanWidget.tsx (git history a0e6e65). Status is never touched by drag — only order, globally dense — matching the reference's own full-array splice semantics. Native HTML5 DnD -> @dnd-kit (Gate 1 deviation #3); the reference's "whole card draggable" look is preserved via a thin unstyled sortable wrapper, no added grip-handle chrome. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Ports the reference's search input + status chip row verbatim, including its own white/black-border card chrome. searchTerm/activeStatuses are controlled props so BacklogBentoWidget owns the filter state, matching the reference's own state placement. Hand-rolled inline SearchIcon -> LucideIcon name="Search" (same glyph). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Ports the reference's modal sidebar verbatim (priority, estimate, tags, assignees, created/updated history). Assignees empty state is "Unassigned" (EN) per the plan's Task 8 note / task doc resolved decision #2, overriding the reference's "Sin asignar". No dedicated test — pure presentational leaf, covered by BacklogCardModal's integration tests (Task 9). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…mments Replaces the F2 Task 1 shell with the full modal ported verbatim from the frozen reference (header with editable title/status, description edit, attachments, related-tasks navigation that swaps canvasModalCard in place, comments + input, BacklogModalSidebar). Canvas-level fixed/sticky/max-h-[90vh] positioning is unchanged (legitimate full-app overlay by design, not the widget-wrapper "wrapper-relative" deviation). New supporting plumbing this task required: - fluxor:update-backlog-card-content IPC handler (main) — generalizes update-backlog-card-status's read-modify-write shape to the body (title/ description/comments) via parseBacklogCard + renderBody + serializeBacklogCard; new comments append at the end (F0 spec §1.2). - updateBacklogCardContent on FluxorAPI (types/index.ts) + preload wiring. - desktop-store.activeBacklogDir (+ setter): a small new transient field so this canvas-level modal (mounted outside the widget's own wrapper) knows which directory to persist edits into — necessary for correctness across multi-project/external backlogs, not just the default in-project one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
… the bento widget Final F2 component: wires BacklogFilters + BacklogPile + the picker/init/scan behavior layer into the bento widget, completing the 1:1 port. Removed debug scaffolding left mid-implementation; stabilized the auto-select widget test (assert on the settled pile card before the sibling filters testid, which flashes during loadCards' loading toggle — component behavior unchanged). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
Net-new presentational component (no frozen-reference counterpart): a compact/full-variant dropdown offering "Run on existing flow" (nested frame-picker submenu), "Autoflow", and — only when the card carries an epic and a handler is supplied — "Run epic as flow". Every action is a callback prop; the component never touches a store or IPC directly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…inst the bento UI Replaces every .fd-*/.backlog-kanban/4-column assertion with the new bento pile's real testids (backlog-bento-widget, backlog-pile, backlog-card, backlog-filters, backlog-card-modal, launch-menu-trigger, run-state-overlay). Ports each old test's intent (open/render, modal open+Escape-close, priority display, multiple-cards rendering) and fixes the baseline's one backlog failure: the empty-state test now seeds one card to reach the pile view then clears it, asserting the pile's own data-testid="backlog-pile-empty" markup instead of tolerating three unrelated strings behind a best-effort waitForFunction. Adds coverage the old suite never had: status filter chips actually filter, search actually filters, and one launcher (autoflow) fires end-to-end with the Meta-Agent/harness IPC bridge mocked (same round-trip constraint documented in new-features.spec.ts's Auto-Chat coverage), asserting a real frame materializes and the card optimistically flips to doing/running. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…nD model Ports each describe block's intent onto the single-pile model: order field still sorts within the same status; multi-select (meta+click toggle, shift+click range) now scopes ranges to matching status (BacklogPile.tsx's handleCardSelect); a keyboard-driven pick-up/ move/drop reorder exercises the same onDragEnd + updateBacklogCards persistence path a pointer drag would, deterministically. Drops the 4-column kanban board and "Reorder by Priority" Sort button coverage (both retired by the F2 Task 1 cutover — BacklogBentoWidget.tsx's own header comment confirms reorderByPriority was intentionally not ported). Batch update IPC coverage now also checks the runState field on update entries. File was renamed from kanban-dnd.spec.ts in the prior commit; this commit is its content rewrite against the new bento DOM. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…xtBridge-unmockable Meta-Agent) The autoflow launcher calls window.fluxorAPI.assemblePipeline — the same seam the working HudAutoChatPanel uses — which is contextBridge-frozen (contextIsolation:true + preload's exposeInMainWorld), so page.evaluate cannot stub it to materialize a frame without a real AI backend (verified via a store probe: mentalNodes stays empty because the real IPC fails offline). Not a product bug — the launcher is identical to HudAutoChatPanel and fully covered by launchActions.test.ts / LaunchMenu.test.tsx / epicPipeline.test.ts. Follow-up: a mockless variant driving the "flow por épica" launcher (pure in-renderer epicToPipelineAssembly mapper, no Meta-Agent IPC). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
…dow-leak strict-mode) Adds a beforeEach that removes all desktop-store windows and opens a single backlog window, so page-scoped card locators stop matching the same card across leaked windows (the single-session persistence let them accumulate). Fixes the Keyboard-reorder + Order + Batch tests. The 3 Multi-select meta/shift+click tests still fail on a separate click-interaction issue (the feature itself is covered by BacklogPile unit tests) — documented residual. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rnz9QsXbdJSzzKMC46vnVu
crashReporter only catches native crashes; an uncaught exception, an unhandled rejection or a killed renderer left nothing behind at all — in dev they print to a terminal that dies with the process, so a crash was forensically silent (empty Crashpad dir, no .ips, no log). installFatalHandlers() adds four listeners that append one durable line each, with zero change to crash semantics: uncaughtException uses prependListener so Electron's own handler still runs, unhandledRejection rethrows to restore Node's default throw-on-unhandled, and the two process-gone events are purely observational. log.fatal() is a new sink that always writes to disk (unlike log.error(), which prefers the console and only falls back when the console itself is broken). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Task 3: findOwningPhase mirrors findOwningFrame one nesting level deeper, for canvas/UI consumers that need "which phase visually owns this step". Task 4: compileFlowFromCanvas gains a phase block structurally parallel to the loop block — same map reuse (stepById/nextByStepId/prevByStepId/ reachableSet), same throw-naming-the-offender discipline. Validates non-empty, resolvable, connected (undirected BFS over the member set), disjoint, unique-id, onError === 'halt'; dedups repeated stepIds. A scoped (includeIds) compile silently omits a phase whose real members are only partly included, but still throws for a stepId that is no step at all. flow.phases is omitted entirely when the canvas declares no phases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Task 6: addPhaseNode mirrors addFrameNode one nesting level deeper and re-parents its named child steps from the frame to the new phase, so the canvas hierarchy and the compiled AgenticPhase.stepIds agree from creation. updatePhaseData mirrors updateFrameData. Task 7: removeMentalNode on a phase DISSOLVES it — children are re-parented up to the owning frame, never deleted (spec §1.1: a phase is pure grouping, so deleting the label must not delete the work). Frame behavior is unchanged. Beyond the plan: the frame cascade now descends to a fixpoint instead of one level. addStepNode never registers a step in the frame's own childIds, so the cascade relies on the parentId scan — once a phase sits between frame and step, the single-level pass deleted the phase and stranded its steps with a parentId pointing at a node that no longer existed. Covered by a new test; with no phases on the canvas the loop converges on the first pass, so the removed set is byte-identical to before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Title (inline-editable) + member count, nothing else — a phase never runs on its own, so no Run/Export control; no exitContract/onError editor either, mirroring AgenticStep.contract's own status quo. Beyond the plan, two things were needed to make it actually render: - MentalGraphCanvas maps store nodes to React Flow nodes by type, and a phase with no branch fell through to the mental-card default. Added a branch parented to its frame (extent: 'parent') and z-stacked between frame (0) and step (2). - addPhaseNode now splices the phase in right after its owning frame instead of appending. React Flow resolves parentId positionally and needs a parent before its children — appending put the phase after the steps it parents, which would render them detached. Covered by a new ordering test. CSS follows .pipeline-frame-node's grammar (fills its box, dashed border, dashed->solid state cue) but subordinates it on every axis the eye scans first — violet not neutral, tighter radius, no blur/shadow, smaller chip — so the two nesting levels never read as peers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
…kpoint Task 10: Checkpoint/SaveCheckpointInput gain an optional phaseBoundary, frozen at creation from the flow's phases as they were when the run executed, so a later flow edit can never corrupt a historical marker. Same conditional-spread discipline as iteration/contextFileSnapshot — omitted entirely, never undefined-valued. SqliteCheckpointStore mirrors it as one JSON TEXT column (the marker is a nested object, not two flat scalars). Task 11: findPhaseStartCheckpoint is the ONLY new piece resume-from-phase- start needs — a pure query composed with the UNCHANGED replayFrom by the caller. replay.ts keeps zero diff. Task 12: CheckpointRecord mirrors the field for the renderer; the IPC handlers already pass Checkpoint objects through unreshaped, so no runtime code changed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
…cutor Mirrors the existing loop sanity block: unique ids, non-empty, resolvable stepIds, connected subgraph (undirected BFS over the member set), pairwise disjoint, onError restricted to 'halt'. Necessary because an AgenticFlow can reach the executor without ever passing through compileFlowFromCanvas — hand-built, imported, or SDK-constructed. A flow declaring no phases skips the loop entirely and is byte-identical to today. loop-plan.ts and replay.ts keep zero diff (red-line 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Capa 1 runtime is now complete and observable. Task 14 — per-run bookkeeping (buildPhaseRuntimeState) counts each phase's expected instances from the ALREADY-EXPANDED ExecutionPlan, so "the phase's last instance" is correct for a phase spanning a loop body. loop-plan.ts is read, never touched. The `before` snapshot is lazy: taken once, only when the phase actually declares an exitContract, so a phase without one costs zero extra snapshots (covered by two tripwire tests counting readdir calls). Task 15 — at the last instance: `after` snapshot, verifyStepContract (guardrails.ts, unchanged), throw on breach naming the phase. The throw lands before saveCheckpoint, so the breaching instance persists no checkpoint — exactly what an uncaught step error already does. maxAttempts is inherited from StepContract's shape and deliberately ignored: the gate never retries. Without a fileSystem the gate is skipped rather than run against an empty snapshot pair, which would false-positive on mustWriteFiles. Task 16 gate: 1819/1819 unit, tsc clean, and zero diff in loop-plan.ts and replay.ts (red-line 2) and in loop-plan/replay/guardrails tests (red-line 4). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
…-log fix Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
Measured, not estimated. Full suite at HEAD: 64 failed, all confined to 3 spec files. Those 3 re-run at the pre-#6 commit 7b3b196: 63 failed. The single delta (desktop.spec.ts:1239) is a confirmed flake — fails in one full run, passes in a second full run of the same file, passes in isolation, and fails via a pointer-interception timeout from the auto-chat HUD widget, not a logic error. Excluding it, the failure sets are identical element by element (59 desktop + 3 backlog-dnd + 1 mental-map). Pins the real e2e baseline at 63 (ONGOING carried "~62", too imprecise to decide a differential gate on), with the per-file breakdown, and records the comparison method for the next gate. Also closes #5's residual 3: mental-connections.spec.ts passed in both runs, confirming those 2 failures were flakiness and not a #5 regression. Diagnoses mental-map.spec.ts:318 for #4 — it races its own consumer, StepConfigCore clears pendingStepFocusId on mount. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4KQV8enMqyweDppzHqcDm
…in reasoning cap The openrouter branch used createOpenAI()(id), which defaults to the OpenAI Responses API (/responses) and is rejected by OpenRouter with a misleading 401 "User not found". Use .chat() (mirrors the mimo branch). Add opt-in FLUXOR_OPENROUTER_REASONING_EFFORT to cap unbounded reasoning (e.g. Kimi K3) via a request-body fetch wrapper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RShBDkQ5Cz2WoCnQj7D4ci
…ruth Anonymize model_under_test in the judge prompt to kill self-preference bias; add opt-in FLUXOR_JUDGE_MODELS ensemble (median per-dimension aggregation + majority verdict); wire real axe-core structural a11y (design-verifier) as groundTruth.a11y for the team-work suite. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RShBDkQ5Cz2WoCnQj7D4ci
…Coverage contract The guardrail no longer surrenders early on a stall; it escalates the deterministic corrective (literal filenames) and retries until maxAttempts. Add StepContract.haltOnBreach to halt instead of cascading on a broken foundation. Add StepContract.localeCoverage: verify every t() key is defined in a catalog and, optionally, actually translated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RShBDkQ5Cz2WoCnQj7D4ci
…ocale mods Scope auth-guarded to protected surfaces (public landing + auth pages must stay unguarded); a11y-enforcer landmark uniqueness; web-vitals no-binary-asset rule. Reframe i18n-ready as the i18n technology mod (flat dotted catalogs) and add per-locale completeness mods locale-en/locale-es, each carrying its own localeCoverage contract. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RShBDkQ5Cz2WoCnQj7D4ci
…steps) Define public/protected route topology (/ public, /app guarded) and add i18n/landmark/inline-SVG guidance; decompose SEO into a dedicated seo-head step and i18n into i18n-source-en + i18n-translate-es (tech x per-locale mods); haltOnBreach on scaffold + maxAttempts bumps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RShBDkQ5Cz2WoCnQj7D4ci
…pp E2E
@electron-forge/plugin-vite does not copy node_modules when packaging: its own
packageAfterCopy writes a package.json and nothing else. Every module
vite.main.config.ts keeps external therefore vanished from the installed app.
The packaged asar's only top-level entries were /.vite and /package.json, so
the main process threw MODULE_NOT_FOUND on the hoisted require("better-sqlite3")
before any handler was installed and NEVER opened a window. Invisible in
development, and invisible to the existing E2E suite too, which launches the dev
bundle from the repo root (e2e/global-setup.ts).
forge.config.ts now copies the dependency closure of better-sqlite3, jsdom and
playwright, computed by walking manifests instead of hand-listing (jsdom alone
pulls 37 transitive packages). Resolution follows Node's ancestor walk, not just
the immediate directory: jsdom keeps a nested tr46@6 that requires punycode,
which a hoisted-only walker never sees — jsdom then dies with "Cannot find
module 'punycode/'" in the package while resolving fine in dev. asar also gains
unpack: '**/*.node', since dlopen cannot load a library from inside an archive.
e2e/packaged-app.spec.ts is the harness that can see this class of defect: it
launches the packaged binary and asserts the window opens, the renderer comes
from file:// and not a dev server, db:status round-trips through the native
addon, and playwright/playwright-core still resolve (both lazy, so startup
would not notice them missing). It isolates BOTH its userData dir and its cwd —
--user-data-dir alone is not enough, since startup runs
migrateLegacyDirectories(process.cwd()), which renames directories in whatever
cwd it is given.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4jBQV1oevWP438MT8S2Lk
The job already runs `electron-forge package` (it needs .vite/build for the dev-bundle specs), so the packaged app is sitting right there unused. Every other spec launches Electron against the repo root, which makes the whole suite structurally blind to defects that only exist once packaged — the reason the missing-node_modules break shipped unnoticed. The spec self-skips when no package is present, so it stays free for anyone running plain `npx playwright test`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G4jBQV1oevWP438MT8S2Lk
`@javadaba/daba-engine` becomes `@cmolg/daba-engine`, and the dependency is now pinned to the EXACT published version (`0.2.0`, no `^`) instead of `^0.1.0` — a range that could not even match what exists, and that an installable must not use anyway: two builds of the same commit could otherwise ship a different engine. Why the scope changed: GitHub Packages ties the npm scope to the login owning the repository. The engine's source lives in `CMolG/javadaba-webpage`, so `@javadaba/*` answered `403 permission_denied: create_package`; no token fixes that, since the Actions `GITHUB_TOKEN` also authenticates as `CMolG`. The `javadaba` login has been held since 2011 by an unrelated third party and GitHub shares one namespace between users and organisations, so an org of that name was not available either. The user's decision (2026-08-07): private packages go to `@cmolg` on GitHub Packages, public ones stay `@javadaba` on npm. With the scope fixed, 0.2.0 is published, so this repo stops depending on `npm link` and installs for real.⚠️ This is a PUBLIC repo now depending on a PRIVATE package: whoever clones it without registry access cannot `npm install`. That is the accepted trade-off of ADR 0003 (closed engine, open Fluxor) and it is now stated outright in `.npmrc` rather than left to be discovered. 28 files, 42 occurrences. Verified against the registry (real directory, not a symlink; lockfile pins `npm.pkg.github.com` with integrity; only `dist/` ships, no source): 116 suites / 1832 tests green, the engine smoke test among them. NOTE FOR WHOEVER OWNS THE WIP ON THIS BRANCH: nine files had uncommitted work in progress (HUD widget layer and friends, plus `tsconfig.json` paths). This commit carries ONLY the rename for them — their content was taken from HEAD and renamed, so the working tree keeps that work untouched and still uncommitted. The `tsconfig.json` engine paths are part of that WIP; they have been renamed in the working tree but are NOT in this commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G4jBQV1oevWP438MT8S2Lk
Un README describe lo que alguien creyo cierto el dia que lo escribio. Si lo que describe cambio DESPUES de su ultima actualizacion, esta obsoleto y se corrige en el mismo cambio que lo dejo desfasado. Y actualizar no es solo anadir: a menudo lo correcto es borrar una seccion de algo que ya no existe, o corregir una que cambio. Un README que solo crece acaba siendo un museo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G4jBQV1oevWP438MT8S2Lk
…aph updates Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UdGUj3YQrsigqpnrJaDNHx
… (F1) Una ventana 'agent-session' aloja el CLI del proveedor (claude/codex/opencode/ gemini) en un PTY real: registro de proveedores + PtyManager con spawn inyectado en src/main/pty/, xterm.js en AgentSessionApp, selector en el dock y log por sesion en userData/sessions/. node-pty es N-API y carga bajo Electron 41 sin electron-rebuild, pero su prebuild trae spawn-helper en modo 644 y todo spawn muere con "posix_spawnp failed."; lo repara un postinstall y lo verifica scripts/pty-smoke.cjs. Un binario ausente se detecta con `which` (mismo mensaje que un cwd malo) y vuelve como valor vendor_not_found, no como excepcion. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QojUyqMC7XjBngED3zjsfX
…sión adjunta (F2) Una sesión abre en su propio worktree y su propia rama antes de que arranque el agente: crear en .claude/worktrees/<nombre> desde un origin/main recién traído (si el fetch falla se sigue con el ref local y se informa cuál se usó), instalar por lockfile con override por proyecto, y al terminar decir si el worktree está gastado — con la prueba de rama-al-dia.sh, contenido y gh, nunca ascendencia, que es lo que miente tras un squash. El borrado se quita el directorio y CONSERVA la rama. Y una sola sesión adjunta por proyecto (invariante 16 hecha mecanismo): la segunda no se bloquea, se ofrece abrirla en un worktree. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QojUyqMC7XjBngED3zjsfX
…ck y carril Needs you (F3) Cuarto `LaunchMenu`: proveedor (no instalados deshabilitados con el motivo) y modo worktree/attached, cada uno con su razón cuando no aplica. Prompt de lanzamiento propio (≤1.200 car.), sin persona ni system prompt. Un fichero, dos claves: el agente mueve `status`, el Cockpit escribe `runState` —running cuando el PTY existe de verdad, completed/failed según lo que el agente dejó, no según el código de salida—. En worktree escribe la copia del worktree y espeja su `status` en la tarjeta. Las HUMAN salen de la pila a un carril fijo con lo que desbloquean y sin lanzador; una nueva se convierte en aviso. Arreglado de paso el registro no idempotente de `registerPtyIpcHandlers` que F2 dejó anotado. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QojUyqMC7XjBngED3zjsfX
…iones (F4)
Endpoint `http` en loopback con token por sesión en la ruta: 200 {} inmediato,
404 para todo lo demás (nunca 401: confirmaría el id), 413 y 400. Los cinco
hooks viajan como `--settings` en línea —no se escribe ningún fichero— y se
parsean las DOS grafías, porque el binario y la documentación no coinciden.
La atención es una máquina pura. Armado es una afirmación, recibido es la
prueba: hasta el primer evento mandan las heurísticas de F1, y la ventana avisa
si nada llega. Un aviso por tramo de espera, nunca por evento.
Preset Cockpit (tablón a la izquierda, rejilla a la derecha, sin solapes) y
lista de sesiones con Focus y End. e2e con el fixture posteando por curl.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QojUyqMC7XjBngED3zjsfX
…a en el worktree (F5) Un worktree se corta de `origin/main`, asi que una tarjeta que aun no ha llegado alli no esta en el checkout y la primera linea del prompt apuntaba a un fichero ausente. `seed-card.ts` la copia entre `worktree-create` y el bootstrap: nunca sobrescribe, crea `.backlog/` si falta y lo dice en la terminal. Con ella, la costura `FLUXOR_AGENT_EXTRA_ARGS_<VENDOR>`. La prueba de campo (`e2e/field/`) esta saltada salvo `FLUXOR_FIELD_TEST=1`: gasta tokens de verdad. Tres tarjetas PROBE en paralelo sobre javadaba-web, las tres cerradas por el agente. Informe en `.harness/reports/` de ese repo. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QojUyqMC7XjBngED3zjsfX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
El Cockpit: un arnés reducido donde una tarjeta lanza una sesión de agente. Cinco commits, uno
por fase, y cada uno deja algo funcionando por sí solo.
F1 — la ventana
agent-session(f14780c7)PTY en el proceso principal, xterm en el renderer. La CLI del proveedor corre de verdad, con
.harness/cargándose como hoy.F2 — un worktree por sesión (
d137ccfe)La sesión abre en su propio worktree y su propia rama antes de que arranque el agente: se crea
en
.claude/worktrees/<nombre>desde unorigin/mainrecién traído (si el fetch falla se sigue conel ref local y se dice cuál se usó) y se instala por lockfile.
Al terminar dice si el worktree está gastado, y lo decide como manda la regla: por contenido y
por el registro de
gh, nunca por ascendencia, que es lo que miente después de un squash. Elborrado se lleva el directorio y conserva la rama.
Y una sola sesión adjunta por proyecto: el invariante 16 hecho mecanismo. La segunda no se bloquea
—se ofrece abrirla en un worktree.
F3 — la tarjeta lanza, y el estado vuelve (
ad7efee6)Cuarto
LaunchMenu: proveedor (los no instalados, deshabilitados con el motivo) y modoworktree/attached, cada uno con su razón cuando no aplica.
Un fichero, dos claves: el agente mueve
status, el Cockpit escriberunState—runningcuando el PTY existe de verdad,
completed/failedsegún lo que el agente dejó, no según el códigode salida. Las tarjetas
HUMANsalen de la pila a un carril fijo, con lo que desbloquean y sinlanzador.
F4 — atención por hooks, no por adivinación (
a227c030)Endpoint
httpen loopback con token por sesión en la ruta:200 {}inmediato, 404 para todo lodemás (nunca 401: confirmaría el id), 413 y 400. Los cinco hooks viajan como
--settingsen línea—no se escribe ningún fichero— y se parsean las dos grafías, porque el binario y la
documentación no coinciden.
La atención es una máquina pura: armado es una afirmación, recibido es la prueba. Hasta el
primer evento mandan las heurísticas de F1, y la ventana avisa si no llega ninguno. Un aviso por
tramo de espera, nunca por evento.
F5 — prueba de campo con un agente real (
ae115d7d)Un worktree se corta de
origin/main, así que una tarjeta que aún no ha llegado allí no está en elcheckout:
seed-card.tsla copia entreworktree-createy el bootstrap, sin sobrescribir nunca.e2e/field/está saltada salvoFLUXOR_FIELD_TEST=1, porque gasta tokens de verdad. Trestarjetas PROBE en paralelo sobre
javadaba-web, las tres cerradas por el agente. El informe estáen
.harness/reports/2026-09-08-cockpit-field-test.mdde ese repositorio.Pendiente
El build empaquetado,
codex/opencode/geminireales, y el modo adjunto con un agente de verdad.🤖 Generated with Claude Code
https://claude.ai/code/session_01GQQ1fEXq4GJzHNs8BPNTFW