Commit Graph
3748 Commits
Author SHA1 Message Date
zhouzheng c4440b0e92 fix(discovery): gate skill reads on current production authorization 2026-10-14 03:40:13 +08:00
zhouzheng 7318ce7f57 fix(discovery): complete authorized plans and verify audible delivery 2026-10-14 02:12:47 +08:00
zhouzheng ccd7601cb2 fix(discovery): retain WebGL intent and isolate reference-only skills 2026-10-14 01:49:26 +08:00
zhouzheng b9288317c3 fix(discovery): distinguish video rendering from editable animation delivery 2026-10-13 15:29:00 +08:00
zhouzheng 808dd9c736 fix(discovery): avoid implementation-only skills and false video delivery 2026-10-13 15:03:28 +08:00
zhouzheng 402b609a86 fix(discovery): require skill reads before copying reference artifacts 2026-10-13 13:18:35 +08:00
zhouzheng 9ef277979f fix(discovery): distinguish reference recreation from new prototypes 2026-10-13 13:04:57 +08:00
zhouzheng 820939f3bb fix(od-next): retain live list containers for empty source data 2026-10-12 19:51:34 +08:00
zhouzheng 7632116a51 fix(od-next): distinguish source refresh from preview reload 2026-10-12 19:43:02 +08:00
zhouzheng dcba43c8f1 fix(od-next): route refreshable sources and preserve live templates 2026-10-12 19:33:43 +08:00
zhouzheng 97af8c84bf fix(od-next): preserve planning intent and make agent CLI probes inert 2026-10-12 18:04:42 +08:00
zhouzheng f6df446afd fix(od-next): maintain discovery prompt assets in English 2026-10-12 17:31:26 +08:00
zhouzheng ee48c381b8 chore(od-next): sync latest marker base and align delivery regression 2026-10-12 11:23:09 +08:00
Cheems 12ef1c4b6e 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.
2026-10-08 17:02:33 +08:00
Cheems 86ace2083a chore: merge main while preserving marker fixture probes
Adapt model and authentication probe regressions to the marker-based Codex fixtures without restoring plan templates or snapshot helpers.

