Commit Graph
163 Commits
Author SHA1 Message Date
digital-garbageandClaude Sonnet 5.5 6bfeb63c4c feat: LTX 2.x model module — recognised from the checkpoint header, joint video+audio latent sized from the audio VAE, decode, text/image-to-video pipelines
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 10:24:43 +03:00
digital-garbageandClaude Sonnet 5.5 587fef3876 fix: module control — off/quarantined modules' values are not checked, repaired means loaded not just edited, quarantine holds when the file cannot be written, cache keys follow it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 03:06:50 +03:00
digital-garbageandClaude Sonnet 5.5 1724e94c2d feat: module control — switch a module off per project, and a module that fails stays off across runs until repaired or turned back on (Settings > Modules)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 02:59:57 +03:00
digital-garbageandClaude Sonnet 5.5 79a7baa2ec feat: project settings grouped as Project / Video settings / Prompt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 02:49:27 +03:00
digital-garbageandClaude Sonnet 5.5 a799846df0 feat: final render is made at a clip's own resolution (first clip, a chosen clip, or the project's), never forced to the project size
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 02:49:03 +03:00
digital-garbageandClaude Sonnet 5.5 7c4f353df2 feat: Models & Pipeline has Save and Cancel; Cancel puts back the pipeline as it was when the window opened
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 02:45:21 +03:00
digital-garbageandClaude Sonnet 5.5 196f8cd807 feat: Composer says when timed/weighted phrases are in the prompt, and that they only work on H3
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 02:42:45 +03:00
digital-garbageandClaude Sonnet 5.5 943a8b52f5 fix: reopening a project keeps a swapped or re-added default slot empty, all-removed pipelines, and the latest group
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:40:22 +03:00
digital-garbageandClaude Sonnet 5.5 a2567151c7 fix: Models shape editing: shown defaults are sent, same-kind slots told apart, unwired links recorded explicitly, swap says what roles it loses
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:35:42 +03:00
digital-garbageandClaude Sonnet 5.5 b037201fa0 fix: swap keeps only roles the new node can take, role-fed inputs are not offered for wiring, an unwire and a group move survive reopen and in-flight saves, swap asks first
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:25:30 +03:00
digital-garbageandClaude Sonnet 5.5 a9cf49d97f feat: Models & Pipeline edits the pipeline's shape — add a node, swap, remove, wire/unwire (one Primitive can drive many inputs), own groups; shape changes travel with the project
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:17:58 +03:00
digital-garbageandClaude Sonnet 5.5 43c29ced07 fix: reserved key names, per-name shape consistency and prompt ids checked on import, Esc leaves a typed field first, a resumed wizard is an ordinary run
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:13:24 +03:00
digital-garbageandClaude Sonnet 5.5 69f3019d9c fix: track modules/system/taste (an unanchored .gitignore rule had kept the whole module out of git); key import validates row shape, clears a stale latest, reports damaged zips; wizard Esc yields to layers above it and keeps a resumable run; icons view keeps its actions
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:07:09 +03:00
digital-garbageandClaude Sonnet 5.5 0edb26f637 feat: closable setup wizard (Esc and X), media bin list/grid/icons views
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:01:17 +03:00
digital-garbageandClaude Sonnet 5.5 865bc926c5 feat: refinement keys export/import (zip, validated) and delete from the Refinement & Taste panel
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 00:00:34 +03:00
digital-garbageandClaude Sonnet 5.5 82de825cda fix: a pipeline that failed to load is never saved over the project's copy, edits wait for an adopt in flight, a failed module-list probe is retried
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 23:58:28 +03:00
digital-garbageandClaude Sonnet 5.5 dfb0cc5a8d fix: manifest refreshed on adopt, deferred adopt after a failed load, split clips count once for length, non-slot project.models keys kept, bounded waits
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 23:51:11 +03:00
digital-garbageandClaude Sonnet 5.5 5673f7513b fix: saved pipeline is validated before it is adopted, answers for a previous project are discarded, a failed load never overwrites the project's copy, pipeline edits persist within a second
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 23:44:57 +03:00
digital-garbageandClaude Sonnet 5.5 0aac66d3e9 feat: the pipeline travels with the project (model picks, node values, module settings) — project.models is kept by PipelineState; exposed-control edits route through it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 23:40:54 +03:00
digital-garbageandClaude Sonnet 5.5 c325ab50b1 fix: regeneration length is the project's, not the scene's own (stated v5 requirement)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 23:38:53 +03:00
digital-garbageandClaude Sonnet 5.5 4c1fa336a5 fix: video roles skip linked inputs, project.video wins over derived values
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 23:38:30 +03:00
digital-garbageandClaude Sonnet 5.5 6591f8c546 feat: project.video roles read the editor's width/height/frames, length = frames the run covers
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 16:37:49 +03:00
digital-garbageandClaude Sonnet 5.5 ece9e2e9d7 fix: ghost previews keep their in-point, empty segments refused, odd canvases render, clip sound padded to its picture, mixed-fps export, render reports what it left out, upscale notice/busy-state
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 16:15:41 +03:00
digital-garbageandClaude Sonnet 5.5 beb5fe331b fix: preview window follows the URL not the unsaved project; export keeps sound/validates windows/unique names; upscale poll survives blips and detects vanished jobs; upscale settings follow the project; upload failures shown; EXIF-upright thumbnails
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 16:05:40 +03:00
digital-garbageandClaude Sonnet 5.5 1e0f9bc49e feat: render stage (serving, preview segments, export, stitch), post-render upscale, media rename/thumbnails, frontend backport from v4
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:48:46 +03:00
digital-garbageandClaude Sonnet 5.5 fd236a6e97 fix: phrase probe re-installs when its switch flips (cache key), sits innermost so other features' extra forwards are not measured, panel keeps peaks; enhancer reads Qwen-style tokenizers, chat comments key on the typed prompt; scenes get eff_frames/eff_fps
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:35:37 +03:00
digital-garbageandClaude Sonnet 5.5 28339e9fec feat: dislikes name what went wrong (bad image / bad composition); composition learners and DynaShift read the other axis as neutral; picker labels reach the taste store
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:23:24 +03:00
digital-garbageandClaude Sonnet 5.5 a9ef7d5c44 fix: enhancer works with ComfyUI's real generate/tokenizer signatures (seed, no unknown args, says when no picture/template), chat comments stay with their prompt, enhancer skips combined multi-scene prompts, revolver draws are atomic, template apply is undoable and says what v4 templates lose
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:21:06 +03:00
digital-garbageandClaude Sonnet 5.5 8be3770080 feat: H3 tiled and X2 Detail VAE decode, phrase probe with Settings panel
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:17:03 +03:00
digital-garbageandClaude Sonnet 5.5 b29fda7a0e feat: prompt enhancer (node module, H3 preset slot, Composer Enhance + Chat tabs, readout route)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:05:22 +03:00
digital-garbageandClaude Sonnet 5.5 dd825979f6 feat: prompt templates and editor settings persist with the project, shortcut revolver (peek vs commit), shortcut ideas stats
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 14:56:23 +03:00
digital-garbageandClaude Sonnet 5.5 0a6959ef17 fix: replacements split on newlines only, edits land on the exact-case entry, a refused shortcut save keeps the editor open
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 12:22:19 +03:00
digital-garbageandClaude Sonnet 5.5 fbedab813b fix: shortcut import checks everything before writing, one case-insensitive name identity, odd types never become text, expander failure keeps anchor/postfix and says so
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 12:17:37 +03:00
digital-garbageandClaude Sonnet 5.5 d5d2989f29 feat: shortcut categories, JSON export/import (reads v4 files), no inert refinement-key field, no dead Files tab; single-scene prompt no longer writes the anchor twice
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 12:10:54 +03:00
digital-garbageandClaude Sonnet 5.5 eed17fce63 fix: Story box -- a timeline change drops a stale failed split, notices retire themselves, clash check covers only scenes the box shows
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 11:53:51 +03:00
digital-garbageandClaude Sonnet 5.5 1db3aece7b fix: Story box -- failed split is kept and retried by Generate, stale applies cannot flip it, cut-word change resyncs the box, a scene holding a cut word is flagged
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 11:51:56 +03:00
digital-garbageandClaude Sonnet 5.5 979a593d3e fix: Story box -- stale draft, Generate waits for an in-flight split and refuses a failed one, empty story applies, cut word refused if a scene already holds it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 11:47:10 +03:00
digital-garbageandClaude Sonnet 5.5 fe98c5c4fc feat: Composer Story view -- every scene as one text cut by typed marker words; split/join on the server, anchor kept apart
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 11:42:50 +03:00
digital-garbageandClaude Sonnet 5.5 01f584a23e fix: clear answers for its own key; block-influence problems shown in the panel; repeated-sigma schedules blamed correctly
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 03:47:02 +03:00
digital-garbageandClaude Sonnet 5.5 54fc8df9d6 fix: clear/export act on the exact key shown; multi-call samplers declared; guards covered by tests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 03:37:40 +03:00
digital-garbageandClaude Sonnet 5.5 313d703846 fix: input steer reports reach not size, resets per run; block influence validates before toggling, finds the real key
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 03:24:03 +03:00
digital-garbageandClaude Sonnet 5.5 7dab350961 feat: rating-driven steering rides into the next step's input (core/input_steer); block influence probe
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 03:13:44 +03:00
digital-garbageandClaude Opus 5.5 2406923802 feat: taste keys -- rating a clip teaches the key its run captured
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 18:24:53 +03:00
digital-garbageandClaude Opus 5.5 ec6e9893b4 feat: hide settings the picked model cannot use, as soon as the file is picked
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 17:20:59 +03:00
digital-garbageandClaude Sonnet 5 4f18eefa69 feat: picker wheel -- customizable radial menu, replaces v4's pinned buttons
[[project_v5_ui_requirements]]: "any action in the UI can be assigned to a
slot... full wheel or half wheel... half wheel positioned left or right...
both draggable... default: middle mouse button, anywhere."

