mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
chore/plugin-previews
146
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a1995a186a |
test(e2e): harden UI flake waits with real completion signals (#6539)
* test(e2e): harden UI flake waits with real completion signals Replace synthetic /projects routing, blind boot sleeps, and call-site create retries with observable readiness: real navigation, suite daemon health warmup, expect.poll, clock fast-forward for coalesce TTL, and quiescence for AMR refresh traffic. * test(e2e): raise Playwright fixture timeout for daemon warmup The suite fixture now polls daemon /api/health for up to 60s, which consumed the prior 390s budget's bookkeeping margin. Raise the worker fixture timeout to 450s so start + web/daemon warmup + stop still leave a full minute for teardown bookkeeping on slow CI workers. Generated-By: looper 0.11.8 (runner=fixer, agent=grok-build) * test(e2e): fail closed on health body drain and narrow billing mock Require warmPlaywrightDaemonRuntime to fully consume ok health bodies before declaring readiness, drain non-ok probes, and fulfill only the exact /api/workspace/billing path so nested billing routes fall through. Generated-By: looper 0.11.8 (runner=fixer, agent=grok-build) * test(e2e): reopen projects by id in cross-project file-tab restore Avoid relying on chrome workspace tabs surviving leave+create hard navigation; assert per-project file-tab restore via project routes. |
||
|
|
5580736c1a |
fix(e2e): align packaged onboarding smoke selector (#6538)
* fix(e2e): align packaged onboarding smoke selector * test(e2e): guard packaged onboarding selector drift * fix(e2e): align platform onboarding probes Generated-By: looper 0.11.8 (runner=fixer, agent=codex) * fix(e2e): align packaged smoke with identity gate Generated-By: looper 0.11.8 (runner=fixer, agent=codex) |
||
|
|
8b3ec59cfe |
feat(campaign): DeepSeek V4 Flash free-week surfaces (landing + web + attribution) (#6507)
* feat(campaign): port DeepSeek V4 Flash free-week surfaces from #6450 1:1 port of the demo net diff (base feat/workspace-team) onto main. Landing home banner, landing pricing benefits, cloud-team-demo review page, in-app home modal, workbench badge, model-switcher benefit badge, and the campaign attribution/analytics pipeline. No behavior changes in this commit; agreed behavior fixes land separately. * fix(campaign): show the DeepSeek V4 Flash modal only on the active home view The dialog portals to document.body while EntryShell hides inactive entry views with display:none, so the campaign escaped the home view and interrupted projects/tasks/plugins routes. Thread EntryShell's existing isActive signal through HomeView into a new `active` prop: when inactive the modal neither opens nor renders (and closes without being marked seen, so returning to home while still unseen re-opens it). Requirement: 弹窗只在 #/home 展示,不在编辑器或其他工作流中打断用户。 * fix(campaign): fail closed when frequency-control storage is unreadable hasSeenCampaign() answered "unseen" when localStorage threw (private mode / storage disabled), so the modal re-opened on every Home mount even though markCampaignSeen() could never persist the dismissal. The campaign promise is one appearance per activity window — an unreadable store now counts as seen. * feat(campaign): make the paid 立即使用 CTA switch to DeepSeek V4 Flash for real 产品拍板 D5 + Demo 表格「点击立即使用模型切换为DSV4」: the paid modal CTA previously only clicked the composer chip open and highlighted it. Now it performs the actual switch — agent to Cloud (amr), model to deepseek-v4-flash — through EntryShell's onAgentChange/onAgentModelChange persistence pair (the same sink InlineModelSwitcher writes through), threaded HomeView → DeepSeekV4FlashCampaign as onUseCampaignModel. The chip keeps the data-campaign-highlight pulse as feedback but no longer opens the picker; the use_now analytics element is unchanged. * fix(campaign): carry metricsConsent + device id on the unpaid modal upgrade The unpaid modal's recordAmrEntry was the only campaign touchpoint that dropped metricsConsent — the workbench badge and the model-switcher upgrade already forward it — so the consent-gated AMR analytics mirror never fired and the plans URL missed od_device_id. Thread config.telemetry.metrics and config.installationId from EntryShell through HomeView into the modal, and stamp the URL via amrHandoffDeviceId + attributedAmrUrl(plansUrl, attribution, deviceId). * fix(campaign): make the campaign/campaignAudience/campaignUsage review params production-inert 产品拍板 D7 + 需求文档「该入口仅用于本地 Demo,不作为线上产品规则」: the review URL fixtures forced campaign surfaces for real users on released builds. Web: new isCampaignReviewAllowed() gate (NODE_ENV !== 'production', inlined at build time) now fronts isDeepSeekV4FlashCampaignReview, the campaignAudience override, the modal's shouldForceCampaignReview, and the switcher's campaignUsage read. Landing (Astro): inline scripts cannot see build-time constants, so the home banner, pricing page, and cloud-team-demo inject the verdict as data-campaign-review-allowed (__OD_LANDING_NOINDEX__: staging/PR previews true, production false) and preview activation now requires it. The [locale] wrappers re-render the same components, so they inherit the gate. * fix(landing): stamp campaign attribution only inside the activity window Pricing subscribe CTAs and the cloud-team-demo upgrade/pricing clicks minted __odRecordCampaignEntry with campaignId and stamped campaign_id on analytics props unconditionally, so clicks outside the fixed Aug 6-13 window were counted toward the campaign. Both surfaces now pass the campaign id and the campaign_id prop only while campaignActive is true; od_entry_* attribution itself is still recorded outside the window, just without the campaign stamp. Inbound first-touch od_campaign_id preservation in posthog-analytics.ts is untouched. * test(campaign): use undefined-safe access for window.open mock calls Strict TS (tsc -b) flags open.mock.calls[0][0] as possibly undefined in the modal spec added for the unpaid-upgrade consent behavior; go through String(...[0]?.[0]) instead. No behavioral change. * chore(campaign): drop demo-only artifacts before shipping Remove the cloud-team-demo static review page (fake team cards and prices, noindex but publicly reachable — review-only material that must not ship), its locale wrapper and test, and five unreferenced campaign poster PNGs left over from demo iterations. The team-modal campaign surfaces the page previewed live in the real Cloud plan-selection component (powerformer/vela#1379). * fix(campaign): make review URLs a pure UI projection with zero config writes Product boundary ruling: the client-side campaign change is a badge next to DeepSeek V4 Flash (auto-hides after the window) plus the modal CTA reusing the existing model-selection callbacks — selection behavior must not change. The demo's review fixtures violated that: an effect force- switched the persisted agent to AMR under ?campaignAudience=, and the model write-back effect persisted the review projection into the user's config. Both writes are removed; review URLs now project AMR + DeepSeek purely in the UI and leave persisted state untouched. This also roots out the CI heap OOM in InlineModelSwitcher.compact-model-click.test.tsx (run 31076791463): the stateful test wrapper re-rendered on every persisted write, looping the unconditional write-back forever. With review write-back gone the file completes in ~10s. The review-URL test now asserts the projection and that onAgentChange/onAgentModelChange are never called. * refactor(campaign): remove DeepSeek V4 Flash URL review backdoors Product decision: the ?campaign= / ?campaignAudience= / ?campaignUsage= review parameter mechanisms are deleted entirely. Campaign visibility is now decided only by the real activity window plus the real subscription audience, and pre-launch acceptance switches to a temporary startAt constant override instead of URL fixtures. web: - campaigns/deepseek-v4-flash.ts: drop review param constants, review gate, review detection, and the audience URL override; visibility and audience resolution take only `now` (plus plan/loggedIn); restricted presentation kept as a reserved branch for the backend usage-limit signal (no trigger wired yet) - DeepSeekV4FlashCampaign.tsx: drop the forced review open and the synthetic openedAt+7d countdown; the countdown always runs against the real endAtExclusive boundary - InlineModelSwitcher.tsx: drop campaignUsage URL read, audience override, review agent/model fixtures and the currentAgent/model review projection (incl. data-campaign-review); 已暂停 and 升级可用 badge branches stay as reserved presentation flags with no trigger - EntryShell.tsx / use-deepseek-v4-flash-campaign.ts: no more location.search plumbing; home-hero.css review-width rule removed landing-page: - index.astro / pricing/index.astro: preview branch removed (review params, review-allowed attribute, synthetic preview countdown); campaignActive follows the fixed window only - _lib/deepseek-v4-flash-campaign.ts: reviewParam field removed tests: review-only specs deleted; convertible specs rewritten as pure time-window assertions (clock pinned inside/outside the real window); new negative specs pin that no campaign surface reads URL parameters. * fix(campaign): device id on badge handoff + impressions on window-open transition Two review findings from PerishCode, both verified real: - EntryShell workbench-badge handoff called attributedAmrUrl without the device id, so opted-in clicks omitted od_device_id (confirmed in live browser acceptance: the modal URL carried it, the badge URL did not). Now derives it via amrHandoffDeviceId like the other two touchpoints; the source-contract assertion pins the three-arg call. - The pricing page emitted campaign impressions only during initial script execution, so a tab opened before startAt showed the surfaces at launch without any surface_view. Impressions now share the reveal loop's cadence with a one-time flag, covering both load-time and mid-session window-open transitions. * temp!: open the campaign window early for pre-launch acceptance — REVERT BEFORE MERGE startAt 2026-08-06T20:00 → 00:00 (+08:00) in both front-end constants so reviewers can see the real campaign state (true countdown, no review backdoors) on local runs and the PR preview today. endAtExclusive is untouched. This commit MUST be reverted before this PR enters the merge queue — merging it would launch the landing surfaces ahead of 20:00. * test(campaign): derive the start-instant countdown from the window constants Pins the assertion to endAtExclusive - startAt instead of a literal '7天 00:00:00', so the temporary pre-launch start-time override (and any future window change) cannot silently break the suite. * Revert "temp!: open the campaign window early for pre-launch acceptance — REVERT BEFORE MERGE" This reverts commit |
||
|
|
1aad2f5ef6 |
fix(release): treat an empty windows smoke mode as core (#6524)
* test(e2e): pin that an empty windows smoke mode means core Two independent holes let an empty value read as a different profile: The workflow-level one — a workflow_call `default:` applies only when an input is OMITTED, so forwarding '' defeats the declared `core` default. The spec-level one — `??` falls back only on null/undefined, so an empty environment variable survives it and `smokeProfile === 'core'` is false. Together they made release/v0.18.1's first prerelease take the `full` path, demand the updater fixture only a genuine `full` request configures, and die before the smoke started — on the branch-cut commit, before anything else had landed there. release/v0.18.0 never showed it because its branch name matched a special case that produced `skip`, so its smoke never ran at all. Red on both layers: the resolver mirrors main's `?? 'core'` verbatim. * fix(release): treat an empty windows smoke mode as core Close both layers that let an empty value read as a different profile. notify-release-feishu now names `core` as its final arm instead of ''. A workflow_call `default:` applies only when an input is omitted, so forwarding an empty string defeated the callee's declared default. win.spec.ts resolves the profile through `resolvePackagedSmokeProfile`, which treats empty, whitespace and unset alike as `core` and rejects anything it does not recognise — a typo must not select the updater path the way '' did. Either fix alone would unblock release/v0.18.1, but they guard different holes: one stops an empty value being produced, the other stops one being misread. |
||
|
|
886bcc4db0 |
feat(web): streamline onboarding model source flow (#6475)
* feat(web): streamline onboarding model source flow * test(e2e): align onboarding coverage with cloud-first entry * test(e2e): isolate cloud status in non-auth specs * test(e2e): keep restoration focused on tab state * test(e2e): close cloud-first onboarding gaps * test(e2e): align runtime checks with cloud-first gate * ci(e2e): retire automations from P0 gate --------- Co-authored-by: Amy <1184569493@qq.com> |
||
|
|
72b1db761b |
fix(e2e): let the Windows packaged smoke settle on the cloud sign-in landing (#6481)
* test(e2e): pin the Windows packaged app-shell rule (red)
Extract the Windows packaged smoke's app-shell DOM probe and the rule that
reads it into a pure module, and cover both from a platform that can actually
run them. The probe reaches the packaged renderer as a plain string through
`tools-pack inspect --expr`, and `specs/win.spec.ts` only executes on a Windows
runner with a packaged build installed, so today neither is checked anywhere.
Behavior is unchanged: the rule still accepts only `homeVisible === true`, the
same test main's inline `ensureMainAppShell` applies. The two new cases that
describe a first run resting on the cloud sign-in landing therefore fail, which
is the bug — a packaged first run nobody signs in to can never reach home
unattended, so the wait can only time out.
× settles on the cloud sign-in landing when the profile only needs a rendered surface
× still requires home when the profile has to drive the entry rail
AssertionError: expected null to be 'onboarding-landing' // Object.is equality
- Expected: "onboarding-landing"
+ Received: null
Test Files 1 failed (1)
Tests 2 failed | 10 passed (12)
* fix(e2e): accept the packaged Windows onboarding landing as a settled shell
A packaged first run that nobody signs in to comes to rest on the cloud
sign-in landing, and `connectStepRuntimeReady` in EntryShell.tsx will not
advance without a signed-in cloud account, an installed local CLI, or a
verified BYOK key — none of which a release runner has. The core Windows smoke
only screenshots from this point, so the landing is a legitimate terminal
state there; demanding home made the wait time out on a healthy app.
The landing is recognised positively, from the same three affordances the [P0]
onboarding smoke asserts (sign-in CTA plus both runtime links), so a blank
window, a crashed renderer, a boot still on the loader, or an onboarding shell
that mounted and then died all still fail — with a named cause rather than an
opaque timeout.
The full profile goes on to click `entry-nav-updater`, which
`clickUpdaterRailExpression` refuses while onboarding is up, so it keeps
demanding home and now fails here with that stated reason instead of later
with a bare `onboarding-visible`.
Test Files 1 passed (1)
Tests 12 passed (12)
* test(e2e): pin the seeded-onboarding postcondition (red)
PerishCode's review on #6481: the core run seeds onboarding as completed and
then accepts onboarding anyway, so a broken completed-onboarding boot path
passes silently.
Name the decision — `packagedAppShellPolicy` — and cover it. The
implementation still keys off the smoke profile, exactly as the previous commit
left it, so the cases that say a run whose daemon confirms completion must
still require home fail.
× requires home once the daemon confirms onboarding is completed
× keeps a seeded run failing when the app ignores completed onboarding
AssertionError: expected { acceptOnboardingLanding: true } to deeply equal { acceptOnboardingLanding: false }
Test Files 1 failed (1)
Tests 2 failed | 16 passed (18)
* fix(e2e): derive the accepted app shell from the daemon's onboarding config
Setup and expectation now come from one fact instead of two. The smoke reads
`GET /api/app-config` — which serves `readAppConfig(RUNTIME_DATA_DIR)`, the
running daemon's own resolved data root — and the accepted terminal state
follows from it:
- daemon confirms onboarding is completed -> home is the only outcome, so a
renderer that ignores a completed-onboarding config still fails the core
release lane;
- daemon reports a genuine first run -> the cloud sign-in landing is the
correct place to stop, and is accepted only when it actually rendered its
sign-in CTA and both runtime links.
The seed's postcondition is also asserted directly, right after the seeded
`tools-pack win start` where it must hold: that launch rewrites the packaged
config's `namespaceBaseRoot` to the tools-pack runtime root
(tools/pack/src/win/lifecycle.ts) and the runtime derives
`join(namespaceBaseRoot, namespace, 'data')` from it
(apps/packaged/src/paths.ts), which is byte-identical to the path
`seedPackagedOnboardingComplete` writes. A daemon that does not see the seed
there is a real data-root regression and now says so, instead of surfacing
later as an unexplained onboarding screen.
The app-shell read is deliberately taken again rather than reused: the core
profile stops the app and relaunches it through the OS protocol handler, and
that cold start inherits none of this process's environment.
Test Files 1 passed (1)
Tests 18 passed (18)
* test(e2e): pin the daemon onboarding-config probe (red)
PerishCode's second review on #6481: the probe converts an HTTP failure into
`onboardingCompleted: false`, which is the exact branch that permits the
onboarding landing. `status` is returned and never read, and the caller's guard
only rejects a malformed shape — so a 500, a 404, or a daemon that is not
serving yet resolves to "genuine first run" and the core smoke passes without
ever establishing the fact its shell policy depends on.
Move the probe text and its reading into the pure module verbatim, then drive
the shipped text against a fake fetch. Behavior is unchanged, so every failure
mode reads as a valid `false`.
× refuses to answer when the daemon returns a server error
× refuses to answer when the route is missing
× refuses to answer when the daemon is not reachable at all
× refuses to answer when the response carries no config
× names the status so a failure says what could not be established
× never lets a failed probe become permission to accept the landing
AssertionError: expected function to throw an error, but it didn't
Test Files 1 failed (1)
Tests 6 failed | 21 passed (27)
* fix(e2e): fail closed when the daemon onboarding config cannot be read
The probe now reports failure structurally instead of flattening it into a
reading: a transport error, a non-2xx, or a body without `config` each come
back as `{ ok: false, status, error }`, and `packagedOnboardingCompletedFromProbe`
raises `PackagedOnboardingConfigError` for all of them. `status` is load-bearing
— only a 200 that actually carried a config object may produce a reading.
There is deliberately no default and no retry. `waitForHealthyDesktop` has
already proven the same renderer gets 200 from `/api/health`, so a failure here
is a real fault; and the only fallback value available is `false`, which is
exactly the branch that permits the onboarding landing. An unestablished fact
must be an error, never a permission.
Test Files 1 passed (1)
Tests 27 passed (27)
* test(e2e): pin malformed-but-successful onboarding config payloads (red)
PerishCode's third review on #6481, same defect class as rounds 1 and 2:
coercion manufacturing a value that hides the absence of one.
`config.onboardingCompleted === true` turns anything into a valid boolean, so a
200 carrying `{ config: {} }` or `{ config: { onboardingCompleted: "false" } }`
returns `{ ok: true, onboardingCompleted: false, status: 200 }`. The reader's
`typeof ... !== 'boolean'` check then passes, because `=== true` already
synthesized the boolean it was meant to require — the round-3 guarantee that a
reading must "be present" was vacuous as written.
× refuses to answer when a 200 carries no onboardingCompleted field
× refuses to answer when onboardingCompleted is the wrong type
× refuses to answer when config is an array rather than an object
AssertionError: expected { ok: true, …(2) } to match object { ok: false }
Test Files 1 failed (1)
Tests 3 failed | 27 passed (30)
* fix(e2e): require the onboarding reading's type instead of coercing it
The probe now returns `{ ok: false, error, status }` when a 200 carries no
boolean `onboardingCompleted`, so a missing key, a null, or the string "false"
can no longer arrive as a real `false` reading — which was the one value that
permits the onboarding landing. `Array.isArray` also rejects an array `config`,
which `typeof === 'object'` let through.
This makes the round-3 guarantee real rather than vacuous: the reader's
`typeof ... !== 'boolean'` check now runs against a value the probe declined to
synthesize.
Swept the rest of the diff for the same defect class and tightened the two
remaining truthiness reads on the policy path, so the closed direction is
structural rather than dependent on a caller staying honest:
- `packagedAppShellPolicy` requires an explicit `false` before granting
permission; anything else requires home.
- `packagedAppShellSettled` requires `acceptOnboardingLanding === true`.
Everything else on the path already failed closed: the app-shell probe's
`instanceof` flags must all be positively true to settle, `asPackagedAppShellSnapshot`
type-checks every field before use and returns null otherwise, and the reader's
`status`/`ok` guards can only reject.
Test Files 1 passed (1)
Tests 32 passed (32)
* test(e2e): pin that a lost seed is not a genuine first run (red)
PerishCode's fifth review on #6481 — the same family, now at the level of the
scenario rather than a single expression.
The run seeds `onboardingCompleted: true` and asserts the seeded daemon reads
it back. The core profile then stops the app and relaunches it through the OS
protocol handler, which inherits none of the test process's environment. If
that cold launch resolves a different data root the seeded config is gone, the
fresh reading is `false`, and the policy calls it a genuine first run: the
landing is accepted and the smoke passes while blind to the regression it
exists to catch. Recording both readings diagnoses it; it does not fail.
Give the policy the seeded observation and leave the implementation ignoring
it, so the two cases that describe a lost seed fail.
× never downgrades a lost seed to a genuine first run
× keeps a lost seed failing at the shell check
AssertionError: expected { acceptOnboardingLanding: true } to deeply equal { acceptOnboardingLanding: false }
Test Files 1 failed (1)
Tests 2 failed | 32 passed (34)
* fix(e2e): make the seeded onboarding state authoritative across the relaunch
Chose the seed-authoritative shape over making the core scenario unseeded: an
unseeded core run would discard the completed-onboarding boot path, which is
exactly what the first review in this chain said not to lose, and every release
workflow defaults `win_x64_smoke_mode` to `core`, so that path would stop being
exercised anywhere routine.
Once this run has seeded completion and observed the daemon confirm it, a later
`false` is a regression, never new information about the user:
- `assertSeededOnboardingRetained` raises `PackagedOnboardingSeedError` naming
the cold launch and the data root to check;
- `packagedAppShellPolicy` additionally refuses permission for any run whose
seeded observation is not an explicit `false`, so the loss cannot buy the
landing even if the assertion were bypassed.
The spec asserts the seeded observation exists rather than coercing `'skipped'`,
which would have read as "never seeded" and handed the permissive branch the one
input it must not get.
This may surface a real packaged-runtime bug on the next Windows release run:
the protocol cold launch inherits none of the test process's environment, so if
it resolves a different data root the seed is genuinely gone. Failing there is
the correct outcome, not a reason to loosen the check.
Test Files 1 passed (1)
Tests 36 passed (36)
* test(e2e): pin both packaged launch scenarios as transitions (red)
PerishCode's sixth review on #6481: the run seeds unconditionally, requires the
first reading to be true, and round 5 requires that seed to survive — so
`seededObserved` is always true at the only policy call site. The policy can
only return `acceptOnboardingLanding: false`, and the unseeded unit cases
exercise a state the release smoke can never enter. This head produces a better
error and still fails, still needing `win_x64_smoke_mode: skip`.
Extract the settle loop and the phase around it so the smoke's own transition —
read the daemon fact, hold the seeded state across it, derive the policy, settle
— can be driven with only the I/O faked, then cover both scenarios the packaged
app legitimately has. `runPackagedAppShellPhase` still hardcodes the seeded
assumption, mirroring the unconditional seed, so a genuine first run fails with
the wrong error entirely:
× settles a genuine first run on the cloud sign-in landing
× fails a first run whose renderer never painted either surface
PackagedOnboardingSeedError: the relaunched daemon lost the seeded
onboarding state — check that the protocol cold launch still resolves the
tools-pack runtime data root
Test Files 1 failed (1)
Tests 2 failed | 39 passed (41)
* feat(e2e): cover both packaged launch scenarios in the core Windows smoke
Adds the explicitly unseeded first-run phase the smoke never had, so the
landing-accepting path is exercised by a scenario the release lane can actually
enter rather than only by unit fixtures.
Both behaviours are real product behaviour, not a contradiction:
`shouldRouteToFirstRunOnboarding` (apps/web/src/App.tsx) keys purely on
`onboardingCompleted`, and `connectStepRuntimeReady` (EntryShell.tsx) lets
onboarding complete through cloud sign-in *or* a local CLI *or* a verified BYOK
key. So a user who finished setup and is merely signed out belongs on home,
while a run that never completed onboarding belongs on the cloud sign-in
landing.
Chose separately asserted phases over a second `test(...)`: it reuses the single
install rather than adding a second install/uninstall cycle to the release
critical path, and it keeps the two scenarios adjacent so the contrast is
legible. Phase 1 resets the daemon data root and the Electron user-data
partition, asserts the daemon reports `onboardingCompleted: false`, and requires
the landing; it then clears both again so phase 2's seed lands clean. Phase 1 is
core-only because the full profile needs its controlled updater environment from
first launch.
The settle loop and the phase around it moved into the pure module, so the
transition — read the daemon fact, hold the seeded state across it, derive the
policy, settle — is now driven by tests with only the I/O faked, for both
scenarios and their failure modes.
Test Files 1 passed (1)
Tests 41 passed (41)
* test(e2e): pin the real fresh-install app-config response (red)
PerishCode's seventh review on #6481: round 4 made a missing
`onboardingCompleted` fail closed, round 6 added a scenario that produces
exactly that, and they collide.
`resetPackagedRuntimeDataRoot()` deletes `app-config.json`; `readAppConfig`
returns `{}` on ENOENT (app-config.ts:769) and adds only telemetry defaults, so
a fresh install's `/api/app-config` OMITS the key rather than reporting `false`.
The probe classifies that as malformed, the reader throws, and the first-run
phase never reaches the landing it was added to assert. win.spec.ts already
documented the daemon behaviour and the probe treated it as corruption anyway.
Move interpretation off the reader and onto the scenario (the reader now returns
the raw probe outcome), then add a fixture whose body matches the daemon's
actual fresh reply — `config` with telemetry defaults and no
`onboardingCompleted`. Interpretation is still round 4's, so absent stays
collapsed into malformed:
× settles a first run whose daemon never wrote the key
× still fails a completed user whose key went missing
PackagedOnboardingConfigError: packaged windows daemon onboarding config
could not be established: daemon config carried no boolean
onboardingCompleted (got undefined) (status=200)
Test Files 1 failed (1)
Tests 2 failed | 43 passed (45)
* fix(e2e): separate an absent onboarding key from a corrupt one
Chose representing absence as its own outcome over having the first-run phase
write an explicit `onboardingCompleted: false`. Writing one would make the
phase assert against a state a real fresh install never has — the same
"exercises a state the release smoke can never enter" flaw the previous review
just corrected — and would leave the probe unable to tell a fresh install from
a corrupt config anyway.
The probe now returns a discriminated outcome, and interpretation moved off the
reader and onto the declared scenario:
| outcome | first-run | completed-user |
|-------------------|-----------|----------------|
| transport-failure | reject | reject |
| http-error | reject | reject |
| no-config | reject | reject |
| absent | ACCEPT | reject (seed) |
| malformed | reject | reject |
| reading | accept | accept if true |
`absent` is the only asymmetric row, and deliberately so: a key that was never
written is the honest state of a fresh install, while in a seeded run its
disappearance means the seed vanished — which now raises
`PackagedOnboardingSeedError` naming the cold launch rather than a generic
config fault.
The table lives in the module docblock. Seven review rounds each found a defect
of one family — a fault and an absence sharing a representation — so this is
written down as the fix for the family, not for the instance.
Test Files 1 passed (1)
Tests 45 passed (45)
|
||
|
|
52f06da79f |
test: port PR 6229 acceptance coverage to main (#6272)
* test: cover updater floor and manual edit history * test: close daemon and E2E acceptance gaps * test: make daemon restart lifecycle budget explicit Replace replay timing sleep with persisted checkpoint polling and allow the multi-process lifecycle test enough time for startup and cleanup. Generated-By: looper 0.11.3 (runner=fixer, agent=codex) * test: restore onboarding analytics stability assertion Generated-By: looper 0.11.3 (runner=fixer, agent=codex) * test: assert manual edit history preserves preview frame Generated-By: looper 0.11.3 (runner=fixer, agent=codex) * test: make manual edit shortcuts and selection assertions portable Use the platform shortcut modifier for browser copy/paste and target the distinct inserted image before deletion so the structural tests verify the correct node.\n\nGenerated-By: looper 0.11.3 (runner=fixer, agent=codex) * test(e2e): drop superseded manual edit acceptance cases Generated-By: looper 0.11.7 (runner=fixer, agent=codex) * test(e2e): drop duplicate updater floor coverage * test(e2e): assert service-error recovery actions Generated-By: looper 0.11.8 (runner=fixer, agent=codex) * test(daemon): await third-boot reconciliation Generated-By: looper 0.11.8 (runner=fixer, agent=codex) |
||
|
|
5a2e56101e |
test(e2e): restore workspace-aware P0 coverage (#6445)
* test(e2e): restore workspace-aware P0 coverage * test(e2e): await collaboration unload and event readiness Generated-By: looper 0.11.7 (runner=fixer, agent=codex) * test(e2e): slim multi-client collaboration P0 * ci(e2e): split workspace editor P0 * test(e2e): avoid ambiguous upload assertion |
||
|
+13 |
356c8c364f |
feat(workspace-team): team workspaces, shared resources, workspace-scoped billing, and the #5517 redesign (#6142)
* fix(web): scope plugin URL imports to workspace * test(web): cover billing interest remount lifecycle * feat(packaged): enable the workspace-team transport for test-profile builds The vela test backend now serves the workspace-team API, so a packaged build baked with the test AMR profile should drive team projects / collab / resource sharing there instead of leaving them dormant. Replace the single feature-test equality check with a profile -> vela web origin map so adding a backend is one entry, and keep every unlisted profile (prod above all) off. * test(daemon): cover billing catch-up after SSE reconnect * fix(collab): surface and start first materialization when opening a shared project QA P0: a brand-new member on a fresh install joins someone's workspace, opens a project from it, and sees no loading state and no files — content only appears on a SECOND open, much later. Two defects, both on the first `/collab/status` request that opening a shared project makes. 1. No pull is started. The daemon's self-materialization block was gated on `callerIsOwner`, so a non-owner member got the placeholder record registered and nothing else. The web's auto-pull is gated on `publishedVersion` advancing past its cursor, and a fresh daemon's first status response cannot carry a published head: `collab.publishedVersion()` reads an in-process map that has never been written, and the real hub head is fetched fire-and-forget into `headEnrichmentCache` for a LATER poll to consume. Materialization therefore arrived only whenever a proactive lane (hub push / reconnect catch-up / the 30s recovery floor) next fired — the "second open" the report describes. 2. No download state is shown. `useProjectCollab.downloadPending` — which picks DesignFilesPanel's "Syncing files from the team…" over its empty state and create-a-file CTAs — reads only `publishedVersion > cursor`, `contentTransferState`, and an in-flight pull. All three are blank on that first response, so the member was shown an empty project inviting them to start creating over content that was still on its way. The fix makes the placeholder stamp the load-bearing signal on both sides: - `materializePlaceholderOnOpen` (routes/collab-sync.ts) replaces the owner-only block: any viewer opening a shared project whose only local record is an unmaterialized placeholder starts its pull on that same request, through the same coalesced flow. The retracted-share heal in its catch stays owner-only — a member who hits the hub tombstone has merely lost access and must not unshare anyone's project. - `/collab/status` reports `awaitingFirstMaterialization`, a purely local, synchronous fact that needs no hub round-trip and is therefore available on the very first response. `od collab status` prints it too. - `localFilesAreNotTheContentYet` (useProjectCollab.ts) makes it always download-pending, bypassing the member-only `shouldAutoPull` gate: whether the local files are the content is a fact about the record, not about who may pull it, so the owner of an unmaterialized placeholder (the reinstall case, recvqzaDvUU6B3) stops seeing the same empty state too. Red evidence: all six new specs fail on origin/feat/workspace-team @ |
||
|
|
ebcba704ef |
feat(prompts): introduce on-demand discovery in SP v2.0 (#6223)
* feat(prompts): introduce on-demand discovery in SP v2.0 * fix(prompts): prevent nested deck label overlap * fix(plugins): stabilize od-default task routing * fix: address prompt and deck audit regressions * fix(prompts): restore plan mode precedence * fix(daemon): accept all form answer headers --------- Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> |
||
|
|
b323a28111 |
test: strengthen E2E coverage and fixtures (#6150)
* test: strengthen e2e coverage and fixtures * test: allow artifact route when starting conversation * test: keep e2e count assertions stable Use the shared stable-count helper for no-request and duplicate-event windows so delayed async events cannot escape the assertions. Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix: add e2e assertion import extension Use the explicit runtime extension required by the e2e NodeNext typecheck.\n\nGenerated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix: preserve design system provenance and settle e2e assertions Keep disabled design systems available to project recovery and provenance while filtering only runtime injection. Make hover and cancellation checks observe their full settled windows. Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * test(e2e): preserve unique restoration run IDs Pass the restoration fixture's run ID prefix through routeSuccessfulRuns so each mocked request receives a distinct run identity. Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * test(e2e): stabilize agent and async count fixtures Route restoration agent requests through the shared JSON and SSE fixture, capture autosave baselines after a quiet period, and observe onboarding cancellation for a bounded stable window.\n\nGenerated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix: honor disabled design systems in daemon runs Filter disabled persisted project selections at prompt and analytics boundaries, and keep restoration run fixtures unique.\n\nGenerated-By: looper 0.11.2 (runner=fixer, agent=codex) * test(e2e): shorten cancellation duplicate check Generated-By: looper 0.11.2 (runner=fixer, agent=codex) |
||
|
|
809d45f27c |
feat(integrations): add the local Open Design Cloud flow for Codex (#6055)
* feat(daemon): expose Vela login through CLI and MCP * feat(mcp): add interactive local brief card * feat(packaged): bootstrap local MCP headlessly * feat(daemon): secure local BYOK credential profiles * feat(cli): manage secure BYOK profiles * feat(web): store BYOK keys in secure profiles * fix(runs): deduplicate cloud generation requests * feat(daemon): add end-to-end plugin observability * fix(pack): include native PTY runtime in desktop packages Lazy-load node-pty in the daemon so missing native binaries only disable Terminal and interactive Keychain operations instead of crashing startup. Ship and validate target prebuilds in macOS and Windows packages. Repair the macOS spawn helper before signing, and invalidate stale Windows packaging caches. Cover the packaged PTY path in macOS and Windows smoke tests. Require Vela CLI for every beta desktop build target. * fix(mcp): localize and stabilize plugin briefs Keep collect and confirm on one MCP Apps card, report intrinsic size changes, and remove the fragile widget-state fallback. Localize brief forms, summaries, status, and public errors from the current request or Host locale while preserving stable protocol ids and selections. Keep internal runtime identifiers out of user-facing MCP guidance. * fix(packaged): register live Studio URLs with daemon Register the packaged web sidecar loopback origin over namespace-scoped daemon IPC after dynamic binding. Invalidate install-info by the live web port and remove the second MCP URL cache so run and project responses use the current Studio address. Validate loopback origins and cover registration, rebind, and cache refresh. * fix(mcp): stabilize brief confirmation lifecycle Keep confirmed briefs locked after Host publication failures and retry only the cached follow-up message instead of confirming twice. Replace blank initialization with a compact loading state, accept immediate and delayed tool results, and bump the MCP Apps resource to v3 so Codex does not reuse the stale card. Add an executable JSDOM Host bridge harness covering double-submit, publication retry, delayed results, and repeated draft notifications. Validated with the full daemon suite, workspace typecheck, and guard. * fix(mcp): prevent brief app resize feedback loops Replace the self-observed intrinsic-height loop with deduplicated body measurements so Codex MCP app iframes do not repeatedly resize themselves and fail sandbox startup. Bump the brief resource URI to v4 to avoid cached v3 cards and cover the regression with the focused brief-app spec. Validated with daemon tests/build, workspace guard/typecheck, a verified beta DMG, and a direct packaged MCP resource smoke. * fix(mcp): use the final Open Design plugin identity Make open-design the only accepted external plugin ID across MCP tools, run attribution, artifact version origins, and telemetry. Rename the Brief MCP App resource to v5 and reject the unpublished old ID instead of aliasing it. Validated with 171 daemon tests, 5 web tests, daemon/web typechecks, and guard. * chore(pack): bump Vela CLI to 0.0.27 * chore(nix): refresh pnpm dependency hashes * fix(mcp): honor host and plugin request contracts Respect independently advertised MCP Apps capabilities and prefer the Codex-native follow-up bridge so confirmed briefs render as readable user turns instead of context-only messages. Bump the brief resource to v6 to invalidate stale cards.\n\nMark Vela login and account probes as open-world interactions, and require stable request IDs for attributed generation so lost responses cannot create a second logical run. * fix(cli): support keyless BYOK profiles Add an explicit --no-api-key save mode for local and self-hosted providers while keeping credential-bearing profiles stdin-only. Reject missing or conflicting credential modes and cover both paths in the CLI tests. * fix(pack): replace headless owner when desktop opens Advertise headless packaged runtimes as having no visible window, then shut them down before a normal desktop launch continues instead of treating SHOW as a successful focus. Validated with the focused packaged headless and launcher lifecycle tests (20 passed). * fix(pack): clean up failed headless startup Acquire the headless identity, sidecars, and IPC server through one failure-atomic lifecycle so later bootstrap errors close every previously acquired owner in reverse order. Cover MCP-install and web-identity publication failures; validated with 22 focused tests and the packaged typecheck. * fix(byok): remove raw provider request contract Expose only daemon-owned BYOK profile references from shared run types and the web transport, while retaining the daemon's fail-closed rejection for legacy or untyped raw credential payloads. Validated with 76 web provider tests plus web and contracts typechecks. * fix(daemon): preserve interrupted run idempotency Hydrate queued or running durable requests as DAEMON_RESTARTED failures before idempotency reuse, preserving the original request and workflow mappings instead of creating a second cloud operation. Share the restart transition with boot reconciliation and expose synthetic terminal events to reattaching clients. Validated with 48 focused tests and the daemon typecheck. * fix(byok): roll back failed credential metadata writes Snapshot secure-store values before mutation and compensate create, update, and delete operations when profile metadata cannot be persisted, preventing orphaned or lost credentials. Validated with nine focused credential-service tests and the daemon typecheck. * fix(web): reconcile selected BYOK profile metadata Treat the daemon's selected secure profile as authoritative for protocol, endpoint, model, and API version so CLI profile edits cannot leave the browser showing stale execution settings. Validated with 66 config tests and the web typecheck. * fix(byok): migrate legacy credentials before cleanup Import each supported legacy browser credential into a stable daemon-owned secure profile before removing plaintext copies. Keep the original browser record on secure-store or unsupported-provider failures and surface a Settings recovery path. Cover successful migration, duplicate projections, and injected secure-backend failure while preserving existing Bedrock downgrade behavior in memory. * fix(byok): secure Windows profiles with DPAPI Dispatch native Windows BYOK profiles to a CurrentUser DPAPI backend rooted under the resolved daemon data directory. Secrets enter PowerShell only through stdin, encrypted blobs stay separate from non-secret profile metadata, and API responses remain secret-free. Add platform dispatch coverage, a Windows-only real DPAPI round-trip test, and the packaged Windows smoke path for create, resolve, response-redaction, and delete behavior. * fix(web): preserve config writes during hydration * fix(byok): persist secure credentials across entry flows * test(byok): cover secure onboarding persistence --------- Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
00041bc43c | fix(e2e): bound tools-dev runtime lifecycle (#6204) | ||
|
|
b6b23b77df |
test(e2e): parallelize restoration group (#6169)
* test(e2e): parallelize restoration group * test(e2e): identify conversations from persisted prompts Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * test(e2e): wait for conversation persistence --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
3f670090d7 |
ci: narrow daemon core merge validation (#6126)
* ci: narrow daemon core merge validation * ci: preserve runtime definition shadow |
||
|
|
a2ba3ee2ad |
feat(updater): manual cache clear, installer-reinstall floor, and crash-recovery lifecycle (#6032)
* feat(updater): manual cache clear + installer-reinstall floor on the installed outer version
Two disaster-recovery capabilities for the packaged updater:
- Reuse control.launcher.version.min properly: the gate now compares the
physically installed outer package version (read at check time from the
outer bundle's open-design-config.json via the launcher launch path;
OD_UPDATE_INSTALLED_VERSION overrides for tests), not the running payload
version. When the floor trips - or min is set but the outer version is
unreadable (conservative) - the updater selects the installer artifact and
offers a same-version installer reinstall when no newer release exists
(clamped to min <= candidate so the offer always converges). The status
snapshot carries a reinstall block {reason, installedVersion, minVersion,
url}; UpdateDialog/UpdaterPopup render reinstall copy with an optional
operator jump link. tools-release publish-metadata publishes the block from
RELEASE_LAUNCHER_VERSION_MIN(_URL) (per-channel repo vars with a _STABLE
fallback wired in all release workflows) and hard-fails when min exceeds
the release version; verify-metadata re-checks the published block and
summary-metadata surfaces the floor.
- Manual clear-cache action (od:update:clear-cache IPC, sidecar clear-cache
action, Settings > About row with a two-stage inline confirm): resets
one-shot update state (downloaded release, install freeze) back to idle,
purges releases/staging/downloads/.back, removes a stale launcher
attempt.json plus any non-confirmed desktop-handoff journal, and deletes
non-retained payload versions. Runtime active/lastSuccessful versions,
retained cleanup entries, install.json, and a confirmed handoff journal
are never touched; locked files defer through the existing cleanup.json
retry machinery.
Also: tools-pack --update-action now validates through sidecar-proto's
exported isDesktopUpdateAction so clear-cache reaches the ops surface;
tools-serve updater fixture gains control min/url knobs and CLI flags;
9 new i18n keys across all 19 locales; tools/pack/AGENTS.md documents the
gate semantics and clear-cache boundaries.
Validated locally per the updater matrix (desktop/web/tools-serve/tools-pack
suites, guard, typechecks) plus a mac release-beta closed loop: platform full
spec, same-version reinstall against a real outer/payload version split,
clear-cache recovery, and a real-feed payload update to 0.15.1-beta.4.
* test(updater): close Windows recovery acceptance
* test(updater): mirror Windows same-version reinstall recovery on the mac lane
Port the Windows runSameVersionUpdaterRecoveryAcceptance shape into the mac
full profile: after the payload cold-start acceptance, restart the packaged
app against a fixture publishing an installed-outer floor at the running
payload version and assert the same-version installer reinstall snapshot
(reason/installedVersion/minVersion/url), the popup reinstall learn-more
link, clear-cache back to idle with launcher pointers untouched, explicit
re-check recovery, and the installer open in dry-run mode — macOS has no
silent DMG install to execute, unlike the Windows NSIS transaction lane.
Extends the popup eval expression/validator with reinstallLinkVisible and
records an updaterRecovery block in the smoke summary. Full-profile test
timeout raised 240s -> 360s for the extra app restart.
Validated locally: release-smoke full profile green in 80s with the recovery
summary populated (reinstall block exact, cleared idle, recovered dmg,
dryRun install).
* refactor(release): centralize launcher version floor channel policy in one resolver
Channel policy for control.launcher.version.{min,url} is now managed as one
repo-vars pair per channel (RELEASE_LAUNCHER_VERSION_MIN[_URL]_<CHANNEL>).
Workflows pass the channel pair plus the STABLE pair through verbatim — the
|| fallback expressions are gone from YAML — and the shared resolver in
tools/release/src/storage/launcher-version-floor.ts owns resolution and
validation: pair-level stable fallback for non-stable channels (never mixing
one channel's min with another's url), version format, http(s) url, orphan
url rejection, and the floor <= releaseVersion guard. publish-metadata and
verify-metadata consume the same resolver, so verify re-derives the expected
block from the same channel policy instead of trusting a pre-resolved env.
release-workflows.test.ts pins the verbatim passthrough keys in all five
release lanes and rejects any reintroduced YAML fallback.
* feat(updater): let clear-cache rebuild a provably-owned corrupt update store
A corrupt store is one of the blocking scenarios the manual clear exists to
recover from, yet the action previously bailed on the very store errors it
should heal. clear-cache now rebuilds the update root when — and only when —
ownership is provable: the current-generation sentinel is the proof, and
everything else inside an owned root is updater cache by definition. Roots
without a sentinel, with a foreign-generation marker, or failing IO are never
touched; the original store error surfaces unchanged. Four specs pin the
boundary (corrupt metadata rebuilt, stray entries rebuilt, unowned root
refused with files intact, foreign-generation marker refused).
* fix(launcher): pre-arm delegated payload launches so pre-bookkeeping crashes roll back
A payload that spawned successfully but died before reaching its own launcher
bookkeeping left no attempt.json behind, so every later cold start re-selected
the same broken active pointer and re-delegated to the dead payload — a
permanent dead loop the installer fallback could never surface (found while
designing the crash-rollback acceptance).
The delegating parent now arms attempt.json BEFORE spawning the payload and
passes the pointer as --od-launcher-delegated-* argv. Selection gains an
active-delegated reason: an attempt matching active AND the delegated pointer
is the launch in progress, not a previous failure; only an exact active match
qualifies, so a stale pointer cannot defeat the rollback. Rollback
(last-successful) delegations deliberately carry no marker and never re-arm —
the attempt on disk IS the rollback evidence the child must re-derive.
Covered end to end: packaged outer delegation pre-arms (and skips pre-arm on
rollback), the updater's payload activation pre-arms and threads the pointer
through the deferred relaunch, and confirm clears the attempt for delegated
launches. launcher-proto 18, packaged 237, desktop 264 all green.
* fix(updater): scrub a stale payload install freeze after a rollback
A payload install freezes the updater with installResult.activeVersion
awaiting the relaunch. When that payload crashed and the launcher rolled
back, the app restarts on the OLD version with the freeze still persisted —
every later check became a frozen no-op, so a rolled-back install never saw
another update offer (the crash-rollback acceptance exposed this in its
self-heal phase). Cold-start restore now detects the broken promise —
installResult.activeVersion newer than the running version on a live process
— and drops the freeze and stale install result while keeping the verified
downloaded release actionable. The installer-artifact freeze (no
activeVersion) keeps its existing restore semantics. Red spec:
'clears a stale payload install freeze when the promised relaunch never
became the running version'.
* test(updater): full-lifecycle acceptance — silent startup, crash rollback, coverage map
Two new packaged acceptance tests on both platform lanes (mac validated
locally; win symmetric for the Windows box):
- 'applies a downloaded payload silently on the next cold start': enables the
daemon-owned allowSilentUpdates through the production GET+PUT
/api/app-config path, restarts, and asserts the first scheduler tick
installs, quits, and relaunches with converged pointers — no updater action
issued.
- 'rolls back a crashing payload and self-heals on the next good update':
repacks the real payload archive with a crash-before-bookkeeping stub
(mac: shebang script via ditto; win: a real executable — System32 where.exe
— via the installed app's bundled 7z, since a script cannot stand in for an
exe), drives the update through the popup, asserts the pre-armed attempt
survives the crash as rollback evidence, cold-starts into the rolled-back
base version (degraded steady state pinned: broken pointer stays active
with its attempt), then self-heals via a version-bumped healthy payload —
real recovery releases ship as version+1.
Spec hygiene: resetPackagedRuntimeState wipes launcher/runtime/daemon state
before each lifecycle test (uninstall keeps runtime data by design, and
leftover pointers silently delegate fresh installs onto stale payloads);
mac waitForHealthyDesktopVersion gains win's requireSettledLauncher opt-out
for rollback waits.
docs/testing/updater-lifecycle.md is the new lifecycle-to-test coverage map
(incl. deliberate manual-only nodes), linked from tools/pack/AGENTS.md and
the e2e coverage status doc.
* fix(updater): harden Windows full-lifecycle acceptance
* test(release): make channel-prepare hermetic against local git tags
prepare-preview derives its latest-stable floor from the clone's real
open-design-v* tags, so the channel-prepare tests were green on tagless CI
checkouts but permanently red on any developer clone once shipped stable
tags advanced past main's package version (0.15.1 vs v0.15.1/v0.16.0 today).
The spawned scripts now run with GIT_DIR pointing at a throwaway repo
holding exactly the tags each test declares, and a new negative case pins
the floor rejection itself (packaged version below a v99.0.0 stable tag).
* test(e2e): model delegated payload launch
Pass the updater's pre-armed payload pointer into the cross-runtime launcher simulation so it represents the spawned payload process instead of a later crash-recovery launch.
Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
* test(web): wait for question form readiness
Wait for the asynchronously derived submit-disabled state before asserting it, removing the suite-order race observed by the Web workspace tests check.
Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
* fix(updater): preserve recovery state across locks and restarts
Generated-By: looper 0.11.0 (runner=fixer, agent=codex)
---------
Co-authored-by: Looper <looper@noreply.github.com>
|
||
|
|
3162da5f23 |
test: cover runtime automation gaps (#5976)
* test: cover runtime automation gaps * fix: remove duplicate runtime startup declarations Generated-By: looper 0.11.0 (runner=fixer, agent=codex) |
||
|
|
2d1f25ac60 |
feat(web): add message center (#5920)
* feat(web): add message center demo * fix(web): align message center actions * fix(web): remove message read toggles * fix(web): show unread count on message filter * feat(web): connect message center to vela (#5777) * feat(web): connect message center to vela * fix(web): harden message center read syncing Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(web): preserve cached message center reads Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(web): repair message center read sync and visual selector Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(web): refresh message center write auth and bound pagination Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(web): preserve message center state across locale and logout Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(message-center): stabilize login and anonymous delivery (#5910) * journal: stop repeated amr login polling * fix(web): drop anonymous message-center window gate Align with Vela audience+TTL visibility by stopping startedAt local windows so anonymous clients can pull all non-expired global messages. * refactor(web): promote message center from demo * fix(daemon): guard vela message center proxy stream Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix(cli): add message center command Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * test(e2e): harden visual workspace file readiness Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix(web): separate message center sync empty states Generated-By: looper 0.11.0 (runner=fixer, agent=codex) --------- Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> |
||
|
|
d8b6b797fe |
Simplify chat execution disclosures (#5667)
* Simplify chat execution disclosures * test: cover collapsed file disclosures * refactor(web): consolidate chat task activity * fix(web): show small file outputs inline * fix(web): separate file outputs from reads * fix(web): collapse completed todo cards * refactor(web): compact completed todo lists * fix(web): make completed todos expandable * fix(web): keep four output files visible * refactor(web): clarify chat activity timeline * fix(web): make file output disclosure interactive * feat(web): emphasize chat run states * style(web): simplify chat run status colors * style(web): remove chat run status icons * feat(web): stream one chat activity at a time * style(web): align chat completion row * fix(web): simplify priority chat states * feat(web): simplify secondary chat details * style(web): simplify secondary chat hierarchy * fix(web): keep execution state out of artifacts * fix(web): use icons for artifact operations * style(web): frame todo disclosure header * fix(web): clarify artifact and tool semantics * fix(web): clarify chat disclosure hierarchy * fix(web): keep execution history neutral * fix(web): simplify user action cards * fix(web): align failure card actions * fix(web): refine chat action hierarchy * fix(web): address chat disclosure review feedback * fix(web): restore chat recovery actions * fix(web): make collapsed action details inert --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> |
||
|
|
20c6c0a6ed |
ci(e2e): shard the full UI functional pool into a merge-ready matrix (#5883)
* ci: benchmark deduplicated UI merge sentinel * ci: benchmark restoration-hosted sentinel * ci: benchmark distributed P0 sentinel * ci: benchmark split P0 sentinel * ci: serialize split sentinel benchmark * ci: finalize deduplicated UI merge topology * ci: prototype all-shades UI domain topology * ci: bound full UI runtime by shade * test(e2e): stabilize full UI suite * fix(web): unclip DS picker popover and propagate patched project metadata Two regressions surfaced by re-enabling the full UI pool: - The New Project design-system popover lost its portal and was clipped by short viewports and the modal body. Render it through createPortal with a viewport-aware anchor that flips upward when space below runs out. - After a working-dir pick, onProjectMetadataChange forwarded only the metadata onto a stale project copy, so ProjectView.currentProject's recency comparison let an older useProjectDetail snapshot shadow the accepted PATCH and the picker label never updated. The callback now carries the daemon's authoritative post-patch project (fresh updatedAt included), matching the design-system switch path, and ProjectView hands it straight to onProjectChange. * test(e2e): repair remaining stale full-suite UI contracts Second repair batch for the failures surfaced by full diagnostic run 29480362163, plus one CI-invisible case that was serially skipped behind the BYOK failure in the same file: - Point the working-dir metadata spec at a directory that exists on the runner instead of a hardcoded absolute path, and assert the label from the picked path (this spec is red without the ProjectView patched-project fix). - Navigate back to All project files before asserting the plugin-folder cards, since a finished run auto-opens the produced file tab. - Resolve the create-run response race in real-daemon-run's sendPrompt via a single waitForResponse alongside the click. - Refresh selectors and copy for entry topbar, home hero rail, chat todo autoscroll, project management, workspace keyboard, design files, manual edit, restoration, and DS picker clipping flows to match the current UI contracts while keeping each spec's oracles. * ci: distribute the full UI suite over a generic 8-shard matrix Replace the diagnostic four-domain P0/P1/P2 serial topology with a single all-shades Playwright invocation per shard (--shard=N/8, two fully parallel workers, 20-minute cap) and drop the scheduled trigger; full runs stay manual until the merge-queue wiring lands. Update the workflow topology guard accordingly. * ci: serialize full UI shards and widen the matrix to twelve The eight-shard two-worker experiment left six light shards healthy (260-477s test steps) but both shards holding runtime-heavy files degraded: repeated two-minute timeouts with retry recovery in one, and a consistent create-run response starvation failure in the other. This matches the earlier finding that runtime-heavy scenarios cannot share a runner under two fully parallel workers. Run each shard with a single worker and rebalance to twelve shards; fully-parallel stays on only for test-granularity sharding. * fix(web): preserve prompt-extracted plugin inputs across apply reconcile The active-plugin apply reconcile rebuilt the inputs from the bind-time optimistic snapshot, so edits the user typed during the apply roundtrip (already extracted into active.inputs by handlePromptChange) were silently reverted to defaults — the submitted pluginInputs then disagreed with the visible prompt. Merge the apply result's defaults into the current inputs inside the functional updater instead, mirroring the guard the prompt-text reconcile already had. * test(e2e): stabilize home gallery flows for all-shades execution Generic all-shades sharding executes tests in orders the shade-filtered domain topology never produced, exposing a home-surface remount window: the async projects fetch can mount or remount HomeTemplatesReveal after a test starts interacting, collapsing the gallery (inert) under the test's cursor. Stabilize the shared helpers instead of individual specs: - gotoEntryHome arms a projects-list response waiter before navigating and holds until it settles. - revealHomeTemplates requires the revealed state (or a true pass-through) to survive a settle window, retrying when the wrapper mounts late; a card's isVisible() is true inside the collapsed container, so openHomePluginDetails now always routes through the reveal path. - The browse-registry spec reveals before clicking. - The DS-picker options moved out of the new-project-modal subtree with the portal fix; query the page-level popover per the clipping spec's convention. - real-daemon-run's sendPrompt reports on timeout whether POST /api/runs was ever issued, so the CI-only BYOK failure can be split into swallowed-click vs unanswered-request on the next reproduction. * test(e2e): make BYOK availability hermetic and reveal remaining gallery clicks The BYOK missing-provider spec could only pass on machines with a real `opencode` binary: daemon detection maps byok-opencode's availability through the `opencode` agent's configured cli env, and the web composer refuses to POST /api/runs for an unavailable agent (the sendPrompt diagnostic confirmed "was never issued" on CI). Point the helper's agentCliEnv at the fake opencode runtime — the run still fails pre-spawn on the missing provider config, so the fake binary never executes. Also route the two remaining collapsed-container gallery clicks (the browse-registry starter journey and the detail-use force-click) through revealHomeTemplates; an inert container swallows force-clicks silently. * ci: probe a 24-shard full UI matrix against the four-minute wall target The first green 12-shard run put eleven shards at 141-354s test steps but concentrated the contiguous runtime-heavy chain in one 894s shard, setting a ~16-minute wall tail. With ~3568 total test-seconds and ~90s per-job overhead, 24 shards should land every job near four minutes. * ci: settle the full UI matrix on twelve shards The 24-shard probe stayed green but proved the runtime-heavy chain is a serial group (test.describe.configure serial in real-daemon-run), which Playwright keeps atomic within one shard: the tail stayed ~16 minutes while the extra twelve cold starts raised aggregate runner time from ~76 to ~102 minutes. Twelve shards dominate; lowering the wall below the serial-chain floor is a de-serialization follow-up, not a shard-count knob. * test(e2e): drop serial mode from shard-splittable files Playwright keeps a serial group atomic within one shard, so real-daemon-run's file-level serial made its ~16-minute chain the floor of the full UI matrix wall regardless of shard count. Every test in the three serial files already performs its full setup per test (config reset, route stubs, own project), so serial only added skip-after-failure and shard atomicity. Verified order independence by running each file's two standalone shard halves locally (fully parallel sharding, one worker): 21/21, 57/57, and 12/12 across the halves. * test(e2e): settle the projects fetch in real-daemon-run home navigation With serial mode gone, the plugin-authoring spec runs after arbitrary shard predecessors, so the daemon holds more projects when it navigates home; the late-resolving projects list re-renders the hero and left the shortcuts trigger unstable for the whole click timeout on CI. Port the projects-settle waiter already used by entry-chrome-flows into this file's gotoEntryHome. * test(e2e): name the plugins-load gate in the plugin authoring spec The home shortcuts trigger is disabled while the plugins list loads, and this spec's mid-flow reload re-fires that fetch after gotoEntryHome's settle has already passed — on CI the click then times out opaquely for 120 seconds. Arm a response waiter across the reload and assert the trigger's enabled state explicitly, so a slow or hung /api/plugins fails with the actual cause named. * test(e2e): enter plugin authoring through the plugins page create button The home shortcuts trigger sits disabled on CI runners while a home plugin apply hangs (plugins list resolves, the pending-apply gate never clears); three reproduction attempts confirmed the anomaly is CI-only and independent of this journey. The create button on the Plugins page drives the same queuePluginAuthoring flow, and this spec's oracle is the generated scaffold plus its action cards, so route the entry there and track the disabled-trigger anomaly separately. * ci: let configure-ci-parallelism drive full UI shard workers The single-worker override predates the repairs that explained the two-worker instability (BYOK agent availability and the reveal remount race, both test-side and since fixed), so it was pinning throughput on a stale diagnosis. Drop it and let the repo's nproc/2 convention apply — two workers on the four-core ui_hot profile — halving the per-shard test step if the runtime holds. * ci: probe three full UI workers against Blacksmith's actual vCPU capacity The ui_hot profile resolves to blacksmith-4vcpu runners that reportedly provide six actual vCPUs while nproc's cgroup view says four, so the nproc/2 convention derives two workers and idles capacity. Pin three workers for this probe and print the CPU topology alongside for verification. * Revert "ci: probe three full UI workers against Blacksmith's actual vCPU capacity" This reverts commit 63c8296ae0ead2c3dadfbfda41f6e068d58331ef. * ci: skip the critical fallback for pure packaged-leaf changes Playwright starts tools-dev web (daemon + web runtimes) and never launches the desktop, packaged, or tools-pack entrypoints, so PRs confined to apps/desktop, apps/packaged, or tools/pack were paying the two-job critical fallback (5.4-13.4 minutes of wall each) for coverage their package tests and preflight already provide — seven of the eight fallback PRs in the latest 100-merge sample were such false positives. Add a fail-closed ui_critical_validation_required scope: it clears only when every non-exempt changed file sits under one of those three leaf roots. tools-dev, any transitive package (including the undeclared metatool edge), scripts, runtime resources, unknown roots, and mixed leaf + runtime changes keep the fallback armed; root manifests keep enabling P0 with the existing critical/P0 mutual exclusion; merge-group full mode is unchanged. * test(e2e): align question-form specs with inline Studio discovery Rebasing onto main picked up #5496, which moved clarification forms inline into the chat flow and removed the legacy Questions workspace tab. Re-point the submit-persistence spec at the inline form, and fix the oracles that no other lane had verified since: the answered summary echoes the picked visual-style card title (not the option label), and the submitted answer message carries the card title plus its value id. * test(e2e): absorb post-rebase drift in BYOK gating and zh-CN hero copy Two more contracts only the full pool guards moved under the rebase: - The composer's BYOK gate silently swallows submits until the incremental /api/agents stream has delivered byok-opencode's availability, so a fast submit races the stream (the sendPrompt diagnostic reports the POST was never issued). Retry through that window; runErrorCard reads the last card, so swallowed attempts cannot shadow the provider-validation oracle. The gate erroring instead of waiting while agents are still loading is a product-side follow-up. - The home hero title copy changed in every locale; re-point the zh-CN P2 smoke at the current translation. * test(e2e): align gallery specs with the all-types default slice The Community gallery now defaults to an All category pill (#5759) instead of pre-selecting Deck: assert the new default state in the hero and category-tab specs, and have the facet-filter spec pick Deck explicitly before asserting the deck-only visibility set. * test(e2e): align the first-run reveal spec with the all-types default slice Same #5759 drift family as the entry-chrome-flows gallery specs, missed by the first sweep because it lives in home-hero-rail: the revealed gallery now shows the All pill selected instead of hiding it with live-artifact pre-selected. * docs(e2e): add UI test stability rules distilled from the full-pool work Capture the invariants a UI test must hold to stay green under the generic sharded full pool, learned from stabilizing that suite and two rebases: - order independence (no serial groups; setup is per-file, not universal), and that neither shade-filtered local runs nor merge-path P0 prove it; - retry-only passes are an order-leak/readiness signal, not flake; - settle async surfaces (best-effort waiter + a state-survives-a-window check) before interacting; - an enabled control is not a ready control when a streamed precondition (e.g. BYOK-OpenCode agent availability over the /api/agents SSE stream) gates it; - never force-click into inert/collapsed reveal containers; use actionability, not visibility, as the readiness signal; - hermetic agent availability via route mocks (with the terminal SSE `done` event) or fake CLI runtimes + agentCliEnv, never host binaries; - realign stale oracles against the product and confirm them in the lane that actually executes the case, since a merged PR does not verify P1/P2 or unregistered-file P0 oracles; - name failure causes so a CI-only reproduction carries its own evidence. Cross-linked from the top-of-file coverage-status pointer. * test(e2e): realign BYOK missing-provider spec to the #5745 client-side preflight main #5745 added a client-side BYOK preflight that blocks a missing-provider run before any POST and opens the execution Settings section, instead of letting the run reach the daemon and fail there. Rewrite the spec to the new "blocked before spawn" behavior: submitting opens the execution-mode dialog, no create-run request is issued, and no artifact is produced (persisted across reload). This drops the now-obsolete daemon-failed-run assertions and the SSE-availability retry loop, which the preflight makes unnecessary. * docs(e2e): explain why the functional config ignores visual specs Clarify that visual-*.test.ts are owned by playwright.visual.config.ts and its playwright_visual lane, so excluding them from the functional config is intentional scope (it keeps a bare test:ui or the full-pool shard run from executing visual specs without their visual config), not a disabled lane. * fix(web): portal the New Project brand-preview flyout with the popover The earlier DS-picker unclip portaled the popover list but left its companion brand-preview flyout on the old inline `position: absolute` against the trigger wrapper. Once the popover moved to a body portal, the flyout for a finalized `user:<id>` brand was still clipped by the modal body and no longer anchored to the popover. Portal the flyout too and place it beside the popover with the same viewport-aware logic (right of it when the 320px card fits, else flipped left, then clamped), mirroring the popover's up/down vertical anchor. Red spec: e2e/ui/new-project-ds-picker-clipping.test.ts "finalized-brand preview flyout is not clipped by the modal body" — red with the popover portaled but the flyout inline, green with this change. |
||
|
|
3447f60a34 |
fix packaged payload desktop handoff (#5678)
* fix packaged payload desktop handoff * fix beta mac full smoke fixture wiring * fix tools-pack mac payload cold start * test payload desktop update restart * fix Nix daemon launcher protocol build * fix(pack): harden Windows long-jump updates * fix(pack): harden mac long-jump acceptance * fix(handoff): defer armed journal writes until spawn and shutdown succeed Previously executeLegacyPayloadDesktopHandoff wrote the armed handoff journal, attempt, and runtime state before spawning the payload desktop and before the old desktop accepted shutdown. When spawn() threw or the shutdown request failed, the armed journal was stranded on disk, so the next cold start bailed out of prepareLegacyPayloadDesktopHandoff() with reason "already-armed" and the install stayed pinned to the old desktop generation indefinitely. Move the three writes to after both the payload child has spawned and the shutdown has been accepted. The old desktop is still alive while it acks the shutdown, and the payload waits for the old pid to exit before resuming, so the state still lands before the payload reads it. Add regression coverage for both the spawn-failed and shutdown-failed paths, asserting the journal stays "prepared" and a later cold start can retry. Generated-By: looper 0.10.3 (runner=fixer, agent=claude-code) * fix(updater): await payload spawn acceptance * fix(packaged): advance confirmed handoff recovery --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
6b90486c97 |
docs: reconcile stale documentation with current code (#5829)
* fix(docs): align question guidance with form flow * docs: reconcile stale documentation with current code * fix(docs): remove retired template metadata from guides Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(e2e): stabilize visual workspace helper Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(docs): align localized template guide metadata Generated-By: looper 0.10.6 (runner=fixer, agent=codex) |
||
|
|
19de7953c4 |
Fix Open Design example logo loading (#5765)
* Fix Open Design example logo loading Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * Stabilize visual home cold start checks Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) |
||
|
|
cb5fd3baab |
fix(web): auto-fit wide html previews (#5751)
* fix(web): auto-fit wide html previews Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * test(e2e): allow auto-fit preview zoom Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * fix(web): gate preview auto-fit on content width Generated-By: looper 0.0.0-dev (runner=worker, agent=codex) * fix: measure preview width through iframe bridge * fix: bridge powered preview sizing |
||
|
|
265aa51630 |
feat(web): make Studio discovery visual and inline (#5496)
* feat(web): make Studio discovery visual and inline Move clarification forms into the chat flow, add artifact-aware visual style choices, and keep follow-up actions hidden until discovery is complete. * feat(web): keep clarification entirely in chat Remove the legacy Questions workspace tab, preserve discovery analytics in the inline form, and keep Skip, Submit, and answered summaries in one conversation flow. * docs: split Studio Chat input and response work Frame visual discovery as the input-side initiative and record response aggregation as a separately reviewed follow-up so the current PR stays bounded. * docs: reorganize Studio Chat experience plans Separate the overall journey, visual discovery, and response architecture so each scope can be reviewed and delivered independently. * docs: define first-artifact satisfaction prompt Limit the feedback prompt to the first successful previewable artifact so it gathers a useful signal without interrupting every iteration. * docs: keep Studio Chat plans independent Preserve the existing discovery proposal as one document and keep response architecture as a separate review surface without an extra master layer. * fix(web): preserve inline discovery behavior Keep visual direction single-select while restoring custom input, optional auto-continue, analytics, and current end-to-end coverage for the inline flow. * fix(web): preserve files when skipping discovery step * fix(web): exclude skipped file answers * fix(web): align inline discovery with slim prompt Preserve the latest discovery contract while keeping inline forms, uploads, drafts, and schema-driven visual selections consistent after the rebase. * feat(web): add style catalog preview images * fix(web): clarify discovery form completion * fix(web): preserve question form context * fix(web): time out unanswered question forms * test(web): cover inline question form next steps * fix(web): roll back partial inline uploads * ci: trigger validation after rebase * fix(web): unlock blocked inline question submits * fix(web): retain previewless visual answers * fix(web): load visual style previews from R2 * fix(web): clean blocked inline uploads * test(web): expect R2 style preview assets * feat(web): show full visual style catalog * fix(web): keep inline question answers consistent --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> |
||
|
|
24c7876b37 | fix(web): preserve delivery for in-place HTML edits (#5689) | ||
|
|
d7463072a8 |
fix(web): Plan 模式生成/重写 HTML 后自动打开生成的文件 (#5602)
* fix(web): re-focus HTML rewritten in place when a turn ends
Plan mode's core loop is plan -> generate -> edit the plan -> regenerate.
On the second generation the deliverable (index.html) already exists, so
the turn-end auto-open — a pure pre/post file-NAME diff — saw no new file
and left the viewer stuck on the markdown plan. Protocols that emit no
Write tool events (codex, gemini, opencode, ACP agents) have no per-write
fallback, so nothing opened at all.
Turn-end selection now also considers pre-existing project files whose
mtime lands inside the turn window (same attribution as AssistantMessage's
inferProducedFilesFromTurn), ranked by the existing HTML > markdown
preview priority. Turns without a start stamp keep the produced-only
behavior.
Red spec: e2e/ui/real-daemon-run.test.ts "Plan mode regeneration re-opens
the existing generated HTML file" (red on main, green here), plus a
first-generation companion spec and unit coverage for the new selector.
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* worker: Plan模式下,不会自动打开生成的HTML文件
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* fix(web): scope the turn-window auto-open to agent-touched files and bound it by turn end
Review follow-ups on the Plan-mode auto-open selector: the mtime
attribution window [turnStartedAt - 1s, +inf) could attribute a file the
USER was editing to the turn - in Plan mode plan.md autosaves from the
split editor during a run, so a text-only turn could yank focus back to
it - and the missing upper bound let post-turn edits fall in-window on
the reload/reattach recovery call sites.
selectAutoOpenTurnArtifact now accepts:
- agentTouchedFileNames: when the protocol emits Write/Edit tool events
(claude stream-json), mtime-window candidates are restricted to files
the agent actually wrote; protocols with no write events (codex,
gemini, opencode, ACP) pass an empty set and keep the pure time
window - the case the window exists for.
- turnEndedAt: bounds the window at endedAt + 60s, matching
AssistantMessage's inferProducedFilesFromTurn on both sides; callers
without an end stamp keep the open-ended window.
All three call sites resolve the agent's raw tool paths to project file
names through the existing findTouchedProjectFile matching (new
resolveAgentTouchedFileNames helper) and pass their terminal timestamp.
Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)
* chore: untrack the looper task-attachment directory
The runner's fallback lifecycle commit (
|
||
|
|
bc5b6f0588 |
fix(daemon): flag runs that end with unfinished work so status never reads "Completed" early (#5470)
A design-generation run that ended its turn with TodoWrite tasks still pending / in_progress / stopped — or was truncated by max_tokens — was stamped `succeeded` and read "Completed" on the Pet task center and the project pill, while the chat footer simultaneously read "Stopped with unfinished work". Users trusted "Completed", assumed the work was done, and re-requested, creating duplicate generations and eroding trust in the run-state UI (#1247 / #1060). Root cause: the daemon equates "the turn/process ended" with "succeeded" and never consults the agent's own declared work; multiple web surfaces then map `succeeded` -> "Completed" without any completeness signal, even though the chat footer already distinguishes unfinished work. Fix — one canonical signal, consumed everywhere so the surfaces cannot drift: - packages/contracts/api/run-completeness.ts defines the canonical "unfinished declared work" predicate (status !== 'completed', so pending / in_progress / stopped all count), matching the web footer's unfinishedTodosFromEvents exactly. - Daemon folds the last TodoWrite snapshot + a max_tokens truncation off the agent event stream (every runtime, via the single emitAgentEvent choke point) and derives run.endedWithUnfinishedWork once at finish(). - The project-status projection derives `incomplete` from the already persisted events_json — no schema migration — so it survives reload/reattach instead of flashing "Completed" once the in-memory run ages out. - Contracts carry endedWithUnfinishedWork on ChatRunStatusResponse and the SSE end payload (backward compatible: absent = finished), plus a new `incomplete` ProjectDisplayStatus. - Web surfaces (Pet task center, project pill, DesignsTab) render `incomplete` as amber needs-attention, never the success color; the footer now sources the same shared predicate. Truncation uses the display-only option (spec Option A): the run stays `succeeded` but is flagged incomplete, avoiding the code===0 / stdin-close hazards of reclassifying a truncated turn to failed. Regression coverage, red on main / green here: an HTTP-boundary e2e (e2e/tests/dialog/task-completeness.test.ts) drives the interactive chat path for unfinished / stopped / truncated / finished runs; daemon + contracts + web unit tests pin the projection and the canonical predicate. Ref: https://plane.powerformer.net/open-design/projects/49832a02-3158-4faf-bf2f-d0e39c40c7e6/issues/011f6f51-7a25-4043-ae94-182e0b8b0931 Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) |
||
|
|
bc6a246c65 |
feat(slides): enhance deck project experience (#5083)
* feat(deck): enhance slide deck functionality with speaker notes and navigation improvements - Added a switch for including speaker notes in slide decks, defaulting to true. - Updated keyboard navigation to include 'R' for resetting to the first slide. - Implemented click navigation for half-slide transitions. - Enhanced the deck framework to support hidden programmatic prev/next controls. - Improved handling of file inputs in question forms to support file submissions. This update aims to improve user experience in creating and presenting slide decks, ensuring better accessibility and functionality. * feat(artifacts): enforce semantic naming for user-facing deliverables - Updated guidelines to require semantic filenames derived from user briefs for new artifacts, moving away from defaulting to `index.html`. - Enhanced documentation to clarify naming conventions for HTML files, emphasizing the use of descriptive names like `investor-pitch-deck.html`. - Adjusted prompts and hints across the system to reflect these changes, ensuring consistency in user-facing outputs. - Improved test coverage to validate the new naming conventions and ensure proper implementation in various contexts. This update aims to enhance clarity and usability in project file management, promoting better organization and user experience. * feat(file-viewer): enhance speaker notes display and improve file workspace functionality - Updated the speaker notes section to include a styled placeholder for empty notes, improving user experience. - Changed the icon in the file workspace from "slides" to "panel-left" for better clarity. - Introduced new sub-category filtering options in the file workspace, enhancing organization and navigation. - Improved styling for the page creator search input and added visual feedback for loading states. These changes aim to enhance usability and visual consistency across the file viewer and workspace components. * test(web): align workspace tests with pages switcher * test(e2e): open design files through pages menu * fix(deck): keep source mode reachable * fix(workspace): restore uploaded file tabs * feat(deck-thumbnail): implement virtualized thumbnail rail for improved performance - Introduced a new `DeckThumbnailRail` component to optimize the rendering of deck thumbnails, reducing memory usage and improving load times. - Enhanced the `FileViewer` to integrate the new thumbnail rail, allowing for lazy loading of thumbnails based on viewport visibility. - Added tests for the `DeckThumbnailRail` to ensure correct functionality and caching behavior. - Updated styles for better visual consistency and performance during thumbnail rendering. These changes aim to enhance user experience by providing a smoother and more efficient way to navigate through deck slides. * feat(deck): enhance deck rendering with thumbnail support and keyboard shortcuts - Integrated `DeckSlideThumbnail` for rendering individual slides in a shadow root, improving performance and reducing main-thread load. - Updated `DeckThumbnailRail` to utilize the new thumbnail component, allowing for efficient slide navigation. - Implemented keyboard shortcuts for deck navigation, enhancing user experience during presentations. - Added tests for `buildDeckRenderInput` to ensure proper functionality of the deck stage fallback. - Improved styling for loading states in the viewer, providing a smoother visual experience. These changes aim to optimize the deck viewing experience by reducing resource consumption and enhancing interactivity. * feat(deck): improve thumbnail loading and speaker notes editing experience - Refactored `DeckSlideThumbnail` to enhance loading states with a new shimmer effect, improving visual feedback during thumbnail rendering. - Updated `DeckThumbnailRail` to manage loading states for thumbnails, ensuring a smoother user experience. - Simplified the speaker notes editing interface by removing the toggle switch, allowing direct editing from the notes body. - Enhanced accessibility by adding roles and focus states to speaker notes elements. - Added tests to verify the new loading states and speaker notes functionality. These changes aim to optimize the user experience in deck navigation and speaker notes management, providing a more intuitive and responsive interface. * feat(file-viewer): enhance version export functionality and speaker notes interaction - Introduced new export options for file versions, including PDF and image formats, improving the ability to download and share content. - Implemented a streamlined process for exporting version content, with progress indicators and error handling for a better user experience. - Enhanced speaker notes editing by refining event handling to prevent unintended focus shifts, ensuring a smoother editing experience. - Updated styles for improved visual consistency in the file version download interface. - Added tests to verify the functionality of version exports and speaker notes interactions. These changes aim to optimize the file viewer's usability and enhance the overall experience when managing and exporting project files. * fix(web): polish export menus and creator filters * fix(file-viewer): fall back to preview exports * test(file-viewer): cover version export fallbacks * test(file-viewer): assert loading skeleton by role * fix(file-viewer): restore html source mode affordance * fix(file-viewer): capture full version fallback snapshots * docs: trim slides handoff eof * test(exports): cover full preview snapshot requests * test(file-viewer): account for snapshot options arg * refactor(file-viewer, file-workspace): streamline export functions and enhance page creator dialog visibility * test(file-workspace): enhance slide template creation and mock plugin responses * feat(export): add support for versioned exports and enhance HTML export functionality * feat(export): implement versioned export support across multiple formats and enhance related tests * feat(file-viewer): enhance manual edit functionality with commit sequence tracking and add test for inline text session saving * style(speaker-notes): update filmstrip and thumb-frame styles for improved responsiveness and add corresponding tests * feat(file-viewer): enhance comment composer functionality with portal metrics and improve draw toolbar layout for mobile views * feat(analytics): track slide deck viewing experience Add analytics for the new deck/slides experience introduced in this PR: the deck viewer surface, in-deck slide navigation, thumbnail rail, and speaker-notes authoring. Presentation entry stays on the existing present_popover click to avoid double-counting. - contracts: DeckViewerSurfaceViewProps (surface_view), DeckViewerClickProps (ui_click), SpeakerNotesSaveResultProps (new speaker_notes_save_result event), wired into the event unions. - web: track* wrappers + fire helpers in FileViewer — deck_viewer surface_view on deck mount, slide_prev/next/reset, thumbnail_select, thumbnail_rail_toggle (expand/collapse), speaker_notes_edit, and speaker_notes_save_result (preview + presenter surfaces). - tests: deck analytics suite asserting the emitted (event, props) pairs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(file-viewer, file-workspace): enhance export toast functionality and improve localization for page creation * feat(home-view, plugins-home-section, agent-skill): update default facet preference, enhance category selection handling, and improve localization support - Set `preferDefaultFacet` to true in HomeView component for better user experience. - Introduced `handlePickCategory` function in PluginsHomeSection to manage category selection based on card layout visibility. - Updated PRIMARY_CATEGORIES to reflect the new order and added localization for titles and descriptions in adaptAgentSkill. - Enhanced tests to verify the correct handling of display copy and tags from SKILL frontmatter. * feat(plugins-home, file-workspace): introduce commercial category labels and enhance deck handling - Added a new module for resolving and localizing commercial category labels for plugins. - Updated the FileWorkspace and PluginCard components to display the commercial category label on deck cards. - Enhanced the PageCreatorPresetFrame to adjust frame classes based on deck presets. - Refactored subcategory handling in facets to align with the new commercial category taxonomy. - Improved localization support for new category labels across multiple languages. * feat(deck-preview): implement deck preview scaling and enhance home hero layout - Introduced `useDeckPreviewScale` hook to manage scaling of deck previews within a fixed 1280×720 logical viewport, ensuring proportional rendering across various templates. - Updated `FileWorkspace`, `HomeHero`, and `PluginCard` components to utilize the new scaling functionality for improved visual consistency. - Enhanced the layout of the home hero section to accommodate new subtype chips and descriptions, including a "More" dropdown for overflow handling. - Improved localization support for new UI elements across multiple languages. * fix(PreviewModal): clarify sidebar prop documentation and update test description - Updated the documentation for the `PreviewSidebar` interface to specify that the sidebar's stage-edge handles are not shown when the sidebar prop is absent. - Modified the test suite description for `PreviewModal` to be more concise and relevant. * test(e2e): select prototype visual card --------- Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9ef4f0daa6 |
[codex] Refine privacy consent choices (#5384)
* Refine privacy consent choices * Add privacy consent value copy * Polish privacy consent copy * Refine privacy banner wording * Fix privacy consent review issues * chore: retrigger privacy consent CI * Fix privacy banner dismissal in AMR onboarding tests * Fix privacy choice telemetry preservation * Preserve settings draft during privacy choice * Preserve pending settings privacy choices * Align privacy policy consent labels --------- Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com> |
||
|
|
b3356807b6 |
fix(amr): improve unavailable model gating (#5335)
* fix(amr): honor full model list metadata * fix(amr): classify tier entitlement failures * fix(amr): refine unavailable model upgrade affordance * fix(web): restore stale AMR model fallback Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(web): surface AMR tier upgrade failures Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): mirror chat upgrade attribution Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): skip disabled default models Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): honor catalog default model * chore(pack): bump vela cli to 0.0.20 * fix(amr): align locked catalog fallback state * chore(nix): refresh pnpm deps hash * fix(amr): refresh entitlement-aware model state * fix(amr): refresh models after upgrade return * fix(amr): preserve default model analytics * fix(amr): tighten model gating follow-ups Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): repair default and refresh follow-ups Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): resolve explicit default before spawn Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): concretize default model in smoke paths Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): repair default model gating Generated-By: looper 0.10.1 (runner=fixer, agent=codex) * fix(amr): share connection-test model cache Generated-By: looper 0.10.1 (runner=fixer, agent=codex) --------- Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com> |
||
|
|
39c8eea0c5 |
test: cover recent daemon and e2e follow-ups (#5354)
* test(e2e): cover recent main follow-ups * test: cover recent main automation gaps |
||
|
|
08da51b3b4 |
test: expand daemon and UI e2e coverage (#5107)
* test: expand daemon and UI e2e coverage * fix: refresh retry assistant metadata Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix: persist inherited run session mode Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix: stabilize AMR inline auth retry Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix: reconcile legacy chat assistant pins Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * test: stabilize fake AMR auth recovery Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * test: restore e2e interaction actionability Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * test: address review feedback for PR 5107 * test: stabilize PR 5107 CI interactions * test: tighten PR 5107 review coverage * fix: inherit run session mode after conversation fallback * test: assert AMR promotion retry renders recovery Generated-By: looper 0.10.1 (runner=fixer, agent=codex) --------- Co-authored-by: Amy <1184569493@qq.com> |
||
|
|
8ca68bbfe6 |
feat(web): pre-run Open Design Cloud balance gate with subscription dialog (#5103)
* feat(web): Open Design Cloud pre-run balance gate — two-tier dialogs with auto-resume Gate every AMR chat send before any run spawns. HARD tier (definitive empty wallet <= $0, or signed out) blocks with a subscription-invitation dialog: distinct copy and CTA per cause (console wallet page vs in-app sign-in), benefits card, and auto-resume — a completed sign-in or a recharge observed by a bounded wallet watch resumes the parked task on its own. SOFT tier (<= $4) shows a dismissible reminder with top-up / start-anyway / persisted don't-ask-again (never silences the hard tier). Blocked project sends park in the conversation queue with their full payload and pause auto-drain until a send passes the gate; home submits hold the create open (continuation promise) so drafts and staged context are never lost, and the home decision carries into the project's first auto-send to avoid double-prompting. Fail-open contract: unknown or unparseable wallet answers never block; hard blocks are confirmed with refresh=1 before firing. New amr_entry sources cover both surfaces and tiers; nine chat.amrBalanceGate.* / chat.amrLowBalance.* i18n key groups ship in all 19 locales. * fix(web): a stale wallet-refresh echo must not confirm a hard block A failed refresh returns the previous cached snapshot with stale=true and an error; treating it as a fresh definitive $0 (or signed-out) answer violated the gate's fail-open contract and could strand a user who just topped up while the wallet endpoint hiccuped. (Review feedback.) * chore: retrigger ci * test(e2e): align AMR UI checks with balance gate * fix(web): preserve AMR gated sends across conversation switches --------- Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com> Co-authored-by: Amy <1184569493@qq.com> Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> |
||
|
|
cd6fb44c4d |
test: expand e2e coverage for main updates (#4998)
* test: expand e2e coverage for main updates * test: remove unrelated landing contract coverage |
||
|
|
ab45324124 |
[codex] Restore Kimi ACP and retire Gemini CLI runtime (#5023)
* fix(runtime): restore kimi acp and retire gemini cli * test(e2e): drop retired gemini fake runtime from p0 sweep * fix(daemon): clear retired Gemini config Generated-By: looper 0.9.11 (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
6be4e56544 |
feat(workspace): add plan mode and Excalidraw sketch flows (#4862)
* feat(daemon): add 'plan' session mode and update related functionality - Introduced a new session mode 'plan' alongside existing 'design' and 'chat' modes, allowing for editable document creation. - Updated various functions and interfaces to accommodate the new session mode, including normalization and usage in commands. - Enhanced markdown rendering capabilities by integrating micromark and its GFM extension for improved markdown processing. - Added new input types for question forms, expanding the range of user interactions. - Updated UI components to reflect changes in session modes and ensure proper handling of next steps based on the current mode. * feat(chat): integrate SessionModeToggle into ChatComposer and HomeHero - Added SessionModeToggle component to both ChatComposer and HomeHero for improved session management. - Updated HomeHero styles to accommodate the new mode switcher layout. - Adjusted countdown timer in QuestionsPanel to extend the skip countdown from 120 seconds to 10 minutes, enhancing user experience. - Added tests to ensure the countdown functionality works as expected. * feat(FileViewer): implement synchronized scrolling for Markdown editor and preview - Added functionality to synchronize scrolling between the Markdown editor and preview panes. - Introduced new types and utility functions for managing scroll behavior. - Enhanced the MarkdownViewer component to handle scroll events and maintain scroll position across different modes. - Updated the component's state management to accommodate the new scrolling features. * feat(excalidraw): integrate Excalidraw into the project - Added @excalidraw/excalidraw as a dependency in package.json. - Updated vitest configuration to include an alias for Excalidraw. - Imported Excalidraw CSS in the layout component for styling. - Modified AssistantMessage component to handle optional projectId. - Enhanced FileOpsSummary to display delete operations. - Implemented new Excalidraw scene management in SketchEditor and FileWorkspace components. - Updated MarkdownViewer to support file mentions and improved file handling. - Refactored various components to accommodate Excalidraw integration and ensure compatibility with existing features. * feat(files): improve sketch and file handoff flows * test: align post-merge expectations * chore(nix): refresh pnpm deps hash * fix(workspace): stabilize sketch persistence and ci checks * fix(workspace): address review blockers in editable files * fix(workspace): persist cleared sketch scenes * test(workspace): type sketch editor mock scene * fix(workspace): serialize sketch autosaves * fix(workspace): keep sketch save revisions current * test(e2e): stabilize project workspace smoke flows * fix(analytics): preserve plan mode for BYOK runs * test(e2e): stabilize new project rail interactions * fix(files): stop bash delete parsing at shell operators * test(e2e): stabilize ui cold-start suites * fix(viewer): preserve absolute markdown image sources * feat(workspace): preload sketches and enhance markdown save options - Added functionality to preload persisted sketches before opening the tab. - Introduced new MarkdownSaveOptions type to manage save behavior. - Updated saveMarkdownText to handle options for refreshing files and showing saving state. - Enhanced FileViewer to maintain focus and selection during metadata refresh. - Implemented a Toast component for user feedback on save and export actions. * fix(web): stabilize markdown and sketch editor polish * fix(web): finish sketch editor merge resolution * chore(nix): refresh pnpm deps hash * fix(plan): bypass discovery and stabilize markdown sync * fix(web): simplify scene retrieval in SketchEditor component * feat(web): enhance markdown viewer with auto-save functionality - Implemented passive auto-save status in the MarkdownViewer component, replacing the manual Save button with an auto-save indicator. - Introduced new hooks and state management for tracking auto-save events and displaying the last saved time. - Added support for synchronized scrolling between the markdown editor and preview. - Created a new markdown-scroll-sync module to handle scroll synchronization logic. - Updated localization files to include new strings for auto-save messages. - Added a SketchEnginePrewarm component to optimize Excalidraw loading times. * feat(web): enhance session mode toggle with cost indicators - Added cost tiers for each session mode in the SessionModeToggle component, providing users with a visual representation of usage costs. - Introduced a new ModeCostTag component to display cost information alongside session mode labels. - Updated localization files to include new keys for cost labels and notes. - Enhanced styling for cost indicators to improve user experience and clarity. - Refactored EntryShell to open the new project modal instead of creating a blank project directly from the rail. - Implemented a utility function in markdown-scroll-sync to check for vertical progression in block offsets. * feat(web): add max height adjustment for session mode description card - Introduced maxHeight prop to the ModeDescriptionCard component to control the height of the description card based on available space. - Implemented useLayoutEffect in SessionModeToggle to dynamically calculate and set the maximum height of the description card, ensuring it does not overlap with the project tab bar. - Updated tests to verify that session modes display their expected usage/cost correctly in the UI. - Enhanced localization files to include new cost-related strings for various languages. * feat(web): implement goBack function for improved navigation and update auto-open logic - Added a new `goBack` function to handle in-app navigation, allowing users to return to the previous route instead of a hardcoded destination. - Updated the `navigate` function to maintain history state for better back navigation. - Refactored auto-open logic to prioritize produced artifacts, allowing markdown files to be opened alongside HTML files. - Updated tests to cover new navigation behavior and artifact selection logic. - Enhanced localization files to include new descriptions for workspace actions. * refactor(web): remove create design system functionality and update design files panel actions - Removed the `onCreateDesignSystem` prop and associated button from the DesignFilesPanel component. - Updated the empty state actions to include a button for creating a new document via the `onPaste` function. - Adjusted tests to reflect the removal of the design system creation action and ensure the new document button is functional. - Enhanced the MarkdownViewer component by adding a placeholder for the text area and removing the header bar for a cleaner interface. - Updated localization files to include a new placeholder string for the markdown editor. * fix(web): restore markdown placeholder translations * refactor(web): streamline MarkdownViewer and enhance localization - Removed unnecessary state management and reload functionality from the MarkdownViewer component for improved performance. - Added a placeholder text for the markdown editor in multiple localization files to enhance user guidance. - Updated styles for the save state indicator in the viewer to improve visual clarity and alignment. - Adjusted tests to reflect changes in the MarkdownViewer and ensure proper functionality. * fix(web): adjust SketchEditor button size and remove shortcut hints - Reduced the icon size in the SketchEditor component from 13 to 12 for better alignment. - Updated the removeSketchMermaidShortcutHints function to also remove the submit shortcut hints from the dialog, enhancing the user interface by decluttering unnecessary elements. - Adjusted tests to verify the absence of shortcut hints in the modal after updates. * fix(web): address plan mode follow-up polish * fix(web): align ci expectations after merge * test(e2e): stabilize project workspace helpers * test(e2e): scale settings visual timeout * fix(prompts): lock ElevenLabs voice picker choices * test(e2e): pin project workspace P0 worker * test(e2e): use rail new project entry * test(e2e): relax app restoration startup waits * fix(web): limit markdown pipe escaping to tables --------- Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com> Co-authored-by: Amy <1184569493@qq.com> |
||
|
|
ca89845d03 |
feat(brands): surface the draft design system live and browse images in a lightbox (#4777)
* feat(brand-extraction): enhance programmatic extraction with reconciliation and UI improvements - Introduced `reconcileProgrammaticExtractionTranscript` to manage the state of brand extraction transcripts, ensuring accurate status updates during extraction processes. - Updated the `cancel-extraction` route to handle asynchronous operations, allowing for better user feedback and immediate reconciliation of extraction states. - Enhanced the `startBrandExtraction` function to support draft design system creation, ensuring that users can see their systems immediately, even if extraction fails or is stopped. - Improved error handling and logging for reconciliation processes, providing clearer insights into failures during brand extraction. - Added tests to validate the new reconciliation logic and ensure that the extraction process behaves as expected under various scenarios. These changes improve the overall user experience by providing more robust handling of brand extraction states and enhancing the visibility of the extraction process. * feat(brand-extraction): enhance brand preview rendering and UI feedback - Added functionality to render brand previews into projects when a draft is stopped, improving user experience by providing immediate visual feedback. - Updated the `startBrandExtraction` function to include metadata for design system IDs and statuses, ensuring accurate tracking of brand extraction states. - Enhanced the `renderBrandPreviewIntoProject` function to support new status types, including 'draft', allowing for better representation of brand states. - Introduced new localization strings for draft-related messages, improving clarity for users during the brand extraction process. - Added tests to validate the new preview rendering and status handling, ensuring robustness in the brand extraction workflow. These changes improve the overall user experience by providing clearer feedback and enhancing the visibility of brand extraction processes. * feat(design-kit): browse design-system images in a lightbox carousel The image-preview lightbox showed a single static image with no way to move between samples. Replace the single-image state with an index into the visible, non-broken samples so the modal becomes a carousel: prev/next chevrons, an "N / total" counter, ArrowLeft/ArrowRight keys, and wrap-around. Broken tiles are filtered once through a shared lightboxItems memo so the gallery and lightbox indices stay aligned with the delete handler. * feat(brands): reveal the draft design system the moment extraction starts A brand extraction pre-creates a draft `user:` design system, but the project view only rendered it once the registry summary had refreshed, leaving the Design System tab empty for the whole extraction. Build a fallback summary from project metadata so the draft renders immediately, auto-open the Design System tab when extraction begins or is cancelled, and hydrate the freshly created project with its brand metadata. Draft pre-create now records the source URL in provenance and fails loudly instead of swallowing the error. Because ProjectView imports DESIGN_SYSTEM_TAB at module scope, every FileWorkspace test mock must export the constant. * fix(design-system-picker): restore fullscreen preview styles dropped in routines.css reorg The brand-extraction routines.css reorganization accidentally removed the `.project-ds-picker-fullscreen` rule block, its `project-ds-picker-fullscreen-in` keyframes, and its responsive overrides. The modal-window drag guard and two style specs still depend on those rules (the fullscreen design-system preview must stay above modal chrome), so they went red. Restore the block verbatim to match main. * feat(brand-extraction): add continue extraction functionality for incomplete brands - Introduced a new API endpoint to restart the deterministic programmatic extraction for existing brands without creating duplicates. - Implemented a tracking mechanism for ongoing extractions to manage their state effectively. - Enhanced the UI components to support the new continue extraction action, including loading states and callbacks. - Updated relevant tests to ensure the new functionality works as expected and integrates smoothly with existing workflows. These changes improve the user experience by allowing users to resume brand extractions seamlessly, enhancing the overall efficiency of the brand management process. * feat(skills): integrate skill management into the application - Added a new SkillDetailsModal component to display detailed information about skills. - Enhanced the ChatComposer and HomeHero components to support skill selection and details viewing. - Updated the ComposerPlusMenu to include a skills submenu, allowing users to search and pick skills. - Implemented functionality to handle skill details in various components, improving user interaction with skills. - Refactored existing components to accommodate skill-related features, ensuring a cohesive user experience. These changes enhance the application's capabilities by providing users with better access to skill information and management, streamlining workflows involving skills. * feat(brand-extraction): improve brand assistant message handling and UI feedback - Enhanced the AssistantMessage component to better manage events and display content, ensuring that messages are rendered correctly based on their content and events. - Updated the ChatPane component to hide empty brand assistant messages and improve the visibility of relevant content, enhancing user experience during brand extraction processes. - Introduced new utility functions to determine the visibility of brand assistant events and content, streamlining the logic for displaying messages. - Refactored the ProjectView component to handle brand browser assist confirmations more effectively, ensuring that the UI responds appropriately to user interactions. - Added tests to validate the new message handling logic and ensure that brand extraction messages are displayed correctly. These changes enhance the overall user experience by providing clearer feedback and improving the management of brand assistant messages during extraction workflows. * fix(brands): address browser assist review blockers * fix(web): restore new project modal entrypoints * fix(web): switch to replacement brand retry conversations * fix(web): restore skill-change preview invalidation * fix(brand): harden retry completion flow * fix(brand): close extraction lifecycle races * test(e2e): wait for privacy banner dismissal * fix(brand): guard retry startup races * fix(brand): isolate extraction retry attempts * fix(design-systems): clean up partial draft creation * fix(brands): let stop supersede stalled transcript * fix(brands): fail thin browser html retries * fix(brands): preserve stopped html retries * fix(brands): reject off-path browser retries * fix(brands): expose deterministic retry in cli * fix(brands): serialize cancel with finalization * fix(brands): bound cancel settlement wait * fix(brands): bound retry takeover waits * refactor(next-step-actions): replace titles with localized keys and update related prompts * fix(brands): retry after browser read failures * fix(brands): accept canonical browser redirects * fix(brands): reset retry assist stall timer * test(web): align picker compact preview assertions * fix(brands): harden design kit cleanup paths * test(e2e): stabilize AMR runtime recovery checks * feat(brands): enhance brand extraction from post-wall pages - Introduced `browserHarvestIsUnusable` function to determine if a harvested page lacks usable brand signals, allowing for more permissive extraction from content-rich pages that may embed anti-bot widgets. - Updated `extractBrandFromHtml` to utilize the new function, ensuring that valid post-wall pages are processed correctly. - Enhanced `isChallengePage` to differentiate between genuine content-rich pages and bot protection interstitials, improving the accuracy of brand extraction. - Added tests to validate the new behavior, ensuring that pages with minimal color palettes or embedded widgets are handled appropriately. * feat(brands): improve handling of recoverable extraction states - Refactored brand extraction logic to maintain a `needs_input` status for recoverable scenarios, such as blocked pages or mid-load content, instead of marking them as `failed`. - Updated related functions and routes to reflect this change, ensuring that the user interface presents a calm, retryable state rather than a terminal failure. - Enhanced tests to validate the new behavior, confirming that the system correctly identifies and manages recoverable extraction attempts. * feat(projects): add design-system project creation from existing projects - Implemented a new command `od project create-design-system` to duplicate a regular project as a design-system workspace, including a prompt for design-system generation. - Enhanced the API to support the creation of design-system projects, ensuring proper metadata and file copying from the source project. - Added a detailed prompt structure for the design-system generation process, outlining requirements and expected outputs. - Introduced tests to validate the new functionality, ensuring that design-system projects are created correctly with the appropriate context and files. - Updated the UI components to integrate the new design-system creation functionality, allowing users to initiate the process seamlessly. * feat(projects): add project duplication workflow * fix(brand): keep browser assist recovery retryable * fix(plugins): roll back failed template duplicates * feat(brand): enhance browser assist functionality and improve user guidance - Introduced a new `brandBrowserAssistOdCard` function to generate browser assist cards for better user interaction. - Updated the content structure in `reconcileProgrammaticExtractionTranscript` to include browser assist cards when applicable. - Enhanced user guidance in error messages for stalled and stopped extraction processes, providing clearer instructions for recovery actions. - Added tests to ensure the new browser assist card functionality is correctly integrated and displayed in the chat interface. - Improved localization for various user prompts and messages related to browser assist actions. * feat(design-browser): enhance design file handling and user notifications - Added support for opening design files directly from the status message in the DesignBrowserPanel. - Introduced a new `actionTarget` property to differentiate between design files and regular files in status messages. - Implemented a `stopLoading` function to halt page loading when necessary, improving user experience during snapshot captures. - Updated localization files to include new status messages and project type labels. - Enhanced toast notifications for browser snapshots with improved styling and functionality. - Added tests to ensure new features work as expected and do not interfere with existing functionality. * feat(app): implement design system project creation with preset prompts - Updated project creation logic to route through the default design router, ensuring user interaction prompts for design system selection. - Introduced a new localization key for the design system creation prompt, enhancing user guidance. - Adjusted plugin ID to avoid assumptions about prototypes, improving the flexibility of project creation. - Updated tests to reflect changes in project creation behavior and ensure correct routing and prompt handling. * feat(chat): update icon sizes and implement draft persistence in HomeView - Increased icon sizes in ChatComposer from 13px to 16px for better visibility. - Added localStorage persistence for the Home composer prompt and design system selection to retain user input across tab switches. - Implemented functions to read and write drafts to localStorage, ensuring a seamless user experience. - Cleared drafts upon run creation to prevent reappearance of previous inputs. - Enhanced Toast component to handle auto-dismissal correctly, even with changing parent components. * fix(pr): address review blockers * fix(web): preserve authoring prompt confirmation * test(daemon): cover project CLI copy commands * fix(web): surface skill detail load failures |
||
|
|
3652fb7237 |
[codex] restore AMR wallet balance follow-ups (#4771)
* feat: show AMR wallet balance * fix: preserve AMR wallet reauth state * chore: retrigger PR validation * fix: bound AMR wallet balance fetch * chore: retrigger wallet validation * chore: bump bundled Vela CLI to 0.0.18 * chore: retrigger Vela CLI validation * chore(nix): refresh pnpm deps hash * feat(web): reposition AMR as Open Design's cloud subscription (#4684) * feat(web): reposition AMR as Open Design's cloud subscription Fold the standalone "AMR" product into Open Design's own cloud service: unify all user-facing copy, surface the signed-in account's plan + wallet balance, and add upgrade CTAs. - Copy: user-facing "AMR" / "Open Design AMR" -> "Open Design" across 19 locales, agent labels, and daemon error strings (balance/recharge wording preserved). - Account: daemon reads plan + balance via `vela billing summary` (CLI route, control-key) and injects them into the vela status; web shows plan + balance on the settings card, the model-switcher account row, and the runtime-switcher avatar row (balance field aligned with the console wallet's headline balanceUsd). - Upgrade: filled "Upgrade" CTA next to the plan on all three surfaces when the tier is below max; opens the console wallet at ?view=plans. - Runtime-switcher Open Design row restructured to carry account info inline, with a selected-state highlight. - Analytics: new amr_entry elements settings_amr_upgrade / inline_amr_upgrade / avatar_amr_upgrade / avatar_amr_agent_card. - specs/: design doc for the Open Design account/avatar direction. * fix(daemon): surface live account for env-backed auth + isolate cache per credential Address @nettee review on #4684: - applyVelaLiveAccount() now populates plan/balance even when the login status has user:null (VELA_RUNTIME_KEY / VELA_LINK_URL env auth), so env-backed Open Design sessions no longer drop the fetched billing data. - Key the live-account cache by the full credential revision (auth source + profile + userId + config mtime), not just profile, and clear it on logout — a logout / account switch can no longer surface the previous account's plan or wallet balance before the background refresh runs. - Regression tests for both in tests/integrations/vela.test.ts. Sync tests to the AMR -> Open Design copy: - web: tests/providers/sse.test.ts error-string assertions. - e2e: onboarding / logout / run-failure / login-pill specs + visual fixture. * fix(i18n): drop duplicated "Open Design" in switchBody fallback copy The AMR -> Open Design rename sweep collided with the existing brand mention in chat.amrCard.switchBody, rendering "Open Design official Open Design model service" across 13 locales (zh-TW, ja, ko, ar, es-ES, hu, id, fa, pl, tr, ru, pt-BR, uk). Remove the redundant second mention so the retry/switch card reads cleanly. Flagged by @nettee on #4684. Also start aligning InlineModelSwitcher unit tests to the new copy (agent display name AMR -> Open Design, compact error string). * fix(amr): resolve live billing before first /status; hide Upgrade until plan known Address @nettee review on #4684 (two correctness issues in the new plan/balance path): - Cold cache: the signed-in /status handler now BLOCKS the first response on fetchVelaBillingSummary() when the cache is empty, instead of returning config-only and refreshing in the background. The new account surfaces read /status once and never re-poll, so the old flow left plan/balance hidden until the user refocused. Warm cache keeps the non-blocking fast path. fake-vela gains a `billing summary` handler and vela.routes.test.ts covers the cold-cache-first-open case. - Upgrade CTA: canUpgradeVelaPlan() now treats an unknown/empty plan as NOT upgradeable, so a signed-in session whose live summary hasn't resolved no longer flashes Upgrade at top-tier users. Unit-tested. * style(amr): bold the plan/balance text in the switcher + avatar account rows The settings card already renders both bold (the plan value reuses .agent-card-amr-balance-value); align the inline switcher account row and the runtime-switcher avatar row so plan + balance read with the same emphasis everywhere. * fix(amr): single-flight cold billing fetch + surface plan/balance on its own field Address @nettee follow-up review on #4684: - Race: the cold-cache decision keyed off the refresh throttle, so a second /status arriving during the first billing fetch saw refreshAccount=false, fell through, and returned config-only — which the read-once surfaces can't recover from. Now `peekVelaLiveAccount(key) === null` is the cold signal and the billing fetch is single-flighted per credential revision: concurrent cold callers await the same in-flight promise. setVelaLiveAccount stamps the fetch time so the warm path doesn't immediately re-refresh. - Identity: applyVelaLiveAccount no longer fabricates a `{ id: '', email: '' }` user for env-backed sessions. The live billing projection now rides on a new VelaLoginStatus.account field, so `user` stays null (preserving the analytics `user.id` null signal) and plan/balance are surfaced uniformly. SettingsDialog / InlineModelSwitcher / AvatarMenu read status.account.{plan,balanceUsd}. Regression coverage updated in vela.test.ts (applyVelaLiveAccount) and vela.routes.test.ts (cold-cache first open now asserts body.account). * style(amr): match the switcher plan text color to the balance The inline switcher account row showed the balance in --text-strong but the plan in --text-muted, so "$247.51 Plus" read with two different weights of grey. Use --text-strong for the plan too so balance + plan sit at the same emphasis. * fix(amr): treat tier-less billing summary as free; register new entry sources Address @nettee review on #4684: - Free vs unknown: fetchVelaBillingSummary() returned plan:undefined when `membershipTier` was absent, but that field is omitted for free accounts. The new surfaces read status.account.plan for both display and canUpgradeVelaPlan, so a successful free-account read rendered as "unknown" — plan hidden and the Upgrade CTA suppressed for the exact users who should see it. A successful summary without a tier now normalizes to the explicit 'free' sentinel; "unknown" stays signalled by a null account (failed fetch). Regression in vela.routes.test.ts (balance, no tier → account.plan === 'free'). - Analytics: the four entry sources this PR adds (settings_amr_upgrade, inline_amr_upgrade, avatar_amr_upgrade, avatar_amr_agent_card) were in the source→page map but not in the AMR_ENTRY_SOURCES validator set, so parseAmrEntryAnalyticsPayload rejected them and /analytics-entry 400ed for the new buttons. Added them to the set; parser regression covers all four. * fix(amr): invalidate the env-backed live-account cache on config/account change Address @nettee 11:19 review (the inline comment did not post, but the flagged env-backed live-account cache path has a real leak): readVelaCredentialRevision forced configMtimeMs to null for env-backed auth, so the live-account cache key became `env|profile|1||` with nothing to distinguish accounts. Because the live billing summary is fetched with the config profile's controlKey, a config rewrite (account switch) left an env-backed (VELA_RUNTIME_KEY) session serving the previous account's plan/balance. Keep configMtimeMs for env auth too so a config/account change yields a fresh key. Regression added in vela.test.ts. * fix(amr): fingerprint the configured AMR env in the live-account cache key Address @nettee 11:35 review on #4684: configMtimeMs alone wasn't enough. The AMR env credentials (VELA_RUNTIME_KEY / VELA_LINK_URL) can come from agentCliEnv.amr in app-config, and env-backed sessions report user:null — so switching the Settings-backed credential from account A to B on the same profile, without touching ~/.amr/config.json, left the revision at `env|profile|1||<same-mtime>` and let B reuse A's cached plan/balance. readVelaCredentialRevision now adds a non-secret credentialFingerprint (sha256 of the runtime key + link url, truncated) and velaLiveAccountCacheKey includes it. Regressions: a unit test (env key differs by fingerprint) and a route test that rewrites agentCliEnv.amr's VELA_RUNTIME_KEY without touching the config and asserts the second account does not inherit the first's cached billing. * feat(amr): label + stack balance/plan in the switcher account row; fix its tests UI: the inline switcher Open Design account row rendered "$247.51 Plus" with no labels, so users couldn't tell what the two values were. Balance and plan now stack on two labelled lines ("可用余额 / Available balance" and "当前套餐 / Current plan"), with the Upgrade CTA on the plan line. The settings.amrBalance / settings.amrPlan labels are made descriptive across all 19 locales (the settings card reuses them), so the meaning is explicit everywhere. Tests: rewrite InlineModelSwitcher.test.tsx for the account-row structure — the agent radio now carries status only in its aria-label (icon-only visible), and the sign-in / signing-in / cancel affordances live on the inline-model-switcher-account-action button. Redundant within(amrButton) getByText assertions are dropped (the radio-name query already asserts status); pending/error assertions target the account row. 22/22 green. * test(amr): align AmrLoginPill tests to the Open Design copy Account-status group is labelled 'Open Design account status', the console link is 'Console', and the compact sign-in error reads 'Sign-in failed.' — update the queries to match. 29/29 green. * feat(amr): redesign the account row — tier badge + balance subtitle; short labels Iterated on the Open Design account row in both the inline model switcher and the runtime-switcher (avatar) list so the plan/balance no longer collide: - Plan tier renders as a small neutral pill right after the "Open Design" name (identity + tier read as one group, à la Claude's "name · Max"). - Balance moves to a second line below the name, labelled "余额 $247.51" (small grey label + bold value) so users know what the number is. - Upgrade stays as the trailing action, vertically centred against the two lines. Account logo bumped to 24px to balance the taller row. - Revert the amrBalance / amrPlan labels back to the short "余额 / 套餐" ("Balance" / "Plan") across all 19 locales. * test(amr): align remaining web specs to the Open Design copy + account row Update the rest of the web component specs that still asserted the pre-rename wording / old account-row shape (the `Web workspace tests` red CI @nettee flagged): - EntryShell.onboarding: "Sign in to Open Design Cloud" -> "Sign in to Open Design"; "AMR sign-in failed." -> "Sign-in failed.". - SettingsDialog.execution: AMR card queried as /^Open Design\b/ (was /^Open Design AMR\b/). - HandoffButton: agent label "Open Design"; website link "打开 Open Design 官网". - AvatarMenu: drop the two obsolete avatar console-shortcut specs (the avatar console link was removed when the row was consolidated; the upgrade entry remains covered by the daemon parser + contract). Full web suite green: 3403 passed. * test(amr): cover the avatar-row upgrade CTA (plan/balance + stamped link) Replaces the two removed avatar console-shortcut specs with focused coverage for the new runtime-switcher upgrade path (@nettee): mocks a signed-in /api/integrations/vela/status, opens the menu on the non-prod `test` profile, asserts the rendered plan badge + balance, and verifies the clicked upgrade link carries view=plans and od_entry_source=avatar_amr_upgrade attribution. * test(e2e): update avatar visual spec to the redesigned account row The Playwright visual (settings-workspace) job was red on a functional assertion, not a pixel diff: the spec queried the removed `.avatar-amr-account-link` console entry and 'AMR account' / 'Balance & recharge' copy. Rewrite it to override the signed-out status with a signed-in plan/balance, then assert the Open Design row renders the Plus badge + $247.51 and the upgrade link points at ?view=plans. * chore: re-trigger CI on updated main — needs-validation gate moved to merge_group (#4714) * test: capture Open Design account balance visuals * chore: retrigger workspace validation --------- Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com> Co-authored-by: lefarcen <935902669@qq.com> Co-authored-by: a1chzt <chizblank@gmail.com> * [codex] keep AMR wallet balance stable during refresh (#4730) * fix: keep AMR wallet balance visible during refresh * fix: remove AMR wallet refresh hover tooltip * chore: retrigger validation * fix(ci): align AMR wallet branch validation * feat(web): Open Design 云账户入口 UI 优化(名牌/置顶/新 logo) (#4787) * feat(web): polish Open Design cloud account surfaces (plan badge, pin-to-top, new logo) - 模型切换器(InlineModelSwitcher): Open Design 账号卡片上位为可点选入口并置顶, 移除重复的代理行 - 头像菜单(AvatarMenu): Open Design 置顶代码代理列表; 执行模式选中态改为勾选标记(不再与代理选中态争色块) - 统一套餐名牌: 新增共享 PlanBadge 组件(全局 CSS, 跟随主题色), 替换设置页/切换器/头像菜单三处各自实现 - 设置页 CLI 卡片: 删除无用的钱包刷新按钮与"更新于…缓存"行; 余额统一为两位小数 - 全局替换 AMR logo 资产(amr.svg) * test(web): align AgentIcon AMR assertion with new logo fill --------- Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com> * fix(web): preserve AMR wallet balance in switcher * fix(amr): avoid stale wallet status on refresh failures * fix(web): align avatar AMR balance row * fix(web): avoid stale AMR wallet snapshots * fix(web): keep avatar AMR console link * fix(amr): support wallet fallback for older vela cli --------- Co-authored-by: michaeltaxman911-hue <michaeltaxman911@gmail.com> Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com> Co-authored-by: lefarcen <935902669@qq.com> |
||
|
|
b55376554b |
test(e2e): expand onboarding, AMR, automation, and home coverage (#4759)
* test(e2e): cover onboarding and automation flows * test(e2e): stabilize AMR project runtime P0 group * test(e2e): cover updated home creation surface * test(e2e): align onboarding coverage with build step Generated-By: looper 0.9.11 (runner=fixer, agent=codex) |
||
|
|
aad9771a6f |
fix(e2e): reduce noisy visual regression diffs (#4744)
* fix(e2e): reduce noisy visual regression diffs * fix(e2e): keep visual captures full viewport * test(e2e): add entry popover visual targets * test(e2e): tighten model dropdown visual targets * Revert "test(e2e): tighten model dropdown visual targets" This reverts commit 52172f05591e1a5c2bed7b6fc12d05d364d5b27d. * fix(e2e): relax visual report diff ratio threshold * fix(e2e): render visual report comparisons horizontally * fix(e2e): tighten accepted visual diff ratio * fix(e2e): surface missing visual baselines as new cases * fix(e2e): render new visual baselines in a grid * fix(e2e): compact visual report case layout * fix(e2e): keep large visual diffs surfaced Generated-By: looper 0.9.11 (runner=fixer, agent=codex) * fix(e2e): seed privacy consent in project-runtime tests * fix(e2e): harden project-runtime settings mocks * fix(e2e): stabilize project-runtime follow-ups --------- Co-authored-by: mrcfps <mrc@powerformer.com> |
||
|
|
488e3d6a6d |
[codex] Refine rich design-system chip previews (#4806)
* fix(web): refine design system chip preview * fix(e2e): extend home catalog visual capture budget Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(web): restore home ask mode toggle Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(e2e): dismiss consent before settings menu click Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(web): remove Hyundai preset brand --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
a5e2f1bcff | test(e2e): add target-level visual baselines (#4765) | ||
|
|
0bf1b6d6b8 |
[codex] converge release workflows and stable dry-runs (#4390)
* fix(tools-pack): use junctions for Windows standalone peer deps * fix(desktop): expose IPC during startup * fix(tools-pack): preserve Windows inspect diagnostics * fix(tools-pack): report Windows inspect status errors * fix(packaged): use Electron net fetch for app protocol * fix(packaged): load Windows renderer from web sidecar * fix(desktop): show Windows packaged window during startup * fix(packaged): disable Windows GPU startup * fix(tools-pack): keep Windows core smoke observable * fix(packaged): remove Windows startup probes * fix(tools-pack): trace Windows desktop IPC status * fix(tools-pack): add Windows IPC diagnose loop * fix(release): default beta-s Windows updater feed * chore: clean merged test eof * refactor(release): unify prerelease channel model * chore(release): close prerelease doc escape hatches * refactor(release): converge release channel workflows * fix(release): install toolchain in metadata jobs * fix(release): build release package before contracts * chore(release): bump development version to 0.10.1 * fix(e2e): seed windows packaged smoke runtime config * fix(release): install toolchain for metadata publish * fix(release): materialize betas metadata checkout * chore(release): bump development version to 0.10.2 * fix(release): allow betas metadata cold start from s3 * fix(e2e): support betas packaged update scenarios * fix(release): pass betas channel into packaged smoke * fix(release): set betas channel during self-hosted builds * fix(release): verify counted channel reservations * fix(release): use pnpm cmd for betas windows publish * fix(release): add betas manifest artifact fallback * fix(release): skip beta-s public metadata fetch * fix(release): read beta-s manifests from storage * fix(release): cache beta windows tools-pack builds * fix(release): inline beta mac tools-pack builds * fix(pack): deep sign unsigned mac bundles * docs(pack): document payload-first beta updater validation * fix(release): align preview tools-pack cache flow * fix(release): align prerelease tools-pack cache flow * fix(release): pass github token to prerelease metadata * fix(release): setup pnpm before feishu notify * fix(release): add stable dry-run prepublish flow * fix(release): accept completed prerelease metadata gate * fix(release): require stable release branches * fix(release): converge r2 access checks * fix(updater): use release channel parser for defaults * fix(updater): harden windows payload relaunch * fix(release): converge updater smoke fixture contract * test(e2e): require silent updater fixture output * fix(release): align stable windows smoke build path * fix(ci): include release workspace in validation * fix(ci): repair release validation lanes Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(ci): restore zero-install Feishu notification Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
86824a30d8 |
feat(web): unify task-failure error card across all failure states (#4656)
* feat(web): unify task-failure error card across all failure states
Collapse the three divergent failure UIs (gray .msg.error card, red
.status-pill.is-error pill, accent .amr-card) into one neutral run-error
card with a consistent four-part structure: ① error-type title, ② detail
copy, ③ 1–2 fix CTAs anchored bottom-right, ④ collapsible error-source
(code-line styled, one line collapsed, expand/copy on the source row).
- amr-guidance: add titleKey mapping (code → title i18n); split "sign-in
required" into AMR (inline AmrLoginPill, single CTA, no promotion) vs
non-AMR ({agent} copy, retry + use-official-agent) per the PRD.
- ChatPane: rebuild the error card JSX into the unified shell, preserving
every recovery handler (authorize/recharge/resume/retry/BYOK); interpolate
{agent} via t(key, {agent}) + agentDisplayName.
- AmrLoginPill: drop the redundant device-code chip (the activation URL
already carries the code); reword the activation hint.
- i18n: add run-error title/source/sign-in keys across all 19 locales.
- tests: update amr-guidance + AmrLoginPill specs for the new behavior.
* test(e2e): align run error assertions with unified card
---------
Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
Co-authored-by: Mason <jinmeihong0201@gmail.com>
|
||
|
|
d19c53d274 |
Agent-driven brand extraction + two-loop memory overhaul (#4260)
* Implement brand management routes and CLI support - Added `brand-routes.ts` to handle HTTP endpoints for brand operations: listing, extracting, retrieving details, deleting, and serving logos. - Introduced `brands-cli-help.ts` for CLI commands related to brand management, including usage instructions for listing, creating, retrieving, and deleting brands. - Updated `cli.ts` to integrate brand commands into the existing CLI structure, allowing headless management of brands via the command line. - Created supporting files for brand metadata handling, including `design-md.ts` for rendering brand information in markdown format and `index.ts` for the brand engine API. - Implemented `prefetch.ts` to fetch and process brand material from specified URLs, ensuring a streamlined extraction process. - Enhanced server setup in `server.ts` to register brand routes and manage brand-related data effectively. This commit establishes a comprehensive framework for managing brands within the application, facilitating both HTTP and CLI interactions. * Enhance memory management and onboarding experience - Introduced canonical profile labels to ensure consistent handling of user input in profile forms, preventing duplicate entries. - Updated the `parseProfileBody` and `captureProfileFromForm` functions to utilize the new canonical label matching. - Added a memory callout section in the onboarding view to highlight the benefits of memory usage, including personalized responses and reduced setup questions. - Implemented new UI elements in the onboarding view to improve user engagement with memory features. - Expanded i18n support for new onboarding messages related to memory benefits across multiple languages. * Refactor onboarding flow and enhance design system integration - Updated the onboarding process to include a new brand extraction step, replacing the previous newsletter step. - Adjusted the tracking logic to reflect the new onboarding steps, ensuring accurate analytics for user progress. - Improved the UI for the onboarding view, including new input fields for email collection during the brand extraction phase. - Refined the EntryShell component to remove outdated comments and clarify the onboarding renderer's purpose. - Enhanced CSS styles for the onboarding steps to improve layout and user experience. - Updated internationalization strings across multiple languages to reflect changes in the onboarding flow and brand extraction messaging. * Add brand management features and enhance font handling - Introduced new modules for managing brand assets, including `chrome.ts` for headless Chrome operations and `fonts.ts` for self-hosting web fonts. - Implemented `prefetch.ts` to streamline the brand material extraction process, allowing for efficient harvesting of colors, fonts, and logos. - Enhanced the brand system with new schema definitions in `schema.ts` to support brand color and font management. - Developed the `engine` module to integrate brand building and rendering processes, including token derivation and artifact generation. - Improved the overall structure and organization of brand-related files for better maintainability and scalability. * Enhance brand extraction and project management features - Updated `brand-routes.ts` to include new dependencies for project management, allowing for the registration of brand-related projects. - Modified the `extractBrand` function to support project ID and system files, improving the brand extraction process. - Enhanced the CLI commands in `cli.ts` to handle project IDs during brand creation, enabling better tracking of brand projects. - Updated the server setup in `server.ts` to register new project-related routes. - Improved the UI components to display project information associated with brands, including buttons for opening projects in the `BrandDetailView` and `BrandsTab`. - Added new metadata fields in the contracts to support project tracking and management for brands. This commit establishes a more robust framework for managing brand projects, enhancing both backend and frontend functionalities. * Enhance onboarding profile management and memory persistence - Added new canonical profile labels for 'Organization size', 'Use cases', and 'Discovery source' to improve user input consistency. - Introduced `OnboardingProfileState` type to manage onboarding profile data more effectively. - Implemented functions to build and persist the onboarding profile body to memory, ensuring user selections are saved accurately. - Updated the `OnboardingView` component to handle profile persistence during navigation and submission steps. - Enhanced tests to verify that user selections are correctly persisted to the memory profile. This commit improves the onboarding experience by ensuring that user inputs are consistently captured and stored, enhancing overall user engagement with the application. * Reflow brand extraction into an agent-driven, live flow Replace the deterministic SSE prefetch/preview/system pipeline with an agent-driven extraction: POST /api/brands now reserves the brand and stands up a backing project with the target site open in an in-app browser tab plus a seeded prompt, so the agent measures, synthesizes brand.json incrementally, and the user can clear anti-bot walls by hand. New /preview and /finalize routes let the agent render the kit page live and register the resulting user:<id> design system, so extracted brand facts persist as a structured, reusable brand kit instead of a one-shot deterministic guess. Adds the brand-extract skill (SKILL.md + brand-kit.html template), kit-render engine, brand-extraction-engine tests, brand project covers in the Designs tab, onboarding extract handoff, and the matching od brand extract/preview/ finalize CLI subcommands and contract updates. Co-authored-by: Cursor <cursoragent@cursor.com> * Sediment finalized brands into structured memory Reflow a finalized brand into the memory store (brandToMemoryEntries + reflowBrandToMemory) so future chats can ground vague requests in the brand's palette, type, voice and rules. finalizeBrand now wires through the runtime dataDir and best-effort persists the brand, MemoryChangeEvent gains a 'brand' source, and the brand kit render hardens its inline JSON escaping. Adds brand.previewEmpty / brand.viewDetails across all locales. Co-authored-by: Cursor <cursoragent@cursor.com> * Implement logo fallback and imagery support in brand extraction - Introduced a deterministic logo fallback mechanism to ensure that brand extraction processes can retrieve and save site logos, even when the agent fails to do so. - Enhanced the `startBrandExtraction` and `finalizeBrand` functions to utilize the new logo fallback, allowing for better handling of logo assets. - Added support for imagery samples in brand validation, enabling the inclusion of representative images in the brand kit. - Updated the brand kit rendering to include self-hosted fonts and imagery, improving the overall presentation of brand assets. This commit strengthens the brand extraction workflow by ensuring that logos and imagery are reliably captured and displayed, enhancing the user experience in brand management. * Enhance memory management with rule proposal and verification features - Introduced new functionality for distilling annotations into rule proposals, allowing users to suggest rules based on in-canvas annotations through the `od memory rule suggest` command. - Implemented a verification system that programmatically enforces compliance with active rules during artifact generation, ensuring that all active rules are covered in the self-verify scorecard. - Added endpoints for managing verification outcomes, including listing, removing, and clearing verification records, enhancing the transparency of the verification process. - Updated the memory management system to support the retrieval of active rule entries, ensuring that only linked rules are considered during verification. - Enhanced tests for both rule proposal generation and verification processes to ensure reliability and correctness. This commit strengthens the memory management capabilities by integrating rule proposals and verification, improving the overall user experience in managing design rules and ensuring compliance. * Distill review annotations into memory and enforce self-verify scorecard Add distillAnnotationsToMemory to mine inline preview comments/highlights/ marks into durable feedback + rule memory via a dedicated distiller prompt, threaded through the existing extract pipeline with an 'annotation' change source. Tighten the self-verify prompt (daemon + contracts) to state the daemon programmatically checks the scorecard, so a missing or uncovered scorecard on an artifact turn is an enforcement failure. Cover the rule suggest and verification-history routes with tests. Co-authored-by: Cursor <cursoragent@cursor.com> * Apply brand design system through web config on "Use in new chat" Thread onApplyDesignSystem from the entry shell into BrandsTab so the brand's registered design system is applied via the web config channel instead of a bare daemon PATCH that left the Home composer stale. Add a transient home-intent latch + event so the Brands tab can request the Prototype chip on the already-mounted HomeView, which consumes it once the plugin catalog loads. Co-authored-by: Cursor <cursoragent@cursor.com> * Wire annotation distillation into background memory extraction Add a background distill pass that mines inline review annotations (comments / highlights / drawn marks) from a turn into durable memory alongside the general LLM extraction, surface an `annotation` memory toast source in the web UI, and cover the flow with a unit test. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix brand design system not applying to composer on "Use in new chat" Selecting a brand's "Use in new chat" applies the brand's design system as the default and fires the Prototype chip intent in the same synchronous click handler. HomeView consumed that intent inside the event listener, so `pickChip` ran before React committed the config change and seeded the composer's design-system field from the stale (empty) default — the composer showed "No design system" instead of the brand until a reload. Split the intent handling: the listener now only bumps a tick, and a separate effect consumes the chip after the re-render lands, so the seeded design system reflects the freshly-applied brand. Add the previously-untracked home-intent latch test coverage. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(web): rework Brands into Brand Kit and add Home create entry Co-authored-by: Cursor <cursoragent@cursor.com> * feat(brands): harvest real cover/hero images for the Images module The brand kit's Images gallery only populated when the extraction agent remembered to save imagery — so a forgetful or bot-blocked agent (and the pre-imagery "Open Design" brand) left it empty. Add a deterministic, server-side imagery fallback (imagery-fallback.ts), mirroring the logo fallback: it parses og:image/twitter:image, large <img> (highest-res srcset/<picture>), <link rel=preload as=image>, and CSS background-image hero blocks, fetches candidates with browser-shaped headers, decodes PNG/GIF/JPEG/WebP dimensions to keep only big representative images (dropping icons/sprites/logos/tracking pixels), dedupes by content hash, and saves up to 8 of the largest into imagery/ with labeled samples. finalizeBrand runs it as a timeout-bounded, failure-tolerant safety net (injectable so tests stay offline) when the agent captured too few samples, first adopting any on-disk images. The extraction prompt and brand-extract SKILL now explicitly direct the agent to harvest the site's large/cover/hero images, filtered by rendered size. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(qa): implement deck layout validation and safety checks Add a new QA module for validating the layout of generated brand decks to ensure robustness against clipping and truncation issues. The `analyseDeckLayout` function checks for critical layout invariants, including the presence of `.slide` sections, correct container types, and necessary runtime layers. Introduce `assertDeckLayoutSafe` to enforce these checks during brand system rebuilds, preventing the deployment of decks that fail validation. Additionally, create comprehensive tests to verify the functionality of the new layout validation features. * fix(brands): apply deck shrink-to-fit synchronously so slides never clip The no-clip runtime scheduled its fit pass through requestAnimationFrame, whose callbacks are throttled while the deck is offscreen or occluded. A slide could therefore stay unscaled — and clip its content — until first paint. Fit synchronously on resize/load/fonts-ready with a trailing setTimeout settle pass for late reflow, removing the rAF dependency. Verified at the previously-broken 1024x620 viewport: container-type:size, zero truncations, runtime auto-applies scale (Problem 0.71, ASK 0.87, Product 0.97, Competition 0.97) and frame clip count drops to 0. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(web): let New Brand modal embed scrollable brand reference picker Add a fillHeight mode to BrandReferencePicker so the heading, quick-pick row and controls stay pinned while only the gallery scrolls inside a bounded-height parent. Wire it into NewBrandModal with a stable, spacious dialog and refresh the related newBrand/brandPicker copy across all 18 locales. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(brands): enhance brand extraction with deterministic seed harvesting Introduce a new `seed-fallback` module to provide a server-side deterministic palette and typography seed during brand extraction. This ensures that the brand kit's initial display includes a harvested logo, an approximate color palette, and font families, improving the user experience by reducing the all-skeleton appearance during the first paint. Update the `startBrandExtraction` function to utilize this new module, allowing for a more seamless and visually appealing brand extraction process. Additionally, enhance the `BrandReferencePicker` component to reflect loading states and errors during brand extraction, ensuring users receive immediate feedback on their actions. Update related tests to verify the idempotency of the `finalizeBrand` function, ensuring that re-finalizing a brand correctly reuses the existing design system without duplication. * feat(brand-extract): enhance BrandReferencePicker and localization updates Updated the BrandReferencePicker component to reflect loading states and errors during brand extraction, improving user feedback. Added a new localization key for the brand extraction process and updated existing translations in English, Simplified Chinese, and Traditional Chinese to enhance clarity and user experience. Additionally, introduced new styles for better interaction with brand assets in the brand kit template. * feat(brands): wire in-page lightbox/masonry/asset preview + refine seed Brand-kit preview improvements for the live extraction kit: - brand-kit.html: add in-page overlay system (sandboxed iframe has no top-nav) — clickable image lightbox with prev/next, a "view all" masonry modal, and a full-page asset preview modal that loads system/artifacts/<kind>.html in an iframe. Defer auto-reload while an overlay is open so it never yanks the modal out mid-interaction. - seed-fallback.ts: prefer vivid mid-luminance hues for the seeded accent/accent-secondary, and drop icon/symbol faces (Remix Icon etc.) from the typography seed so specimens never render glyph soup. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(brands): wire in-page lightbox/masonry/asset preview + refine seed Brand-kit preview improvements for the live extraction kit: - brand-kit.html: add in-page overlay system (sandboxed iframe has no top-nav) — clickable image lightbox with prev/next, a "view all" masonry modal, and a full-page asset preview modal that loads system/artifacts/<kind>.html in an iframe. Defer auto-reload while an overlay is open so it never yanks the modal out mid-interaction. - seed-fallback.ts: prefer vivid mid-luminance hues for the seeded accent/accent-secondary, and drop icon/symbol faces (Remix Icon etc.) from the typography seed so specimens never render glyph soup. Co-authored-by: Cursor <cursoragent@cursor.com> * i18n(web): add brandPicker.opening across remaining locales + picker test Completes the brand-reference picker i18n key that was committed only for en/zh-CN/zh-TW, so every locale satisfies the typed Dict, and lands the BrandReferencePicker extraction-feedback test left untracked by the concurrent worker. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(EntryShell): enhance AMR cloud card visibility post-detection Updated the EntryShell component to ensure the AMR cloud card remains visible after detection settles, even when the AMR runtime is unavailable. This change prevents the card from disappearing and allows it to degrade gracefully to fallback content and sign-in flow. Additionally, added tests to verify the new behavior, ensuring a better user experience during onboarding. * feat(brands): programmatic-first design system extraction + rename Make brand extraction two-phase so a usable design system is ready the moment the user enters a URL — the instant "aha" — instead of waiting on the AI agent: 1. PROGRAMMATIC-FIRST (synchronous): startBrandExtraction now harvests the site deterministically (logo, palette, typography, one-line description, cover imagery, source URL) via prefetchBrand, synthesizes a valid design system with brandFromMaterial (no LLM), and finalizes + registers it before returning. finalizeBrand is refactored into a reusable finalizeBrandCore shared by both the programmatic path and the agent path. 2. ASYNC AI ENRICHMENT: the seeded agent prompt is reframed to enrich the already-usable design system and re-finalize in place (same user:<id>), updating every artifact/template. Bounded + best-effort: a blocked/unreachable origin skips phase 1 and stays `extracting` for the agent to drive. Gated on userDesignSystemsRoot so the legacy agent-only path stays intact for tests. Also rename the user-facing "Brand Kit" surface to "Design System" across en + zh-CN strings, project names, and the enrichment prompt. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(brands): restore design-systems nav entry + reconcile BrandsTab on re-activation Address review feedback on PR #4260: 1. EntryNavRail dropped the only control that reached view==='design-systems' when Brands replaced it in the rail, leaving the still-rendered/routed design-system manager deep-link only (the entry-nav-design-systems e2e specs assert this). Restore a reachable rail entry (blocks icon, existing navDesignSystems key) alongside Brands. 2. BrandsTab only fetched once on mount, but EntryShell keeps sub-views mounted and toggles visibility, so a brand finishing extraction in its backing project never reconciled until a full reload. Refresh whenever the Brands view becomes active again, and poll while any brand is extracting (torn down once settled / when hidden). Red spec: tests/components/BrandsTab.refresh.test.tsx (fails pre-fix: fetchBrands called once, not twice). * fix(web): surface missing backing projects * fix(web): re-enable brand actions after use * fix(daemon): serve brand logos from data roots * fix(brands): reconcile failed extractions * fix(brands): non-blocking extraction start + lifecycle-accurate status (#4470) Acceptance fixes for the Brand Kit surface (PR #4260, even-ferry), addressing five reported issues: - Perf: `startBrandExtraction` no longer blocks the POST /api/brands response on the synchronous programmatic harvest+finalize. It now waits only a short budget (~1.2s) so fast origins still land on a ready, applyable design system (the instant "aha"), while slow/blocked origins return immediately on the "Extracting…" skeleton and finalize in the background. Measured: example.com POST dropped from a ~19s block to ~1.2s, then finalized to `ready` in the background. - Brand Kit stays stuck on "Extracting…" after a manual stop: the backing run's canceled/failed status now reconciles the brand to `failed` with a reason (this extends the existing reconcile; adds a regression spec). - Brand Kit ignores a backing run that is awaiting user input (anti-bot wall / question form): new reversible `needs_input` brand status, derived on read (never persisted) so it flips back once the user answers. Surfaced as a "Needs input" badge + hint in the card and a distinct status dot in the list; the list keeps polling while paused. - Home → Recent projects showed brand-extraction projects as "Not started": /api/projects now falls back to the brand lifecycle for brand projects whose run-derived status is `not_started` (extracting→running, needs_input→awaiting_input, ready→succeeded, failed→failed), so a live extraction is never shown as not started. - "Use in new chat" produced no visible result: it now carries a confirmation notice through the Home intent channel so Home shows a "Using <brand>" toast, making the navigate+apply verifiable (the composer already preselects the brand's design system). Tests: daemon brand-routes (canceled→failed, needs_input transient) and brand-extraction-engine (fast return + background finalize) specs; web BrandPreviewCard specs (needs_input badge/hint, Use-in-new-chat notice). #4 validated end-to-end against a real daemon. guard + typecheck green. * [codex] Fix brand extraction incomplete states (#4486) * fix brand extraction incomplete states * fix web memory tests for advanced modal Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix onboarding P0 brand-step navigation Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix daemon brand extraction test timeout Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix brand extraction fallback prompt state Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> * [codex] Fix brand extraction terminal status reconciliation (#4532) * Fix brand extraction terminal status reconciliation * Keep prefetched brand pages previewable * fix(brands): preserve ready extraction status Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(brands): persist terminal extraction signal Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(brands): clear stale terminal retry markers Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> * Fix brand kit modal intent handling (#4528) Co-authored-by: Siri-Ray <2667192167@qq.com> * fix(web): let design system contents scroll in narrow review layout (#4526) Co-authored-by: Siri-Ray <2667192167@qq.com> * [codex] Fix Brand Kit preview lifecycle guards (#4527) * Fix brand kit preview lifecycle guards * fix(brands): keep detail selected on delete failure Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * fix(brands): handle delete HTTP failures Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) --------- Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> * ci: retrigger pull_request checks * test(e2e): stabilize entry settings shard --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: PerishCode <perishcode@gmail.com> Co-authored-by: lefarcen <935902669@qq.com> Co-authored-by: PerishFire <39043006+PerishCode@users.noreply.github.com> Co-authored-by: Siri-Ray <2667192167@qq.com> Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
6cf48c29b5 |
ci: reduce Blacksmith usage and stabilize PR checks (#4603)
* ci: move lightweight workspace checks to hosted runners * ci: split UI P0 project runtime shard Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex) * Stabilize UI P0 project runtime tests --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
15d3759834 |
[codex] Optimize CI topology and Playwright suites (#4460)
* Consolidate PR validation into ci * Tune absorbed CI runner tiers * Fold visual validation into CI Playwright shards * Run PR shards during manual CI dispatch * Optimize CI topology and scopes * Increase UI P0 Playwright workers * Relax visual Playwright timeout |
||
|
|
8ff19c6b41 |
[codex] Add main-risk smoke and E2E coverage (#4322)
* test(e2e): cover daemon reload artifact recovery * test(e2e): expand critical flow coverage * test(daemon): add startup and recovery smoke coverage * test(e2e): add visual and desktop chrome smoke coverage * ci: gate packaged onboarding smoke to nightly * fix(web): repair artifact replay type narrowing Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(ci): repair preflight smoke coverage checks Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(web): tighten artifact recovery polling Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(web): keep error recovery retries alive Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(e2e): relax brittle UI P0 assertions Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(web): recover pointer artifact outputs Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(e2e): stabilize manual edit reload smoke Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(e2e): avoid noisy win onboarding cleanup Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(web): stop failed artifact recovery polling Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(daemon): isolate startup smoke data root Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(web): recover standalone html artifacts Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(web): guard pointer artifact recovery by run time Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(ci): narrow strict visual gate to critical smoke Generated-By: looper 0.9.7 (runner=fixer, agent=codex) * fix(ci): limit PR visual capture to critical cases * fix(ci): keep PR visual capture complete * fix(web): keep reload artifact recovery retryable * fix(ci): clarify PR visual gate layering * fix(e2e): stabilize visual home P2 capture * fix(e2e): align visual gallery detail clicks * fix(e2e): preserve packaged install during onboarding cleanup * fix(ci): shard PR visual capture * fix(ci): remove duplicate nix validation from ci * fix(ci): keep visual capture screenshots flat * fix(ci): point nix hash autofix at ci-nix * fix(ci): stabilize PR P0 recovery gate * fix(web): ignore stale artifact pointers during recovery * fix(web): reset BYOK model after clearing key * ci: run critical UI P0 subset on PRs * ci: combine PR UI P0 critical shards * ci: combine PR visual capture shards * ci: preserve visual capture shard manifests * fix(web): clear ProjectView delayed timers on unmount * test(e2e): harden onboarding connect gate coverage * test(e2e): align AMR auth recovery and visual catalog timeout |
||
|
|
891981d460 |
[codex] Optimize CI runtime topology (#4450)
* Optimize e2e tools-dev runtime parallelism * Remove visual networkidle wait * Optimize e2e vitest parallelism * Optimize Nix flake caching * Test CI on Blacksmith runners * Allow parallel manual CI runs * Tier CI runner sizes * Temporarily narrow CI debug scope * Instrument watcher CI timeouts * Instrument watcher event diagnostics * Avoid default polling in watcher tests * Skip runtime trace during watcher debug * Probe ARM runner tiers for CI * Focus CI runner probe on x64 browser * Probe browser workers by runner size * Probe Playwright file parallelism * Probe Playwright worker scaling on 8v * Reshape CI topology * Fix split E2E Vitest CI lane * Simplify daemon CI topology * Optimize Windows payload CI setup * Revert "Optimize Windows payload CI setup" This reverts commit |