Skip to content

[Release] 2026-09-27: image tools, sd-server install, drop on Linux, clean exit - #315

Merged
nibor1896 merged 20 commits into
mainfrom
release-2026-09-27
Sep 27, 2026
Merged

nibor1896 merged 20 commits into
mainfrom
release-2026-09-27

Conversation

@nibor1896

@nibor1896 nibor1896 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

22 commits since origin/main (9f56600), Crow 2.8.0.

Scope

state issues
close on merge #309, #310, #314
already closed (accepted live 2026-09-27) #308, #311, #312, #313
stays open (meta) #300
total 7 closed + 1 meta

Resolved issues (close on merge)

Closes #314 — The installer does not provide sd-server (Linux build measured: 3 min 10 s, rerun 1.4 s, ldd on <install>/cuda/lib; Windows -SdBuildDir not run)
Closes #310 — Stop does not interrupt a running run_command (live check pending: during a sleep 110 run_command press Stop -> the turn ends within ~2 s)
Closes #309 — run_command ceiling thrashes big jobs instead of failing (live check pending: see the implementation comment)

Resolved, pending live verification

Issues shipped (already closed)

Checks

  • c54385a: test_crow_core + test_crow 2074 OK (5 skipped), test_crow_gui + test_crow_remote 1026 OK (3 skipped), ruff clean, check_shared_core 85/85, check_operating_point 10/10, install.sh --selftest 51 checks, 0 failed
  • Live: robin generated 2 images, edited 1, used the lightbox and the phone mirror (2026-09-27 12:08–13:10, no ERROR in sd-server-8097.log / engine.log)
  • 9f56600: Windows CI caught the image result's relative path written with \; now / on every platform. CI green on ubuntu-latest and windows-latest.
  • Not run: PowerShell parts (install.ps1, pack-release.ps1 -SdBuildDir), Windows

CHANGELOG

2.8.0 — 2026-09-27