app/legacy/actions.js: ported the composer tree's tiny action registry
(app/shell/actions.js, an ES module, unreferenced from boot) as a classic
global window.FunPackActions -- offerAction({id,label,icon,run}), offered(),
run(id). Whatever announces itself is what the wheel (or anything later --
a command palette, a keymap) can show.

app/legacy/wheel.js: middle-mouse (anywhere) opens a radial menu of
whatever's currently on it. Full wheel spaces items evenly around 360°;
half wheel spaces them over a 180° arc on the chosen side, with drag
locked to the vertical axis only (full wheel drags both axes) per the
spec's "half wheel moves up/down, full wheel up/down and left/right" line.
Dragging repositions the CURRENTLY OPEN wheel only, not persisted -- read
"draggable" as "don't get stuck somewhere awkward this time" rather than a
remembered dock position, since the spec doesn't say which and this is the
simpler reading. Customize dialog (reuses pinned_buttons.js's existing
.pin-modal/.pin-slot CSS) toggles shape, side, and which offered actions
are on the wheel. pinned_buttons.js is NOT removed -- the spec says this
supersedes it, but retiring a working control felt like a separate
decision from adding a new one; both coexist for now, confirmed to not
conflict (separate storage keys, no shared DOM, never both open at once).

app/legacy/wheel_actions_seed.js: seeds 9 starter actions (Generate,
Generate selected, Render, Auto Montage, Undo, Redo, Models & Pipeline,
Engine settings, Sampler quick-access) so the wheel isn't empty on first
use.

