Skip to content

Contributor-reported fixes: paths with spaces, redactor gaps, safe Slack - #464

Closed
ReganBell wants to merge 38 commits into
mainfrom
upstream-1841
Closed

Contributor-reported fixes: paths with spaces, redactor gaps, safe Slack#464
ReganBell wants to merge 38 commits into
mainfrom
upstream-1841

Conversation

@ReganBell

Copy link
Copy Markdown
Collaborator

cuts, jsonb-safe serialization, CAS promotion, mid-run files, IME Enter Seven first-principles fixes for reported bugs, one commit per bug. bench:memory and the twin-instance script broke under any directory containing a space (new URL(...).pathname keeps percent-escapes) — use fileURLToPath everywhere a file URL becomes a path (#77). The audit redactor missed base64url-shaped (JWT-alphabet) secrets and its --with-token rule replaced the match with itself, a literal no-op (#80). Slack section splitting, clip, and inlineCode cut with bare slice, bisecting emoji surrogate pairs, <url|label> entities, and format runs — one safe-boundary cutter now backs all three (#82). The Postgres-backed durable map JSON.stringifies into jsonb, which rejects NULs and lone surrogates the system's own truncation helpers manufacture — sanitize at the serialization boundary (#62). Scratch-memory promotion wrote back with a blind replace, reverting any edit that landed during its model call — the write is now compare-and-set against the revision read at the start (#79). Steering a live run with a captionless file dropped the file while reporting steered:true — wakes now carry attached file names so the file is announced to the run (#89). And the Enter that confirms an IME composition (Japanese/Chinese/Korean) no longer submits the half-composed message (#140, issue #225). toyoshi

Deployment notes

Batch of small fixes; mostly behavior-neutral (fileURLToPath, base64url secret masking, Slack
safe-cut splitter, durable-map jsonb tweak).
Secret masking now redacts base64url tokens and --with-token payloads — audit lines get MORE
redaction; any org tooling that parsed raw tokens out of audit logs (unlikely, undesirable) loses
them.
Slack messages near the 2900-unit boundary split at slightly different points; cosmetic.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

16francej and others added 30 commits August 13, 2026 10:19
* feat: surface named environments in admin

Co-Authored-By: QM <qm@users.noreply.github.com>

* refactor: clarify environment metadata response

---------

Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: QM <qm@users.noreply.github.com>
Stored-file responses passed the file's MIME type through verbatim, so text-like types without a charset parameter (text/plain, text/markdown, application/json, …) were served bare and browsers fell back to their default decoder — non-ASCII content rendered as mojibake when opened via the files content endpoints. A shared contentTypeWithUtf8Charset helper now appends charset=utf-8 to text-like MIME types that omit one, correctly skipping types that already declare a charset (including quoted-parameter edge cases) and leaving binary types untouched. Both the user-facing and admin stored-file routes use the helper, so downloads and inline views decode as UTF-8 everywhere.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/381"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237806&installation_model_id=19911&pr_number=381&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F381&signature=7541e25e0bfd664c1700810b8e67601fe421866d546e8deca069758d061a32bd"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…e crons (#382)

When several crons were due in the same scheduler tick, a throwing fire aborted the whole batch: the remaining due crons were never attempted, and since the failed cron stayed due it was selected first again next tick, starving the others indefinitely. Each fire in the batch now runs in its own try/catch — the failure is recorded in that cron's fire log and logged at the fire level, and the loop proceeds to the rest of the batch. The capped fan-out is additionally rotated by durable attempt order so a persistently failing cron cannot monopolize the cap, and a cron whose attempt marker fails to persist is held back. Failing crons still retry on later ticks.

**Deployment notes**

Adds optional Cron.lastAttemptAt persisted via backing.merge into the existing cron DurableMap
— additive JSON field, no DDL; old instances ignore it and rollback is safe (rotation just degrades
to insertion order)
New CronStore.markAttempted method is in-repo only (memory + durable map implementations
both in this commit); no cross-version contract

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/382"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237810&installation_model_id=19911&pr_number=382&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F382&signature=9024b164262a51252b4b16e5f29face2b44743136ba4e7a5089ce032d44953b4"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
In the local durable byte store, two concurrent writes of identical bytes shared the same <sha256>.<pid>.part temporary path: both passed the initial existence check, the first rename won, and the second failed with ENOENT. Each write now uses a random per-write temp path; identical content still converges on the same content-addressed final path via atomic rename, so  tidti l l d ll d dth tilfil i l d h th fil concurrent identical uploads all succeed, and the partial file is cleaned up when the rename fails. A repo-wide check confirmed this was the only affected temp-path site — the blob-transfer path already mints a unique id per put. Includes a deterministic concurrency regression test that fails on the unfixed code.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/383"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237813&installation_model_id=19911&pr_number=383&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F383&signature=b73861f1e99293de318a2d176575091db84a1c01d58e971cda5473bacf0287fe"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Collapsed work folds could render 'Worked for 0s' or 'Failed after 0s': the duration label only appears for tool-less segments, which span a single transcript entry, so the computed span was always zero — and demoted bookkeeping entries produced entirely empty 'Worked' folds. Work duration now falls back to the span of activity timestamps when start/finish markers are missing, labels drop the 'for Ns' suffix when no measurable time elapsed, and a fold with nothing visible to show is not rendered at all.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/384"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237818&installation_model_id=19911&pr_number=384&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F384&signature=9405f68081d31938855f30f863ebe6c40baaac0b81c43ca06af51a2e30d86113"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…ss (#385)

The reattach probe in the background exec broker treated any readProcess failure as proof the process was gone: it deleted the durable registry row and launched the command again. A transient backend error could therefore leave the original process running unrecorded, start a duplicate, and lose the record of the first. Route the decision through the shared processIsGone predicate: only a definitive no-such-process error drops the row and relaunches; any other failure keeps the row intact and surfaces to the caller. A regression test pins a transient backend error preserving both the process and its row. Fixes #285.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/385"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237822&installation_model_id=19911&pr_number=385&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F385&signature=8f006475316521ef110cb63fe2b3b9a802e1f9504fef87d4aef7f82876cb900a"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
If an attempt's lease expired and the run was reclaimed by a newer attempt, the finishing stale attempt called the lease-fenced complete(), ignored its false result, and returned an ok reply anyway — reporting success for a run still executing under the new attempt. processRun now rejects when complete() returns false. The subsequent lease-fenced fail() with the stale token is a no-op, so the live attempt's claim, status, and result are untouched.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/386"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237825&installation_model_id=19911&pr_number=386&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F386&signature=e4b451a47672a0c69d4d9d2d9dda5fcce2fb8965bdc59e8a02527c3f079b9149"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…#387)

A cron whose principal destination is someone other than its owner requires the recipient's consent, but a fire skipped for missing consent was logged as {status: "ok"} with only a note, and the owner-notification path was gated off — the owner never learned the reminder didn't go out, and the fire log was indistinguishable from a delivered one. Both consent-skip paths (verbatim relay and task output) now record status "refused" with the explanatory note, and the owner gets a "Scheduled delivery skipped" notice. Tests cover the declined and awaiting-consent cases and that fire history distinguishes withheld from delivered.

**Deployment notes**

Behavior flip (a fix): consent-skipped and not-visible cron fires now record status 'refused'
instead of 'ok' — dashboards/queries keying on fire status will see new values for events
previously logged as ok.
New unsolicited owner DM on consent-skip: cron owners in upstream orgs start receiving skip
notices with no opt-in; idempotent via fire key so no double-send on replay.
No schema change; reuses existing fire-log fields.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/387"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237828&installation_model_id=19911&pr_number=387&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F387&signature=e8d086b1dc488538a5c5a2f51f46e2077f6a34c633f75b436dc89e7edd902a46"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Dragging a session onto the multiview canvas rendered all five drop zones (open-here plus four splits) unconditionally, with legitimacy decided only inside the drop handlers after the drop. So the UI advertised actions that wouldn't happen: at the pane cap a "Split" drop silently became a tab, and dragging a session already on the canvas showed full zones but any drop just focused its existing pane. The overlay now computes which targets are legitimate before rendering and only offers those, so what the user sees is what the drop will do. Tests cover the cap, the already-open session, and single-view cases.

**Deployment notes**

Builds on the multiview pane work in #1885 (e06ba40af) — land that first or together
Web-ui drag/drop UI logic only

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/388"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237832&installation_model_id=19911&pr_number=388&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F388&signature=255307e27382f83752dda99ea9a7cf5b6fc53bd872c7b581cb28061fe9f1e106"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Replace the projects card grid with a dense single-line-per-entry list grouped by source: Personal (pinned on top), Web (projects and web groups), and chat channels/group DMs — each group with a count. The shared/owned/private badge is dropped; the scope description moves to the row tooltip. Rows show icon, name, lock indicator, and right-aligned meta (members, conversations, last active), making large project lists scannable.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/390"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237839&installation_model_id=19911&pr_number=390&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F390&signature=9e673488d7f23e5476b51a6d7e5fccb6e282a26030802a288f1ee7b64e5798a3"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Deployed apps on sleeping microVMs hung for the full 20s dial timeout and then showed raw gateway JSON — they looked broken while merely waking. The deployment proxy now tracks when each upstream last answered; a document GET/HEAD to an upstream not seen healthy recently gets a short first-byte window, and on a dial timeout or connection failure the browser receives an auto-refreshing warming page instead of an error blob. Applies to every proxy path (path-prefix, subdomain, and admin routes) since they share the layer.

**Deployment notes**

Behavior flip at the proxy: browser GET/HEAD to an upstream not seen healthy in 60s now gets a
4sfirstbytewindowthenanHTML503warmingpage(autoretry2mingiveup)insteadof
4s first-byte window then an HTML 503 warming page (auto-retry, 2min give-up) instead of
hanging the full dial timeout and landing on raw gateway JSON — anything programmatically
fetching app pages with document Accept headers and expecting JSON errors sees HTML now;
non-document requests keep the JSON 502/504 contract
No config, no DB; recently-healthy upstreams keep the full timeout so slow pages aren't
misclassified

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/392"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237848&installation_model_id=19911&pr_number=392&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F392&signature=854169d0df2b3fb067e0b3f7a4cdcbf454d271d06dc19308e3dadfd4a5e23694"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
background job returns its tail instead of erroring Arming a watch on a background job that had just finished threw "background job already exited — nothing left to watch", so the agent got an error at exactly the moment it did the right thing — watching a job right as it completes — and had to spend another call polling for output it was owed. Watching an already-exited job now succeeds and hands back what the caller actually wanted: the final status, the exit code, and the tail (about 4KB) of the job's output, with wording that makes explicit no watch was armed. Watching a still-running job is unchanged.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/393"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237850&installation_model_id=19911&pr_number=393&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F393&signature=e3cf200d601dfb1e9fb067fd1c4a1896b9164efeb6b60c299a74aa616f281edb"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Agents routinely call the memory tool with action 'remember' but without a usable facts array — putting the fact text in content, in query, or passing a bare string — and every such call errored, wasting the turn and silently losing the memory the agent meant to save; in practice this was the single largest cluster of agent tool errors. The common miscalls are now coerced into a fact list in priority order: a bare-string facts becomes one fact, content is split on newlines with leading bullets stripped, and query becomes one fact. Only when all three are empty does the call still error, and the message now names what was passed. The tool result records when coercion happened so the miscall rate stays visible rather than masked, and well-formed calls are entirely unchanged.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/394"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237855&installation_model_id=19911&pr_number=394&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F394&signature=eadf992b4726cdb0a0410c2f4c6bf189d96bd7e3f2c5a434af520e6660072251"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…ols (#395)

Live chat sessions get a top bar: a muted project crumb before the session title (personal chats show just the title), a status pill ("working" while the agent streams, "needs you" when an approval is pending), and quick tools for crons, files, and memory. Clicking a tool opens that view scoped to the session's project — only that project's items show, the scope filter is locked, and the same top bar persists across the view with the title linking back to the chat. The crons button carries a live count of enabled crons in the session's scope.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/395"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237860&installation_model_id=19911&pr_number=395&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F395&signature=f33a1f00cd5a0e0aeb9914c76097a182f47148eeb09fc600f814757d5556c13f"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Brokered CLI credentials in the non-legacy cutover modes were still injected into the conversation's general sandbox environment in direct messages, where any executed command can read them, and the shared-room owner-auth path interpolated vended values into shell function text that session records then persist. Non-legacy brokered services are now reachable only through a credential_exec tool that takes a service enum plus literal argv — the model never supplies a command string or binary path. Each invocation vends credentials on demand, runs the deployment-declared binary once in a fresh scratch box that is destroyed afterward, and masks stdout/stderr with the vended values (including encoded variants) before anything reaches the model or durable records. Ephemeral-only mode denies direct binary execution with a deterministic pointer to the tool, the eager per-turn credential vend is gone, credential_exec consumes command approvals exactly like execute, and legacy mode is unchanged for rollback.

**Deployment notes**

New credentialexec tool + orchestrator brokering only surfaces when the deployment layer
_ g y py y
marks tools as broker/ephemeral_only — stock upstream (no such layer) sees no new tool and no
behavior change
Behavior flip for layers already using ephemeral_only: direct execution of those commands is now
denied (prepended to the scope policy so a scope-level allow can't outrank it) — the intended
contract, but a layer relying on direct runs would notice
Harness interface gains a member — out-of-tree harness implementations need a one-line
update; no DB, no env, approval-grant flow reuses the existing execute path

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/396"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237863&installation_model_id=19911&pr_number=396&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F396&signature=2116baa3792227e3dd0820b79c4feb727d31bb795004a12542ac1be72f78a90b"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…397)

The per-channel ambient-replies toggle could only be changed from the UI — the agent's guidance tool couldn't see or manage it, leaving a parity gap between what a person can configure and what they can ask the agent to configure. The guidance tool now reports the current ambient mode when reading channel guidance and accepts an ambientEnabled parameter on writes: true judges every message for an unprompted reply, false responds only when addressed, and null resets to the platform default. Ambient-only writes work, omitted values stay unchanged, and conversation scope rejects the channel-only setting.

**Deployment notes**

Behavior flip: ambient channel reply handling moves under guidance control (tool schema/prompt
changes in surface-tools/pi-tools/primitives) — agents may reply differently in ambient channels
with no opt-in; no persisted or config changes

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/397"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237866&installation_model_id=19911&pr_number=397&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F397&signature=679335f67d943ff9f914ac6ab0fe1556ba6fe4a1c9cb9c4c4e6e496f60364c35"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
on a unix socket, access log, config validation The egress proxy is a forward proxy that dials from its own network namespace, so a sandbox asking it to CONNECT to 127.0.0.1 reaches the colocated decision service and the Envoy admin endpoint — previously loopback was only denied when a policy set denyPrivateNetworks, and the admin listener sat on a loopback TCP port where /quitquitquit could drop fleet egress on demand. Loopback destinations (127.0.0.0/8, ::1) are now denied unconditionally in the decision service, and the Envoy admin interface moves to a mode-0600 unix socket. An stdout access log with response flags and code details makes proxy-side failures diagnosable, and the decision-service config is validated at startup so a malformed policy fails fast instead of silently allowing. The proxy VM's memory reservation is raised to leave headroom for Envoy plus the decision service under real traffic.

**Deployment notes**

Release-note: redeploy the egress-proxy image, expect the 512MB reservation, loopback
egress now denied
Change lives in the egress-proxy container (envoy.yaml, Dockerfile, fly.toml) plus egress-authz-
main — orgs running forced egress must rebuild and redeploy the egress-proxy image to get it;
core alone doesn't deliver it
fly.toml memory reservation rises 256MB → 512MB — a sizing/cost change deployments should
expect
Behavior flip by design: CONNECT to loopback through the proxy is now unconditionally denied (it
previously reached the proxy's own namespace, including Envoy's admin) — any workload that
legitimately tunneled to loopback breaks, which is the point of the security fix
DNS cache resized 1024→8192 hosts / 300s→120s TTL and a new access log — operational
improvements, no config input from orgs required

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/399"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237874&installation_model_id=19911&pr_number=399&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F399&signature=34a993cb904597ead04f21f6480816eb2f5d8a00749934680a2459a7c7976fa3"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…on (#402)

POST /v1/conversations with a channel-or group-scoped capability created the session but started the seed turn without the shared scope's channelRef, so the turn was refused and the caller got a 202 with no runId while an orphaned empty conversation stayed behind. The route now parses the validated session scope and forwards its ref as channelRef for channel and group scopes; personal scopes are unchanged. A refused seed turn now discards the just-created session and returns 409 seed_turn_refused instead of persisting an empty conversation. Route-and store-level tests cover the member spawn succeeding and the refusal path cleaning up.

**Deployment notes**

No schema change; adds SessionStore.deleteSessionIfEmpty implemented in both memory and
pg stores (guarded DELETE, safe on old data)
pg acquireLease now refuses a lease unless the sessions row exists (INSERT ... WHERE EXISTS)
— any out-of-tree caller that acquired a lease before inserting the session would break; in-tree
callers create first
New pg_advisory_xact_lock serialization around lease/delete: during the blue-green window old
instances don't take the lock, so the empty-session-discard race protection is only partial until
the deploy completes (transient, worst case is the pre-fix behavior)
POST /v1/conversations behavior change: a refused seed turn now discards the just-created
empty session instead of leaving it persisted (this is the fix)

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/402"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789239161&installation_model_id=19911&pr_number=402&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F402&signature=32bea3cfc2a051226752fa3c313b61656c3cbfe98d410f25b30dbc5538c57ee0"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…405)

The command screener only stripped heredoc bodies when the line had a redirect, so a heredoc piped to cat, gh, or jq — for example a PR body that merely mentions destructive SQL — tripped the destructive-SQL approval gate as a false positive. Heredoc bodies are now stripped from the scannable text unless the consumer actually executes its stdin: shells, SQL clients (psql, mysql, sqlite, …), and script interpreters (python, node, perl, ruby) keep their heredocs fully visible to the q , ), p p (py , ,p, y) p y rules. Command substitutions inside unquoted heredocs are also kept, since those do execute even when the body is data.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/405"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789239226&installation_model_id=19911&pr_number=405&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F405&signature=3d21b3a9d36d648f8676db51b7952c33decdfdf35ab6f7d3d35a9b08ad3fe680"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Archiving a session left any pane or tab still displaying it on screen, showing a conversation the user just put away. A new closeSessionSurfaces(sessionId) removes every split-canvas pane and tab whose params point at the archived session and runs the normal post-close reconcile (last pane maximizes or the canvas exits); outside the canvas, if the main conversation is on that session it resets to a new chat. Other sessions' surfaces are untouched.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/406"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789239277&installation_model_id=19911&pr_number=406&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F406&signature=8085bd0688a7c449039f84d7808594e9c24061a5df978bfcd543ef29e21d8581"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
* ci: reject GitHub noreply addresses in Co-Authored-By trailers

A commit landed with 'Co-Authored-By: QM <qm@users.noreply.github.com>'.
GitHub resolves a users.noreply.github.com address to whichever account
owns that username, so the unrelated github.com/qm account was credited
as a contributor to this repository. Fail PRs whose commits carry such
trailers so attribution can never leak to a stranger's account.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: scope the noreply co-author check to actual trailers

Parse each commit's trailer block instead of grepping the whole
message, so a commit that merely quotes an offending trailer (docs,
reverts) is not rejected. State the blanket ban on privacy addresses
explicitly in the failure output.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…456)

