mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
codex/tools-dev-telemetry
3764
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b724b5829f | feat(tools-dev): diagnose telemetry and verify exact ODEval traces | ||
|
|
7702323625 |
fix(share): reuse cloud file identity when local mapping is missing (#8859)
* fix(share): reuse cloud file identity when local mapping is missing * fix(comments): preserve pre-share comments during identity recovery |
||
|
|
2b41bc5c3d |
feat(share): publish files as public links with stop/resume and synced comments (#8408)
* wip: wire deleted-file stop retry and cover owner-scoped HTTP behavior
* wip: persist published comment backfill state
* wip: connect backfill delivery receipts and preserve completed batches
* wip: expose exact-file backfill state and retry through HTTP and CLI
* wip: wire scoped comment sync pause into preview panel
* test: cover backfill terminal rejection and stale publication receipts
* wip: separate published content from unavailable viewer origin
* feat: distinguish publication success from unavailable viewer links
* fix(web): gate export share guide on authoritative project history
* test: restore publish backfill HTTP proof with current publisher pipeline
* fix(web): show authoritative stopped-share guidance
* fix(web): restore publish help before creating a share
* fix(web): show unread comments on collapsed rail
* fix: share annotated selectors across URL and srcdoc bridges
* test: verify saved comment selector reanchors in Chromium
* fix(web): warn about active shares before project deletion
* fix: authorize and bootstrap public share project bindings
* wip: prepare dispatched live share-chain probe (not run)
* fix(web): deliver per-file share residuals after deletion
* fix(web): prevent stopping shares in read-only viewers
* fix(e2e): retain complete share probe HTTP evidence
* fix(web): name shared projects in delete confirmation titles
* docs(e2e): clarify live share acceptance and human login boundaries
* fix(e2e): preserve share query context in diagnostic evidence
* fix(web): restore share-panel copy and comment-pin visuals per board8
chain1-publish G4: delete the stale "仅支持分享单个文件,内嵌图片等本地
资源暂不支持" sentence from fileViewer.publishSingleFileDescription (19
locales) — it contradicts the current multi-resource share and G4 required
its removal.
chain1-publish S1: add the missing "链接访问" title row + its static
description ("接收者可查看预览和已有评论,不包含对话和代码。") to
ShareTab's public-share section, as new fileViewer.linkAccessTitle /
linkAccessDescription keys (19 locales). No switch added — that control
overlaps the existing "停止分享" button and is left as a 需确认 item.
chain4-owner 4.2b: canvas comment pins go from 20x20/weight 600/2px white
ring/fixed #282828 to 28x28/weight 500/no ring, and now derive their
background/foreground from the same per-author color used by that author's
sidebar avatar (commentAuthorAvatarColor), both pure local CSS/TSX with no
packages/ or protocol change.
chain4-owner O7: formatCommentTime now buckets by calendar day (adds
"昨天", drops the "N 天前/N 周前" buckets, switches the hour bucket to
same-day instead of <24h elapsed, and formats older dates via
toLocaleDateString with year only when it differs from the current year),
and comment-side-time gets a title attribute with the full absolute
timestamp on hover.
Verification: pnpm --filter @open-design/web typecheck passes. Not run
through a real renderer — no pixel-level claim.
* fix(web): share entry icon, delete-confirm title, OP2 read-only hint
chain1-publish E0: swap the share toolbar entry's icon from RemixIcon
share-forward-line to the board's own upload-arrow glyph (13px path
"M12 4v11M7 9l5-5 5 5M5 14v5h14v-5") — same size/shape as the board's
.shareBtn icon, glyph only, no behavior change.
chain6-dialogs D-04: drop the extra "确定" from designs.deleteConfirm's
zh-CN/zh-TW title ("确定删除「{name}」?" → "删除「{name}」?") to match
the board and every other locale, which already read "Delete "{name}"?"
without an "are you sure" prefix.
chain4-owner OP2: add the missing "分享页评论不可编辑" explanation line
under a comment's textarea specifically when the viewer can't edit it
AND the comment is a share-page (external) one — team-member-reads-
external-comment (OP3) is unaffected, matching the board's OP2-only
scope. New comment.sharePageCommentReadOnly key, 19 locales.
Verification: pnpm --filter @open-design/web typecheck passes. Not run
through a real renderer — no pixel-level claim.
* test(web): update FileViewer specs for the G4/O7/4.2b restorations
Three specs encoded the exact pre-fix behavior the previous two commits
intentionally changed, so they went red:
- "reads the publish help without publishing" located the help bubble by
the now-deleted stale sentence ("Only a single file can be shared for
now..."); relocates it by the sentence that remains.
- "keeps relative comment-time boundaries stable across clock boundaries"
asserted the old <24h-elapsed hour bucket; the O7 rewrite buckets by
calendar day, so the fixture's 23h-ago comment (which crosses this
fake clock's midnight) now correctly reads "昨天" instead of "N 小时前".
- "keeps D1-D4 marker and deck-page presentation on the rendered
selectors" asserted the old 20px/weight 600/white-ring pin CSS; updated
to the board's 28px/weight 500/no-ring geometry.
Verification: pnpm --filter @open-design/web typecheck passes;
tests/components/FileViewer.test.tsx: 334/334 passed (via
node_modules/vitest/vitest.mjs --pool=forks, run directly against the
node 24.18.0 binary — this shell's `npx`/`node` wrap nvm in a way that
blows bash's FUNCNEST under vitest's fork pool).
* feat(web): draw the export guide's countdown, title and description
The 10s countdown already existed as state - remainingMs, checkedAt and
paused were computed and consumed - but nothing rendered it, so the guide
showed no sign that it was about to dismiss itself.
The bar is one CSS width transition per run rather than a per-frame timer:
the remaining time is already known when the run starts, so animating to
zero over exactly that duration needs no re-render, and a pause just freezes
the transition.
Board copy added across all 19 locales.
* test(web): update AfterExportShareGuide specs for the P1 card restoration
Three assertions encoded the pre-restoration visual/DOM shape that
|
||
|
|
78d5637cb4 |
fix(daemon,web): forward pure plugin applies and honor persisted capability grants (#7597)
* fix(daemon,web): forward pure plugin applies and honor persisted capability grants Pure apply returns snapshotId "" for existing projects, so the web run path now forwards pluginId and pluginInputs when no snapshot id exists. The daemon trust vocabulary now accepts pipeline:* and applyPlugin honors stored capabilitiesGranted with prompt:inject floor. Fixes #6186 * test(web): cover pure-apply plugin identity fallback in run requests |
||
|
|
86cb177228 |
allow custom model entry in the onboarding BYOK model picker (#6076)
* fix(web): allow custom model entry in onboarding BYOK dropdown The onboarding wizard's BYOK model picker (OnboardingDropdown) always showed the static SUGGESTED_MODELS_BY_PROTOCOL list with no way to type an arbitrary model id, unlike the equivalent Settings dialog picker (ByokModelField/SearchableModelSelect) which has a Custom sentinel option. This blocked selecting any locally-installed model (e.g. an Ollama model) that isn't in the hardcoded suggestion list. Add an allowCustomValue prop to OnboardingDropdown: when enabled and the search query doesn't match an existing option, a 'Use "<query>"' entry is offered that sets the value directly. Enabled it for the BYOK model field in OnboardingByokSetupPanel. * fix(i18n): add settings.onboardingModelUseCustom to Dict and all locales * add allowCustomValue tests; place custom entry last; single-quote CJK locale strings |
||
|
|
9b5dc619d0 |
fix(desktop): count active runs for update preflight without an unscoped listing (#8462)
The update restart-safety preflight called the unscoped
`GET /api/runs?status=active`, which answers 400 PROJECT_SCOPE_REQUIRED as
soon as any run belongs to a Workspace-bound project. Workspace users
therefore always got `active-runs-unknown` and could not install or quit
into an update without forcing it.
Add a loopback-only `GET /api/runs/active-count` that returns only
`{ activeRunCount }` and switch the preflight to it. The unscoped listing
keeps refusing, so Workspace-bound runs still cannot be enumerated.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
94f7a48633 |
fix(web): kick the compositor on a chat scroll freeze, then take the wheel and keyboard over by default (#8251)
* fix(web): kick the compositor on a chat scroll freeze, then take the wheel and keyboard over by default When the freeze probe calls the chat log frozen, apply one frame of `will-change: transform` so Blink rebuilds the scroller's compositing state from the current layout, let the next downward wheel through natively and measure it against what it asked for (the detector's own normalisation and 8px yardstick), and only if it stuck, fell short or snapped back answer the wheel and the scrolling keys from JavaScript. The takeover is on by default now; `open-design:chat-scroll-takeover = '0'` is the escape hatch. `ChatPane` releases the takeover — and asks the probe to start a fresh surface — when `activeConversationId` changes, because the log node is reused across conversations. A healed surface is released the same way so a recurrence can be judged again. One new event, `client_chat_scroll_heal`, carries the outcome, the kick geometry and the notch arithmetic, joined to the freeze by `probe_id`; `client_chat_scroll_frozen` is untouched. * fix(web): keep Home/End finite and let the takeover go when the chat log is removed Home and End were ±Infinity folded into the same pixel accumulator as the arrows, so Home-then-End in one frame (or key repeat) summed to NaN and the browser read the NaN scrollTop as 0 — End could not reach the bottom. Edge jumps now live in their own `pendingEdge` slot: the last edge pressed wins, pressing one discards the steps queued before it, and steps pressed after it apply on top; applyPending refuses to write a non-finite value. A tab or route unmount removes the chat log without a conversation change, and the probe only notices on a scroll the missing node never sends, so the takeover stayed engaged with its document-level keydown listener cancelling arrows and paging with nothing to scroll. Every input path (wheel, keydown, frame) now checks `isConnected` and disengages, and ChatPane's release effect also releases in its cleanup. |
||
|
|
1eaa2381aa |
feat(release): validate version-only bumps before approval-exempt queueing (#8800)
Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
5a221d5043 |
fix(amr): refresh retained Home funding blocks after billing updates (#8786)
* fix(amr): invalidate Home funding hints on billing changes * test(amr): stop replaying funding events on fixture reconnect * fix(amr): retain confirmed Home funding blocks until recovery * fix(amr): recheck blocked Home funding after billing refresh --------- Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
41afc74c88 |
chore(release): bump main to 0.25.1 ahead of stable 0.25.0 (#8787)
Co-authored-by: open-design-release-bot[bot] <open-design-release-bot[bot]@users.noreply.github.com> |
||
|
|
7abd6fc2b1 |
fix(amr): keep Home blocked on unknown funding confirmation (#8775)
* fix(amr): keep Home blocked on unknown funding confirmation * test(web): await sign-in callout state independently --------- Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
6410d3622a |
fix(od-next): restore production follow-up host instructions (#8770)
* fix(od-next): restore production follow-up host instructions Compose production host instructions with the same fresh key persisted on the run, including native resume, cold-start input, and UI locale. Keep the instructions independent of retired model state declarations and exclude the nonce-bearing text from internal continuation retry identity. Verify optional suggestions, message persistence, and repeated preparation through the real server and run registry. Validated with main red specs, focused regression tests, guard, and the workspace typecheck. * test(od-next): preserve production test entry points Keep the existing production test header and fixture setup while sharing host-protocol assertions with a separate suggestions case. This avoids adding a conflict with the pending agent rollout tests. Validated with the focused real-server regressions, guard, and the full workspace typecheck. |
||
|
|
5cd1a51ff6 |
chore(pack): update Vela CLI to 0.1.6 (#8767)
Vela CLI 0.1.6 adds core/amr#192: Vela passes OpenCode a 3 MiB history attachment budget, which the OpenCode fix already bundled in 0.1.5 (amr-opencode#8) needs before it bounds the images and PDFs resent from history. The bundled OpenCode commit is unchanged. |
||
|
|
ae321ab2e6 |
fix(cms): fence offline replay across revocation and process death (#8676)
* fix(cms): fence offline replay across revocation and process death * feat(cms): define paginated Test catalog and immutable runtime context * fix(cms): synchronize Test and Production host presentation lifecycles * test(cms): retain cross-host lifecycle and browser acceptance regressions * fix(cms): retain request tickets through body classification --------- Co-authored-by: heggria <bshengtao@gmail.com> Co-authored-by: ivy-tinggg <986810707@qq.com> |
||
|
|
aa3a834046 |
fix(preview): refresh file snapshots after completed runs (#8744)
Co-authored-by: 罗高 <luogao@192.168.5.196> |
||
|
|
535fa8eab7 |
fix(amr): restore Home funding checks and decouple run feedback (#8688)
* fix(web): surface live AMR funding failures without delaying sends * fix(amr): check funding independently of agent startup * chore(amr): pin Vela funding feedback test package * fix(amr): route early funding hints through isolated CLI command * fix(amr): restore scoped Home funding cache gate * fix(amr): restore Home wallet and plan memory gate * test(amr): align send audits with independent funding checks * chore(amr): bundle Vela CLI 0.1.5 for funding checks --------- Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
ae8038e7ce |
fix(tabs): preserve saved local selections during restore (#8745)
Co-authored-by: 罗高 <luogao@192.168.5.196> |
||
|
|
af53d83a99 |
fix(upload): preserve same-batch duplicate filename order (#8742)
Co-authored-by: 罗高 <luogao@192.168.5.196> |
||
|
|
784025c04a |
fix(daemon): resolve the AMR default model from the caller's catalog (#8519)
* fix(daemon): resolve the AMR default model from the caller's catalog A run that asked for `default` before the caller's `vela model list` had arrived was concretized from the bundled `vela model preset` seed. The seed is the same for every plan and OD orders deepseek-v4-flash first, so free-tier callers (entitled only to deepseek-v4.1-flash since 09-24) had Vela reject `session/set_model` before any work began. On 0.24.1 that was 22 runs from 21 users in the last 7 days, 13 of 16 bundled runs showing the user's choice as `default`. - When `default` is requested and only the preset is cached, wait up to 12s for the caller's remote catalog (`getAuthoritative`). - Remember remote catalogs separately; a later preset seed never displaces one when a default model is chosen. - Order deepseek-v4.1-flash first: it is the one chat model every plan, including free, is entitled to, so a flagless list still lands on it. * fix(daemon): bound the AMR default-model catalog wait per refresh CI follow-up. A `default` run looked the catalog up twice (the resume probe and the run itself) and each lookup waited up to 12 s for the caller's remote catalog, so a slow or broken `vela model list` held the run queued for up to 24 s. The AMR e2e runs timed out at 20 s that way. - The wait is counted from the start of the remote refresh, so one run, or several concurrent runs, share a single wait. - When the last refresh failed, the preset is used at once; the next refresh still starts in the background. - e2e fake vela: answer `model list --all --format json`, the form the daemon actually sends. It only matched the flag-less form and hung. * test(e2e): let the fake vela answer the daemon's `model list --all` probe The catalog probe spawns `vela model list --all --format json`. The matcher stripped `--all` with its preceding space only, so `' --format json'` never equalled `'--format json'`: the probe fell through to the login check, the cache recorded a failed refresh, and default runs settled on the preset. Match the subcommand and the `--format json` flags in any order, as fake-vela.mjs and turn.test.ts already do, and cover the exact daemon argv for both the catalog and the 401 path. |
||
|
|
14fee234e6 |
feat: add motion design workflow and curated motion skills (#8619)
* feat: add Motion Design skill and OD Next task route
* fix(web): rename motion design entry and place it second
* fix(web): reconcile motion design catalog consumers
* feat(web): add motion design templates to Home and Community
Five motion design example templates (3D procedural island, explainer,
product launch, showreel, data story), chosen by community reach, under the
Home motion-design chip and a new Community "Motion design" type.
Each template follows the bundled example layout: an OD-generated
example.html with its runtime libraries under assets/, an HTML preview baked
by the existing preview pipeline, and a SKILL.md that carries example.html
as the reference when the card is picked on the OD Next motion-design route.
Home cards ship curated copy for every UI locale. Motion templates stay off
the Video and HyperFrames chips.
* fix(skills): keep motion-design procedural layers visible in video export
The MP4 exporter seeks timelines with callbacks suppressed
(renderSeek(t, { suppressEvents: true })), so content drawn only from a GSAP
onUpdate callback is missing from exported video. Recommend a per-frame draw
loop that reads the timeline clock, and state that visible content must not
depend on timeline callbacks. The OD Next task asset is re-synced with
scripts/sync-motion-design-skill.ts.
* fix(motion): preserve reference assets and exported animation frames
* feat(skills): integrate curated motion helpers with complete runtime files
* feat(skills): add Huashu, Oil Motion and Motion.Lab adapters
* test: classify animate design guidance in narration guard
* feat(motion): refine five community templates and portable previews
* fix(motion): refine launch transitions and center gallery previews
* fix: allow free-form briefs on automatic motion task route
* feat(motion): add template soundtracks and audio export
* fix(motion): require rendered MP4 alongside editable video source
* test(motion): align strategy activation expectation with package version
* fix: scope motion delivery and make editable sources playable
* fix(motion): bundle source dependencies and valid closing protocol
* feat(motion): rebuild the five templates on the most-viewed community posts
Re-select topics by single-post views in the latest awesome-opus-5.5-video
snapshot and anchor each template to the top eligible post of its genre:
camera-focus explainer, showreel, product launch, procedural island and a
new wordless animated short that replaces the data story.
All five example.html files are hand-authored canvas/Three.js films drawn by
one render(t) from the GSAP master timeline, so preview, scrubbing and MP4
export produce identical frames. Each ships an original procedural
soundtrack, updated SKILL.md and 19-locale copy; Home order follows reach.
* fix(plugins): load bundled fonts in plugin previews
Plugin previews blocked every bundled font: the preview CSP had no font-src,
and relative url() references inside inline <style> blocks kept pointing at
the preview URL instead of the plugin folder. Allow same-origin fonts, map
inline-style url() references through the existing asset route (escapes,
absolute and data: URLs stay untouched), and serve font files with font
MIME types.
* feat(community): make motion template Use match the Home example pick
Community 「做同款」 on a motion design template now binds it as that type's
own example card, carrying the type's project metadata, so the run takes the
same OD Next motion-design route as a pick from Home's motion design list and
delivers the MP4 together with the editable source. Other task types keep
the existing plugin-pinning hand-off.
Community use clicks now record use_source (card | detail_modal) and
use_action (use | use_with_query); the details modal Use is tracked for the
first time. The Home hand-off no longer records a second community_gallery
click for uses Community already tracked.
* fix(plugins): count the five motion templates in the official registry metadata
* fix(media): keep HyperFrames audio filters compatible with FFmpeg 4.1
CI's bundled Linux FFmpeg 4.1 rejects adelay all=1 and amix normalize=0.
Make each track stereo and delay both channels explicitly, skip amix for a
single track, and undo amix averaging with a gain for several tracks.
* fix(motion): keep template previews bakeable on slow CI renderers
CI's software-GL baker skipped the 3D island (preview readiness timeout):
under slow frames GSAP lag smoothing slowed the timeline, so the 8 s
poster frame never arrived within the baker's 15 s wait. Play every
template on the wall clock and move the island poster to 6 s. With
simulated 300 ms frames all five now report ready within 10 s.
* feat(motion): add the kinetic typography template
Template selection now follows the motion design spec's four content types
(brand and product films, kinetic typography, explainer animation, procedural
art). Kinetic typography takes the fifth slot, replacing the animated short.
The new template is a 15-second, 120 BPM type film with an original
soundtrack and 19-locale copy.
* fix(motion): let the project motion player fit template stages
Inside a project the motion source player wraps the composition, fits it and
adds its own controls. The templates also scaled their stage, so editable
sources from Remix and Community use rendered at a fraction of the preview.
Templates now keep their own fit and controls only outside that player.
* feat(motion): restage the 3D island as a midday lagoon
The island moves from golden hour to a bright tropical midday closer to its
anchor post: a shader lagoon coloured by a baked depth map with ripples,
shallow-water shimmer and shore foam, a wide white-sand beach, palms and
instanced bushes, a village with a pier, soft sun shadows and a lower
camera path. The CPU wave mesh is gone, so frames cost no more than before.
Copy is updated in all 19 locales.
* fix(motion): keep each soundtrack inside the composition root
A Community use regenerated the island source tail and dropped the root
<audio> element, so its MP4 had no sound. Templates now place the element
inside the composition root next to the stage.
* docs(motion): state the template selection rule as complete works
* fix(motion): enforce video clocks and bound content verification
* feat(motion): replace the motion templates with remakes of viral posts
The five Motion design templates are now frame-faithful remakes of viral
motion posts, so each preview shows the look users came for: the 15-second
motion designer showreel, a high-energy motion reel (copy set in English), a
one-shape UI motion piece, a pixel-art wizard and a 20-second electric-blue
tech reel. Each ships open-licensed fonts, an original soundtrack, the
creator's published prompt where one exists, and credits its source post.
The explainer, product launch, 3D island and kinetic type templates are
removed. Tests follow the new set; a backward-seek check now covers hidden
WebGL layers.
* feat(motion): feature The Future Is Already Here first and start preview sound with the film
* chore: ensure PR CI
* fix(motion): match The Future Is Already Here controls and reorder the motion templates
* fix(motion): make the one-shape UI preview controls legible
* fix(motion): hide The Future Is Already Here controls inside the project player
* fix(motion): plan suitable sound and synchronize source audio playback
* feat(motion): keep remake soundtracks by default and fade exported audio where it stops
* test(motion): cover audible source controls in Chromium
* fix(test): use explicit ESM imports in audio player regression
* fix(motion): align preview track discovery with video export
* feat(motion): autoplay looping HTML without a player bar
* fix(test): consume the built motion playback contract
* docs(motion): state explicit soundtrack rules for make-same and the music line in replies
* chore(motion): version the audible looping delivery profile
* docs(motion): let template sound rules lead the general policy and freeze the audio contract
* fix(motion): scope autoplay to declared video motion sources
* fix(motion): reject audible MP4s under an explicit silent contract
* docs(motion): drop the routine music note from make-same replies
* test(motion): align delivery regressions with looping source playback
* fix(motion): isolate preview and audio export from legacy HyperFrames
* test(motion): retain the existing desktop legacy audio limitation
* fix(motion): suspend audio when previews leave the active workspace
* feat(motion): replace two motion templates with a product promo and a visual lesson; sign the showreel as Open Design
* feat(motion): give the showreel the Open Design palette and a full-size stacked wordmark
* feat(motion): give the product promo a livelier mascot girl
* refactor(motion): rebuild The Future Is Already Here as readable, editable scene code
* fix(motion): pick gallery cover frames that survive the baker's capture delay
* feat(motion): sharpen the showreel opener, depth, truchet and end card
* feat(motion): make the product promo mascot talk, add a speaking score and the flow pop
* feat(motion): give the visual lesson the original's paper-collage texture
* fix(motion): bundle gallery covers for fresh branch checkouts
* feat(motion): feature and refine Bring Ideas to Life
Adapt the paper story around OpenDesign capabilities, with short rounded hands, clearer timing, continuous paper actions, and a larger audience invitation. Feature it first in Motion and synchronize localized names, metadata, cover, guidance, and regressions.
Keep product promo audio music-only with sparse percussion.
* fix(motion): stabilize artifact cards and capture declared covers
* fix(web): share creation type order with community
* test(motion): exercise audio controls through project UI lifecycle
* fix(motion): scope live cover behavior to actual video sources
* test(motion): use real HEAD responses in cover regressions
---------
Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com>
Co-authored-by: William <zhouhaoran@refly.ai>
Co-authored-by: open-design-crew[bot] <4197780+open-design-crew[bot]@users.noreply.github.com>
Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
Co-authored-by: Amy <1184569493@qq.com>
|
||
|
|
7da9a8aaa2 |
chore(pack): update Vela CLI to 0.1.4 (#8728)
Co-authored-by: nettee <nettee.liu@gmail.com> |
||
|
|
3faaab0f20 | fix(e2e): align packaged Codex fixture with recipe identity (#8727) | ||
|
|
81f1249fb9 |
fix(amr): switch to the catalog default when the selected model was delisted (#8602)
On AMR 0.24.1, 9 runs from 7 users (10/5 to 10/7) ended with "session/set_model modelId is not available": the model the user had picked (deepseek-v4-flash, claude-opus-4.8, claude-sonnet-5, gemini-3.1-pro-preview) had left the AMR catalog. The daemon forwards such a model on purpose, because its cached catalog can lag the live one, and vela's set_model is the authoritative check. Act on that rejection instead of ending the turn: the daemon passes the catalog default as fallbackModel, and the ACP session switches to it once when vela rejects the selected model, then tells the user with a model_fallback status. If vela rejects the fallback too, the turn fails as before. |
||
|
|
e0b250663d |
fix(release): allow re-cutting an unchanged packaged version (#8725)
Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
1343f374c6 |
docs: align README positioning and clarify service disclosures (#8718)
* docs: align README positioning and clarify service disclosures * docs: restore shipped migration and import contracts * docs: list task-kind values in condensed translations --------- Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com> |
||
|
|
014bffbf77 |
fix(collab): synchronize owner devices with overwrite consent (#8683)
* fix(collab): synchronize owner devices with overwrite consent * docs(collab): add owner device synchronization QA handoff * chore(collab): move delivery reports and screenshots to Plane * fix(collab): preserve owner pull fallback and ghost heal Generated-By: looper 0.16.1 (runner=fixer, agent=codex) * fix(collab): probe null owner heads for retractions Generated-By: looper 0.16.1 (runner=fixer, agent=codex) * fix(collab): preserve manual checks across coalescing Generated-By: looper 0.16.1 (runner=fixer, agent=codex) * feat(collab): hide update check behind a dismissed-version badge Show the header entry only when the owner skipped a cloud version, as a "Cloud update available" badge that re-opens the overwrite dialog. Rewrite the dialog description in plain product language. * fix(collab): clarify device sync copy and place entry before present * fix(collab): silence update reminders without automatic overwrite --------- Co-authored-by: Looper <looper@noreply.github.com> Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com> |
||
|
|
424f5c68cc |
fix(od-next): remove output-contract gates and unblock continuation (#8356)
* fix(od-next): continue plans with keyed markers and honor explicit deliverables * fix(od-next): retire output contracts and hand off continued tasks * fix(od-next): record round settlement and recover production cold * fix(od-next): resume marker sessions with context deltas * fix(od-next): separate completion facts and honor plan-only intent * fix(od-next): preserve physical failures and legacy chat compatibility * test(web): align run recovery fixtures and await campaign mount * fix(od-next): tolerate terminal production marker formatting * fix(od-next): unblock follow-ups after a stop or unreadable history (#8423) Treat a previous task this build cannot read as absent so the follow-up starts a new task, and stop counting a Run with a pending cancel as holding its conversation. Add end-to-end coverage for the marker continuation flow and restore the remote Workspace directory gate cases. * docs: clarify focused local validation Keep local daemon and web validation scoped to affected files and integration boundaries. Reserve full suites for PR CI unless the user explicitly requests them. * fix(web): scope folded task completion to its final run Keep the final physical Run key and conclusion together when OD Next history is folded or accumulated live. Reuse the existing predecessor offsets while retaining the full display history and remaining Todo snapshot. Add regression coverage for completed and unfinished production, live continuation, multiple Runs, legacy history, wrong and quoted markers, question handoff, and failed or canceled Runs. Validated the parent regression before the fix, 165 focused Web tests, workspace typecheck, and guard. * fix(od-next): compact historical context without restricting clarification Reuse confirmed artifact summaries for old assistant history, preserve cross-agent plans and original requests, and represent earlier questionnaires as neutral historical information without inferring answers. Keep user replies, skips, changed answers, unpersisted bodies, examples, and unfamiliar content intact. Do not add question repetition checks, output gates, repair rounds, or limits on clarification. Validated red regressions, shared context and Web provider tests, focused handoff/resume/cold-production coverage, real server and fake CLI input, workspace typecheck, and guard. The repeated-question server fixture remains successful. --------- Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> Co-authored-by: Cheems <hihicheems@gmail.com> Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> |
||
|
|
f29b1d6a02 |
fix(web): re-measure marquee travel when the document direction changes (#8692)
MarqueeLabel read the computed direction only when its text changed or a box resized. I18nProvider writes <html dir> in a passive effect, so on first mount in Arabic and on an English -> Arabic switch the label kept the LTR sign and slid the workspace name the wrong way. Watch the dir attribute as well. Refs OPEND-3112 |
||
|
|
9041ca60bc | chore(release): bump main to 0.25.0 ahead of stable 0.24.1 (#8700) | ||
|
|
0b0dad9191 |
fix(sidecar): bound macOS private IPC socket paths (#8002)
Long macOS temporary-directory paths can push private sidecar sockets beyond the 103-byte pathname limit and crash startup. Fall back to /tmp only for oversized macOS paths, preserving the full digest and UID isolation. Add byte-boundary, identity, platform-compatibility, and native macOS IPC regression coverage. |
||
|
|
8d602a5265 | docs: document headless BYOK runs over REST (#8622) | ||
|
|
8e5bd8ec59 | fix(packaged): propagate OD_JSON_IPC_TRACE to sidecars (#8539) | ||
|
|
0bd8251c9b |
fix(daemon): name AMR runs failing on Windows older than 1809 as os_unsupported (#8629)
The bundled OpenCode is a Bun binary and Bun requires Windows 10 1809 (build 17763). On older builds it exits with STATUS_ENTRYPOINT_NOT_FOUND (0xc0000139) before readiness, which was classified as a retryable fatal_rpc_error and shown as a generic failure. Classify it as a non-retryable os_unsupported when the host build is below 17763 and show a card telling the user to update Windows. |
||
|
|
af48a420eb |
fix(web): keep empty Home content reachable in short windows (#8649)
* fix(web): keep empty Home content reachable in short windows Use safe centering when the empty Home hero exceeds the scroll viewport, and let wheel input continue from the examples list to Home at its boundaries. Add CLI and BYOK browser regression coverage for short windows, responsive boundaries, scrolling, and centering when content fits. Validated with the focused Playwright cases, pnpm guard, and pnpm typecheck. * test(web): align Home acceptance with safe centering Update the existing empty-Home style acceptance to expect safe center while preserving its padding checks. The accepted layout change keeps content reachable when the hero exceeds the viewport. Verified the CI assertion fails before the test update and all 8 cases in acceptance-visual-fixes.test.ts pass afterward. Also passed pnpm guard, pnpm typecheck, focused TypeScript diagnostics, and git diff --check. * test(web): cover safe Home scroll boundaries --------- Co-authored-by: PerishCode <perishcode@gmail.com> |
||
|
|
e5d19cbf5f |
fix(desktop): record why a run ended without a clean shutdown (#8571)
A desktop run that dies without a clean shutdown is reported as desktop_unclean_exit, but the report could not tell a crash from the machine shutting down, sleeping, or a quit whose teardown never finished. In production 26 of 28 recent unclean exits behind AMR runs failed with DAEMON_RESTARTED carried no exit evidence at all. - session-lifecycle: the run's marker keeps the last 8 host events (suspend, resume, shutdown, session-end with its reasons, quit-requested), written synchronously so they land before the OS ends the process. Repeats of the same event within a second (one per window) are kept once. An unclean run carries its events into the next launch. - observability: desktop_unclean_exit adds exit_hint (system_shutdown, user_logoff, closed_by_system, system_suspend, quit_incomplete or unknown), ended_suspended, quit_requested and the last host event. attachDesktopHostLifecycleRecorder wires powerMonitor suspend/resume/ shutdown and the Windows window session-end event. - main: the recorder is attached once the session marker exists, and a quit records quit-requested when its cleanup starts. |
||
|
|
8145e9120b |
fix(daemon): keep ACP turns succeeded when the daemon force-closes the agent (#8514)
* fix(daemon): keep ACP turns succeeded when the daemon force-closes the agent After a clean ACP end_turn the daemon waits 500ms and then terminates the agent. On Windows a child killed by pid reports exit code 1 with no signal, so the close classifier (which only forgave SIGTERM or code 130) marked the completed turn failed with exit_nonzero and suppressed retry. In the last 7 days this hit 143 AMR runs from 65 Windows users on 0.24.1; every sampled bundle (76/76) had already returned stopReason end_turn. Treat any exit as succeeded once the daemon itself began shutting down a cleanly completed ACP attempt. * fix(daemon): only forgive a completed ACP exit the daemon itself caused Review follow-up. terminateProcessTree waits gracefulWaitMs before it signals anything, so a vela that exits 1 on its own during that wait used to count as a daemon shutdown and was reclassified as succeeded. terminateProcessTree now takes onChildSignal, called just before the first signal to a direct child that is still alive (POSIX group, pid-less and Windows pid-tree paths). server.ts sets acpCompletionShutdownRequested from it for the completed-turn termination only, so a non-zero exit during the grace wait stays failed. * fix(daemon): report a daemon close only after the signal was delivered Review follow-up. `onChildSignal` ran before the stop helpers dispatched anything. If that dispatch then failed (a non-ESRCH error from the Windows stop path) or found the child already gone (ESRCH), the flag was still set, and a child that later exited 1 on its own was reported as succeeded. - platform: `stopProcesses` takes `onSignal`, called for each PID a signal was actually delivered to. ESRCH and thrown dispatches are not reported. - runs: the completion-shutdown callback fires once, after the first delivered signal to the still-owned direct child, on the Windows pid-tree, POSIX group and pid-less paths alike. |
||
|
|
e0946f9423 |
fix(od-next): recover planning replies that repeat the runtime state block (#8520)
* fix(od-next): recover planning replies that repeat the runtime state block
OD Next treats a reply with more than one open-design-runtime-state block
as non-repairable, so the task ends before anything is produced. On AMR
0.24.1 that surfaced as OD_NEXT_CONTINUATION_FAILED ("The parsed response
was not eligible for contract repair.") on 16 design-mode prototype runs
from 15 users in the last 7 days, 15 of them with no artifact. Most of the
daemon logs we could read show `Expected at most one
open-design-runtime-state block, received 2.`
- Collapse runtime state blocks that carry the same JSON value (key order
aside) into one declaration and record a normalization.
- Let disagreeing runtime state blocks take the existing one-time
serialization repair. Nothing has been written at this point. When every
block agrees on executionIntent, that intent counts as the reply's
explicit intent for the repair gate; otherwise the gate stays closed.
- Plan Contract duplicates still fail closed.
* fix(od-next): send agreed-produce duplicate runtime states straight to repair
Review follow-up. A duplicate Runtime State reply has no strict runtimeState,
so requiresStrategyIntentResolution treated a new task's intent as missing
and spent an intent-resolution turn before the serialization repair: two
provider turns where one was promised.
When every duplicate block declares `produce`, the intent is already
explicit, so the automatic continuation now claims the contract repair Run
directly. An agreed `plan_only` still takes the intent-resolution turn,
because only that turn can complete a planning-only task; the repair gate
would block it.
* test(od-next): cover duplicate runtime states that go through intent resolution
On AMR 0.24.1, 19 of 20 duplicate runtime-state failures asked the intent
supplement first. The model answered produce with one clean block, then the
original reply, still carrying the duplicate, was refused with "The parsed
response was not eligible for contract repair." This path already repairs
on this branch; the test fails with that exact error on the parent commit.
* fix(od-next): let the supplement complete a duplicate-state planning-only task
A planning reply whose two Runtime State blocks both declare plan_only goes
through intent resolution, but the source keeps no state of its own, so the
validated plan_only reply could not be copied anywhere and the task was blocked
on the duplicate. When the duplicate is the source's only defect, the
supplement's schema-validated plan_only state now completes the task and the
source Plan Contract is kept. Any other source defect stays fail-closed.
|
||
|
|
39e8301764 |
fix(daemon): drive Antigravity through agy's stream-json stdin channel (Windows ENAMETOOLONG) (#8594)
* fix(daemon): deliver Antigravity prompt on stdin to avoid Windows ENAMETOOLONG
agy received the full composed OD prompt as the -p argument. On Windows
that routinely exceeds CreateProcess's 32,767-char command line, so the
spawn failed with ENAMETOOLONG before agy started and users saw a generic
"This task failed to run" (OPEND-3495).
Pass a short fixed pointer as the -p value and deliver the prompt on stdin,
which agy print mode reads (verified on agy 1.3.1).
* fix(daemon): drive Antigravity through agy's stream-json stdin channel
The previous attempt passed `-p "Follow the instructions provided on
stdin."` and wrote the prompt to stdin, but agy ignores stdin whenever a
prompt is given with `-p` (agy 1.1.1), so the model never received the
OpenDesign prompt. Earlier "successes" came from the model reading files
in its working directory on its own.
agy's documented headless stdin channel is
`--input-format stream-json --output-format stream-json`, which reads
one NDJSON `{"event":"user","message":{"content":...}}` message per
turn. The prompt now travels only through that frame, handed over as a
complete file-backed stdin at spawn, so argv no longer grows with the
prompt (fixes Windows `spawn ENAMETOOLONG`, OPEND-3495).
- add an `encodeStdinPrompt` runtime hook used by the chat-run spawn and
the connection test
- parse agy stream-json events (text deltas, tool steps, terminal
result, usage) in json-event-stream, falling back to the Gemini JSONL
branch for frames without `event`
- drop the antigravity-only plain-stdout buffering, Gemini re-parse and
log-file empty-output classification
- recognise agy's headless signed-out output as AGENT_AUTH_REQUIRED and
keep the per-model quota guidance for `Individual quota reached`
- fixtures recorded from agy 1.3.1 plus the samples in agy's headless docs
* fix(web): show Antigravity quota guidance instead of the generic run-failure copy
The Antigravity RATE_LIMITED card had no message key, so it rendered
chat.runError.fallbackMessage ("This task failed to run. Please retry")
-- the exact sentence in the OPEND-3495 report -- with no hint that the
per-model quota was the cause. Give it its own copy (switch model in the
model menu or via agy /model) and the quotaExhausted title, in all 19
locales.
* Revert "fix(web): show Antigravity quota guidance instead of the generic run-failure copy"
This reverts commit
|
||
|
|
c2a28e3cee |
fix(chat): clear the composer on submit instead of after the send gate settles (#8380)
* fix(chat): clear the composer on submit instead of after the send gate settles
The host paints the sent turn and flips to Working before the OpenDesign
Cloud balance preflight settles, but the composer only reset after onSend
resolved, so the sent prompt lingered in the input for the preflight round
trip. Snapshot the composer at submit, clear it immediately, and restore the
snapshot only when the host hands the send back ('restore-draft' or a
throw) and the user has not started typing a new prompt.
Refs OPEND-3392
* test(chat): type the deferred onSend mock so its call args typecheck
* fix(chat): skip restoring a handed-back send over any new composer content
Review follow-up: the restore guard only looked at editor text, so an
attachment, visual comment, skill, MCP server, connector, workspace
context, plugin or quote staged while the send was pending was
overwritten by the old snapshot. Mirror committed composer content in a
ref and restore only when nothing new appeared since reset().
|
||
|
|
17e2559597 |
fix(od-next): isolate SVG icon geometry on latest main (#8298)
* fix(od-next): bound prototype SVG icon geometry * fix(od-next): classify prototype SVGs by role, not canvas size The icon contract listed example glyphs on each side but gave no rule for anything outside those lists, so a logo inside a button or a deliberately large UI glyph had to be guessed. State the basis: classify by the role the SVG plays, not by canvas size or the presence of a viewBox. --------- Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> |
||
|
|
802708f6c9 |
feat(web): land sign-in on Hosted and pitch free credits across entry points (#8567)
* feat(web): land sign-in on Hosted and pitch free credits across entry points - Onboarding: drop the "Choose your model source" step. Signing in from the welcome screen finishes onboarding on OpenDesign Hosted; Local AI and API Key stay reachable from the welcome screen. Hosted select_runtime now reports step `connect` instead of `model_source`. - Welcome screen: the pending sign-in shows one quiet "Sign-in page didn't open? Reopen" line (after 5s, or at once when the browser failed to open) instead of a nested card with two cancels, and the primary button no longer moves between idle and pending states. - Home rail card: "Get free credits" pitch with a sparkle mark; the pending state turns the call to action into "Signing in…" with a single cancel and the same delayed reopen line. Dark mode keeps the button visible. - Settings → Local CLI: callout reuses the free-credits copy; selecting a signed-out OpenDesign row selects it in place and offers Sign up / Sign in (no bounce to onboarding), committing the CLI once a session exists. Both buttons share the solid pill and show "Signing in… | Cancel". - Fix the selected CLI card flashing on hover, and make the Home @ picker tabs clickable where they overlap the desktop window's drag strip. * fix(web): drop pending OpenDesign pick when DeepSeek Harness setup commits Installing DeepSeek Harness from its setup dialog committed agentId without clearing amrPendingSelect, so the OpenDesign card stayed highlighted and a later sign-in overwrote the DeepSeek choice with 'amr'. Clear the pending intent alongside that commit and cover the sequence with a regression test. --------- Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com> |
||
|
|
7eb1e217be |
fix(web): align client error copy with the product error-copy doc (OPEND-2849) (#8620)
* fix(web): align export and update-check error copy with product (OPEND-2849)
- S26a: a generic export failure now shows the product title + body
("导出失败" / "本次导出未完成,请重新尝试。") through the same Toast
message + details shape as S26c. fileViewer.exportFailed is split into
fileViewer.exportFailedTitle / fileViewer.exportFailedDescription in all
19 locales; the old key is removed.
- S31b: drop the sentence-final period from the title line of
updater.dialogCheckFailed (zh-CN and 17 other locales; th had none).
* fix(web): never surface raw exporter errors on export failure (OPEND-2849)
Product copy S26: an export failure shows the S26a title + body by default;
only an already-localized, user-facing reason may replace it. Raw exporter
strings (HTTP status lines, renderer/daemon errors, internal exceptions)
no longer reach the toast.
- New export-failure-toast module: LocalizedExportError marks errors whose
message comes from an i18n key; exportFailureToast passes only those
through and falls back to S26a for everything else.
- Localized reasons now thrown as LocalizedExportError: PPTX daemon
unreachable / PPTX not available, version image capture failed.
- Image export catch-all uses the same rule instead of echoing err.message.
- The original error object is unchanged, so console.warn and
exportErrorCode analytics still see the raw message.
* fix(web): align disk-write failure and browser-open hint copy with product (OPEND-2849)
- chat.runError.localStorageFailureMessage now matches the product supplement
row 13 verbatim in zh-CN ("…请确认有足够的剩余空间后,再重新尝试。"); the
old "permission to save to the current folder" clause is dropped and all
19 locales are retranslated to the new meaning.
- settings.amrActivationBrowserFailed (S32 browser not opened): half-width
comma replaced by a full-width one in zh-CN and zh-TW; wording unchanged.
* fix(web): align S03/S04/S06/S09a/S15/S24/S28a/S31c/S32a error copy with product (OPEND-2849)
zh-CN copied verbatim from the product error-copy doc; all 19 locales translated.
- S04 pre-send signed out (balance gate dialog): "Open Design 尚未登录" + body.
- S06 pre-send insufficient allowance: owner dialog "可用额度不足" + body (no
balance figure); member dialog "团队额度不足" + body. Benefits list and
buttons unchanged.
- S15 mid-run allowance exhausted: the turn-anchored upgrade card's $0 state
shows title + body, personal vs. member chosen by the billing audience
ProjectView already resolves. Low-balance tier, amount and Upgrade button
unchanged; the pre-send tail card keeps "现在无法开始新任务".
- S24a unfinished todos: "任务尚未完成" + "本次任务仍有 {n} 项内容未完成。" with the
real unfinished count; S24c user stop: "任务已停止" + body. Buttons kept.
- S03 / S28a Home send failures: the optimistic create's rollback toast (the
surface users actually see) and HomeView's inline block now map
AMR_AUTH_REQUIRED to S03 and transport failures to S28a, as title + body.
- S31c update download failed (updater error code download-failed): update
dialog shows "更新下载未完成" + body; Settings status shows the title.
- S32a browser not opened during sign-in: title + body via one shared
component for the three sign-in surfaces; the sign-in page link is kept.
- S09a rate-limit auto retry: run_retry_attempted now carries
failure_category in the SSE contract; a rate_limit retry row reads
"模型服务请求繁忙" + body, other retries keep "正在重试".
|
||
|
|
d9dd6fefa7 |
feat(release): add one-dispatch withdrawal for an unshipped cut (#8509)
* feat(release): add one-dispatch withdrawal for an unshipped cut A release that was cut but will not ship had no undo. cut-release creates a branch, a backport label, a Feishu card, and — through the prerelease build its push triggers — moves prerelease/latest onto the new line. Abandoning that version meant reversing four surfaces by hand, and the one that actually matters is easy to forget: internal validators auto-update, so they sit on a package nobody intends to release. release-withdraw reverses each, in the order that leaves the least mess if a later step fails: repoint prerelease/latest at an older published prerelease, delete the label, delete the branch, post the matching withdrawal card. The branch delete uses the release App token because the release/v* ruleset blocks deletion and that App is one of its bypass actors — the same token that created the branch. It refuses more than it does. A version that reached stable is not an unshipped cut, and the error names release-rollback instead. A branch carrying any commit that is not on main and not from the release bots would lose work, so it stops. Open PRs targeting the branch, or still carrying its label, stop it. The prerelease pointer is read live rather than trusted from the input, and is only moved when it actually belongs to the withdrawn version — at which point a target becomes mandatory rather than silently skipped. dry_run defaults to true: a withdrawal is never the urgent case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(release): make the withdrawal queue behind the pointer's other writer, and give the dry run teeth Both findings from review. Concurrency. `open-design-release-withdraw` was a group of one, so it serialised this workflow against nothing, and the header comment claimed a guarantee it never had. `release-prerelease.yml` is the only other writer of `prerelease/latest` and holds `open-design-release-prerelease`; the withdrawal now joins it. The publish this races is the ordinary cut timeline, not a manual re-run: the cut push and the preview-manifest push that follows each start `notify-release-feishu` -> `release-prerelease`. Three failures came from the unique group. Reading the pointer before an in-flight publish finishes resolves `belongs=false`, so the repoint is skipped and the publish then installs the withdrawn version after a green run. Interleaved writes mix `latest`, because the publisher writes metadata first and feeds second while `applyLatestRollback` writes feeds first and metadata last, and every PUT is unconditional. And a publish landing *after* a repoint restores the abandoned pointer, because the publisher's CAS refuses only backward moves. The group is workflow-level and must stay that way, which is the part worth keeping in mind: it is held through the branch delete, so a queued trailing publish cannot enter the publisher until `release/vX.Y.Z` is gone and then fails closed on a checkout of a deleted ref. A job-level group would release the lock first and lose that. A P0 assertion pins the shared string against release-prerelease — renaming the publisher's group now breaks a test rather than the invariant — and pins the single workflow-level block. `cut-release.yml` stays out of the group: it writes no R2 object of its own, and what needed serialising was the publisher it triggers. The branch also gets a compare-and-delete, re-reading the tip and refusing if it has moved off the SHA that "nothing but cut commits" and "no open PRs" were established against. Not a substitute for the lock, which is what fixes the publish race — this covers the likelier window the lock does not see, a backport landing while a human reads the dry run. GitHub's ref delete takes no expected-SHA precondition, so the compare is explicit. Dry run. `Setup pnpm`, `Install dependencies` and `Repoint prerelease latest` were all gated on `!inputs.dry_run`, which removed the credentialed half of the validation from the mode that exists to validate. `prerelease_to_version` only had to be syntactically plausible: an absent, incompletely published or feed-less target, or one below the prerelease launcher floor, passed the plan and failed for the first time during the real run. It still fails before the label and branch deletes, so nothing was destroyed by it — but the dry run is the path this workflow tells the operator to trust, and `[P0] plans before it destroys` required `!inputs.dry_run` on the repoint step, locking the skip in. The three steps now run whenever the pointer needs moving and the planner takes `RELEASE_DRY_RUN: ${{ inputs.dry_run }}`, matching how release-rollback already wires it. "The dry run passed" now means the real run has nothing left to discover, and the header and the step summary say so. The two deletions and the Feishu card stay gated on the input. Each of the five behaviours was mutation-checked: reverted at exactly one site (three for the `if:` gate), exactly one test went red. Workflows re-linted with the CI-pinned pair, actionlint 1.7.12 with shellcheck 0.11.0 on PATH, proven wired by a probe workflow that reports SC2086. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
426386581b |
docs(chat): record the OPEND-2807 error-card ruling (#8271)
The error card has shipped with a fixed set of three actions since #8140, but that ruling was never written down: `git grep -i 2807 -- specs docs` returns nothing. Two documents still describe the world before it. `chat-panel-decisions-sheet.md` still reads "稿子 2 颗, 产品 4 颗" and points at `run-error-catalog.md:421-430` for "A/B 两案仍挂着等产品挑". Neither is true: the catalog's three candidates were all overruled, and the card has three actions in both environments. `run-error-catalog.md` §6.ZB still carries that candidate table as live, and §6.T still frames the mapping as a ranking of secondary actions that no longer exists. This records the ruling from main's own behaviour, not from the proposal that lost: the criteria are quoted from `showCloudRetry` and `showCloudSwitchCta` as they exist today, and the three exceptions (a host that cannot take the handoff, `git_bash_missing`, a zero balance) are the ones main actually ships. Historical passages stay; each one now carries a pointer to the outcome. The comment above `withCloudSwitchCta` pointed readers at `ChatPane`'s `errorActionVariant`, a symbol #8140 deleted. It now describes the two branches that exist. No behaviour change: every `.ts` line in this diff is a comment. Refs OPEND-2807 |
||
|
|
0520fde34b |
fix(chat): retain live thinking when older history arrives (#8167)
* fix(chat): retain live thinking when older history arrives * test(web): cover full replay through the actual recovery host --------- Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
e38462fd50 |
fix daemon skill roots missing from the run-scoped external_directory allowlist (#8178)
resolveChatExtraAllowedDirs built the allowlist from SKILLS_DIR only, so a skill installed under the daemon data dir or loaded from a bundled plugin folder resolved to a root outside it. withSkillRootPreamble still advertises that root as the absolute fallback path, so OpenCode asked for external_directory approval on files OD itself pointed the agent at, and a headless run reported the ask as a rejected tool call. Pass the turn's active skill dirs so the allowlist is keyed on the roots actually in play. Codex stays excluded: it treats allowlisted dirs as writable and skill roots are read-only resources. |
||
|
|
cc73b0e93f |
fix(daemon): retry transient OAuth refresh contention (#8160)
When two local processes race to refresh the same stored OAuth credential, the agent aborts its refresh and reports the condition as transient: Failed to refresh OAuth token: another Claude Code process is refreshing it or exited mid-refresh. This is usually transient; retry in a minute... The classifier had no branch for this text, so it fell to the generic process-exit fallback as `exit_nonzero`, which `transientSuppressedReason` refuses for `process_exit` with `non_retryable_category`. The safe-retry path was suppressed and the run died on a dead-end failure card, for a condition that clears as soon as the contending holder releases the lock. Name it `credential_refresh_contention` and wire it the way `session_resume_expired` already is: classified at `session_init` as retryable with `user_action: 'retry'`, and added to the `process_exit` transient allowlist. The branch is claimed ahead of the auth verdicts on purpose. The message ends "...or sign in again", and `auth` is fixed at `retryable: false` / `user_action: 'login'` — reaching it would prescribe re-authenticating a credential that never expired. The detector is anchored on the contention itself rather than on the word "refresh", so a genuinely spent or replayed refresh token keeps its non-retryable auth verdict; a test pins that direction. Retry is safe without further gating: the failure is raised before a request is sent, so nothing streamed, no tool ran and no artifact was written, leaving the side-effect gates in `decideSafeRunRetry` satisfied. |
||
|
|
92fe7e87b1 | feat(release): decouple stable Docker reconciliation (#8517) | ||
|
|
f86adccf3a |
fix(web): reveal full model names on hover in model pickers (#8409)
* fix(web): reveal full model names on hover in model pickers Long model ids in the model pickers ellipsise to a shared prefix (e.g. openrouter/google/gemini-...), so rows become indistinguishable and no title was available to confirm a choice. Add the full label as the hover title on every model-selection surface named in the report: - the shared SearchableModelSelect option rows and trigger; - the compact home list in InlineModelSwitcher; - the composer/sidebar AvatarMenu lists (daemon and BYOK). A locked row keeps its upgrade reason as its title, and accessible names are unchanged. Adds regression tests using two same-prefix long OpenRouter ids on each surface. Fixes #8407 * chore(ci): retrigger web workspace tests after flaky artifact-tab shard The ProjectView.auto-open-turn-artifacts spec timed out on shard 2/2; it passes locally and is unrelated to the model-picker title change. |
||
|
|
33fd35e07b |
fix(packaged): treat Chromium ERR_NO_BUFFER_SPACE as local resource exhaustion (#8283)
Electron net.fetch reports ENOBUFS as net::ERR_NO_BUFFER_SPACE. The existing guard only matched the POSIX name, so the proxy fell through to undici and kept retrying on an already-exhausted T2 Intel Mac. Co-authored-by: leoric <leoricchen@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> |