Skip to content

feat(desktop): raise the install ceiling and make installs observable - #3368

Merged
wpfleger96 merged 11 commits into
mainfrom
duncan/install-ceiling-pipeline
Jul 30, 2026
Merged

feat(desktop): raise the install ceiling and make installs observable#3368
wpfleger96 merged 11 commits into
mainfrom
duncan/install-ceiling-pipeline

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Windows installs of Goose and other harnesses failed at exactly five minutes with an empty error (#2401). The 300s ceiling was killing installs that were working, just slowly — the Goose step pulls a ~79MB release asset, and Windows Defender scans every file npm extracts. When the ceiling fired it discarded the output it had already read, so the user got a bare timeout string and no way to tell a hang from a large download.

The ceiling

INSTALL_TIMEOUT is 900s, and the error names the limit: install command exceeded the 15m ceiling and was terminated. It stays a pure wall-clock ceiling with no inactivity kill — nothing observable distinguishes a hung installer from one silently transferring a large artifact, so silence alone never kills an install. A ceiling kill remains non-retryable; re-running a command that already burned 15 minutes costs the user more time with no plausible path to success.

The child's exit and both stream drains fold into one resumable settle governed by a single deadline. Waiting on the drains outside that deadline would let a descendant that outlived the install shell hold the output pipes — and the per-runtime install guard behind them — open with no bound, which is the failure the ceiling exists to prevent. So the deadline path terminates the process group on the normal-exit branch too: a leader that exited with a real status still gets its stragglers killed, and the guard cannot stick either way. Whether the leader had already exited only decides the verdict — its real status outranks a timeout.

The install shell is a session leader and its descendants inherit the output pipes, so signalling only the leader left them running and the drains blocked on a pipe nobody would close. Escalation keys off the group's liveness rather than the leader's, since a descendant that ignores SIGTERM outlives the leader and would otherwise never receive the group SIGKILL. Reaping the killed child and finishing the drains share one bounded grace, so a termination that failed outright cannot extend the ceiling that just fired.

Output capture

Each stream drains into a bounded capture that is shared with the reader rather than returned by it, so whatever arrived before a stall is readable at the ceiling — exactly when the output matters most. Output of any size costs a fixed amount of memory.

One capture holds two independently bounded views of the same bytes:

View Head / tail Cut marker
UI (InstallStepResult) 512 B / 1024 B ... (N bytes omitted) ...
Log file 128 KiB / 128 KiB ... [N bytes omitted at cap] ...

The UI budget is screen space; the log's is disk. Both markers are inline, so neither ever implies completeness it does not have. Both ends are cut at arbitrary byte offsets, so a partial character is trimmed and the partial token each cut left behind is dropped — the marker's byte count includes both trims.

Install log

steps carries only the last attempt of each step, truncated for display. Everything else — earlier retries, the prerequisite step that actually broke, the managed-Node bootstrap — used to be discarded. InstallReporter now appends one self-contained record per attempt of per step to install-<runtime-id>.log beside the agent logs, and InstallRuntimeResult.log_path carries the file to the UI, where a failure message ends with Full log: <path>.

Each record is bounded independently by the log-scale capture that produced it, so a first attempt that printed megabytes cannot push out the later record explaining the failure; the run's total is bounded by steps × attempts × per-record cap. Every early return builds its result through one InstallReporter::failed helper, so no failure path can omit the log pointer, and synthesized steps go through record_step — a step that reaches the UI without passing it would be invisible in the file.

Install output can echo a registry token or proxy credential from the environment it ran in, and the file is written unattended. Redaction keys off the names of the environment variables the install inherited, snapshotted once per run, rather than a list of known secret value prefixes: a credential with no recognisable shape is exactly the one a prefix match misses. Three name rules apply, because the variables need different treatment:

Rule Variables Redacted
URL userinfo HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NPM_CONFIG_PROXY, NPM_CONFIG_HTTPS_PROXY, NPM_CONFIG_REGISTRY user:password only
Exact name NPM_CONFIG_KEY, NPM_CONFIG__AUTH, NPM_CONFIG_OTP whole value
Marker substring *TOKEN*, *SECRET*, *PASSWORD*, *_PAT, … whole value, 8-byte floor

A proxy or registry keeps its host and port, because an install that fails behind one is diagnosable only if the record still says which one it went through, and a bare user@ with no password is not treated as a credential. npm's own settings are listed by exact name rather than matched on KEY or AUTH substrings — both occur throughout an ordinary environment on values that are paths and people's names — and they bypass the 8-byte floor, since a six-digit one-time password is a credential at that length. Matching is case-insensitive, which is what npm's lowercase npm_config_* spelling needs. 0o600 is set by the create rather than a later chmod, which would leave a window where the umask decides. A runtime id that cannot safely be a filename yields no log rather than a sanitized one — a rewritten id could collide with another runtime's log.

The file holds exactly one run. A run opens its own session after the runtime id has been canonically resolved — the previous file rotates to .1 and any older .1 is removed before the rename, since a rename that will not replace its destination would otherwise wedge rotation permanently on Windows. The session writes a header naming the runtime, the app version (app.package_info().version on the Rust side — cannot be mocked or fail), the OS (std::env::consts::OS), and the start time: a Windows failure and a macOS one on the same runtime are different bugs, and a stale app version explains a failure that no longer reproduces. Each record carries its attempt's elapsed time.

Live output line

A 15-minute ceiling with nothing behind it but a spinner is indistinguishable from a hang. The same drain seam feeds an acp-install-output event carrying the newest complete line, and the three install entry points — Doctor harness rows, the harness catalog dialog, and onboarding runtime cards — render it under the spinner with aria-live="polite".

Ordering is keyed on a seq monotonic across the whole install, not on the attempt number, which restarts at 1 for every step: keyed on attempt, one step succeeding on attempt 2 would make the next step's attempt-1 output look stale and freeze the display for the rest of the install. Each executed attempt begins with an unthrottled line: null clear signal, so a stale failure line cannot sit under the spinner while the retry runs. Events are otherwise throttled to four per second, and the throttle retains the newest pending line and flushes it when the window reopens rather than dropping it — at an attempt boundary a drop would silently eat the new attempt's first line.

The subscription is mounted for the runtime's whole lifetime rather than started when the install begins. The install command is invoked from the click handler, so the clear and a fast command's first lines can be emitted before React has committed the pending state, and nothing replays them — a subscription that waited for that state would lose the entire output of a short install. The run boundary resets the ordering key when the install settles, since seq restarts for the next run, and the line renders only while installing, so a straggler from a finishing drain cannot appear under a fresh Install button.

The 15-minute ceiling deliberately stops waiting on stuck drain threads — a hung installer must not freeze the app. That means a drain thread can outlive its InstallReporter. Without a generation guard, a drain that calls offer after the run settles would publish an event with the run's high seq, poison the permanent listener's React state, and cause the next install's restarted seq=0 events to be rejected. Live now carries a lifecycle: Arc<RwLock<bool>>; drain threads hold a shared read guard from the admission check through the (self.emit)(...) call, making the check-then-emit pair atomic with respect to shutdown. InstallReporter::drop takes the exclusive write guard and stores false — this blocks until every in-flight drain publication releases its read guard, then prevents any new admission. Deactivation is bounded: the write lock holds only for the flag store, so it can block at most for the duration of one emit call (microseconds to low milliseconds). Rust drops locals in reverse-declaration order, so reporter drops before _guard, ensuring the exclusive write completes before the per-runtime concurrency guard releases and a new install can start.

Also

Install result types move to desktop/src/shared/api/installTypes.ts, following the existing searchTypes.ts / workflowTypes.ts convention, and are re-exported from tauri.ts and types.ts — both already over the file-size cap, so neither can grow to carry them.

Two comments described AdapterOutdated as applying only to the deprecated package; it also covers a version below the supported floor.

Report: #2401

@wpfleger96
wpfleger96 requested a review from a team as a code owner July 28, 2026 19:22
@wpfleger96
wpfleger96 force-pushed the duncan/install-ceiling-pipeline branch from 8e04e9b to 31416cf Compare July 28, 2026 21:02
@wpfleger96 wpfleger96 changed the title fix(desktop): raise the install ceiling to 15 minutes and keep its output feat(desktop): raise the install ceiling and make installs observable Jul 28, 2026

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bounded capture/logging and timeout-triggered process-tree cleanup are useful improvements, but the inline issues need addressing before merge. Please also resolve the current conflict with main and rerun CI on the resulting head.

Comment thread desktop/src/features/agents/lib/useInstallOutputLine.ts Outdated
Comment thread desktop/src-tauri/src/commands/agent_discovery/install_exec.rs Outdated
Comment thread desktop/src-tauri/src/commands/agent_discovery/install_report.rs Outdated
Comment thread desktop/src-tauri/src/commands/agent_discovery/install_report.rs Outdated
@wpfleger96
wpfleger96 force-pushed the duncan/install-ceiling-pipeline branch 2 times, most recently from 16b6bfa to dc6421a Compare July 29, 2026 17:55
…tput

A hard 300s wall killed installs that were working, just slowly: the Goose
step downloads a ~79MB release asset and Windows Defender scans every file npm
extracts, which routinely pushes a healthy install past five minutes (#2401).
The ceiling is now 900s, and it stays a pure wall-clock ceiling — nothing
observable distinguishes a hung installer from one silently transferring a large
artifact, so silence alone never kills an install.

A ceiling kill used to return empty stdout and a bare timeout string, discarding
the one piece of evidence that says where the install stalled. Output now drains
into a bounded head/tail sink shared with the reader rather than a String the
reader returns, so the partial capture is readable at the ceiling and an
installer printing megabytes costs a fixed amount of memory.

The install shell is a session leader, so signalling only its PID left
descendants alive holding the output pipes — the drain joins could then block
past the ceiling, holding the concurrency guard that rejects the user's next
install attempt. The ceiling now terminates the whole process group through the
same SIGTERM/grace/SIGKILL path used for managed agent runtimes, and waits a
bounded grace for the drains instead of joining unconditionally.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
A failing install surfaced only its last step's stdout/stderr, truncated to
1.5KB for a toast. Everything before it — earlier retries of the same step, the
prerequisite step that actually broke, the managed-Node bootstrap — was
discarded, so the user got a symptom with no history behind it. The install now
writes a log file: one self-contained record per attempt of per step, appended
under 0o600, and the failure message ends with `Full log: <path>`. Each record
is bounded independently at 128KiB of head and tail per stream, so an early
attempt that printed megabytes cannot push out the later record that explains
the failure, and the run's total is bounded by steps x attempts. A record cut at
the cap says so inline, so the file never implies completeness it lacks.

Both bounds hang off one drain seam: each stream's drain feeds a capture holding
two views of the same bytes, the UI's 512/1024 and the log's 128KiB/128KiB.
Install output can echo a registry token from the environment it ran in and the
file is written unattended, so records are redacted and the owner-only mode is
set by the create rather than a later chmod. A runtime id that cannot be a
filename yields no log rather than a sanitized one, which could collide with
another runtime's.

The same seam feeds the live output line the install cards now show. A 15-minute
ceiling with nothing but a spinner behind it is indistinguishable from a hang;
the newest line the installer printed makes the wait observable. Lines are
throttled to four events a second and tagged with their attempt, so a line
emitted just before a retry starts cannot sit under the spinner describing work
that has already been superseded.

The ceiling's own kill now escalates on the group's liveness rather than the
leader's: a descendant that ignores SIGTERM outlives the install shell, and
escalation keyed to the leader would leave it running with the output pipes
open. Reaping the killed child and finishing the drains share one bounded grace,
since a termination that failed outright must not extend the ceiling that fired
or the per-runtime guard behind it.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
… seq

The ceiling only bounded the child's exit: the drain joins ran after it, so a
descendant that outlived a normally-exited install shell held the output pipes —
and the per-runtime install guard behind them — open with no bound at all. Exit
and drains now fold into one resumable settle under a single deadline, and the
deadline path terminates the process group on the normal-exit branch too, so the
guard cannot stick either way.

Live output was keyed on the per-step attempt number, which restarts at 1 for
every step, so one step succeeding on attempt 2 froze the display for the rest of
the install. The key is now a sequence monotonic across the whole install, paired
with an unthrottled clear signal at each attempt start; the throttle retains the
newest pending line and flushes it rather than dropping the first line of a new
attempt.

Log redaction matched only known secret prefixes, so a value with no recognisable
shape survived; it now redacts by env variable name, snapshotted for the run.

Install result types move to `installTypes.ts` so `tauri.ts` and `types.ts`, both
already over the size cap, do not have to grow to carry them.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…arts

The live-output subscription was created only once React had committed the
pending install state, but the install command is invoked from the click
handler: the backend emits the attempt-start clear and can emit its first line
inside that window, and nothing replays them. A fast command's entire output
could therefore never appear. The listener is now mounted for the runtime's
whole lifetime; the run boundary resets the ordering key when the install
settles, and the line is rendered only while installing, so a straggler from a
finished drain cannot show up under a fresh Install button.

The E2E seam was hiding this: it delayed every event, with the first gap
existing specifically to let the clicked row mount its listener. The clear and
the first line now emit synchronously with the invocation, and the spec asserts
the first line is observed, so it pins production ordering instead of
accommodating it. The bridge's sequence also restarts per install, matching the
backend's per-run counter, and a second install asserts the display accepts a
restarted sequence.

The install log header now names the app version and OS: a Windows install
failure and a macOS one on the same runtime are different bugs, and a stale
version explains a failure that no longer reproduces. The version is read from
the app's own package info rather than the frontend plugin, so it cannot be
mocked out from under the log. The bridge gains the `plugin:app|version` stub it
was missing, which also removes an unhandled page error on every Settings
render.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
A drain thread holds an owned clone of `Live` and can call `offer`
after `InstallReporter` is dropped (the run boundary). An atomic flag
check before emit is insufficient: a thread admitted while active can
pause between the check and the emit, and `Drop` can complete in that
window — letting the late publication land in the permanent listener's
React state with run 1's high `seq`, causing run 2's restarted
`seq=0` events to be rejected by the `event.seq <= current.seq` guard
and displaying run 1's stale output.

Fix: replace `Arc<AtomicBool>` with `Arc<RwLock<bool>>` in `Live`.
Drain threads hold a **shared read guard** from the admission check
through the `(self.emit)(...)` call, making the check-then-emit pair
atomic with respect to shutdown. `InstallReporter::drop` takes the
**exclusive write guard** and stores `false`; this blocks until every
in-flight publication has released its read guard, then prevents any
new admission. Deactivation is bounded: the write lock holds only for
the flag store, so it can block at most for the duration of one emit
call (microseconds to low milliseconds for the Tauri IPC broadcast).

No deadlock is possible: `(self.emit)` in production is
`app.emit("acp-install-output", event)` — fire-and-forget Tauri IPC
that does not call back into `Live`. In tests it is a Vec push.

The declaration order in `install_acp_runtime_blocking` is load-
bearing: `reporter` is declared after `_guard` (line 311 vs line 306),
so Rust drops it first (reverse-declaration order), ensuring the
exclusive write completes before the per-runtime concurrency guard
releases and a new install for the same runtime can begin.

Three pin tests:
- `test_a_detached_observer_cannot_emit_after_the_reporter_is_dropped`:
  sequential drain-after-drop is a no-op. Fails when the lifecycle
  guard is removed from offer.
- `test_deactivation_blocks_until_in_flight_publication_completes`:
  white-box concurrency pin — acquires a read guard, asserts
  `try_write()` fails while the guard is held, releases the guard, then
  completes deactivation. Fails to compile on the old atomic shape
  (`dc6421ac4`) because the `lifecycle` field does not exist.
- `test_run2_output_replaces_stale_run1_state_through_shared_consumer`:
  one shared event sink for both runs; consumer resets to null at
  run-1 settlement (modeling the frontend `isInstalling` reset); verifies
  run 2's output wins through the shared reducer. Fails when the
  lifecycle guard is removed from offer (late drain emits with high seq,
  poisons the null-reset consumer before run 2 can emit seq=0).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 force-pushed the duncan/install-ceiling-pipeline branch from dc6421a to 79593af Compare July 29, 2026 18:55
@wesbillman

Copy link
Copy Markdown
Collaborator

Disclosure: Carl is commenting on Wes Billman's behalf.

The concurrency/timeout/log-rotation work is clean at 79593af8c, and the other earlier findings are resolved. One redaction blocker remains before approval.

env_secret_values() only collects values whose variable names contain TOKEN, SECRET, PASSWORD, PASSWD, APIKEY, API_KEY, PRIVATE_KEY, ACCESS_KEY, or CREDENTIAL. Common inherited credentials therefore remain outside self.secrets, including:

  • HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY values containing URL userinfo such as http://user:password@proxy.example;
  • GITHUB_PAT / GH_PAT values such as ghp_… or github_pat_….

Those complete values also match neither fallback prefix (nsec1, sprt_tok_), so an installer echoing them can place them verbatim in the install log and live output event. Please extend the secret-name/value handling and add regressions for both surfaces. Avoid a broad contains("PAT") or contains("_PAT"), which would also match *_PATH; exact names or ends_with("_PAT"), explicit proxy names, and recognized GitHub token prefixes are safer.

There is a third frontend-visible path to cover in the same fix: install_exec.rs builds InstallStepResult.stdout/stderr directly from capture.ui(), and installError.ts renders the failing step output. That returned step output is currently unredacted even when the log/live paths redact. Please scrub it before returning the result and add a regression for the rendered/returned error surface too.

Required coverage: proxy and PAT credentials are removed from (1) the log record, (2) the live event, and (3) returned step stdout/stderr.

npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 and others added 6 commits July 30, 2026 11:20
An install inherits Buzz's environment and installers echo it back, but
the secret filter missed two credentials that are routinely present:
proxy URLs carrying `user:password` userinfo, and personal access tokens
under `GITHUB_PAT`/`GH_PAT`. Neither matched a name marker nor a value
prefix, so an installer that printed one wrote it verbatim to the install
log and the live output line.

For proxies only the userinfo is treated as secret, not the whole value.
An install that fails behind a proxy is diagnosable only if the record
still says which proxy it went through, and the host and port are not the
credential — redacting the entire value would destroy that while
protecting nothing more. A bare username with no password is likewise not
a credential, and scrubbing it would erase every occurrence of a common
word from the log.

PAT variables match `_PAT` as a suffix rather than a substring:
`contains("_PAT")` would match every `*_PATH` variable and scrub
directory names out of the whole file.

The name-based and shape-based paths do not overlap. A token in our own
environment under a PAT-ish name is caught by name whatever its shape;
the GitHub value prefixes added to `redact_secrets_with` catch a token
that reaches output from outside the environment — embedded in a git
remote URL an installer echoes — which no name-based rule can see. That
list lives in the shared scrubber so the next caller cannot silently miss
GitHub tokens.

The third surface was the step returned to the frontend:
`InstallStepResult.stdout/stderr` came straight from the capture with no
scrubbing, and `getInstallErrorMessage` renders it on failure. Scrubbing
happens in the two reporter funnels every step already passes through,
which covers the ordinary exit, the status-check failure and the timeout
path together rather than at each construction site.

Secret classification is split into a pure function so the proxy and PAT
rules are assertable without exporting a live `HTTPS_PROXY` into the test
process, where every HTTP client the suite builds would read it.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…g-pipeline

* origin/main: (25 commits)
  Refine agent sharing dialog (#3699)
  desktop: enable getUserMedia in the Linux WebKitGTK webview (#3607)
  fix: align responsive agent views (#3688)
  Add macOS agent menu-bar menu (#3565)
  Fix pending message feedback (#3543)
  fix(desktop): remove remaining Projects panel fills (#3742)
  feat(mobile): desktop-parity emoji and thread experience (#3485)
  desktop: restore direct community member adds (#3634)
  fix(desktop): explain open agent access (#2561)
  fix(cli): resolve agents from owner records (#3178)
  fix(desktop): remove Projects overview card fills (#3416)
  feat(replica): portable heartbeat-token fence with snapshot-local reader routing (#3268)
  fix(git): channel binding tooling + author remediation for unbound repos (#3626)
  feat: configure S3 URL addressing style (#3400)
  feat: add first-class OpenRouter provider support (#1975)
  feat(agent,acp): wire provider total_tokens through NIP-AM publish chain (#3593)
  chore(release): release Buzz Desktop version 0.5.2 (#3624)
  docs: add Linux rendering troubleshooting guide (#3573)
  fix(desktop): discover bun-installed agent CLIs in ~/.bun/bin (#3343)
  feat(tracing): correlate trace IDs in relay logs (#3608)
  ...

Signed-off-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…g-pipeline

* origin/main:
  feat(catalog): resolve publisher display name in catalog detail pane (#3640)
  feat(mesh): upgrade embedded mesh to v0.74 and harden shared compute (split 1/2 of #3467) (#3741)
  docs(nips): specify kind:30621 multi-repo projects (NIP-MP) (#3163)

Signed-off-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
npm resolves NPM_CONFIG_PROXY and NPM_CONFIG_HTTPS_PROXY ahead of the
conventional proxy variables and echoes the resolved value back, but
neither name carries a marker the name-based classifier recognises, so a
credential set only under an alias never entered the scrub list and could
reach the log, the live output line and the returned UI step.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
npm accepts every setting as an npm_config_* environment variable and
echoes its resolved config on an auth failure, so a client key, a
basic-auth blob, a one-time password or a credentialed registry URL could
reach the install log, the live output line and the returned UI step. None
of those names carries a marker the name-based classifier recognises.

The credentials are listed by exact name rather than matched on KEY or
AUTH substrings: both occur throughout an ordinary environment on values
that are paths and people's names, and scrubbing on them would delete
unrelated text from every record. The registry follows the proxy policy
instead — which registry an install talked to is what a 401 has to be read
against — so only its userinfo is secret, which is why the URL list is no
longer proxy-specific.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The redaction cases grew the single test file past the desktop 1000-line
ratchet, which is a hard cap for a file that does not exist on main. They
are a self-contained concern, so they move to their own module alongside
the shared harness, following the split migration.rs already uses.

No test changes: 37 before, 37 after.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96 added a commit that referenced this pull request Jul 30, 2026
Removes the Require-main gate so this workflow can be dispatched from
a throwaway branch for pre-merge testing of #3368. The gate is in the
workflow file itself, not a repo rule, so running on a branch that
omits it leaves main's copy untouched.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 merged commit d40a332 into main Jul 30, 2026
26 checks passed
@wpfleger96
wpfleger96 deleted the duncan/install-ceiling-pipeline branch July 30, 2026 21:07
wpfleger96 pushed a commit that referenced this pull request Jul 30, 2026
* origin/main: (29 commits)
  feat(desktop): raise the install ceiling and make installs observable (#3368)
  fix(db): isolate usage metrics advisory-lock test on scratch DB (#3670)
  Add Devin as a preset ACP harness (#3225)
  feat(desktop): improve agent activity header ui (#3321)
  perf(presence): reduce heartbeat frequency (#3783)
  Tighten continuation message rows (#3724)
  Fix video reviews in thread replies (#3719)
  feat(release): make desktop releases immutable (#3568)
  Make relay reconnect backoff authoritative (#3774)
  feat(desktop): add password-protected backups in settings (#3701)
  fix(desktop): reuse profiles when joining communities (#2155)
  Render mobile agent mention chips (#3702)
  fix(catalog): update Amp description (#3758)
  fix(acp): preserve truncated thread context (#3340)
  feat(catalog): resolve publisher display name in catalog detail pane (#3640)
  feat(mesh): upgrade embedded mesh to v0.74 and harden shared compute (split 1/2 of #3467) (#3741)
  docs(nips): specify kind:30621 multi-repo projects (NIP-MP) (#3163)
  Refine agent sharing dialog (#3699)
  desktop: enable getUserMedia in the Linux WebKitGTK webview (#3607)
  fix: align responsive agent views (#3688)
  ...

Signed-off-by: npub1g8493u0xfsjrvflg4n08ezd7vec99mnwzlv0qgwpr9d7gvjwhuzqx59rhw <41ea58f1e64c243627e8acde7c89be667052ee6e17d8f021c1195be4324ebf04@buzz.block.builderlab.xyz>
tellaho pushed a commit that referenced this pull request Jul 30, 2026
* origin/main:
  fix(desktop): allow linux-only media items as dead code off-linux (#3811)
  fix(desktop): report authenticated relay recovery (#3812)
  fix(desktop): don't gate hover affordances on the hover media query (#3657)
  feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358)
  test(desktop): click visible thread collapse guide (#3800)
  feat(desktop): raise the install ceiling and make installs observable (#3368)
  fix(db): isolate usage metrics advisory-lock test on scratch DB (#3670)
  Add Devin as a preset ACP harness (#3225)
  feat(desktop): improve agent activity header ui (#3321)
  perf(presence): reduce heartbeat frequency (#3783)
  Tighten continuation message rows (#3724)
  Fix video reviews in thread replies (#3719)
  feat(release): make desktop releases immutable (#3568)
  Make relay reconnect backoff authoritative (#3774)
  feat(desktop): add password-protected backups in settings (#3701)
  fix(desktop): reuse profiles when joining communities (#2155)

Signed-off-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>
wpfleger96 added a commit that referenced this pull request Jul 30, 2026
Main's d40a332 (install ceiling PR #3368) grew types.rs by +5 lines
after the 8c87f57 paydown, pushing the merge-commit count to 1005
(limit 1000). Reclaim 7 readability-neutral lines from doc comment
blocks in ManagedAgentRecord and ManagedAgentSummary — three field
comments reflowed to eliminate wrapped-word lines
(turn_timeout_seconds, model, provider, persona_source_version) and
two pairs condensed in the Summary section (agent_command_override,
mcp_command/turn_timeout_seconds). No semantic change.

Simulated merge count: 998 (verified via git merge-tree --write-tree
origin/main HEAD).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
brow pushed a commit that referenced this pull request Jul 31, 2026
* origin/main: (70 commits)
  fix(catalog): update Amp tagline (#3806)
  fix(desktop): channel topic and membership metadata cleanup (#3642)
  fix(desktop): align data deletion labels (#2230)
  fix(relay): align NIP-11 max_limit with REQ ceiling (#3635)
  fix(desktop): allow linux-only media items as dead code off-linux (#3811)
  fix(desktop): report authenticated relay recovery (#3812)
  fix(desktop): don't gate hover affordances on the hover media query (#3657)
  feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358)
  test(desktop): click visible thread collapse guide (#3800)
  feat(desktop): raise the install ceiling and make installs observable (#3368)
  fix(db): isolate usage metrics advisory-lock test on scratch DB (#3670)
  Add Devin as a preset ACP harness (#3225)
  feat(desktop): improve agent activity header ui (#3321)
  perf(presence): reduce heartbeat frequency (#3783)
  Tighten continuation message rows (#3724)
  Fix video reviews in thread replies (#3719)
  feat(release): make desktop releases immutable (#3568)
  Make relay reconnect backoff authoritative (#3774)
  feat(desktop): add password-protected backups in settings (#3701)
  fix(desktop): reuse profiles when joining communities (#2155)
  ...

Signed-off-by: npub15w828kxsxu2684ynste0uah2jwkgatd99flt7ds4523hzm8ju6cshdr8hh <a38ea3d8d03715a3d49382f2fe76ea93ac8eada52a7ebf3615a2a3716cf2e6b1@buzz.block.builderlab.xyz>
wpfleger96 added a commit that referenced this pull request Jul 31, 2026
Main's d40a332 (install ceiling PR #3368) grew types.rs by +5 lines
after the 8c87f57 paydown, pushing the merge-commit count to 1005
(limit 1000). Reclaim 7 readability-neutral lines from doc comment
blocks in ManagedAgentRecord and ManagedAgentSummary — three field
comments reflowed to eliminate wrapped-word lines
(turn_timeout_seconds, model, provider, persona_source_version) and
two pairs condensed in the Summary section (agent_command_override,
mcp_command/turn_timeout_seconds). No semantic change.

Simulated merge count: 998 (verified via git merge-tree --write-tree
origin/main HEAD).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96 pushed a commit that referenced this pull request Jul 31, 2026
…chive

* origin/main: (25 commits)
  feat(desktop): import local Pocket voices (#3259)
  fix(desktop): open profiles from avatars (#3751)
  refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands #2467 + #3208) (#3910)
  docs: add VISION_REMOTE_AGENTS.md (#3924)
  feat(desktop): auto-enable huddle transcription for agents (#3180)
  feat(agent): optional reply guard reminds a silent turn to publish (#3763)
  feat(desktop): upgrade Pocket TTS model (#3266)
  feat(desktop): delete a message by clearing its edit to empty (#3813)
  feat(relay): raise hosted community limit to five (#3829)
  feat(desktop): locally stored NIP-49 encrypted key backup (#2937)
  fix(catalog): update Amp tagline (#3806)
  fix(desktop): channel topic and membership metadata cleanup (#3642)
  fix(desktop): align data deletion labels (#2230)
  fix(relay): align NIP-11 max_limit with REQ ceiling (#3635)
  fix(desktop): allow linux-only media items as dead code off-linux (#3811)
  fix(desktop): report authenticated relay recovery (#3812)
  fix(desktop): don't gate hover affordances on the hover media query (#3657)
  feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358)
  test(desktop): click visible thread collapse guide (#3800)
  feat(desktop): raise the install ceiling and make installs observable (#3368)
  ...

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>

# Conflicts:
#	desktop/src/testing/e2eBridge.ts
#	desktop/tests/helpers/bridge.ts
wpfleger96 pushed a commit that referenced this pull request Jul 31, 2026
…chive

* origin/main: (25 commits)
  feat(desktop): import local Pocket voices (#3259)
  fix(desktop): open profiles from avatars (#3751)
  refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands #2467 + #3208) (#3910)
  docs: add VISION_REMOTE_AGENTS.md (#3924)
  feat(desktop): auto-enable huddle transcription for agents (#3180)
  feat(agent): optional reply guard reminds a silent turn to publish (#3763)
  feat(desktop): upgrade Pocket TTS model (#3266)
  feat(desktop): delete a message by clearing its edit to empty (#3813)
  feat(relay): raise hosted community limit to five (#3829)
  feat(desktop): locally stored NIP-49 encrypted key backup (#2937)
  fix(catalog): update Amp tagline (#3806)
  fix(desktop): channel topic and membership metadata cleanup (#3642)
  fix(desktop): align data deletion labels (#2230)
  fix(relay): align NIP-11 max_limit with REQ ceiling (#3635)
  fix(desktop): allow linux-only media items as dead code off-linux (#3811)
  fix(desktop): report authenticated relay recovery (#3812)
  fix(desktop): don't gate hover affordances on the hover media query (#3657)
  feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358)
  test(desktop): click visible thread collapse guide (#3800)
  feat(desktop): raise the install ceiling and make installs observable (#3368)
  ...

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>

# Conflicts:
#	desktop/src/testing/e2eBridge.ts
#	desktop/tests/helpers/bridge.ts
joahg added a commit to joahg/buzz-dev-mode that referenced this pull request Jul 31, 2026
…-style

* origin/main: (22 commits)
  feat(desktop): import local Pocket voices (block#3259)
  fix(desktop): open profiles from avatars (block#3751)
  refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands block#2467 + block#3208) (block#3910)
  docs: add VISION_REMOTE_AGENTS.md (block#3924)
  feat(desktop): auto-enable huddle transcription for agents (block#3180)
  feat(agent): optional reply guard reminds a silent turn to publish (block#3763)
  feat(desktop): upgrade Pocket TTS model (block#3266)
  feat(desktop): delete a message by clearing its edit to empty (block#3813)
  feat(relay): raise hosted community limit to five (block#3829)
  feat(desktop): locally stored NIP-49 encrypted key backup (block#2937)
  fix(catalog): update Amp tagline (block#3806)
  fix(desktop): channel topic and membership metadata cleanup (block#3642)
  fix(desktop): align data deletion labels (block#2230)
  fix(relay): align NIP-11 max_limit with REQ ceiling (block#3635)
  fix(desktop): allow linux-only media items as dead code off-linux (block#3811)
  fix(desktop): report authenticated relay recovery (block#3812)
  fix(desktop): don't gate hover affordances on the hover media query (block#3657)
  feat(relay): gate kind 30178 team-catalog reads behind the shared tag (block#3358)
  test(desktop): click visible thread collapse guide (block#3800)
  feat(desktop): raise the install ceiling and make installs observable (block#3368)
  ...

Amp-Thread-ID: https://ampcode.com/threads/T-019fb8e1-6ece-72a7-8808-9b12e0f7e833
Co-authored-by: Amp <amp@ampcode.com>
Signed-off-by: Joah Gerstenberg <joah@squareup.com>

# Conflicts:
#	desktop/src-tauri/src/linux_media.rs
#	desktop/src/app/AppShell.tsx
wpfleger96 added a commit that referenced this pull request Aug 2, 2026
Main's d40a332 (install ceiling PR #3368) grew types.rs by +5 lines
after the 8c87f57 paydown, pushing the merge-commit count to 1005
(limit 1000). Reclaim 7 readability-neutral lines from doc comment
blocks in ManagedAgentRecord and ManagedAgentSummary — three field
comments reflowed to eliminate wrapped-word lines
(turn_timeout_seconds, model, provider, persona_source_version) and
two pairs condensed in the Summary section (agent_command_override,
mcp_command/turn_timeout_seconds). No semantic change.

Simulated merge count: 998 (verified via git merge-tree --write-tree
origin/main HEAD).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
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.

2 participants