Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
13 KiB
2026-05-16
02:00 — Framework C++ anti-jitter v2 + floating panel survival + Alt drag/resize + bulk redeploy
Extensiones al anti-jitter del framework C++ (cpp/framework/app_base.cpp + .h):
- Multi-HWND subclass.
g_subclassedahoraunordered_map<HWND, WNDPROC>. Scan per-frame enpio.Viewportsinstala subclass en cada HWND nuevo (cubre main + cada viewport flotante).prune_dead_subclassed()conIsWindowlimpia stale.uninstall_sizemove_subclass_all()al exit restaura cada HWND. Fix del temblor en paneles arrastrados fuera del main. - Iconified main + flotantes vivos. El legacy
glfwWaitEvents+continueparaba todo el frame loop. Con multi-viewport activo eso congelaba los flotantes. Ahora detecta secondary viewports y, si existen, fall-through al frame normal (main GL clear en HWND minimizado es harmless, contexts GL secundarios siguen pintando). - Alt + RMB resize anywhere. WndProc detecta
WM_RBUTTONDOWN+GetAsyncKeyState(VK_MENU) & 0x8000, calcula direccion por cuadrante del cursor (WMSZ_TOPLEFT/TOPRIGHT/BOTTOMLEFT/BOTTOMRIGHT relativo al centro del client rect),ReleaseCapture()+PostMessage(WM_SYSCOMMAND, SC_SIZE|dir). Modal nativo, gate sizemove existente pausa render automaticamente. - Alt + LMB move anywhere. Misma estructura para
WM_LBUTTONDOWN. PostaWM_SYSCOMMAND, SC_MOVE | HTCAPTION. Modal MOVE nativo. io.ConfigWindowsMoveFromTitleBarOnly = trueenfn::run_app. Floating panels (OS window borderless + UNA ventana ImGui rellenandolo) ahora respetan "solo header arrastra". Fix del drag-anywhere-sin-alt en flotantes.fn::internal::*test observability.sizemove_enter_count(),alt_rmb_resize_count(),alt_lmb_move_count(),rbuttondown_seen_count(),set_force_alt_for_test(bool). Counters monotonicos zero-cost. En test mode los handlers de Alt cuentan pero NO postean SC_SIZE/SC_MOVE.
Tests en apps/altsnap_jitter_test/main.cpp extendidos a 6 phases (p1 sync, p2 main HWND modal, p3 secondary HWND modal, p4 iconify+restore preserva flotante, p5 Alt+RMB consumed, p6 Alt+LMB consumed). Todas PASS en Windows.
Pipeline nuevo: redeploy_all_cpp_apps_bash_pipelines (bash/functions/pipelines/redeploy_all_cpp_apps.sh + .md). Cross-compila TODO el arbol cpp/ en un solo cmake pass + redeploy de cada .exe al Desktop. Filtro opcional por substring. Tolerante a fallos (build best-effort, summary OK/SKIPPED/FAILED). Composicion: build_cpp_windows_bash_infra + loop taskkill.exe + deploy_cpp_exe_to_windows_bash_infra. Primera corrida: 12 OK / 1 SKIP / 0 FAILED.
Fix resolve_cpp_app_dir_bash_infra v1.1.0: ahora busca apps en apps/<X>/ (canonical issue 0096), luego cpp/apps/<X>/ (legacy), luego projects/*/apps/<X>/. Antes solo veia los dos ultimos → ./fn run compile_cpp_app dag_engine_ui fallaba. Deduccion desde CWD tambien cubre los tres layouts.
Pitfalls / gotchas registrados
ImGui_ImplGlfwsubclassea el HWND DESPUES que nuestro framework. Captura nuestro WndProc comobd->PrevWndProcy chainea viaCallWindowProc→ todos los mensajes nos llegan en orden correcto. NO re-subclassear despues de ImGui init (genera recursion infinita por cycle).keybd_event(VK_MENU)no es fiable para drivearGetAsyncKeyStatedesde tests headless cross-compilados (sesion de input no foreground). Usarset_force_alt_for_test(true)+SendMessageWsincrono mismo-hilo.PostMessage(WM_RBUTTONDOWN)sintetizado tambien es dropeado por el kernel input filter.- Pre-existing build break en
cpp/tests/test_llm_anthropic.cpp+cpp/tests/test_graph_icons.cppporsetenv()no disponible en mingw-w64. NO bloquearedeploy_all_cpp_apps(build best-effort). Candidato a guard#ifdef _WIN32+_putenv_so skip cross-compile.
Lo siguiente que pega
- Resolver el build break de
test_llm_anthropic.cpp+test_graph_icons.cppcon_putenv_sbajo#ifdef _WIN32. Quitar el SKIP del log deredeploy_all_cpp_apps. - Considerar regla nueva sobre ImGui io flags criticos (
ConfigWindowsMoveFromTitleBarOnly,ConfigViewportsNoAutoMerge,ConfigDragClickToInputText, etc.) que cambian comportamiento de viewports. Sub-seccion encpp_apps.mdo archivo separado en.claude/rules/imgui_io_flags.md. - Documentar en
cpp/PATTERNS.mdqueadd_imgui_appya embebe el iconoappicon.icosi esta en el<app_dir>(verificado en sesion; el usuario lo mantuvo entre redeploys).
Archivos tocados
cpp/framework/app_base.cpp(multi-HWND, iconified-gate, Alt+RMB, Alt+LMB, ConfigWindowsMoveFromTitleBarOnly, fn::internal::*)cpp/framework/app_base.h(declaracion de fn::internal::*)apps/altsnap_jitter_test/main.cpp(phases 3-6)apps/altsnap_jitter_test/app.md(6 phases doc)bash/functions/pipelines/redeploy_all_cpp_apps.sh(nuevo)bash/functions/pipelines/redeploy_all_cpp_apps.md(nuevo, growth log v1.0.0)bash/functions/infra/resolve_cpp_app_dir.sh(v1.1.0)bash/functions/infra/resolve_cpp_app_dir.md(v1.1.0 + growth log).claude/rules/cpp_apps.md(seccion 7.1 ampliada con v2)docs/capabilities/cpp-windows.md(tabla + seccion bulk redeploy + layouts)CHANGELOG.md(entrada 2026-05-16)
01:05 — Iconos .ico para apps C++ + funcion del registry
Las 11 apps C++ desplegadas a Windows no tenian icono → imposible distinguirlas en Desktop/taskbar (todas con el icono generico de exe).
Pipeline build-time end-to-end
-
Fuente de glyphs: clonado
phosphor-icons/core(MIT) ensources/phosphor-core/congit clone --depth=1. 1512 SVGs en 6 weights. Registrado ensources/sources.yaml. -
Mapping inicial en
dev/gen_app_icons.py(script reproducible, NO es del registry — vive endev/). TablaAPPS = [(app_id, dir, phosphor_icon, accent_hex), ...]con un Tailwind color 500-700 por app:- chart_demo → chart-bar / sky-500
- dag_engine_ui → tree-structure / violet-600
- data_factory → factory / orange-500
- engine_smoke (no aplicado: usa raw add_executable, no
add_imgui_app) - graph_explorer → graph / cyan-600
- navegator_dashboard → compass / blue-600
- odr_console → terminal-window / zinc-600
- primitives_gallery → shapes / pink-600
- registry_dashboard → gauge / emerald-600
- runtime_test (no aplicado: raw add_executable)
- shaders_lab → palette / orange-600
- text_editor_smoke → note-pencil / teal-600
- altsnap_jitter_test → arrows-clockwise / red-600
-
Funcion del registry:
generate_app_icon_py_infra(python/functions/infra/generate_app_icon.py). Lo escribefn-constructor. Signaturegenerate_app_icon(phosphor_icon_name, accent_hex, out_ico_path, *, weight='fill', sizes=None, phosphor_root=None) -> str. Tagscpp-windows, icon, phosphor. Depscairosvg + Pillowya enpython/.venv(uv pip install cairosvgenpython/). Validado con./fn show+ smoke test/tmp/test_icon2.ico. -
Wiring CMake (
cpp/CMakeLists.txt):- Linea 1-5:
project(... LANGUAGES C CXX RC)solo en WIN32. Linux ignora. - Macro
add_imgui_app(linea ~241): siWIN32 AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/appicon.ico, genera${target}_appicon.rcen build dir conIDI_ICON1 ICON "<full_path>"y lo anade aadd_executable.x86_64-w64-mingw32-windres(ya en toolchain) lo compila a.resy se enlaza al.execomo seccion.rsrc.
- Linea 1-5:
-
Rebuild + redeploy:
cmake --build cpp/build/windows -- -j$(nproc)+deploy_cpp_exe_to_windowspara las 11. Verificacion:x86_64-w64-mingw32-objdump -h <exe> | grep rsrcmuestra la seccion en todas.
Decision: build-time vs post-build
Existia set_exe_icon_go_infra (Go puro, embebe .ico post-build modificando PE). Descartado porque:
- Falla si el
.exeya tiene seccion.rsrc(limita robustez). - Anade paso extra al pipeline redeploy.
- Build-time es atomico: el
.exerecien linkeado YA tiene el icono.
Gotchas
- engine_smoke y runtime_test usan
add_executableraw, noadd_imgui_app— no reciben icono automatico. Son smoke tests, no apps user-facing. Skip aceptable. - shaders_lab vive en
apps/shaders_lab/, no encpp/apps/shaders_lab/(confusion inicial del mapping; corregido). - Pillow
save(format='ICO')conappend_images: si pasas la imagen 16x16 como base, el.icofinal solo tiene 16x16. Hay que pasar la imagen MAS GRANDE (256x256) como base + lista de variants per-size. Variants per-size dan crispness en 16/24 mejor que dejar Pillow downscalear. - Cache iconos Windows (
iconcache.db): tras desplegar nuevo.ico, Explorer puede seguir mostrando el viejo. Refresh:ie4uinit.exe -showo restart explorer.
Para anadir icono a una app nueva
# 1. Elegir nombre Phosphor desde sources/phosphor-core/assets/fill/
ls sources/phosphor-core/assets/fill/ | grep <keyword>
# 2. Generar el .ico
./fn run generate_app_icon "<phosphor-name>" "#<accent_hex>" "<app_dir>/appicon.ico"
# 3. Rebuild + redeploy
./fn run redeploy_cpp_app_windows <app_name> <app_dir> --build
Archivos tocados
sources/phosphor-core/(nuevo, clonado)sources/sources.yaml(entry phosphor-icons/core)dev/gen_app_icons.py(nuevo, script reproducible con mapping inicial)python/functions/infra/generate_app_icon.py(nueva funcion registro)python/functions/infra/generate_app_icon.md(idem)python/functions/infra/__init__.py(export)cpp/CMakeLists.txt(project LANGUAGES + add_imgui_app icon wiring)- 11 x
<app_dir>/appicon.ico(nuevos, multi-res) .claude/rules/cpp_apps.md(§11 Icono Windows)CHANGELOG.md(entrada 2026-05-16 Added: iconos .ico)- 11 x
.exerebuildeadas + redesplegadas a/mnt/c/Users/lucas/Desktop/apps/
Lo siguiente que pega
- Anadir icono tambien a
engine_smokeyruntime_testsi se promueven a apps user-facing (hoy son smoke tests). - Considerar
fn doctor cpp-appscheck: app C++ sinappicon.ico→ warning. - Si aparecen iconos antiguos en Explorer tras redeploy, anadir
ie4uinit.exe -showal final dedeploy_cpp_exe_to_windows.
20:54 — dag_engine — fix function-not-found nocturno + panel Logs en RunDetail
- Hecho: diagnostico de 3 fallos nocturnos (
fn_backupx2 2026-05-15/16,daily-registry-audit2026-05-16) que reportabanerror: function "<id>" not found (tried as ID and name)aunqueaudit_capability_groups_go_infra,backup_all_bash_pipelinesycdp_extract_recipe_py_pipelinesexisten enregistry.dbraiz. - Hecho: raiz identificada en
cmd/fn/ops.go:1597-1628 tryOpenRegistryDB— sinFN_REGISTRY_ROOTel resolver cae al walk-upgo.mody devuelveapps/dag_engine/donde habia una copia staleapps/dag_engine/registry.db(262 KB, May 15) que violaba.claude/rules/db_locations.md(registry.db SOLO en raiz). - Hecho: stale db borrada.
- Hecho:
~/.config/systemd/user/dag_engine.serviceampliado conEnvironment=FN_REGISTRY_ROOT=/home/lucas/fn_registry,FN_BIN,PATH=/usr/local/go/bin:...(sin PATHgo vetfallaba conexec: "go": executable file not found),HOME.daemon-reload+restart. - Hecho:
apps/dag_engine/executor.gobelt-and-suspenders — stepsfunction:exportanFN_REGISTRY_ROOTen env del spawn y defaultdir = fnRegistryRootsistep.Dir/dag.WorkingDirvacios; rebuildCGO_ENABLED=1 go build -tags fts5 -o dag_engine .. - Hecho: smoke test
POST /api/dags/daily-registry-audit/run-> stepaudit_capabilitiesSUCCESS 387 ms (era el step que fallaba con not-found).audit_unusedSUCCESS,audit_artefactsfalla con exit 1 (bug aparte) yfn_backuprun_backup_allexit 4 sin respetarcontinue_on.exit_code(bug aparte). - Hecho: panel "Logs" anadido a
apps/dag_engine/frontend/src/pages/RunDetail.tsx—<Paper>final con<Code block>(max-h 480 scrollable) +CopyButtonMantine (icono toggle copy/check teal 1.5s). HelperbuildLogText(run, steps)compone texto plano con metadata del run (dag/path/status/trigger/started/finished/duration/error) + por-step ([status] name exit=N Nms, stdout/stderr indentado 4 espacios). Type-checkea limpio. - Hecho: documentadas BBDDs canonicas —
dag_engine.dbenapps/dag_engine/,data_factory.dbenapps/data_factory/(tablas nodes/connections/runs/databases),navegator_dashboardNO tiene BD propia (sololayouts.dbdel framework viafn::local_path). - Hecho: append en
apps/dag_engine/app.md(seccion fechada + "Lo siguiente que pega"),apps/dag_engine/README.md(Function steps: aviso sobreFN_REGISTRY_ROOTyPATHen systemd),CHANGELOG.md(Added panel Logs + Fixed function-not-found bug). - Pendiente: investigar exit 1 real de
audit_artefactsendaily-registry-audit(probable artefacto huerfano o git drift). - Pendiente: bug en executor —
continue_on.exit_code: [4]no se respeta; solo se mirastep.ContinueOn.Failure(bool). ParsearContinueOn.ExitCode []inty comparar conresult.ExitCodeantes de marcarrunFailed=true. - Pendiente: frontend
pnpm buildroto por API drift de Mantine (<Collapse in={opened}>enStepTimeline.tsx:49) y CSS type import enmain.tsx:1. Bloquea ver el panel Logs en vivo; type-check ya pasa.