Guildwise HQ

← All releases

Guildwise HQ 1.6.0

Runner 0.1.71.

What's new

Release prep can start by itself

Turn on Start automatically when the release is ready on the test site in the release prep settings, and prep begins as soon as the release is live and healthy on the test site and meets what the live site needs before it goes out (release hours and freeze do not count). The Release prep tab shows whether the release is ready, why not if it is not, and whether a run was started automatically or by whom.

Full changelog

Added

  • PDF copy of a public form's answers. Next to the .json and .html copies, the firm's storage now also gets a .pdf with the same base name in the same folder, made on the firm's workstation from the HTML copy it receives (the server never renders, stores or keeps it). The browser that prints it (Chrome Headless Shell through playwright-core) runs with scripts and network off, is installed by the Linux and macOS installers in a step that never fails the install, and is repaired by the runner after an update; guildwise-runner pdf-renderer install|status and a doctor line manage and show it. If the copy cannot be made the submission still succeeds and the desk gets one notice, "PDF copy missing", pointing to the HTML copy. The submissions list shows the PDF entry. New optional derive on storage.write.open and derived on storage.write.result (no protocol version change).
  • Optional malware scan of public form uploads, set per workstation (uploadScan, off by default). With a clamd running on the workstation, each uploaded file is scanned before it is written to the firm's storage. An infected file, or a scan that cannot run, is never written and the whole submission is taken back; infected files are kept in an owner-only quarantine folder on the workstation. The submitter sees a plain message and keeps their answers. doctor and "Test connection" report whether clamd answers.

Changed

  • Inbound webhook relay: body limit per kind. A whatsapp_cloud integration now accepts up to 3 MiB (Meta's payload size) without any setting, and the new AOM_RELAY_MAX_BODY_BYTES_BY_KIND (kind=bytes pairs, at most 4 MiB each) overrides the limit of any kind; other kinds keep AOM_RELAY_MAX_BODY_BYTES. An over-limit body is refused with 413 before it is read in full.
  • Bundled Caddy: every log line, errors included, now goes through a filter that deletes token, signature and credential headers and redacts the secret part of the public relay, hook, form and invitation addresses; request body limits apply to /relay/in/*, /hooks/in/* and the public form API; the image is pinned to caddy:2.11. AOM_STORAGE_MAX_FILE_BYTES, AOM_JOURNEY_HOOK_MAX_BYTES and AOM_RELAY_MAX_BODY_BYTES now reach the app and the proxy from .env.
  • Public forms on installs served over plain http: attachments are hashed in the background (in a worker, or a chunk at a time on the page), so a large file no longer freezes the page. When the check before sending takes longer than 3 seconds the page says so, a browser that cannot do the check at all is told the form needs a secure (https) link while the answers stay on the page, and a 403 bad_origin now says to use the link the firm gave instead of a generic error.

Fixed

  • The server no longer trusts every X-Forwarded-For hop. The new AOM_TRUST_PROXY setting decides which proxies may set the client address that every per-address limit uses: unset trusts loopback only (127.0.0.0/8, ::1); false, 0 or none never trusts the header; a number from 1 to 32 trusts that many hops; a comma-separated list of IPv4/IPv6 addresses and CIDR ranges (and the names loopback, linklocal, uniquelocal) trusts those peers; true restores the old behaviour and logs a warning at startup. An invalid value stops the server at startup with a message naming the variable. Default changed: before, any client that reached the server directly could choose its own address and get past the per-address rate limits. A reverse proxy on the same host keeps working unchanged; a proxy in another container or on another host needs the setting, or every visitor shares the proxy's address. The bundled docker-compose.prod.yml sets loopback,uniquelocal for the app and the video worker. See docs/SELF-HOSTING.md "Running behind a reverse proxy".
  • Runner: the temp dir of an agent whose folder was removed outside the runner (a reset of the data folder, a hand cleanup, a wipe that stopped half way) no longer stays in /tmp for good. Each agent temp dir now holds a small .aom-owner file, and at start the runner removes the temp dirs of its own agents that no longer exist (never another runner's, never a live or resumed agent's, never a dir without that file).
  • Release ship recovery: Retry on a stopped release is refused once the release was dismissed or is otherwise no longer approved, and nothing is sent to the workstation. A release whose workstation went offline, was removed or lost the request while it prepared the release commit now shows as Release stopped with Retry and Dismiss instead of waiting forever; Retry goes back to the same workstation and makes no second commit or tag when the commit was already pushed. Dismiss removes the unpushed release commit the workstation kept for a Retry (runner capability release-ref-cleanup:1, new runner command release.ref_cleanup).
  • A rebase onto the base branch that fails for a reason other than a conflict is no longer reported, shown or routed as a conflict. The runner reports a conflict only when git stopped on conflicting paths and it listed them; any other failure (a held index.lock, a read-only git dir, an untracked file in the way, a missing base ref) is a rebase error carrying the base ref, the git command, its exit code and git's message (secrets redacted, at most 2000 characters), sent in a new optional rebaseError field on the finalize result, the shift.rejected message (reason worktree_failed) and run.status. A branch that already contains its base is left alone (no rebase, head unchanged); only git merge-base --is-ancestor exit 1 leads to a rebase, other exits are errors. After a conflict or an error the runner aborts only a rebase or merge that is actually in progress and never resets, cleans or stashes, so untracked files stay as they are. The server treats a conflict without files (also from an older runner) as a failure on all three paths: finalize raises the desk escalation, a shift rejection backs off like worktree_failed, a test environment fails normally; the card thread names the base branch and quotes git, and the card is not sent back to Rework and gets no DevOps conflict attempt.
Many hands. One master.

Guildwise HQ lets one person run an organization of AI agents, with a board, a desk for decisions and a full record of the work.

See how Guildwise HQ works