A cron or monitor homed in a private channel could be skipped on every fire with 'the acting person is no longer a member of this trigger's home scope' even though the owner never left: the directory push silently drops a private channel from its snapshot whenever the roster cannot be fully verified, and the home-scope gate treated 'the directory has no row for this channel' as 'the actor is not a member'. When the directory has no row for the home scope, the gate now falls back to the actor's session participation in that scope — the same fallback scope membership already uses — and the same fallback applies to delivering to the trigger's already-validated home scope. A genuine, affirmative roster that excludes the actor still skips as before, and when there is truly no signal the skip note names the snapshot gap instead of blaming membership.

**Deployment notes**

Release note: crons previously stuck on 'no longer a member' due to snapshot gaps may
resume
Behavior flip (a fix): crons homed in a private channel missing from the directory snapshot now
fall back to the actor's session participation instead of permanently skipping as 'no longer a
member' — dormant crons upstream orgs believed dead may resume firing after upgrade.
No schema/config change; scope-membership now distinguishes 'no rows' (undefined) from
'empty roster' — in-process only.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/456"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245895&installation_model_id=19911&pr_number=456&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F456&signature=ed5c4cb912d2d409330891850d5f500592581eb9ee79efb67dd26a602c602f5c"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…writes (#454)

Memory consolidation read the notebook, spent seconds in a model call, then wrote back unconditionally — any capture or manual edit landing during the call was overwritten by a body derived from the stale read. Worse, the post-write verification re-read the notebook and treated any mismatch as a store that cannot rewrite, so one badly timed edit silently disabled consolidation for the scope. Consolidation and scratch promotion now snapshot with readHead() and write back with replaceIfRevision(); a lost race skips the cycle and retries later instead of degrading. The capture-only degrade heuristic now applies only to stores without compare-and-set support, and the file-backed service serialises capture/replace/readHead/replaceIfRevision per scope so its read-across-await sections are atomic in-process. Fixes the second half of the concurrency report in issue #339.

**Deployment notes**

No schema change; adds readHead/replaceIfRevision (compare-and-set) usage in
consolidation/promotion with per-scope queues in the file-backed service.
Deployments whose memory store lacks CAS support keep the old degrade heuristic explicitly —
the diff scopes the degrade path to non-CAS stores, so no store implementation is newly
required.
Blue-green: an old instance still doing unconditional write-back can race a new instance's CAS
write during overlap; the new code loses the race and retries later — no data corruption beyond
today's behavior.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/454"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245745&installation_model_id=19911&pr_number=454&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F454&signature=77b6946f28e78a8ea95b4a235c675b401c119243c584de5af41949bdf22e463c"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
The multi-view (split canvas) arrangement was persisted only in localStorage, so it survived relaunching the same browser but came up empty on a new device, new profile, or cleared storage — nothing tied the layout to the user. Core gains a small per-user ui-state record (GET/PUT /v1/ui-state, backed by a durable map with a Postgres table and an in-memory fallback, 128 KB value cap); the web-ui server proxies it with the authenticated user's principal stamped in. The frontend keeps writing localStorage, pushes to the server debounced, and at boot adopts whichever of the local or server copy is newer — last write wins across devices.

**Deployment notes**

New DurableMap web_ui_state via the existing artifactMap pattern — table created idempotently
at boot, no migration step.
New GET/PUT /v1/ui-state (auth: source). Blue-green: during overlap an old instance 404s the
route; the client treats missing server state as absent and keeps localStorage, so degradation is
graceful.
Stale-write guard, 64KB byte cap, and +5min clock-skew clamp are server-side only; no config or
secret needed.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/452"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245583&installation_model_id=19911&pr_number=452&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F452&signature=94238addcc6c5fa4a66b305cb86f5b24c91684b9a32185d77eae461a03e147d3"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
A web project and a Slack channel are separate scopes with separate rosters, and web sessions can'treceivescheduledornotificationoutput—projectcronsandreport-outshadnoreal cant receive scheduled or notification output — project crons and report-outs had no real destination. A project can now declare one optional home channel: the platform treats it as the project's default external audience for deliveries, without merging scopes (channel members don't become project members, and memory, files, and the project computer stay project-scoped). Linking is verified at link time — the linker must be a member of both sides — and the link is exposed to the agent's prompt context and the project page UI.

**Deployment notes**

Verify upstream already has the directory channel-members sync schema
(directory_channel_members table + directory_sync.channel_members_synced); if not,
upstream that sync first
Project record gains optional slackChannel + channelMemberIds fields (JSON-additive in the
project store) — old instances ignore them; after rollback, derived channel memberships silently
stop applying until re-upgrade, which is degraded access rather than corruption
Postgres directory store queries directory_channel_members and
directory_sync.channel_members_synced — this table/column must already exist upstream (it
came from the fork's channel-members sync work); if upstream lacks that schema, this commit's
queries fail at runtime for linked projects
Behavior: linking a channel makes the channel roster the project roster and bumps scope version
(invalidating stale approvals) — entirely opt-in per project, plus a new '## Project home channel'
prompt block only on linked projects
New PUT/DELETE /v1/projects/:id/slack-channel endpoints — additive

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/451"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245519&installation_model_id=19911&pr_number=451&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F451&signature=0931c40cf697a1f675b10d3644e2071b6a75af577dd283dea19530f620d05974"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Auto-load person-to-person skill grants into the turn's skill list Sharing a skill to another user records an ACL grant, but the per-turn skill list was built only from visibleSkillScopes (own scope, shared-room layers, org) and never consulted grants — so the grantee's agent never saw the shared skill in its prompt index and it never materialized on disk. Deployments, files, and shared credentials all read grants on the turn path; skills were the odd one out. The ACL store gains sharedOfKindForAudience, and the orchestrator folds skill grants reaching the conversation's audience into the turn's skill list and sandbox materialization. A test covers a user-to-user share appearing in the grantee's next turn.

**Deployment notes**

Release note: pre-existing skill grants activate on upgrade; orgs that shared skills before (no-
op then) will see them start loading
Behavior flip on existing data: skill-share ACL grants that were previously inert (written but never
read on prompt assembly) become live on upgrade — any grants already sitting in upstream orgs'
acl_grants tables suddenly inject skills into grantees' prompts/sandboxes with no action taken at
upgrade time.
Security posture is considered in the diff (P0 fix validates grant owner scope against the skill's
home scope before dereferencing, blocking forged grants), which matters precisely because old
rows become live.
API change is additive: /v1/skills now folds in grants; no schema change (new
AclStore.sharedOfKindForAudience reads existing rows).

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/450"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245505&installation_model_id=19911&pr_number=450&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F450&signature=e3a25c14e3d9d3bb1baf11dc64f1203296e6797cd4bc58d888b933845d6fa9c4"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
The chat header and composer toolbar showed a per-session 'View session log (admin)' icon to admin users, duplicating navigation the admin panel already provides and cluttering the conversation UI for everyone with the admin capability. Remove the icon from both surfaces and delete the now-unused adminSessionLogUrl helper. Admins reach session logs through the admin panel as before.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/449"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245454&installation_model_id=19911&pr_number=449&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F449&signature=d79f474fac388c974389d7e7c6d856bf4060cd0aa19a313579c0a8aca185fdfa"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
)

Pressing Enter while a turn was running always steered — it redirected the live turn, which is destructive and was never explicitly asked for. Mid-turn sends now queue by default, with steering available as an explicit action. The queue is the core's durable one, not the browser's: core already parks a second web turn pending behind the running one, so the client's parallel localStorage queue (which could double-send from two tabs or lose a message when the tab died) is deleted and the core queue is rendered instead. RunStore gains inFlightForThread (every non-terminal run for a thread, oldest first — the tail is the queue) and withdraw (one guarded UPDATE so cancelling a queued turn either beats the worker's claim or reports it started, never both). Steering withdraws the queued run first, then signals, so a message is folded into the live turn or runs as its own — never both. Because the queue is durable, closing the tab no longer drops a message and a second tab sees the same queue.

**Deployment notes**

Release note: first boot rewrites the runs table to add seq (brief lock); mid-turn send now
queues by default
Schema: ALTER TABLE runs ADD COLUMN IF NOT EXISTS seq BIGSERIAL at boot. A BIGSERIAL
column has a volatile default (nextval), so Postgres does a full table rewrite under ACCESS
EXCLUSIVE lock — on a deployment with a large runs table this is a slow boot migration that
blocks run claiming; release notes should mention possible pause on first boot.
Blue-green: old instances insert runs without touching seq (default fills it); the claim query's
added 'seq ASC' tiebreak is compatible. Rollback safe — old code ignores the column.
Behavior flip: mid-turn Enter in the web UI now queues instead of steering; upstream users'
muscle memory changes (Steer becomes an explicit control). Deliberate fix, but zero opt-in.
Client-side localStorage queue deleted: any message sitting in a browser's local queue at
upgrade time is not migrated (edge case, tab-lifetime data).

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/448"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245403&installation_model_id=19911&pr_number=448&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F448&signature=7efc3a5f3a0e98b8391c1b22a7e3cbcf585bbb108ab6667215de838273277b1a"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
The sessions header renders outside the scrolling session list, so when the list's scrollbar appears it shrinks only the rows — leaving the header's Web-only toggle overhanging the row edge by the scrollbar width. Reserving a stable scrollbar gutter (scrollbar-gutter: stable) on both the list and the header gives them one shared right edge whether or not a scrollbar is visible. CSS-only, five lines; the no-scrollbar case is unchanged.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/447"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245189&installation_model_id=19911&pr_number=447&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F447&signature=d7851eddd164bd801b43f09328cd5578b42b6bd666a8f195f7a395e2566fa7be"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
mountLoadingPane renders .chat-loading as the sole child of .custom-chat-shell, a grid with rows auto/1fr/auto — the spinner sat in the top auto row (flex:1 is inert inside a grid) and hugged the top of the window. Spanning it across every row with grid-row: 1 / -1 lets its own flex centering put the spinner in the middle of the pane. Includes a test pinning the rule.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/444"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245110&installation_model_id=19911&pr_number=444&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F444&signature=e81f9137a124a0284b6fada80e76c187848b1fcf92b935fcb780a9be8b6a9c3a"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
ReganBell and others added 8 commits August 13, 2026 13:53
A surface post with files staged the blobs and enqueued the delivery correctly, but the web delivery pump only nudges the client and acks the delivery — the attachments were discarded and session history never carried them, so the post text rendered while the files silently vanished even though the tool reported them sent. The post/reach result now carries the sent attachments' metadata (name, mimetype, sizeBytes, artifactId — never the internal blob id), the tool_result entry persists it as files, and the web renderer surfaces those as delivered files on the reply bubble, with images inline via the existing artifact content route. File-only posts (empty text) render correctly and no longer leave a typing placeholder; the native Slack delivery path is untouched.

**Deployment notes**

tool_result session entries now persist a files array (name/mimetype/sizeBytes/artifactId, never
blobId). Additive persisted-format change: old code replaying/rendering these entries ignores the
extra field; new code reading old entries sees no files and renders as before.
Blue-green: an old web-ui instance won't render deliveredFiles written by the new instance during
overlap — cosmetic only.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/443"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245103&installation_model_id=19911&pr_number=443&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F443&signature=0546dd993a6625c762a205e253f81060b7e9b59fc85eb43e89ec0797fce97371"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
on redeploy, soft-skip unsupported backup Two avoidable ways a publish aborted. A redeploy that omitted entrypoint failed late, deep inside the deploy service, with "publish requires an entrypoint" — even though the deployment's previous version already had one; the entrypoint is now inherited from the current version, and with no prior version and none supplied the tool layer fails fast with a message that says what to pass. Separately, when the sandbox substrate doesn't support the optional backup step, the publish now skips it with a note instead of failing entirely. Tests cover inheritance, the fail-fast message, and the backup soft-skip.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/442"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245097&installation_model_id=19911&pr_number=442&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F442&signature=dab4fa5f5075a12ec570416ef0ff8fbe1c4d333174bc98c0786d954b4786cfab"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
When a user attached a large screenshot, the model provider rejected the entire request (image dimensions over the many-image limit), killing the whole turn with no partial result and no useful error for the person. Images are now capped at 1568px on the long edge — the provider's optimal maximum — at the attachment chokepoint (src/core/attachments.ts via a new src/core/image-downscale.ts), so every request path gets correctly sized images and oversized attachments degrade gracefully instead of failing the turn.

**Deployment notes**

Downscaling shells out to ffmpeg via spawn; ENOENT is caught and treated as converter-missing
so hosts without ffmpeg keep today's behavior (oversized image passed through) rather than
crashing.
Release-note nicety: installing ffmpeg in the core image enables the feature; upstream Dockerfile
should be checked to include it or the feature is dormant.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/441"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245090&installation_model_id=19911&pr_number=441&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F441&signature=25479105c4f0bcd6130151f371ae9bf236de5dced264743cd5afbfb19e5a6c35"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…F-8 (#440)

Agent-written email that ships styled HTML (fonts, colors, CSS buttons) reads as an automated blast and overrides the recipient's client fonts, and body files written in the wrong encoding turn em dashes and emoji into mojibake that is unrecoverable once sent. Add an Email section to the shared protocol and tighten the email skills: write plain text only and let the mail helper generate its bare, composer-shaped HTML mirror; write body files as UTF-8 and read the draft back after creating or updating it to confirm special characters came through intact.

**Deployment notes**

Behavior flip: prompt + seed-skill text now steers all orgs' agents to plain-text email and away
from styled HTML with no opt-in — intended, but visible output change
skills-seed edits only take effect where the deployment re-materializes seed skills; orgs with
already-customized copies of google-workspace/email-draft-in-voice keep their old text

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/440"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789245083&installation_model_id=19911&pr_number=440&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F440&signature=e19d635545d56d84ae774215ccb3456387aa77736219e8c6dc3cad4b65996173"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
so the archive icon doesn't overlap long titles Long ellipsized session titles in the sidebar ran underneath the hover archive quick-action. The row's right padding (34px desktop, 48px touch) was sized for a single 26px menu button, but the absolutely-positioned hover menu now holds two buttons, so the title's ellipsis point sat under the archive icon. Reserving 62px on desktop and 92px on touch layouts makes titles end just short of the first button. CSS-only, two lines.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/439"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789244919&installation_model_id=19911&pr_number=439&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F439&signature=df81330605f6f7371aa59d900d586a58969fcec504e14e296820d0da18bd5125"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
The session top bar added a third child to .custom-chat-shell, but the grid kept two rows (minmax(0,1fr) auto): the auto row swallowed the height, the header's row collapsed to 0px, and the message scroller painted over the bar — overlapping ghost text and unclickable header buttons. Rows are now auto minmax(0,1fr) auto, with the card/strip glance tiers (which render no top bar) keeping the old two-row template.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/433"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789244888&installation_model_id=19911&pr_number=433&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F433&signature=c2bfcf56939ff1dde7bbfec67f82168e24d3feafe567b16f3144c6ff0ed6ad4a"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
…424)

A chat pane's column width and gutters were driven by window-level responsive state: a max-width media query set the layout variables globally on :root, and the height-driven compact density tier hard-coded the chat scroll's horizontal padding. In the split canvas a pane's size is decoupled from the window, so resizing the window flipped panes between a centered column with wide gutters and a full-bleed layout — user messages crowded the pane edge. Each chat surface is now an inline-size container and the layout variables are driven by container queries on the surface's own width; the compact density tier only squeezes vertical padding. Single-pane behavior at the same widths is unchanged.

<!-- codesmith:footer -->
---
<a href="https://app.blacksmith.sh/yc-software/codesmith/qm/pr/400"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1789237877&installation_model_id=19911&pr_number=400&repository=yc-software%2Fqm&return_to=https%3A%2F%2Fgithub.com%2Fyc-software%2Fqm%2Fpull%2F400&signature=3d4a1d708fdac29a61ecb6becbfb764621031eb26578e634623d9c429472b8d7"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
cuts, jsonb-safe serialization, CAS promotion, mid-run files, IME Enter Seven first-principles fixes for reported bugs, one commit per bug. bench:memory and the twin-instance script broke under any directory containing a space (new URL(...).pathname keeps percent-escapes) — use fileURLToPath everywhere a file URL becomes a path (#77). The audit redactor missed base64url-shaped (JWT-alphabet) secrets and its --with-token rule replaced the match with itself, a literal no-op (#80). Slack section splitting, clip, and inlineCode cut with bare slice, bisecting emoji surrogate pairs, <url|label> entities, and format runs — one safe-boundary cutter now backs all three (#82). The Postgres-backed durable map JSON.stringifies into jsonb, which rejects NULs and lone surrogates the system's own truncation helpers manufacture — sanitize at the serialization boundary (#62). Scratch-memory promotion wrote back with a blind replace, reverting any edit that landed during its model call — the write is now compare-and-set against the revision read at the start (#79). Steering a live run with a captionless file dropped the file while reporting steered:true — wakes now carry attached file names so the file is announced to the run (#89). And the Enter that confirms an IME composition (Japanese/Chinese/Korean) no longer submits the half-composed message (#140, issue #225).  toyoshi

Co-authored-by: Hawthorn <217181565+lamenting-hawthorn@users.noreply.github.com>
return createSecretValueMasker(env)(command)
.replace(/(--?(?:token|password|secret|client[-_]?secret|api[-_]?key)[ =])\S+/gi, "$1<redacted>")
.replace(/(--with-token\b)/gi, "$1")
.replace(/(?:printf|echo)(?:\s+(?:-\w+|"[^"]*"|'[^']*'|\S+))+(\s*\|[^|]*--with-token\b)/gi, "echo <redacted>$1")
@ReganBell ReganBell closed this Aug 13, 2026
@ReganBell
ReganBell deleted the upstream-1841 branch August 13, 2026 21:33
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.

3 participants