Two rounds of extensive_testing, plus a bug I found myself in live
testing before either round: the half wheel's fixed radius, sized for a
full wheel's 360° spread, packed the same item count into half the
angular room and produced heavily overlapping items -- fixed by growing
the radius only as far as needed to keep adjacent items from touching,
confirmed visually before/after.

Round 1: no functional break found in outside-click-vs-item-click
ordering, listener leaks on repeated opens, or coexistence with
pinned_buttons.js.

Round 2: found the real defect -- enabledIds()'s first-call snapshot
("default to everything offered so far") could run in the gap between
wheel.js executing and wheel_actions_seed.js finishing (classic <script>
tags block sequentially, and this window widens on a slow/cold-cache
load), permanently persisting an empty or partial action list with no
error, no indication -- the user would just experience "the wheel doesn't
work" and have no way to know why. Fixed by deferring the snapshot to the
window `load` event (guaranteed after every script has run); before that,
enabledIds() shows whatever's offered so far live without writing it
down as the permanent default. Also cleaned up a dead if/else in the
half-wheel angle math flagged as a "looks like a bug that got half-fixed"
smell.

Live-verified after both fixes: real physical drag (manual mousedown/
mousemove/mouseup sequences, not just JS calls) confirms half-wheel drag
is genuinely locked to the y-axis (x stays exactly put) while full-wheel
drag moves both, and neither drag opens Customize -- only a press that
never crosses the drag threshold does. npm test: 691 pass, 1 pre-existing
unrelated flake (shell/tests/projects.test.js:285).

