[[project_v5_ui_requirements]]: "steps, scheduler and sampler are reached for constantly, and in v4 they are several clicks deep... a thin hovering window above the timeline, which keeps them visible without spending timeline height." Nothing in v5 built this yet -- the only existing path was Settings > Engine > Sampling, a modal several clicks deep. app/legacy/sampler_quickbar.js: a toggle button in the timeline header (next to Assets/Preview/Properties/Composer) opens a fixed-position panel above the timeline showing only category="sampling" module settings. Hidden until PipelineState confirms at least one installed module has a sampling setting (the "absent, not greyed" convention this codebase already uses for a module/role that doesn't apply). The quickbar needed to read/write the SAME module-values tree engine_settings.js already edited. That tree gets serialized into one opaque JSON blob and written into a pipeline slot by the server (core/graph.py's place()) with no server-side merge -- a second, naive editor sending a partial tree would silently erase every other module's settings. To avoid two independent caches of the same server data diverging (the exact bug class pipeline_state.js's own header comment already describes for `slots`, from an earlier fix), extracted the shared pieces instead of duplicating them: - PipelineState gained currentValues() (always-fresh: defaults + valuesAlreadyPlaced()) and setModuleValue(moduleId, name, value) (patches one field, sends the whole tree). Single source of truth, used by both editors. - app/legacy/settings_field.js: the field-widget builder (checkbox/ slider/enum/color/text, the `when`-clause visibility gate) extracted out of engine_settings.js verbatim, parameterized on a values tree and an onChange callback instead of a private cache -- one place renders a setting, one place saves one, for every editor of this tree from now on. - engine_settings.js refactored to use both instead of its own private values/seeded/setValue/ensureSeeded/commit/controlFor. Two rounds of extensive_testing. Round 1 found a real, live-reproduced defect: setModuleValue's "always fresh, no cache" design had its own race -- two calls fired before either's round-trip resolved could silently lose the earlier edit, because the second call's "read the whole tree" snapshot didn't yet include the first call's in-flight write. Fixed with a `pendingValues` overlay in pipeline_state.js, written synchronously before every read, reconciled (per-key, not wholesale) once valuesAlreadyPlaced() actually confirms it server-side. Round 2 re-verified the original race closes -- checked against valuesAlreadyPlaced() specifically (decoded straight from the server's own response, not the optimistic overlay) for both a two-different- modules race and a three-calls-same-field race -- and found one more thing, currently inert: setModuleValue's returned promise doesn't mean "this specific edit is confirmed" for every concurrent caller, only for whichever one owns save()'s queue at that moment. Documented in place (both real callers only re-render from shared state, which is already correct regardless of promise timing) rather than reworking save()'s shared queue for a guarantee nothing currently needs. Live-verified: button appears only when a sampling setting exists; opens positioned above the timeline; editing in the quickbar changes only the target field (confirmed via full before/after tree diff); same change visible in the Engine Settings modal and vice versa; real outside-click closes it; 5 open/close cycles leave no DOM leak. npm test: 691 pass, 1 pre-existing unrelated flake (shell/tests/projects.test.js:285). No test file exists yet for pipeline_state.js/engine_settings.js/settings_field.js/ sampler_quickbar.js -- a real, named test gap, not fixed here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ComfyUI-FunPack v5 — "Cunning Cranberry"
FunPack v4.0.0 is going to be the latest release of classic FunPack. Next update is another milestone update, or shall I say, a full rework.
Maintenance of current FunPack became a mess — forgetting to add or remove buttons from/to UI, finding functions that don't do anything but still present in the code absolutely randomly, trying to keep the UI neat while it has no strict boundaries on how it should look like, and of course — making it easy for users to understand how FunPack operates and how you can operate it — this is all time, money and token-consuming.
General idea behind the FunPack v5 rework is writing it from scratch, with a new architecture where a feature can't be forgotten, where a wire can't be missed, where one failing module never stops whole process from executing. Loaders and features would tell the UI by themselves what sorts of inputs they need and where to put it — and UI will compose them according to design guidelines it would have. Samplers would become independent from features — if a feature is available and enabled, sampler would call it. If it's not — it gets skipped and doesn't even appear in the UI so it won't confuse you.
Most of this comes from a FunUI backend draft that got shelved after understanding on how much time has to be invested into polishing it. Without a community support and wide usage it would become another dead project only one person in the world needs but no one else.
Come to think of it, FunPack already became something alike, with an exception — this project is more than alive, and while I can, I will support it.
Final goal is to make FunPack an ultimate answer for a novice's question "I don't know how to generate — what do I install and how do I start?" and for a professional's question "I need a UI with all the cutting edge techniques available on day 0 — which one?"
Preparation for the v5 had started.
FunPack v5.0 "Cunning Cranberry" — coming fall 2026.
This branch is a clean start. Classic FunPack lives on main.