Validated the affected daemon server file (56 tests), web refresh recovery file (61 tests), workspace typecheck, and guard.
2026-10-08 17:02:05 +08:00
PerishFireandGitHub 92fe7e87b1 feat(release): decouple stable Docker reconciliation (#8517) 2026-10-08 07:52:45 +00:00
Pratik RaiandGitHub 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.
2026-10-08 07:36:52 +00:00
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>
2026-10-08 07:11:00 +00:00
matthew6sandGitHub 4771bb2f87 fix: remove duplicate web-clone chip in HOME_HERO_CHIPS (#7777)
* fix: remove duplicate web-clone chip in HOME_HERO_CHIPS

HOME_HERO_CHIPS defined two objects with id: 'web-clone'. They were identical
except the second lacked automaticDefault: true. A duplicate id collides as a
React key and makes findChip/orderedCreateChips lookups ambiguous, and the
second copy silently dropped the automatic-default binding. Remove the second
duplicate, keeping the canonical entry that carries automaticDefault: true.

* test(home-hero): assert HOME_HERO_CHIPS ids are unique

Existing findChip and rail tests only observe the first match for an id, so
they passed while two web-clone chips were present. Add a catalog-wide
uniqueness invariant that fails on a reused id, so a duplicate cannot silently
return with its React-key and lookup ambiguity.
2026-10-08 06:37:50 +00:00
df2ebd6b57 fix(web): keep late memory cards in their source conversation (#8065)
* fix(web): keep late memory cards in their source conversation

* fix(web): preserve memory polling window ownership across retries

* fix(web): preserve late memory attribution across consecutive turns

---------

Co-authored-by: lefarcen <935902669@qq.com>
2026-10-08 05:55:15 +00:00
1bf9bf52f0 fix(projects): settle empty catalogs and expose list failures (#8443)
Co-authored-by: lefarcen <935902669@qq.com>
2026-10-08 05:28:22 +00:00
open-design-crew[bot]GitHubelifive555555open-design-crew[bot] <4197780+open-design-crew[bot]@users.noreply.github.com>
3449fa6ffd feat(templates): add original Aster Atelier studio website (#8314)
* feat(templates): add original Aster Atelier studio website

* fix(templates): brighten Aster Atelier artwork and palette

* chore: ensure PR CI

---------

Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com>
Co-authored-by: open-design-crew[bot] <4197780+open-design-crew[bot]@users.noreply.github.com>
2026-10-08 04:02:02 +00:00
LukasandGitHub c190f264e0 fix(daemon): keep pi's config-directory override across a config save (#8119)
`agentCliEnv` is validated against a per-agent allowlist on every save, and
pi exposed only `PI_BIN`. `PI_CODING_AGENT_DIR` — pi's own override for its
config directory, default `~/.pi/agent` — was therefore dropped on every save
cycle, leaving no way to isolate a pi config but a wrapper script that sets
the variable and is pointed at by `PI_BIN`.

This extends pi's contract by the one key rather than turning the allowlist
into a pass-through: `PI_CODING_AGENT_DIR` is the same kind of entry
`CLAUDE_CONFIG_DIR` and `CODEX_HOME` already are for their CLIs, and nothing
else about pi's environment exposure changes.

Persistence is half the fix, so the tests follow the value the rest of the
way: one cell writes the config, reads it back and hands
`agentCliEnvForAgent`'s projection to `spawnEnvForAgent`, asserting the
variable arrives in the env pi is launched with; two more pin the launch env
directly, including `~` expansion. A neighbouring key that is NOT part of the
contract (`PI_CODING_AGENT_SESSION_DIR`) is asserted to still be dropped.
2026-10-08 04:01:33 +00:00
Ray XiandGitHub 3f83439dfe fix(chat): wait for successor run boundary before folding (OPEND-3463) (#8401) 2026-10-08 03:49:39 +00:00
53231d40b7 docs(readme): refresh product tour and 13 translations (#8534)
* docs(readme): refresh product tour and translations

* docs(readme): keep product tour media under blob limit

* docs(readme): introduce OpenDesign Go plan

---------

Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
2026-09-30 15:31:47 +00:00
zhouzheng 28d7d0f151 fix(observability): settle successful headless task telemetry 2026-09-30 17:11:55 +08:00
zhouzheng 6b409ee9b1 feat(observability): expose actual task delivery receipts for evaluation 2026-09-30 16:51:02 +08:00
zhouzheng d5e95ae5d3 fix(od-next): refine discovery and live delivery evidence 2026-09-29 16:46:51 +08:00
zhouzheng 10cc151fc3 feat(od-next): add deliverable discovery and ten-type routing 2026-09-29 14:16:22 +08:00
5b19dfa435 fix(release): resolve the rollback tag from published metadata (#8508)
The first live dry run failed at the badge preflight: I had written the tag
as v<version>, but prepare-stable.ts publishes open-design-v<version>. A
hand-built prefix reads plausibly and is wrong, so take the tag from
.versionTag in the restored release's own immutable metadata — the value the
publisher recorded — probing the same prefix candidates rollback-latest.ts
probes, and hand it to the badge step as a step output.

The summary checklist had the same wrong shape; it now names the version
rather than constructing a tag. The regression test pins both: the tag must
come from .versionTag, and no step may rebuild one from the version input.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-29 03:41:33 +00:00
54139504d4 feat(release): add one-dispatch stable rollback (#8507)
* feat(release): add one-dispatch stable rollback

A stable release publishes its artifacts to an immutable
stable/versions/<version> prefix and then copies the pointer objects into
stable/latest. latest is therefore derived state, and retracting a release is
copying an older version prefix over it again — but until now nothing in the
repo could do that, so a bad stable release had no stop button.

Add `tools-release rollback-latest` plus a release-rollback workflow that
dispatches it. The CLI refuses unless the live pointer still serves the version
the operator typed as from_version, the target published completely (not
partial, not a dry run), every ready platform's manifest and updater feed exist
in the target prefix, and the current installer floor is satisfiable by the
target. It re-resolves control.launcher.version from live channel policy rather
than restoring the snapshot's, records rollback provenance, writes metadata.json
last so latest never advertises a version whose feeds it does not yet serve, and
verifies every object through both the origin and the public URL.

The workflow shares release-stable's publish concurrency group so a rollback
cannot overlap a publish, moves only the GitHub Release "Latest" badge (never a
release body), and ends with a checklist of what a rollback does not reach: the
download page's version-pinned links, the What's New card, the group
announcement, and above all the installs already on the retracted version —
the updater never offers a version that is not strictly newer than the running
one, so this stops a rollout and cannot recall one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(release): group the rollback summary fallback redirects

shellcheck SC2129 — CI runs actionlint with shellcheck wired in, which my
local actionlint could not see without it installed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(release): prove the restored tag has a release before writing

The badge move runs after the R2 write, so a missing GitHub Release for the
restored version would have failed the run with stable/latest already moved.
Check it up front instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(release): pass the stable installer-floor policy into rollback

resolveLauncherVersionFloor() reads process env, and repository variables are
not process env. Without the handoff a rollback resolved no floor at all: it
would strip an active control.launcher.version from the restored metadata and
stop refusing targets below the current minimum — the safeguard the workflow
documents as enforced. Latent today only because no stable floor is set.

release-stable.yml passes the same pair to metadata publish and verify; mirror
it, with a topology assertion so a later edit cannot drop it silently. Also
stamp RELEASE_BRANCH/RELEASE_COMMIT so the rollback provenance is not blank.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(release): require the restored release to be badge-eligible

gh release view succeeds for a draft or a prerelease, but GitHub will not put
the Latest badge on either — so the preflight passed and the edit failed with
the R2 rollback already done, which is the half-complete state the preflight
exists to prevent. Check isDraft and isPrerelease too, and cover the
eligibility guard in the workflow test alongside its ordering.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-29 03:21:12 +00:00
64710082d0 fix(diagnostics): collect the AMR run's runtime log records (OPEND-3498) (#8488)
* fix(diagnostics): collect the AMR run's runtime log records (OPEND-3498)

AMR incidents never carried AMR-side evidence. The collector looked for
OpenCode logs under <dataDir>/amr/opencode-home, but Vela drops the
OPENCODE_TEST_HOME it receives and runs OpenCode under per-conversation homes
in $AMR_HOME/opencode-sessions, so nothing was listed and no note explained
the gap. $AMR_HOME/logs/agent-runtime.jsonl was never listed either.

- Take the incident run's records from agent-runtime.jsonl, plus those of the
  OpenCode sessions it owns until another run takes a session over, so other
  runs' records never enter the bundle.
- Report a missing runtime log, a missing run id and the not-yet-located
  session logs as explicit collection notes, and keep those reasons instead
  of a consent verdict.
- Give sources that appear after opting in a boundary at their current size
  on start, so a newly listed shared log is not omitted forever.

Locating the per-conversation OpenCode session logs is left for a follow-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(diagnostics): keep a rotated log's baseline when extending the fence

On Windows the packaged launcher rotates latest.log to previous.log at every
start. extend() saw previous.log as an unbaselined path and recorded a
boundary at its current size, so the rotated log's bytes written after the
real boundary were dropped as consent_boundary. Found in a packaged Windows
run: the daemon log written after opting in was missing from the bundle.

Skip files that share a baselined creation time; the fence decides their
boundary from that baseline. Skipping only defers to apply() and never
admits bytes by itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 10:16:34 +00:00
6ed97944c8 fix(diagnostics): keep Windows rotated logs inside the consent boundary (OPEND-3497) (#8487)
* fix(diagnostics): keep Windows rotated logs inside the consent boundary (OPEND-3497)

The packaged launcher rotates latest.log to previous.log and immediately
re-creates latest.log. On Windows, file-system tunneling gives the new file
the creation time of the file that previously held the name, so the consent
fence saw a new inode with a pre-consent birthtime and omitted the whole
file as pre_consent_source on every launch after opting in. The rotated
previous.log was omitted too because its baseline was keyed by the old path.

Match baselined identities across paths so a rotated file keeps its offset,
and admit a new identity whose creation time equals a baselined one, which
only a re-created (tunneled) name produces. Unrelated old files are still
omitted, and no pre-consent bytes are backfilled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(diagnostics): scope tunneled log admission to its source path

Preserve original consent offsets and persist admitted identities for later rotations and daemon restarts. Cover unrelated birth-time collisions, rotation ordering, and consent resets.

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

* fix(diagnostics): remember tunneled logs at startup, keyed by identity

A session that recorded no incident never called apply(), so its tunneled
latest.log was not remembered as admitted. After the next launch rotated it
to previous.log, that incident-time log was omitted as pre_consent_source,
which is the relaunch-after-crash case. Admitted identities were also keyed
by path, so a newer latest.log replaced the entry of the file that had just
rotated to previous.log.

Observe the baseline sources once per daemon process, after the launcher has
rotated, and key admitted identities by inode and creation time, keeping only
those still present. Verified on Windows (NTFS, default tunneling) with real
rotations: with no incident in the middle session, previous.log is admitted
on the next launch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(diagnostics): report a missing source as not found, not pre-consent

The fence labelled a source that does not exist as pre_consent_source, which
reads as a consent decision. A packaged Windows bundle showed
logs/desktop/renderer.log this way although the file was never created.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 09:40:21 +00:00
PerishFireandGitHub b52fafd474 feat(ci): enforce reusable workload plans (#8393)
* feat(ci): enforce reusable workload plans

* fix(ci): skip incompatible convergence upgrades
2026-09-28 08:29:12 +00:00
e5d75aa8a1 fix(diagnostics): stop repeating API failures from flooding automatic uploads (#8461)
* fix(diagnostics): stop repeating API failures from flooding automatic uploads

Stable 0.24.1 devices uploaded thousands of diagnostic incidents a day from
one deterministic failure: GET /api/runs answering 400 PROJECT_SCOPE_REQUIRED.

- Key API-failure incidents by failure signature per hour instead of the
  per-request id, so a polling caller yields one incident per hour.
- Drop earlier "[diagnostics] incident delivered" receipt lines from
  automatic bundles; on busy devices they filled the daemon log tail.
- Desktop pet task center: stop interval polling once the daemon requires a
  project scope, and stop restarting the poller on every 1.5s config reload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(diagnostics): filter receipts before allocating the log tail budget

Scan automatic text logs backward with bounded buffers, preserving complete lines and consent offsets before applying the retained byte limit. Cover receipt suffixes larger than 4 MiB and filtered-tail boundary cases.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 06:56:27 +00:00
Ray XiandGitHub 512f302d40 fix(web): retire stale recent-project status polling (#8442) 2026-09-28 06:56:12 +00:00
1b47e60bd4 fix(cms): mount Test campaigns with the requested app locale (#8432)
Co-authored-by: lefarcen <935902669@qq.com>
2026-09-24 06:58:26 +00:00
3ede8daf11 test(daemon): answer Codex fixture probes without waiting for stdin (#8426)
Co-authored-by: lefarcen <935902669@qq.com>
2026-09-24 05:26:37 +00:00
61bda5c78c fix(ci): allow setup headroom for prerelease daemon tests (#8424)
Co-authored-by: lefarcen <935902669@qq.com>
2026-09-24 04:22:53 +00:00
Cheems 9a97d4eede Merge main into the marker continuation branch 2026-09-24 12:12:41 +08:00
CheemsandGitHub d61e64ec68 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.
2026-09-24 11:57:29 +08:00
eb27acd322 feat(billing): support Coding Plan usage and wallet fallback (#8339)
* feat(billing): support Coding Plan usage and wallet fallback

* fix(web): keep AMR send off billing preflight

Workspace send no longer waits on advisory vela billing preflight; recovery still requests it. Realign zero-wallet P0 oracles and the credits-card wallet label.

Generated-By: looper 0.15.0 (runner=fixer, agent=omp)

* fix(billing): serialize recovery preflight and bound hung vela

Skip overlapping AmrBalanceDialog recovery ticks and stop the watch after
ten minutes even if a preflight is still pending. Give vela billing
preflight a 60s runVelaCommand timeout so a hung CLI cannot pin recovery.

Generated-By: looper 0.15.0 (runner=fixer, agent=omp)

* fix(web): restore coding plan text contrast in billing card

* feat(web): render Coding Plan windows and Go tier in the credits panel

- CodingPlanUsage renders one row per preflight window (name, used %,
  remaining USD, reset countdown + absolute time) with loading/unavailable
  states; refreshes once on mount and once at resetsAt (no 30s polling,
  setTimeout delay clamped to the 32-bit limit).
- Pure model in coding-plan-usage-model.ts; creditsPerUsd comes from
  `vela billing summary` through WorkspaceBillingSummary and falls back to
  10,000 only when the backend omits it.
- PlanWordmark/EntryNavRail accept the `go` tier (placeholder wordmark,
  design asset still pending).
- i18n: 7 new billing keys + entry.billingTierGo across all 19 locales;
  real translations for the #8339 keys; drop unused codingPlanNone /
  codingPlanRemaining.
- CLI wording: unstarted window reads "not started yet".

* build(pack): pin vela-cli 0.1.4-test.0 and gate on billing preflight

The packaged client needs `vela billing preflight` for the Coding Plan
window rows. Bump the bundled CLI to the npm `test` prerelease that ships
it and add a third capability gate in tools-pack: a CLI without the
subcommand prints the parent `billing` help and exits 0, so the gate
checks the help markers (preflight, --workspace-id, --model, --format)
instead of the exit code.

TEMPORARY: replace 0.1.4-test.0 with the stable 0.1.4 once it is
released; do not merge with a `test` prerelease pinned.

* fix(web): make Coding Plan rows legible on the inverted credits card

The credits card is a hard-coded #202020/#fafafa inverted surface, but
CodingPlanUsage.module.css read page-level --text-* / --bg-fill-* tokens,
so on the card the window names rendered #202020 on #202020 (1.00:1) and
the stat/reset lines sat below WCAG AA. Derive every colour from
currentColor instead (name 100%, stat 72%, reset/note 60%, separator ~50%,
track 36%, exhausted = --red mixed toward currentColor); measured in Chrome:
name 15.6:1, stat 8.7:1, reset 6.4:1, track 3.2:1, exhausted 6.5:1.

Keep the stat on one line (nowrap) and let the name ellipsize instead of
wrapping "60% / used" onto two lines; drop the block's 12px side padding so
it aligns with the card's own rows.

Also add a minutes tier to the reset countdown: the last hour before a
window resets used to show no countdown at all. New key
billing.codingPlanResetsInMinutes in all 19 locales.

* feat(web): rebuild the plan panel 1:1 from design PR #8364

Replace the improvised Coding Plan block with the design's panel, measured
against docs/ui-previews/plan-panels/index.html in Chrome (computed styles
and a 4x pixel diff of the Plus specimen):

- Header: tier name + 16px wordmark, 升级 pill (管理 on the top tier).
- One row 「7天额度免费用 · 已用 N% ›」 (7-day window only; rounded percent;
  100% when spent, no red state) over a 5px #b1f38b track, then the
  separator and the 「钱包余额 · US$x.xx ›」 row. No headings, window names,
  remaining USD, reset time, note or unavailable line.
- Team workspaces keep the pre-existing card unchanged (all team_* tiers);
  the quota row renders only for personal workspaces.
- Free personal workspace: no quota row, but the header sells 升级 like the
  design (a personal workspace needs no billing permission; an account B
  reports without a plan upgrades as free).
- Top-right pill shows the wordmark only, no balance.
- Wallet always reads US$ regardless of locale (product ruling 2026-09-23).
- zh-CN tier names follow the design: 免费版 / 标准版 / 专业版 / 旗舰版.
- Drop the dead billing.codingPlan* keys and model helpers; add
  billing.codingPlanWeeklyAllowance and entry.creditsManage in 19 locales.

* feat(web): show 管理 on personal Max per design PR #8364

The design's Max card sells 管理 (console auto-recharge settings) where
every other tier sells 升级; product ruled on 2026-09-23 to follow the
design for personal Max too, superseding the earlier "personal tiers are
always upgradeable" ruling. The gate now asks isMaxPlanTier and 管理 wins
over 升级 when both would show.

* feat(web): route the plan card's three entries per product ruling

2026-09-23 ruling on the card's landings: 升级 opens the console's pricing
dialog (billing=plan, unchanged), the allowance row opens the console
dashboard (unchanged), the wallet row asks for the manual top-up dialog
(new billing=recharge intent; B does not honor it yet and degrades to the
dashboard), and 管理 on Max opens the plain dashboard instead of the
auto-recharge dialog.

* fix(web): align personal plan cards with v2 design and scoped loading

* fix(web): center plan wordmarks inside the top-right pill

* fix(web): reuse shared billing cache for plan hover cards

* test(web): match personal billing preflight in avatar fixture

* fix(billing): require usable quota evidence for funding recovery

* test(billing): cover scoped preflight and quota event refresh end to end

* feat(daemon): relay scoped coding plan usage events and health

* fix(billing): refresh quota caches from scoped realtime events

* test(daemon): accept capability query on mock event stream

---------

Co-authored-by: lefarcen <935902669@qq.com>
2026-09-24 03:22:31 +00:00
5885573546 feat(web): localize welcome screen and starter credit ribbon (#8351)
Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com>
2026-09-24 03:13:16 +00:00
lefarcenandGitHub 419c735843 docs(release): add v0.24.1 changelog (#8419) 2026-09-24 03:09:03 +00:00
bone3deep1962-collab 3a39994430 Merge main and reconcile campaign lifecycle regression test 2026-09-24 11:00:55 +08:00
bone3deep1962-collab 264858d123 fix(od-next): tolerate terminal production marker formatting 2026-09-24 10:35:30 +08:00
f166c02636 fix(packaged): let a macOS headless runtime become the desktop in place (#8398)
* fix(packaged): let a macOS headless runtime become the desktop in place

When Codex starts Open Design headlessly through MCP, macOS treats that
windowless process as the running app. Opening the app from the Dock,
Finder, Launchpad or `open -a` then only reactivates it, so no launcher
runs and no window ever appears (OPEND-3426).

On macOS the headless runtime now runs the desktop path with its window
deferred, and restores the window in the same process when the user
opens the app: through `activate`/`open-url` paired with the app becoming
active, or through SHOW from a newer launcher that sees a `restorable`
owner. The daemon, its port and connected MCP clients stay. A new outer
hands headless launches to the active payload and marks the launch as
managed; payloads started by older outers keep today's behavior.

Managed MCP registrations carry absolute sidecar endpoints for every mode
of the namespace, so the MCP process finds the daemon whichever mode owns
it, waits for a running owner instead of reopening it, and cold-starts
only when nothing runs. The daemon refreshes an existing Codex
registration on start and never installs one. A write interrupted by a
service restart now says it may or may not have been applied.

* fix(daemon): scope Codex refresh to its managed install

Require the existing registration's managed discovery marker to match before refreshing it, so local, stable, and prerelease installs cannot take over the global name from one another. Cover the unrelated-owner path without invoking a config mutation.\n\nGenerated-By: looper 0.11.2 (runner=fixer, agent=codex)

* fix(daemon): prove Codex registration ownership by data root and app

Tighten the ownership check from d2d47a5f8e. Matching the discovery
endpoints alone still let a copy of the app that reuses the installed
namespace take over the registration (the endpoints depend only on
channel, namespace and source), and it could never refresh a
registration written before the managed contract, which has no
discovery value and still names a payload version that cleanup removes.

Read the existing registration and rewrite it only when it serves the
same daemon data root and bootstraps the same installed app; the managed
marker is ignored so a pre-managed registration of this install still
counts. Anything else, including a registration that cannot be read, is
left untouched.

---------

Co-authored-by: Looper <looper@noreply.github.com>
2026-09-23 12:47:31 +00:00
PerishFireandGitHub 7bad1a45f2 feat(telemetry): classify publish and deploy failures additively (#8402)
Publish-public and deploy failures were only visible as one opaque bucket
each (`publish_failed`, generic HTTP_400 / Error), so neither PostHog nor the
automatic diagnostics bundles could tell why they failed.

Purely additive — no existing status, error code, event value, trigger or
copy changes:

- daemon: failed publish/unpublish/deploy responses gain an optional
  closed-token `failure` { stage, reason, upstreamStatus?, upstreamCode? }.
  Vela CLI failures are classified from the CLI's stable stderr contract
  (vela-cli 0.0.33–0.1.3); deploy failures separate provider rejection,
  unreachable provider, rejected Vercel token, local file and internal
  errors. Each failure also writes one structured, text-free log line.
- web: artifact_publish_result / artifact_deploy_result gain optional
  failed_stage, failure_reason, upstream_status, upstream_error_code, and
  (publish) daemon_error_code. `error_code` keeps its values.
- correlation: each attempt's analytics request id is sent as
  x-od-request-id, logged by the daemon, and reported as request_id.
2026-09-23 12:19:20 +00:00
Ray XiandGitHub 282416ccd8 feat(diagnostics): automatically collect consented failure evidence (OPEND-3397) (#8357)
* feat(diagnostics): persist and upload consented Agent fault evidence

* feat(diagnostics): capture cancellation and delivery experience failures

* feat(diagnostics): collect visible frontend failures through consented relay

* fix(web): reset cached analytics before diagnostic test mocks

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

* fix(web): reset template picker before it becomes interactive

* test(web): await campaign presentation before retry polling
2026-09-23 11:12:53 +00:00
Ray XiandGitHub 055621c906 fix(web): keep the task-type menu open when the click follows a type change (#8386)
TemplatePicker closed its menu from a passive effect keyed on activeChipId and
disabled. On a loaded machine React runs a commit's passive effects in a later
task, so a click on a trigger that already showed the new type opened the
menu and the stale effect closed it again. Close in the render that
introduces the change instead.

Home also enabled the picker one render before its first-visit default type
(or restored draft / handoff) landed, so a click in that gap opened a menu the
arriving type then closed. Keep the picker disabled until the initial type is
settled.
2026-09-23 09:38:12 +00:00