No test file exists yet for actions.js/wheel.js/wheel_actions_seed.js --
a real, named test gap, not fixed here. Real hardware middle-click and
cross-browser autoscroll-blocking are also unverified (browser automation
has no native middle-click) -- declared, not chased further without
physical hardware.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 06:25:12 +03:00
digital-garbageandClaude Sonnet 5 4a1f60bda6 feat: sampler quick-access -- steps/scheduler/sampler in one click
[[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>
2026-09-16 06:09:29 +03:00
digital-garbageandClaude Sonnet 5 bac2f3c5af feat: overlay tracks -- no default lane until the user adds one
v4 always presented an overlay lane whether or not anything used it.
The user's own v5 UI requirements explicitly reject this: "the
timeline starts with no overlay tracks. One appears when the user
adds it explicitly." store.js's normalizeOverlayLanes() force-created
a default "Overlay 1" lane the moment overlay_lanes was empty -- on
every project load AND every timeline render -- so a fresh, empty
project always showed one anyway.

Fixed at the two real sources:
- normalizeOverlayLanes() now only auto-creates a lane to house
  ORPHANED tracks (old-format projects, or a lane removed out from
  under its tracks) -- never just because nothing asked for one yet.
- defaultOverlayLaneId() (reached only from addImageOverlay/
  addTextOverlay when the user is explicitly adding their first
  overlay) now creates the first lane itself at that exact moment --
  the "user adds it explicitly" trigger the spec asks for.

Traced every overlay_lanes/overlay_tracks consumer across store.js,
timeline.js, inspector.js, view_bus.js, tour.js: none assume >=1 lane
always exists (removeOverlayLane's own guard already handles "never
below 1 once lanes exist"; drag-drop onto a lane row is naturally
unreachable before one exists, matching intended behavior).

Live-verified: a fresh project (window.Store.newProject) renders zero
overlay rows; addTextOverlay("Hello") creates exactly one lane, wires
the new track to it, and the row appears with a live text-overlay
preview on the canvas. JS suite: 691 pass, 1 pre-existing unrelated
flake (shell/tests/projects.test.js:285).

One round of extensive_testing (adversarial review) came back clean.
Declared, not fixed: a project saved under the old behavior keeps its
already-persisted empty "Overlay 1" lane -- a forward-only fix, no
migration was asked for and the lane is now an ordinary, removable one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 05:42:07 +03:00
digital-garbageandClaude Sonnet 5 0a71e0b929 fix: tour -- clear tour-s1's dead rating: "good" left over from round-9's scene_renders fix
Round 9 emptied demoProject()'s scene_renders to stop a real unmocked
network fetch against the live backend. Round 10's adversarial review
caught the sibling: tour-s1 still had rating: "good" in the demo data,
but the rating badge (timeline.js's sceneRatingRaw -> genUnitHasRender)
is gated on hasRender(), which now reads false for every scene since
scene_renders is empty -- so the badge silently never renders on the
scene the tour spotlights, self-contradicting the stored rating.

Cleared the rating to "" to match the no-render state honestly. Traced
every step/FAQ reference to tour-s1 and ratings: the FAQ answer is
generic ("after a render, rate a generative scene"), no step claims
tour-s1 specifically shows a badge, so this is a pure consistency fix
with no user-visible regression.

Live-verified: fresh tour boot, tour-s1.rating reads "" via
window.Store.get(). JS suite: 691 pass, 1 pre-existing unrelated flake
(shell/tests/projects.test.js:285).

Round 10 of the tour extensive_testing chain otherwise came back clean:
no dangling onCancel overlay (PipelineSetup's cancel-button variant is
unreachable in tour mode -- onboarding.js explicitly skips opening
during the tour), no crash from the empty scene_renders object across
every reader (store/timeline/inspector/player/montage_dialog/view_bus/
history), and the patchApi()/patchStore() mock surfaces still match
their consumers' expected shapes on a fresh full read.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 00:52:50 +03:00
digital-garbageandClaude Sonnet 5 ecbdc42785 fix: tour -- restart mock was reloading the real page, plus a stray player fetch
Round 9's module-definition sweep came back clean (the four standalone
modules found in rounds 5/7/8 are all still correctly covered, and no
fifth exists) -- but it caught two real bugs my own round-8 live
verification missed by not waiting long enough:

- Both restartComfy() implementations call FunPackRestart.waitForReload()
  after API.restart() resolves. That function polls API.health() starting
  3.5s later and calls location.reload() once it reports ok -- and
  API.health is ALREADY mocked to ok:true for the Settings About panel's
  own unrelated reasons, so the very first poll after a restart click
  reloads the real page mid-tour, silently resetting all tour progress.
  Nothing actually restarted, so there's nothing to wait for -- fixed by
  short-circuiting waitForReload() in tour mode instead of polling toward
  a reload.
- demoProject() pointed a fake scene_renders entry at a real-shaped
  ComfyUI /view URL for a file that doesn't exist. Since bootstrap()
  notifies immediately on tour start, player.js's render() (a plain Store
  subscriber, never blocked or mocked) picks it up and issues a real GET,
  then a real HEAD retry, against the live backend -- zero clicks, always
  404s, but still a genuine unmocked reach into the real install. Fixed at
  the source instead of patching player.js's internals: an always-
  unrendered demo scene is an honest trade-off the tour's own FAQ text
  already accounts for.

Verified live: clicked both restartComfy implementations, waited the full
5s past the 3.5s poll delay this time (my round-8 verification hadn't
waited long enough to catch this) -- confirmed no reload, still on
?mode=tour; confirmed zero /view?filename= requests; full tour sequence
still completes cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 00:48:40 +03:00
digital-garbageandClaude Sonnet 5 e9a570405f fix: tour -- mock restart/git/refinement-key ops, the most severe gap yet
Round 8's module-definition sweep found a fourth standalone module (after
GenerateBridge, PipelineState): window.FunPackGit (git_actions.js) and an
independent window.FunPackMaintenance.restartComfy (menubar.js) both call
window.MovieEditorAPI.restart() directly -- a REAL server restart, killing
any generation in progress -- one click from the same .settings-win
sidebar rounds 5-7 already proved reachable (Custom Nodes' inline
"Restart ComfyUI" button, and the built-in "Updates & ComfyUI" section,
which also fires a real GET /api/git/status the instant it mounts, zero
clicks needed -- same shape as pipeline_state.js's ensureLoaded()). That
same section's "Switch branch"/"Update FunPack" reach real git
checkout/pull. Worse than any prior finding: not a stray read, not even
round 7's directory-delete, but restarting the live production server and
mutating the FunPack install's own git state.

While fixing this, found two more real, unmocked, irreversible operations
in the same file (menubar.js's FunPackMaintenance, not caught by round 8's
own report): deleteRefinementKey and clearGlobalTaste, both described by
their own confirm dialogs as "This cannot be undone." Currently dormant --
v5's own api.js has these as stubs ("not built in v5 yet") -- same shape
as saveClipToMediaBin/renameMedia, closed pre-emptively rather than
waiting for a future backend to wire them up for real.

Fixed by mocking all ten functions in patchApi(): restart, gitStatus (also
cleanly short-circuits git_actions.js's own _ensureStatus() gate via its
existing alert path), gitUpdate/gitCheckout/gitRollback, and the five
refinement-key/taste functions.

Verified live in a genuinely fresh tab: called both restartComfy
implementations directly (auto-accepting their confirm dialogs) plus
refresh/update/switchBranch/deleteRefinementKey/clearGlobalTaste -- zero
/api/git/* requests in the network log, zero errors, page stayed on
?mode=tour rather than reloading, full tour sequence still completes
cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 23:10:32 +03:00