Crow makes and edits images, and the 27B on crow-nest sees them. generate_image and edit_image run
Qwen-Image 2.1 on a resident sd-server beside crow-nest's dense 27B on one 32 GB card: 2752×1536 in about
2.6 min, an edit in two stages (1 MP edit, full-size redraw) because a 4 MP edit comes out grainy (#300, #308).
In the chat an animated square in the theme's colours becomes the picture; a lightbox opens it with folder,
download and info (#311), on the phone mirror too. install.sh --build-image-server builds sd-server (#314).
Images dropped from the file manager reach the model on Linux (#312), the window's X ends the process (#313),
Stop interrupts a running command (#310), and a command over its memory ceiling dies instead of crawling (#309).
20 commits since v2.7.0.

Added

  • Crow makes and edits images ([meta] crow-nest toward a model-agnostic engine: 27B CNQ, images #300 phase 3, Image generation shows no progress in the window #308, Generated images are not shown in the chat window #311, 2026-09-27). Two tools on a resident sd-server (stable-diffusion.cpp 2f88688, Qwen-Image 2.1, BF16 DiT streamed, --max-vram 7, text encoder on the CPU), started on first use or warmed at window start, stopped with Crow:

    • generate_image(prompt, aspect_ratio): the model card's sizes (16:9 = 2752×1536). Measured beside crow-nest's 27B (8.15 GiB free): 155 s warm, 175 s cold, card peak 31,338 MiB, the 27B's output unchanged.
    • edit_image(images, instruction, description): two stages in one call, because a 4 MP edit comes out grainy (measured E1/E2). Stage 1 edits at ~1 MP, the reference pipeline's size; stage 2 redraws the result at full size (img2img without references, strength 0.25). Measured 105.7 s + 55.3 s for 2752×1536, clean; chosen by robin from a side-by-side (crow-nest/decode_out/p3-img/compare-img2img.png).
    • Images land in <working root>/images/; the model sees its own result (vision).
    • In the chat: a square in the image's aspect ratio with a flow animation in the active theme's colours (static under reduced motion) and the phase line (loading, encoding, sampling i/40 · ETA, decoding, stage 1/2 · 2/2) stands where the image will be; the finished picture replaces it in place. Error: a red tile with the reason. After a restart an unfinished job shows "interrupted".
    • Lightbox: a click on the picture opens it large; top right: Show in folder, Download (Save as…; on the phone a real download), Copy image, Copy path, Open in viewer, Move to trash (two clicks, never a plain delete), "i" with name, W×H, size in MB and bytes, format, created, path, tool, seed; Esc closes. The phone mirror shows previews, the lightbox and the info.
    • robin's live check (2026-09-27): generate 162.2 s / 163.6 s, a two-stage edit 109.4 s + 60.3 s, the tile, the swap, the lightbox and the phone as described. Not measured: Windows.
  • install.sh --build-image-server (The installer does not provide sd-server #314, 2026-09-27): builds sd-server and sd-cli (stable-diffusion.cpp 2f88688 with its four submodule pins, CUDA, sm_120) into bin/ with tools/build-sd-server.sh, reusing the llama-server builder's CUDA toolkit; no web UI. Measured on the RTX 5090 box: 3 min 10 s (8 jobs), a rerun 1.4 s with nothing to do, ldd resolving CUDA from <install>/cuda/lib. An older sd-cli is kept as sd-cli-<commit>. Windows: tools/pack-release.ps1 -SdBuildDir puts sd-server.exe and its DLLs into the release zip, recipe in docs/user-guide/install.md; not run yet (needs Windows).

  • Crow knows crow-nest's dense Qwen3.8-27B container ([meta] crow-nest toward a model-agnostic engine: 27B CNQ, images #300, 2026-09-27). New models.entries.qwen38-27b-cnq for Qwen3.8-27B-CNQ4.5.cnq, the container crow-nest's serve opens on port 8099 (not booted from Crow, like flash-next-cnq45-m). model_key_for pairs it with what the running serve reports (checked live: key qwen38-27b-cnq), so a request to it carries the 27B card's rows (thinking 1.0 / 0.95 / 20 / 0.0 / 0.0, non-thinking 0.7 / 0.80 / 20 / 0.0 / 1.5), thinking fixed at high (= the template's xhigh) and the 1024 reasoning cap, the same policy as the crow-nest Flash-Next point. Reasoning levels measured on the running 27B serve (The operating point is spelled in one file and every copy is checked against it #74 method): none / low / medium / high accepted, max / minimal / off / High / empty refused with 400; identical to Flash-Next's, since the 27B's chat template and tokenizer files are byte-identical to Flash-Next's. docs/operating-points.md has its row. Not measured: answer quality in Crow on this point.

Changed

  • The README is a generated image (docs: image README, crow-nest as the documented default #307, 2026-09-25; 4664c3a, f1c941d): one picture per GitHub theme and a one-column variant for phones (docs/images/readme/, drawn by tools/readme_image.py), then the install lines, the docs links, the licence and Ko-fi; the old text front page lives in docs/archive/README-v2.7.0.md. For 2.8.0 the picture shows the image tools and takes the tool count from crow_core.BUILTIN_TOOLS (30, was drawn as 28) (0c08fb1).
  • install.ps1 sees a running sd-server.exe holding bin\ during an update, as it did llama-server (The installer does not provide sd-server #314). Not run: no PowerShell on the Linux release machine.

Fixed

  • An image dropped into the window on Linux is lost (An image dropped into the window on Linux is lost #312, 2026-09-27). The drop took the file's path from pywebview's GTK drag handler; robin's drops from the file manager reached no chip and no request. Measured on the retest (crow.log 09:38:03, 09:38:47): WebKitGTK handed the page the drop with zero File objects, so neither the path nor the bytes existed. The page now takes a picture's bytes when the drop carries files (FileReader → stage_image_data → written like a paste → staged under its own name, also on the phone mirror), and otherwise reads the file manager's URIs where GTK has them: the second retest (crow.log 10:00:46) showed the page types text/uri-list and text/html with zero files and an EMPTY uri text, and pywebview reads the GTK drag data with get_text() (None for a uri-list), so Crow connects the WebKit widget's drag-data-received itself, keeps Gtk.SelectionData.get_uris(), and on_drop turns them into paths for the normal drop route (drag_uri_path; the page-side dropUriPaths stays for backends that expose the text). Every drop leaves [drop] lines in crow.log (types, file count, uri length). Harness: an 11,528,977-byte PNG dropped synthetically into WebKitGTK arrives byte-identical. Tests red without the fix; a real file-manager drop is robin's live check.

  • The process stays alive after the window's X (The process stays alive after the window's X #313, 2026-09-27). robin's closed window left the process running (pid 34193, SIGINT ignored), and from a terminal Ctrl+C was always needed. Cause, measured with the new exit watchdog's stacks on robin's next close (crow.log 09:39:45): the main thread in threading._shutdown, joining pywebview's JS-bridge thread Thread-14 (_call), which waited in evaluate_js for WebKit's reply to an answer still in flight when the window went. pywebview runs bridge calls in non-daemon threads and waits on GTK with no timeout (webview/util.py:335, platforms/gtk.py:693-695). Crow now makes those threads daemon threads (daemon_bridge_threads) before the window opens. A harness with one answer in flight at the close hung 2 of 2 without it (killed after 15 s) and ended 2 of 2 in 1-2 s with it. The exit watchdog stays as the backstop: 5 s after the window loop returns, a process still alive logs its threads and stacks, stops the MCP servers and exits.

  • Stop interrupts a running run_command (Stop does not interrupt a running run_command #310, 2026-09-27). Before, Stop set a flag that nothing read while a tool ran: a sleep 110 poll ran to its end, every remaining call of the round still ran, and one more chat request went to serve before it was dropped (engine.log 2026-09-27 00:27:39, 535 tokens prefilled for nothing). Now Stop ends the running command within ~2 s: SIGTERM to its process group and its scope, up to 2 s for a cleanup, then the existing SIGKILL sweep; on Windows taskkill /T /F on the tree, for the clock and the cap too. The model reads error: stopped by the user after <N>s -- the command and everything it started in this call were ended: <command> plus the output so far, booked like a declined call, not a failure. The round's later calls do not run (error: stopped by the user -- not run), and no further request goes to the server. Jobs an earlier call put in the background (nohup … &) survive, as documented. build_bundle and the syntax check stop the same way. Not verified: the GUI click end to end and Windows.

  • A command over its memory ceiling dies at the ceiling instead of crawling, and a background job's kill or thrash is said (run_command ceiling thrashes big jobs instead of failing #309, 2026-09-27).

    • run_command's scope drops MemoryHigh=7G: the default is MemoryMax=8G, MemorySwapMax=0, OOMPolicy=kill, the shape CROW_COMMAND_MEMORY_MAX already had. memory.high throttles and never kills, and with no swap the anonymous part cannot be reclaimed.
    • Before, measured 2026-09-27 on aios (62 GiB, crow-nest serve holding the 27B): a Qwen-Image 2.1 load started with nohup sd-cli … & sat at 7.40 GiB of the 7G throttle for 10 min 47 s, in D state, memory.pressure full avg60 = 88.13, loading at ~11–22 MB/s instead of ~5 GB/s, and never reached the 8G kill. The same argv under a 40G ceiling loaded all 397 tensors in 2.58 s.
    • Same mechanism at 1/40 scale (2026-09-27, systemd 261, 300 MB anonymous hog, no swap): MemoryHigh=150M + MemoryMax=200M was still throttled when timeout 20 ended it (21.8 s); MemoryMax=200M alone killed it in 42 ms.
    • A job a command leaves in the background is recorded while its scope still holds a process. Every later tool result starts with a note: (after the first line of an error: result) when that job was killed at its ceiling (the kernel's oom_kill count for session.slice rose while its scope vanished) or when its scope's memory.pressure reads full avg60 ≥ 50 %. Before, the model polled the starving job 7 times and read "RUNNING".
    • run_command is the unbounded way around #208/#213: the model launched software-WebGL headless chromium 20 times through it on 2026-09-22 (the 54 GiB-freeze flags, --enable-unsafe-swiftshader --no-sandbox), and run_command has no memory ceiling and kills only the shell on timeout #218's protection stays: 8G still stops the 54 GiB software-WebGL runaway a seventh of the way, with no swap. Windows is unchanged (no command scope there).
    • Not measured: the 8G ceiling kill of a 12 GiB foreground hog through run_command (the ≤ 15 s threshold), and the live sd-cli case with the note (needs the GPU and serve's slot). A job that really needs more than 8G still needs CROW_COMMAND_MEMORY_MAX at GUI launch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh

nibor1896 and others added 20 commits September 27, 2026 02:05
models.entries.qwen38-27b-cnq for Qwen3.8-27B-CNQ4.5.cnq (crow-nest serve,
port 8099, not booted from here). Checked live against the running serve:
model_key_for -> qwen38-27b-cnq, reasoning fixed high, no menu, sampling
1.0 / 0.95 / 20 / 0.0 / 0.0 (the 27B card's thinking row).
Reasoning levels measured on that serve (#74 method): none/low/medium/high
200, max/minimal/off/High/empty 400 - as Flash-Next: the 27B's template
and tokenizer files are byte-identical to Flash-Next's.

check_operating_point 10/10; test_crow_core 1529 OK, test_crow 476 OK,
test_crow_remote 53 OK; test_crow_gui 915 with the same 6 folder-picker
errors as before this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
Stop set INTERRUPT, but nothing read it while a tool ran: the command ran
to its end, the round's remaining calls still ran, and one more chat
request went to serve before the stream reader dropped it.

- _bounded_run: INTERRUPT is a third stop reason beside the clock and the
  cap, read every 0.25 s tick. Stop sends SIGTERM to the group and the
  scope, waits up to STOP_GRACE (2 s), then the existing SIGKILL sweep.
  The output so far is kept. Windows: taskkill /T /F (kill_tree) for the
  clock, the cap and Stop.
- tool_run_command: "error: stopped by the user after <N>s -- ...".
- run_turn: a call after the Stop does not run (STOPPED + " -- not run");
  a stopped call is booked like a declined one; the turn ends after the
  round and at the head of the next round, so no further request is sent.
- Background jobs of earlier calls are not touched (#218 contract).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
…said (#309)

The default command scope drops MemoryHigh=7G and keeps MemoryMax=8G,
MemorySwapMax=0, OOMPolicy=kill -- the shape CROW_COMMAND_MEMORY_MAX already
had. memory.high throttles and never kills; with no swap an over-budget
job sat at 7.40 GiB for 10 min 47 s (full avg60=88.13) and never reached
the 8G kill.

A scope that still holds a process when run_command returns is recorded.
run_tool_cached prefixes every later tool result with a note when that job
was killed at its ceiling (session.slice oom_kill rose while the scope
vanished) or its memory.pressure reads full avg60 >= 50.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
…e X (#312, #313)

#312: on Linux the drop's path came from pywebview's GTK drag handler,
which reads the drag data only as text; robin's drop from Nautilus
reached no chip and no request. The page now reads every dropped picture
with FileReader and hands it to the new Api.stage_image_data, which
writes it like a paste and stages it under the dropped name; the path,
where pywebview delivers it, is skipped for a picture already read.
Classified `upload` for the phone mirror. One [drop] line per drop in
crow.log. Harness: an 11,528,977-byte PNG dropped synthetically into
WebKitGTK arrives in Python byte-identical.

#313: after the window's X the process could stay (pid 34193, main
thread in a futex wait, SIGINT ignored), and from a terminal Ctrl+C was
always needed. arm_exit_watchdog() after webview.start: 5 s later a
process still alive logs its threads and stacks to crow.log, stops the
MCP servers and exits. The blocker is not identified yet.

test_crow_gui 921 OK (2 skipped; +6, 5 red without the fix), test_crow_core
+ test_crow 2020 OK, test_crow_remote 53 OK, ruff clean, check_shared_core
83/83, check_operating_point 10/10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
… hold the exit (#312, #313)

#312, measured on robin's retest (crow.log 09:38:03, 09:38:47): WebKitGTK
handed the page a file-manager drop with zero File objects. The page now
reads the drag's text/uri-list when there are no files (dropUriPaths:
file:// URIs -> local paths -> the normal drop route) and logs what each
drop carried (drop_seen: types, file count, uri length).

#313, cause measured with the exit watchdog's stacks on robin's close
(crow.log 09:39:45): MainThread in threading._shutdown joining
pywebview's JS-bridge thread Thread-14 (_call), stuck in evaluate_js
waiting for WebKit's reply to an answer in flight when the window went
(webview/util.py:335 non-daemon, platforms/gtk.py:693-695 no timeout).
daemon_bridge_threads() makes those threads daemon before the window
opens. Harness with one answer in flight at the close: 2/2 hung without,
2/2 ended in 1-2 s with it (crow_gui.daemon_bridge_threads itself).

test_crow_gui 924 OK (2 skipped; the three new tests red on 0d9a092),
ruff clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
Second retest (crow.log 10:00:46, 10:00:49): the page saw types
text/uri-list and text/html, zero files and an EMPTY uri text, and
pywebview's GTK handler reads the drag data with get_text(), which is
None for a uri-list. Crow now connects the WebKit widget's
drag-data-received on the GTK main thread, keeps the non-empty
SelectionData.get_uris(), and on_drop takes them once (30 s fresh) as
paths for the normal drop route; the [drop] line names the source.
Checked in a real pywebview window: the signal connects on WebKit2
WebView. test_crow_gui 927 OK (3 new), ruff clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
…ghtbox (#308, #311)

#308: Turn.tool_progress pushes {"k":"imgjob"} (throttled to 4/s per job;
the first line, a phase change and every end pass). The page draws one
figure per job in the chat flow (its own turn, so a folded round cannot
hide it): the image's aspect ratio, a flow animation from --accent,
--bevel and the surfaces only (keyframes move positions, never colours),
still under prefers-reduced-motion, a phase line; error = red tile,
stopped = still tile. One band mark per job; a replay draws a job that
neither runs nor got its picture as "interrupted", never animating.

#311: Turn.image_created vets (regular file, IMAGE_TYPES extension with
matching magic bytes, <= IMAGE_MAX_BYTES, working area or an approved
outside path) and pushes {"k":"image"}; the card replaces its job's tile
in place (512-px GdkPixbuf preview; Windows shrinks in a canvas). The
lightbox is a modal <dialog>: Show in folder (FileManager1.ShowItems,
else reveal_command), i (image_info), Copy image, Copy path, Save as...
(a phone gets Download: <a download> on the data URL), Open in viewer,
Move to trash (two clicks, Gio trash / SHFileOperation+ALLOWUNDO, never
unlinked), Close; Esc closes. Every image_* method re-vets the path
against the images this window announced. Phone: thumb/full/info
proxied (full is a data URL there), reveal/copy/open/trash desktop,
save_as "download". The window warms the image server when the core
offers image_tools_available/image_server_warm.

test_crow_gui + test_crow_remote 1026 OK (3 skipped, pre-existing);
45 new tests, 35 red against ee4261f's crow_gui.py, 14 targeted
mutations all red. ruff clean, node --check clean on both page variants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
, #308, #311)

- generate_image(prompt, aspect_ratio, seed) and edit_image(images,
  instruction, description, aspect_ratio): Qwen-Image 2.1 over
  sd-server's async job API (img_gen + jobs), started on the first
  call, kept loaded, stopped at exit; image_server_warm() for surfaces.
- edit runs B5 in one call: a ~1 MP edit (refs stretched by the server
  to calculate_dimensions(1024^2), vae_input_max_pixels=1048576), then
  img2img at full size, strength 0.25, the full description, no refs.
- SdProgress reads the server's log (#308's table); TurnEvents gains
  tool_progress(name, state) and image_created(path, source, job), fed
  by a thread-local sink armed around each call in run_turn.
- PNGs land in <root>/images/, never overwritten, and ride to the model
  like read_image's; a blind server keeps the result as a success.
- "image" and "imgjob" session notes keep facts only.
- Terminal: one redrawn line per call, "image: <path> (WxH, N KB)".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
…#300, #308, #311)

- push: "imgjob" is a session note kind since the core half, so the plain
  note append added a second mark per progress line next to the in-place
  update; it is skipped there (TheImageBandReplaysTests red on the merge).
- image_model_dir: without CROW_IMAGE_MODEL_DIR, look beside the target of
  a linked <install>/models when the plain place is empty (install.sh's
  layout; robin's ~/Projects/models/qwen-image-2.1). New test.
- test_crow_gui: a concrete /home path from the #312 uri test replaced
  (test_no_concrete_home_directory_is_written_down).
- CHANGELOG Unreleased: the image tools, the chat tile, the lightbox.

test_crow_core + test_crow 2074 OK (5 skipped), test_crow_gui + test_crow_remote
1026 OK (3 skipped), ruff clean, check_shared_core 85/85.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
AnImageJobThatDoesNotFinishSaysWhyTests asserted image_tools_available()
is False after leaving the patch that hides the binary; since 8eb5247
finds the real model beside the linked tree, the machine's real install
answered True. 8eb5247's message claimed test_crow_core OK -- it was
FAILED (failures=1) on exactly this test; corrected here.

test_crow_core + test_crow: see below in the ticket comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
…_core (#300)

- tools/readme_image.py: the tool count is len(crow_core.BUILTIN_TOOLS) (30, was a
  hard-coded 28); the tool table must name every built-in tool or the script stops.
- New "Images" section (desktop and mobile): generate_image 2752x1536 155.2 s warm /
  175.3 s cold, edit_image two stages 105.7 + 55.3 s, measured beside crow-nest's 27B
  on one RTX 5090 (docs/reference/tools.md); the chat's animated placeholder.
- Features: Images and Lightbox added; Vision names the drop/paste and the 27B.
- Intro: one line for the images. Section rule no longer runs into long titles.
- README.md alt text follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
tools/build-sd-server.sh builds sd-server and sd-cli from
stable-diffusion.cpp 2f88688 (master-920-2f88688, submodule pins
recorded and verified) with the CUDA 13.3 prefix and cmake/ninja that
build-llama-server.sh already keeps under $CROW_HOME; it sources that
script for ensure_cuda/ensure_cmake_ninja, which now runs main only when
executed. SD_CUDA=ON, sm_120 (-> 120a), frontend off, DT_RPATH to
$CROW_HOME/cuda/lib, ldd and --version checked, idempotent, disk guard;
a binary of another commit in bin/ is kept as <name>-<commit>.

install.sh --build-image-server / CROW_BUILD_IMAGE_SERVER=1 runs it and
reports where the core looks for Qwen-Image 2.1. pack-release.ps1
-SdBuildDir adds sd-server.exe/sd-cli.exe with their DLLs resolved like
llama-server's. Docs: Linux build, Windows recipe, tools reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
Version 2.8.0 in cli/crow.py, install.ps1 and the operating-point manifest;
CHANGELOG 2.8.0 with the release summary and a Changed section (#307's
image README, install.ps1 seeing a running sd-server for #314); the README
image regenerated (version pill). install.ps1's change is not run: no
PowerShell on the Linux release machine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
…platform (#300)

Windows CI on the release PR #315: test_the_file_lands_in_images_and_the_result_names_it
expected 'images/…' and got 'images\…'. The relative path in the result now uses '/'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyBV1tX2JWocGLTjFkNYMh
@nibor1896
nibor1896 merged commit dba4a88 into main Sep 27, 2026
4 checks passed
@nibor1896
nibor1896 deleted the release-2026-09-27 branch September 27, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The installer does not provide sd-server Stop does not interrupt a running run_command run_command ceiling thrashes big jobs instead of failing

1 participant