forge-again v1.7.12
macOS installs work again, clearing a saved session actually clears it, and the server now keeps its own console log — so the next time something misbehaves, the evidence is already on disk.
Fixes
- macOS could not launch at all.
requirements_versions.txtpinstorch==2.13.0+cu126, a CUDA build that has no Apple-silicon wheel, so pip could only answer "No matching distribution found". The launcher already knew this and filtered the torch pins into a temporary requirements file — butlaunch.pyrunsprepare_environment()itself moments later and installed from the unfiltered file, undoing the filtering before the UI ever came up. The filtered copy is now kept and handed tolaunch.pythroughREQS_FILE. Thanks to @jasonmello114 for the report and the complete log (#15). - Clearing a saved session now clears it. There was previously no way to make one go away while a page was open, which is exactly when you would want to: the page seeds its snapshot at boot and never re-syncs, saves merge per tab, and the unload beacon writes the stale copy back on the way out — so anything removed server-side reappeared within a minute. A new 🗑 button beside Restore empties the page's own copy first, then deletes the file. Nothing on screen changes; it forgets what was recorded, not what is set.
- An emptied edited-tab list meant "unknown" instead of "empty". Which made that reset useless — the very next capture wrote back the untouched tab it had just removed. Absent now means "this page is too old to say"; empty means "nothing has been edited", and only the active tab survives.
- A name shared with a script kept settings alive forever. Defaults are indexed by the last two path segments, so a tab's own control and every script reusing the name landed together — img2img's Width (1024) with Ultimate SD Upscale's tile Width (64), Sampling steps 20 with 25, Mask blur 4 with 8 — and the rule that every recorded default must agree could never be satisfied. A bare label now resolves to the tab's own control. This was most of what survived pruning in a tab nobody had configured.
- Values that name no control, and values that are not choices. A double-ended slider with no label of its own is captured as a bare "(start)"/"(end)", which no default list can judge and which restore would apply to whichever unit it found first — a coin toss between three ControlNet units. An empty string, meanwhile, is a dropdown whose options have not loaded yet, not a deliberate setting. Both are now dropped when captured and when saved, so existing sessions heal themselves.
Reliability
- The server keeps its own console log.
server-console.login the Forge root, written by the server rather than depending on how it was launched: model loads and unloads, memory decisions, per-run peak VRAM, step rates, tracebacks. Launching normally sent all of that to a window that closes, and redirecting it block-buffered — so during a stall, which is precisely when the process will not exit to flush, the log ran thousands of characters behind the truth. Flushed on every write, rotated at 8 MB, and enabled by the existing forensics setting. start.bat > run.logis no longer thousands of characters behind. The script recommends that redirect for bug reports; Python only line-buffers to a console, so it now setsPYTHONUNBUFFERED=1.- VAE decode reports itself when it matters. One line when a decode is slow or asked for more memory than was free, giving what it needed, what was already resident and what was actually available. Measurement first: the marginal cost is 0.1563 MB per latent pixel at fp16, holding across five resolutions, and exceeding free VRAM degrades gracefully rather than falling off a cliff — 4.3 GB over budget still decoded in 7.7 s, because the memory manager evicts the diffusion model to make room. Three plausible fixes were tried against those numbers and all three were wrong, so this ships the measurement and not a guess.
- The test suite can no longer write into your saved session. It isolated
config.jsonbut not the session file, and the browser tier opens img2img, clicks around inside it and generates at 128×128 — all of which was captured into the real session, so a later restore opened and rebuilt a tab that had never been configured.
Documentation
- docs/first-models.md — a step-by-step walkthrough for a first working model set. Chroma is transformer-only and needs three sidecar downloads nothing in the UI asks for; missing them fails with "You do not have CLIP state dict!", which does not tell you what to fetch. Every link was checked rather than recalled, with sizes and a running total. It also flags that the obvious VAE link is gated and answers HTTP 401 in a way that reads as a broken install, and states plainly that GGUF runs on Metal and ROCm as well as CUDA.
Upgrading
Pull and restart. JavaScript and Python changes both need a real server restart rather than a browser reload. No configuration or model changes are required. If a saved session has been picking up tabs you never configured, press 🗑 once after restarting — the earlier fixes stop new ones being recorded, but only the reset clears what is already there.