Commit Graph
2983 Commits
Author SHA1 Message Date
PerishFireandGitHub 657fb09f3a revert(pack): restore working Windows installer (#6008) 2026-07-23 11:41:17 +00:00
Chanhyo JungandGitHub 506c2900b9 fix(message-center): guard invalid published dates (#6007) 2026-07-23 07:16:15 +00:00
PerishFireandGitHub ff445a7a43 fix(web): remove duplicate preview run elapsed (#6005) 2026-07-23 05:15:22 +00:00
open-design-release-bot[bot]GitHubopen-design-release-bot[bot] <open-design-release-bot[bot]@users.noreply.github.com>
ca4ecf0bf2 chore(release): bump main to 0.16.1 ahead of stable 0.16.0 (#6000)
Co-authored-by: open-design-release-bot[bot] <open-design-release-bot[bot]@users.noreply.github.com>
2026-07-23 03:15:11 +00:00
Chanhyo JungandGitHub 2f1778752e feat(mcp): add Raven installer target (#5969) 2026-07-23 02:48:11 +00:00
Pavel CherkashinandGitHub 99bc3d60d9 fix(web): dedupe project workspace tabs on repeated open (#5993)
* fix(web): dedupe project workspace tabs on repeated open

The openWorkspaceTab event handler unconditionally appended a new tab on
every project-open event, so reopening the same project stacked duplicate
tabs instead of focusing the existing one. Mirror the dedup logic already
in syncStateToRoute: when a project tab with the same projectId exists,
update its conversationId/fileName/lastActiveAt and activate it rather
than appending.

Fixes #2641

* fix(web): coalesce duplicate project tabs on workspace restore

normalizeTabsState deduplicated entry tabs and tab ids but not project
tabs sharing a projectId, so workspaces persisted before the dedupe fix
restored with their pre-existing duplicate project tabs still visible.
Coalesce project tabs by projectId in normalizeTabsState (keep the active
match, else the newest), mirroring the entry-tab dedupe. This repairs
affected persisted state on restore, not just new corruption.

Adds a restore regression with two distinct tab ids for the same project.

Follow-up to #2641 / review feedback on #5993
2026-07-23 02:47:35 +00:00
Abhishek SarkarandGitHub 034c3895d1 fix(web): hide empty tool_call/tool_call_update status rows (#4621)
buildBlocks() in AssistantMessage filters a fixed list of internal status
labels before they reach StatusPill, but tool_call / tool_call_update are
not in it, so they fall through and render as raw, expandable status pills
with no tool name, input, output, or detail — looking like "a tool ran but
produced no output".

These are transient ACP markers: on the live SSE path the daemon already
normalizes them to `running` (TRANSIENT_ACP_STATUS_LABELS in
providers/daemon.ts), which buildBlocks() skips. The persisted-events path
does not normalize, so the bare labels survive into the UI. Add both labels
to the existing skip list, with a comment pointing at the daemon source of
truth.

Add a red-spec test asserting the two empty status rows render no pill, plus
a guard that status rows carrying a real detail still render.
2026-07-22 14:36:07 +00:00
AmyandGitHub 3162da5f23 test: cover runtime automation gaps (#5976)
* test: cover runtime automation gaps

* fix: remove duplicate runtime startup declarations

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
2026-07-22 14:29:34 +00:00
PerishFireandGitHub 910e5d3387 docs: add 0.16.0 release notes (#5979)
* docs: add 0.16.0 release notes

* docs: make 0.16.0 notes user focused
2026-07-22 12:45:14 +00:00
netteeandGitHub adbb0ff9a4 fix(message-center): honor active AMR profile for anonymous sync (#5968)
* fix(message-center): honor active AMR profile for anonymous sync

* fix(vela): keep control context on one config snapshot

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
2026-07-22 08:45:24 +00:00
dcdb0c4204 fix packaged updates after payload cwd cleanup (#5967)
* fix packaged payload startup after cwd cleanup

* fix deferred installer helper cwd

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)

---------

Co-authored-by: Looper <looper@noreply.github.com>
2026-07-22 08:15:45 +00:00
jaehanbyunandGitHub 2337932714 feat: expose GPT-5.5 Fast service tier (#4287)
* feat: support Codex service tiers

* fix: forward service tiers through MCP runs

* fix: clear default service tier selections

* fix: preserve service tier on model option updates

* fix: preserve service tier without explicit model

* fix: preserve service tier in connection tests

* test: stabilize API empty stream UI check

* fix: preserve codex service tier labels

* fix: preserve service tier without saved model

* fix: address service tier review follow-ups

* fix: pin legacy chat assistant rows before start

* fix: accept bare model catalog responses
2026-07-22 07:11:03 +00:00
lefarcenandGitHub df58a5f3d8 feat(daemon): attribute stable-prefix drift to the input that caused it (#5802)
`stable_prompt_cache_miss_reason='stable-prompt-changed'` says THAT the
cached instruction prefix moved between turns, never WHICH input moved.
Diagnosing a drift has meant pairing Langfuse traces by hand and eyeballing
two multi-KB prompts for a diff, so the dominant bucket in production --
4,673 of 6,612 AMR drift events over 14 days, on later-resume turns -- has
no explanation telemetry can give.

Hash each named input of the prefix per turn, store the map alongside the
existing hash on agent_sessions, and diff it when the hash no longer
matches. `run_finished` gains `stable_prompt_changed_sections`; the Langfuse
turn gains the same field.

Attribute over the composer's INPUTS rather than by slicing the composed
prompt on its `---` separators: the question a drift has to answer is what
CAUSED the prefix to move, and the cause is always an input -- splitting the
output would report which bytes differ but still leave the mapping back to a
cause to a human. It also keeps prompt assembly untouched.

stablePromptHash stays the only source of truth for hit/miss; section hashes
never gate a re-send, so a section-table bug can mislabel a drift but never
suppress or fabricate one. A drift no tracked section explains reports
`unattributed` -- a coverage-gap alarm rather than a silently clean turn,
which is what keeps the table honest as new inputs enter the prefix.

The composeSystemPrompt argument literal is hoisted to a const and passed
unchanged, so one object both composes the prompt and feeds attribution
instead of a second hand-maintained copy that would drift from the real
inputs and mislabel the telemetry it exists to explain. No prompt bytes
change.
2026-07-22 07:10:46 +00:00
4fe8bb1db6 fix(pack): make Windows updates transactional (#5860)
Installer-managed processes can respawn while NSIS replaces the active executable. Quarantine the launch path and preserve the previous installation until system registration succeeds.

Co-authored-by: Kirill Turanskiy <thebtf@users.noreply.github.com>
2026-07-22 07:10:18 +00:00
lefarcenandGitHub 50843ff149 give the unattributable client failures a real error code (#5960)
* give the unattributable client failures a real error code

Three buckets in the daily stability report name nothing, and in every case the
evidence was already in scope at the emission site:

- BYOK connection test: 801 failures across 201 devices in 24h — 10% of ALL
  connection tests — reported `result.kind` verbatim, so every response the
  daemon's status→kind map had no case for collapsed into `unknown`. The user
  is told "connection failed" and we cannot say whether it was an out-of-credits
  402, a self-signed cert, or a base URL pointing at an HTML login portal.
  `ConnectionTestResponse` already carried `status` and a redacted `detail`;
  only the emission site threw them away.

- Frontend exceptions: the Top-5 table literally renders a row as
  `Error  — 235 次 / ~74 台`. Two independent sources — `buildExceptionList`
  copied `error.name`/`error.message` straight through and both can be '', and
  `parseStack` returned a zero-frame stacktrace for a stackless error, which
  PostHog drops at ingestion so neither `$exception_type` nor
  `$exception_value` survives.

- Export failures (8.1%, 210/24h): everything that was not a sidecar-skew
  message fell through to `err.name`, i.e. the literal "Error".

The daemon side of the same path flattened every sidecar contract violation to
`UPSTREAM_UNAVAILABLE`, which forced the web layer to regex-match English prose
to tell a version-skewed mesh from a dead renderer; it now forwards the
sidecar's real code, and the web classifier treats the remaining generic
envelope codes as non-classifications so a specific message still wins.

Two existing export-code expectations changed on purpose and say why inline: a
generic envelope `.code` no longer outranks message classification, and a
message carrying an HTTP status now reports that status instead of "Error".

* keep the forwarded sidecar code inside ApiErrorCode

Follow-up on the same PR. Forwarding the sidecar contract violation's `code`
compiled, but it was leaving the declared union: `ctx.http.sendApiError` is
typed `(...args: any[]) => any` in server-context.ts, so nothing caught that
`SIDECAR_UNKNOWN_MESSAGE` is not an `ApiErrorCode`. Every web-side handler
typed against that union would have failed to match the code the daemon
actually put on the wire.

Declare the two SIDECAR_* codes in API_ERROR_CODES and narrow the helper's
return type to ApiErrorCode, allowlisting exactly those two so a future sidecar
code cannot silently leave the union again.

No consumer of the export 502 switches on the old code — the UPSTREAM_UNAVAILABLE
call sites are finalize (useFinalizeProject), AMR run guidance, and ChatPane run
errors, none of which are on this route — so this is additive, not a behavior
change for anything that exists today.

* make the attribution actually fire on the production paths

Three review findings, all correct, all verified against the real code paths
rather than the synthetic ones the first cut tested.

1. The sidecar code passthrough was dead. `requestJsonIpc` rejects with
   `new Error(response.error?.message)` — its response type does not even
   declare a `code` — so SIDECAR_UNKNOWN_MESSAGE never reaches the route, and
   the helper always fell back to UPSTREAM_UNAVAILABLE. Removed the passthrough
   (and the two API_ERROR_CODES entries added for it: nothing emits them). The
   message-based classifier already achieves the attribution and is tested;
   dead code that reads as working is worse than no code. Threading the code
   through IPC → API → web export result is a three-layer change and belongs in
   its own PR.

2. The zero-frame guard checked the input instead of the output. A header-only
   stack ("Error: Script error.") is truthy, so it skipped the fallback, and the
   parser then dropped that single line as a message — yielding `frames: []`,
   the exact ingestion failure this change exists to prevent. The guard now runs
   on the PARSED result, covering missing / empty / header-only / unparseable
   stacks, with a fixture matrix over all four.

3. The certificate bucket could not fire in production. undici reports a TLS
   failure as a TypeError whose message is the generic `fetch failed`, with the
   reason only on `cause.code`, and `networkErrorToKind` maps just an allowlist
   — so a self-signed cert became `kind: unknown` + `detail: "fetch failed"`.
   The unit test passed only because it was fed a detail string production never
   emits. The daemon now appends the cause code to `detail`, and the client
   tests assert against that real shape.

* stop a 2xx status from claiming a failure it cannot explain

Review catch, and it made this PR's headline case unreachable. The status
fallback ran before every detail classifier, so the daemon's
`{ kind: 'unknown', status: 200, detail: 'Unexpected token < …' }` — which is
exactly the 'base URL points at an HTML login portal' shape, returned when a 2xx
body fails JSON.parse (connectionTest.ts) — was reported as HTTP_200, and
INVALID_JSON_RESPONSE could never fire.

Reproduced before fixing:
  byokErrorCode({kind:'unknown',status:200,detail:'Unexpected token < …'})
    → 'HTTP_200'

The cut is now at 300 rather than 0. A 2xx that still failed did so for a reason
the status cannot express, so it falls through to the detail classifiers; 3xx
stays on the status side because the daemon fetches with `redirect: 'error'`,
making a redirect a real failure the status does name.

* read the daemon-appended cause code instead of enumerating codes

Review catch on a gap my own previous commit opened: forwarding cause.code from
the daemon put OpenSSL's TLS codes on the wire, and this file could not read
them. UNABLE_TO_GET_ISSUER_CERT_LOCALLY, CERT_NOT_YET_VALID and CERT_HAS_EXPIRED
have no Node-errno shape, and the `\bcertificate\b` fallback never matches a
name that spells it CERT — so the signal was preserved on the wire and dropped
here, landing back in UNKNOWN_NO_SIGNAL.

Read the daemon's known trailing `(CODE)` position directly rather than
extending an allowlist: an enumeration would silently drop every code added
upstream after this file was written, which is the same failure mode one layer
down. Inline codes keep a widened pattern, and the TLS fallback now also matches
CERT-shaped names.

Fixtures cover all seven codes the daemon can now forward.
2026-07-22 06:57:48 +00:00
lefarcenandGitHub 2e377a5152 name every packaged startup failure instead of bucketing it as unknown (#5956)
* name every packaged startup failure instead of bucketing it as unknown

The weekly `packaged_runtime_failed` alert is dominated by failures the event
had enough evidence to name and reported as opaque anyway. Triaging a 7d window
turned up three places where the emitter threw away a cause it was already
holding:

- 62 devices died with the daemon log tail read successfully, but
  `parseDaemonLogTail` only ever matched `ERR_*`. A daemon that threw anything
  else (SQLite corruption, EPERM, a plain throw) reported error_code=null AND
  missing_module=null with its reason printed in the tail we had just read.
- 21 devices hit win32 CreateProcess failures. Node puts the real cause on the
  error's `code`/`errno`/`syscall`; the event sent `.message` only, so
  `spawn UNKNOWN` was indistinguishable from any other opaque failure.
- 149 devices produced an Error with an empty `.message` and no `.stack`. Every
  free-form field went null, leaving residue that could not even be counted
  apart from "no error at all".

So: parse the sidecar's own fatal line as a backstop when `ERR_*` misses, carry
the errno triplet off the thrown object, classify a rejected spawn as its own
`spawn-failed` kind rather than `unknown`, and guarantee a thrown error never
serializes to error_message=null — an unnamed leftover is now a named, countable
bucket.

Classification-only; the failures themselves are unchanged. Every test input is
a verbatim field payload from the alert window.

* reduce syscall to its operation token before sending it

Review catch, and a real leak. Node does not guarantee `syscall` holds only the
operation name: spawning a missing binary sets it to the whole invocation.
Verified against real Node —

  spawn('/Users/elian/nonexistent/bin/thing')
    → syscall === 'spawn /Users/elian/nonexistent/bin/thing'

Forwarding that verbatim would have put the local username and install path
into an event that is retained even for opted-out users, while every other path
this module sends goes through scrubUserPaths.

Keep the first token — the operation is the whole analytic value, and the path
is already available (scrubbed) via error_message — then scrub what survives
and cap it, as a second line of defence. `code` is capped too.

This also fixes a classification miss the same review implies: the spawn-failed
branch compared the RAW syscall to 'spawn', so a spawn error carrying a path
never matched and fell through to `unknown` — the exact bucket this PR exists
to drain.
2026-07-22 06:20:33 +00:00
91a3df9a34 fix: preserve dark-first brand canvases in derived themes (#5502)
* fix: preserve dark-first brand canvases in derived themes

A brand extracted with an explicitly dark background role and a light
foreground role previously rendered as a white kit: seedFromBrand
clamped any background below 0.72 luminance to #ffffff, and
deriveTokens re-clamped the seed and hardcoded #141414 for dark mode.
Every dark-first source (near-black app UIs, dark portfolio sites)
produced a default theme that looked nothing like the brand, and
re-running finalize reverted agent-made dark rethemes.

seedFromBrand now preserves the true canvas when the brand carries a
confidently dark background (or surface) plus a light foreground, and
deriveTokens honors a dark seed across all three algorithms: the
default theme keeps the brand canvas with dark palette math, and the
dark algorithm uses the brand's own near-black instead of the generic
fallback. Ambiguous brands (mid-gray canvas, missing roles) keep the
light baseline unchanged, and the programmatic URL fast pass
(seedFromMaterial) intentionally stays light.

* fix: align exported theme.json algorithm with dark-first tokens

Review follow-up: the derived tokens, variables.css, and kit.html use dark
palette + neutral math for a dark-first seed, but both theme.json producers
still serialized tokensToThemeJson(seed, 'default'). An Ant ConfigProvider
consumer would then apply the light algorithm to the dark canvas, diverging
from the rest of the generated system.

Add defaultThemeAlgorithm(seed) as the single shared decision (dark-first
-> 'dark', light/ambiguous -> 'default'), exported from the engine and used
by both the build.ts and system.ts (finalize) theme.json paths. Assert the
exported algorithm for both the dark-first and ambiguous cases so the
ConfigProvider artifact can't drift from the kit/CSS again.

* fix: gate dark-first predicate on dark bg AND light fg

Second review follow-up (@nettee): seedPrefersDark() keyed only off
colorBgBase, but neutralBases() (the extraction-path gate) requires a dark
background AND a light foreground. The rebuildSystem seed-override path
(sanitizeSeedOverrides) can merge a background-only override like
{ colorBgBase: '#050505' } onto an otherwise light brand, which flipped
deriveTokens to the dark ladder (forcing white text) while
tokensToThemeJson still serialized the seed's dark colorTextBase — the same
ConfigProvider mismatch under overrides instead of extraction.

Make seedPrefersDark mirror neutralBases exactly (dark <= 0.3 AND light
>= 0.6) so a background-only override stays on the light/default path
consistently across deriveTokens, defaultThemeAlgorithm, and theme.json.
Add a regression locking the override seed both ways (bg-only -> default,
bg+light-fg -> dark).

---------

Co-authored-by: wiggdevin <wiggdevin@gmail.com>
2026-07-22 06:20:06 +00:00
VERSATILandGitHub 1912c3ba97 Add Atelier Zero — Image Generation Prompt Pack plugin (#5873) 2026-07-22 06:18:52 +00:00
mehmet turacandGitHub c401b99fa1 fix(desktop): capture framework decks at authored size (#5853) 2026-07-22 06:18:35 +00:00
Nicholas-XiongandGitHub 6302432571 fix(i18n): localize BYOK provider titles to English (#5826)
* fix(i18n): localize BYOK provider titles to English

Five BYOK provider titles in apps/web/src/state/config.ts were hardcoded in
Chinese while the rest of the provider list used English-facing names:
  qwen       千问     -> Qwen
  volcengine 火山引擎 -> Volcengine Ark
  qianfan    百度千帆 -> Baidu Qianfan
  mimo       小米 MiMo -> Xiaomi MiMo
  zhipu      智谱     -> Zhipu AI

These were rendered into the Settings > Execution mode > BYOK provider chip
list verbatim, producing a mixed-language list when the UI was set to
English (issue #5693). The providerLabel for each was already in English;
only the user-facing title was inconsistent.

The new titles mirror the providerLabel phrasing where the existing
providerLabel read naturally as a standalone name (Qwen, Volcengine Ark,
Baidu Qianfan, Zhipu AI) and use a friendly "Xiaomi MiMo" for mimo where
the providerLabel carried extra "OpenAI" suffix not appropriate for a chip
title.

No i18n catalog entries needed — these were never translated, the title
field is the display string.

Fixes #5693

* fix tests: update BYOK provider tab labels to English

Two test assertions in apps/web/tests/components/SettingsDialog.execution.test.tsx
hardcoded the old Chinese tab names that were just localized to English in
the BYOK_PROVIDER_PRESET_SPECS array (commit 13037c5):

- "小米 MiMo" -> "Xiaomi MiMo" (line 1190)
- "智谱" -> "Zhipu AI" (line 1628)

Without these test updates the Web workspace tests job fails because the
tab element with the old Chinese accessible name no longer exists — the
config change renamed the chip title and the tab role name derives from it.
2026-07-22 06:18:07 +00:00
EthanandGitHub 2fd9d8134a fix(web): show full workspace tab labels and capitalize Design System (#5129) 2026-07-22 06:17:27 +00:00
Aria ZhaoandGitHub 3a5c52931c fix(web): lift home context picker secondary text to a legible token (#4468) (#4851)
* fix(web): lift home context picker secondary text to a legible token (#4468)

The home context picker (the @-mention surface above the prompt) drew its
secondary text — per-tab counts, section labels, option meta, and the
hover-card kicker — in `--text-faint`. In dark mode that token (#4e4b46)
sits at ~1.8:1 against the picker panel, far below WCAG AA, so the counts
and category labels read as illegible bleed-through.

Move those four selectors to `--text-muted`, matching the option
description that already uses it. The picker's secondary tier now clears
AA in dark mode (~5.3:1) and stays consistent across the tabs and list;
light mode improves from ~2:1 toward AA on the same selectors.

Adds a stylesheet-level contrast guard that resolves each selector's
color token and asserts WCAG AA against the surface it renders on.

* fix(web): extend picker contrast lift to the hover-card meta row (#4468)
2026-07-22 06:17:10 +00:00
netteeandGitHub d5b6cc8e34 fix(web): localize message center dates (#5954)
* fix(web): localize message center dates

* test(web): avoid Intl constructor spying in message center locale test

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
2026-07-22 04:32:29 +00:00
10201251ee feat(web): make message center close button visible by default (#5959)
Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
2026-07-22 04:19:54 +00:00
e3f6b6c7ed feat(landing): gate free-tier trial promo copy behind kill switch (#5937)
Mirrors vela's TRIAL_CREDIT_PROMO_ENABLED (powerformer/vela#912): the
new-user signup trial-credit promotion is temporarily offline, so the
/pricing/ Free card must stop advertising it while keeping every string
in place for relaunch.

While the switch is false:
- the Free card drops its trial-credit benefit row and both hosted-model
  lists (free hosted-model access, incl. the Grok trial pool, only exists
  through the signup grant)
- the Free tagline swaps to a no-promo variant (10 locales)
- the FAQ drops the "what is the limited-time trial credit" entry and
  swaps the plans-differ answer to a trial-free variant (10 locales)

Flipping the switch back to true restores all promo copy untouched.

Claude-Session: https://claude.ai/code/session_01SaoLc5kR92BffzDP8acfrA

Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
2026-07-22 04:14:29 +00:00
PerishFireandGitHub bb6c79c86d fix packaged Windows obsolete outer cleanup (#5955) 2026-07-22 03:50:42 +00:00
PerishFireandGitHub 447b18b98e fix packaged mac relaunch blocked by obsolete outer (#5940) 2026-07-21 15:01:26 +00:00
Marc ChanandGitHub 1226773663 feat(daemon): route completed-run telemetry through Vela (#5666)
* feat(daemon): route completed-run telemetry through Vela

* fix(daemon): migrate test telemetry relay domain

* feat(daemon): send Vela feedback scores with completed-run telemetry

Map score-create into the Vela envelope and use the same Vela sink for
thumbs feedback, binding scores via the client run id instead of skipping
them when account-aware telemetry is selected.

* fix(daemon): skip anonymous fallback for Vela feedback auth errors

Score-only feedback batches must stay on the account-scoped Vela path.
When Vela returns 401/403, fail the delivery instead of posting to the
anonymous relay, which has no matching trace for those scores.

Generated-By: looper 0.11.0-beta.1 (runner=fixer, agent=grok-build)
2026-07-21 13:48:54 +00:00
2d1f25ac60 feat(web): add message center (#5920)
* feat(web): add message center demo

* fix(web): align message center actions

* fix(web): remove message read toggles

* fix(web): show unread count on message filter

* feat(web): connect message center to vela (#5777)

* feat(web): connect message center to vela

* fix(web): harden message center read syncing

Generated-By: looper 0.10.6 (runner=fixer, agent=codex)

* fix(web): preserve cached message center reads

Generated-By: looper 0.10.6 (runner=fixer, agent=codex)

* fix(web): repair message center read sync and visual selector

Generated-By: looper 0.10.6 (runner=fixer, agent=codex)

* fix(web): refresh message center write auth and bound pagination

Generated-By: looper 0.10.6 (runner=fixer, agent=codex)

* fix(web): preserve message center state across locale and logout

Generated-By: looper 0.10.6 (runner=fixer, agent=codex)

* fix(message-center): stabilize login and anonymous delivery (#5910)

* journal: stop repeated amr login polling

* fix(web): drop anonymous message-center window gate

Align with Vela audience+TTL visibility by stopping startedAt local
windows so anonymous clients can pull all non-expired global messages.

* refactor(web): promote message center from demo

* fix(daemon): guard vela message center proxy stream

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)

* fix(cli): add message center command

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)

* test(e2e): harden visual workspace file readiness

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)

* fix(web): separate message center sync empty states

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)

---------

Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com>
2026-07-21 11:50:57 +00:00
PerishFireandGitHub 142edb4ac7 fix(pack): preserve native fsevents in mac bundles (#5928) 2026-07-21 11:46:08 +00:00
PerishFireandGitHub a5f0e060b3 fix packaged upgrades blocked by stale payloads (#5915)
* fix packaged upgrades blocked by stale payloads

* fix packaged duplicate launchers exiting cleanly
2026-07-21 10:22:27 +00:00
Ray XiandGitHub 068c9ae83f fix(daemon): normalize Anthropic-compatible BYOK base URLs (#5807)
* fix(daemon): normalize Anthropic-compatible BYOK base URLs

* test(e2e): stabilize home plugin details flow

Wait for Home project loading to settle before revealing templates, then target the semantic Details control after verifying actionability so layout shifts cannot collapse the gallery or trigger the wrong card action.

Generated-By: looper 0.10.4 (runner=fixer, agent=codex)

* fix(daemon): version Anthropic gateway URL paths

Append /v1 through the parsed URL pathname so gateway query parameters and fragments remain in their proper URL components. Preserve the prior string-concatenation fallback for invalid URLs.

Generated-By: looper 0.10.4 (runner=fixer, agent=codex)
2026-07-21 10:17:14 +00:00
Ray XiandGitHub d1372da029 fix(daemon): reconcile run terminals after restart (#5817)
* reconcile run terminals after restart

* fix(daemon): preserve replayed failure taxonomy

Reclassify analytics-incomplete terminal failures from their persisted state and events while keeping the interrupted template exclusive to daemon-restart recovery.

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)

* fix(daemon): preserve repaired errors and skip completed logs

The repair path previously collapsed every failed message to restart copy and hydrated event logs before checking completed telemetry checkpoints. Use durable recovery metadata for status detail and gate log reads on outstanding PostHog or Langfuse work.

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
2026-07-21 10:02:42 +00:00
Ray XiandGitHub 197e61803a fix(daemon): bound macOS watcher file descriptors (#5889)
* fix(daemon): bound macOS watcher file descriptors

* fix(daemon): preserve symlink roots and refresh Nix hashes

Keep the watch-root exemption ahead of the symlink traversal guard and lock the behavior with a real directory-symlink assertion. Refresh the daemon and web pnpm dependency hashes reported by the failing Nix build.

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
2026-07-21 09:55:49 +00:00
6fb644a57d feat(analytics): report conversation turn index (#5917)
Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com>
2026-07-21 09:44:51 +00:00
Ray XiandGitHub 4e8db9a9b7 add runtime version and retry provenance (#5814) 2026-07-21 09:23:36 +00:00
1b1f010395 fix(landing-page): keep locale variants of proper-noun blog posts out of the index (#5914)
* fix(landing-page): keep locale variants of proper-noun blog posts out of the index

The marp / slidev / reveal.js posts each rank for a single navigational
product-name query. Those queries are language-neutral, so Google ranks all
ten translated copies against the same English SERP. Over 2026-07-01..07-18
the thirty localized URLs took ~96k impressions and returned 19 clicks — a
0.02% CTR — while accounting for the entire site-wide impression surge that
pushed average CTR from 14% down to 3.7%. The Spanish copies were outranking
the English originals (/es/blog/slidev/ 27,465 impressions vs 3,431).

Add an opt-in `noindexLocaleVariants` frontmatter flag. When set, the
localized variants emit `noindex, follow` (outbound equity still flows) and
the hreflang cluster is dropped from every variant including English, since
hreflang must not advertise noindexed URLs. English stays indexable.

SeoHead grows a page-level `noindex` prop, kept distinct from the existing
site-wide staging flag: staging continues to emit `noindex, nofollow` for the
whole mirror, verified unchanged by an OD_LANDING_NOINDEX=1 build.

* refactor(landing-page): give the hreflang suppression its own prop

`localeCanonicalOnly` is documented as "this page has no per-locale
variants" and also drives the language switcher and locale auto-redirect in
sub-page-layout. These posts do have locale variants, all thirty are built
and remain reachable through the switcher; only their hreflang advertisement
has to go. Borrowing the flag happened to produce the right HTML today
because SeoHead ignores the switcher half of its meaning, which is exactly
the kind of coincidence that breaks on the next refactor.

Split out `noindexedLocaleVariants`. Output is byte-identical: 30 variants
still emit `noindex, follow`, the three English posts still carry no robots
meta and zero non-x-default hreflang, the control post keeps its 11.

---------

Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com>
2026-07-21 09:13:35 +00:00
Ray XiandGitHub 7b27d4ba62 fix(daemon): keep canceled runs canceled after late agent errors (#5904)
* fix(daemon): keep canceled runs canceled after late agent errors

* fix(daemon): preserve failures that precede cancellation

Record whether stream and ACP failures were observed before a cancel request, and let close-time classification win over the cancel fallback in that ordering. Add a startup smoke case that posts cancel only after the provider error is visible.

Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
2026-07-21 08:04:16 +00:00
421ac5ad56 fix(web): keep model picker anchored within visible bounds (#5907)
Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com>
2026-07-21 08:02:51 +00:00
5435274ab4 Add Humanize PPT plugin (#5655)
* feat(plugins): add Humanize PPT community plugin

Ports LearnPrompt/humanize-ppt (MIT) into plugins/community/ following
the community/hallmark precedent, and registers it in the community
marketplace index (0.2.0 -> 0.2.1).

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

* fix(plugins): harden humanize-ppt per review — out-dir guard, PPTX fail-closed, packaging (v1.1.1)

- brief mode no longer wipes a non-empty --out unless it carries Humanize
  run markers or --force is passed; wipe semantics documented in SKILL.md
  and docs/local-demo.md
- read_source fails closed on .ppt/.pptx with guidance (extract text
  first; rendered decks go to --qa-from); SKILL.md/SPEC.md wording aligned
- vendor examples/01-ai-tool-update/source.md, inline-fixture fallback in
  smoke_check.py, drop repo-only record_demo_gif.py, point dangling doc
  links at the upstream repo

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

* fix(plugins): humanize-ppt review follow-ups — outline-gate markers, shim exit codes (v1.1.2)

- HUMANIZE_OUT_MARKERS now includes outline-preview.md and
  preview-confirmed.json, so the documented --preview-outline ->
  --confirm-outline -> brief flow on one --out is no longer refused by
  the out-dir guard; refusal text, --out help, SKILL.md/SPEC.md/
  docs/local-demo.md list all four markers
- humanize_ppt_v3/v4/v5 shims call sys.exit(main()) like the stable
  entrypoint, so validation failures propagate exit 2 instead of 0
- smoke_check.py gains an outline-gate check (preview -> confirm ->
  brief on one --out, plus the unrelated-out refusal negative path) and
  an exit-code matrix across all five public entrypoints
- plugin 1.1.2, community registry 0.2.3

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 07:52:47 +00:00
d8b6b797fe Simplify chat execution disclosures (#5667)
* Simplify chat execution disclosures

* test: cover collapsed file disclosures

* refactor(web): consolidate chat task activity

* fix(web): show small file outputs inline

* fix(web): separate file outputs from reads

* fix(web): collapse completed todo cards

* refactor(web): compact completed todo lists

* fix(web): make completed todos expandable

* fix(web): keep four output files visible

* refactor(web): clarify chat activity timeline

* fix(web): make file output disclosure interactive

* feat(web): emphasize chat run states

* style(web): simplify chat run status colors

* style(web): remove chat run status icons

* feat(web): stream one chat activity at a time

* style(web): align chat completion row

* fix(web): simplify priority chat states

* feat(web): simplify secondary chat details

* style(web): simplify secondary chat hierarchy

* fix(web): keep execution state out of artifacts

* fix(web): use icons for artifact operations

* style(web): frame todo disclosure header

* fix(web): clarify artifact and tool semantics

* fix(web): clarify chat disclosure hierarchy

* fix(web): keep execution history neutral

* fix(web): simplify user action cards

* fix(web): align failure card actions

* fix(web): refine chat action hierarchy

* fix(web): address chat disclosure review feedback

* fix(web): restore chat recovery actions

* fix(web): make collapsed action details inert

---------

Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com>
2026-07-21 07:44:52 +00:00
b4f2677618 fix release: notarize prerelease mac builds (#5906)
* fix release: notarize prerelease mac builds

* fix(release): inject Apple notary env on prerelease mac retry steps

The cache-miss retry steps for both mac_arm64 and mac_x64 prerelease
builds pass --notarize but lacked the APPLE_ID /
APPLE_APP_SPECIFIC_PASSWORD / APPLE_TEAM_ID env block present on the
primary build steps. notarize.cjs fails closed when those vars are
missing, so a recovery build could not produce a notarized candidate.
Mirror the primary step env on both retry steps and assert the notary
env appears twice per mac job in release-workflows.test.ts.

Generated-By: looper 0.10.3 (runner=fixer, agent=claude-code)

---------

Co-authored-by: Looper <looper@noreply.github.com>
2026-07-21 07:30:29 +00:00
Ray XiandGitHub f751c17279 fix daemon Langfuse error redaction (#5778) 2026-07-21 06:57:41 +00:00
lefarcenandGitHub ef35a08e24 feat(daemon): E-lite root-cause telemetry for inactivity_timeout attribution (#5775)
* feat(daemon): E-lite root-cause telemetry for inactivity_timeout attribution

Add four run_finished fields that separate WHY a stalled run died, which
the coarse `last_observed_phase` (WHICH phase) cannot:

- approval_requested: an ACP approval/permission gate fired. Only the ACP
  path is daemon-observable (stream/CLI runtimes pass a skip-permissions
  flag so no gate fires); surfaced via an acp_approval_request diagnostic
  and folded in by summarizeRunDiagnosticsForAnalytics.
- stdin_backpressure: the prompt write to the child's stdin was queued
  because the OS pipe buffer was full (the child was not draining stdin) —
  the corroborating signal for a stdin_write-phase stall.
- tool_result_sent: a tool_result came back for the run's LAST tool_use.
  A stall with tool_call_seen && !tool_result_sent is the
  tool-result-not-delivered root cause.
- last_progress_age_ms: age of the last agent activity at finish (the
  inactivity-watchdog clock). Near the ceiling on a stall, ~0 on a clean
  finish.

Contract fields on RunFinishedProps; daemon populates two off the run
object (stdin_backpressure, last_progress_age_ms) and derives two from
run.events in the diagnostics summarizer (tool_result_sent,
approval_requested).

* fix(daemon): pair tool_result_sent by id so parallel tools attribute correctly

Review catch (nettee/Looper): the first cut flipped `tool_result_sent` to
true on any tool_result after a tool_use, so a multi-tool turn like
tool_use(A), tool_use(B), tool_result(A) reported delivered even though B
was still outstanding — bucketing multi-tool stalls as "provider stalled
after delivery" instead of "tool result not delivered".

Now paired by id (`tool_use.id` <-> `tool_result.toolUseId`, the same
pairing summarizeRunTimingAnalytics uses): `tool_result_sent` is true only
when EVERY committed tool_use received a matching tool_result (outstanding
set empty). Tests cover the reviewer's regression case plus parallel
all-resolved and sequential-last-outstanding.

* fix(daemon): count-pair id-less tool events so degraded stalls aren't "delivered"

Second review catch (nettee/Looper): id-based pairing alone still fell
through to `tool_result_sent: true` when a runtime emits a tool_use with a
null id, because those were counted in `sawAnyToolUse` but never tracked as
outstanding. That is not hypothetical — `agent-protocol/pi-rpc/events.ts`
and `copilot-stream.ts` both emit `toolCallId ?? null` for tool_use.id AND
tool_result.toolUseId on degraded provider events, so an unpaired id-less
tool call would mask exactly the stall this metric attributes.

Id-less tool events are now paired by count alongside the id-keyed set:
`tool_result_sent` requires both an empty outstanding-id set and at least as
many id-less results as id-less uses. Tests cover an unpaired id-less stall
and an id-less pair that did resolve.

* fix(daemon): capture stdin backpressure on the default text-input path

Third review catch (nettee/Looper): `stdin_backpressure` never recorded
anything for non-`stream-json` runtimes. `child.stdin.end(composed, ...)`
returns the stream rather than a boolean, and `writableNeedDrain` is already
back to false by the time it returns — even for a chunk that `write(chunk)`
would have rejected. Claude is the only runtime on the stream-json path, so
the field was permanently false on exactly the runs whose `stdin_write`
stalls it exists to attribute.

The write and the close are now issued separately through
`writePromptAndEndStdin`, which returns the boolean the OS pipe actually
gave us. Extracted into chat-run-lifecycle.ts so it is unit-testable:
tests cover the backpressured write, the accepted write, and the flush
callback still firing (the `stdin_write_end` lifecycle mark). Verified red
against the previous behavior.
2026-07-21 06:34:31 +00:00
lefarcenandGitHub c9e622d0a9 fix(daemon): ship baseline OpenCode for Windows and stop retrying AVX2 illegal-instruction crashes (#5733)
* Classify AVX2 illegal-instruction agent crashes as cpu_unsupported and stop retrying them

The Windows opencode.exe bundled with the AMR runtime is a Bun build that
requires AVX2. On CPUs without it (Intel Atom/Celeron/Pentium N-series
through 2021) the binary dies with STATUS_ILLEGAL_INSTRUCTION before
readiness; vela surfaces an ACP fatal, the daemon classified it as a
retryable fatal_rpc_error, and the automatic retry deterministically
failed again. 88 of 105 pre-readiness Windows crash traces in Langfuse
are this single failure.

The crash text (Bun 'Illegal instruction' banner with a no_avx2 CPU
feature line, or the raw 0xC000001D / decimal 3221225501 exit status) now
classifies as process_exit/cpu_unsupported ahead of the fatal_rpc_error
close-reason promotion, is never auto-retried, and renders a dedicated
error card telling the user to update Open Design instead of a dead
Retry button.

* Bump @powerformer/vela-cli to 0.0.23 so packaged Windows builds bundle the baseline (non-AVX2) OpenCode

The 0.0.23 win32-x64 platform package compiles the OpenCode fork with
--target=windows-x64-baseline, so the bundled opencode.exe no longer
requires AVX2 and starts on Intel Atom/Celeron/Pentium N-series CPUs.
Verified in vela CI: the build log shows the baseline target and the new
post-publish smoke job boots the published bundle's opencode.exe on a
real Windows runner (powerformer/vela#838).

* Refresh Nix pnpm deps hashes for the vela-cli 0.0.23 lockfile change

* Add the abort-after-panic (exit status 3) production shape to cpu_unsupported specs

A user on an AVX-but-no-AVX2 CPU (Sandy/Ivy Bridge era) hit the same
illegal-instruction crash, but Bun panicked during its own panic handler
and abort()ed, so vela reported exit status 3 instead of
STATUS_ILLEGAL_INSTRUCTION. The stderr banner (no_avx2 / Illegal
instruction) is the only signal; encode the real Langfuse trace shape so
the classifier keeps catching it.

* Bump @powerformer/vela-cli to 0.0.25 so packaged Windows builds bundle the baseline (non-AVX2) OpenCode

0.0.25 is the first stable cut after powerformer/vela#838 merged: its
win32-x64 package compiles the OpenCode fork with
--target=windows-x64-baseline (verified in the release CI log), the
post-publish smoke boots the published bundle on a real Windows runner,
and the lockfile regenerator now pins the baseline asset so a routine
version bump cannot silently flip back. 0.0.24 predated that merge and
still shipped the AVX2 build.

* Tighten cpu_unsupported to precise signals only (no bare 'Illegal instruction')

Review is right that a bare illegal-instruction line is too broad: an
unrelated SIGILL on an AVX2-capable machine (runtime bug, corrupted
jump) would be mislabeled 'Processor not supported' and lose its retry.
Bun's crash banner always prints the CPU-feature line, so machines
actually missing AVX2 are identified by no_avx2; the bare Windows
STATUS_ILLEGAL_INSTRUCTION renderings (0xC000001D / 3221225501) stay
because those runs carry no banner at all. Generic illegal-instruction
banners without no_avx2 return to process_crashed / fatal_rpc_error,
locked by a new negative spec.

* Refresh Nix pnpm deps hashes for the vela-cli 0.0.25 lockfile change

* Gate raw STATUS_ILLEGAL_INSTRUCTION on the bundled-opencode startup context
2026-07-21 06:10:22 +00:00
ArseniyGlandGitHub 06ce4eeba2 fix(packaged): prewarm linux AppImage sidecar payload + widen linux status budget (#5836)
Every AppImage launch mounts a fresh FUSE squashfs whose VFS page cache
is cold, so the daemon sidecar demand-pages its 124 MB bundled node
binary (plus dist and the ~70 MB bundled plugins registry) through FUSE
on EVERY launch while Electron faults through the same mount. The
daemon could not bind its IPC socket within the 35s DAEMON_STATUS_TIMEOUT_MS
and every launch failed with a sidecar status timeout (white screen /
recovery error).

- Add apps/packaged/src/prewarm.ts: best-effort sequential read of the
  sidecar cold-start set into the page cache before spawning, gated to
  linux + FUSE-backed payloads (plain-file installs skip). Sequential
  reads measure ~45 MB/s through squashfuse vs ~5 MB/s demand-paged
  under launch contention; daemon ready drops from ~25-60s+ to ~3-19s.
- Widen the linux status-wait baseline to 90s as a safety net for slow
  devices, mirroring the win32 rationale (#5515): same "slow, not
  dead" failure class.

Fixes #5835
2026-07-21 03:49:28 +00:00
Ethan GuoandGitHub 4fb217c957 fix(web): keep loaded config when re-persisting a downgraded protocol fails (#5506) 2026-07-21 03:20:50 +00:00
mehmet turacandGitHub ace06eac10 fix(web): respect preview viewport in image exports (#5828) 2026-07-21 03:10:38 +00:00
df50cffbd2 fix(platform): discover Grok Build on Windows (#5843)
Co-authored-by: Kirill Turanskiy <thebtf@users.noreply.github.com>
2026-07-21 02:43:13 +00:00
mehmet turacandGitHub 39a2dedc53 fix(packaged): use bundled node for wrapper env (#5786) 2026-07-21 02:26:12 +00:00