mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* fix(web): keep the project split still across the Home hand-off
The optimistic creation frame left `.split` on its stylesheet default
(460px) while ProjectView resolved the saved width, or the equal split of
the container, only after it mounted — and that first write ran through
the 200ms width transition, so the chat column moved once the real view
arrived (OPEND-3207).
Move the split geometry into `project-split-layout.ts`, have both surfaces
resolve their first-paint width through `resolveProjectSplitLayout`, and
settle a surface's first measured write without the transition.
Red spec: e2e/ui/home-send-split-width.test.ts (red on main, green here).
* test(web): read the 4px handle constant from project-split-layout
The material spec pinned `SPLIT_RESIZE_HANDLE_WIDTH = 4` in ProjectView's
source; the constant now lives in project-split-layout.ts and ProjectView
imports it, so assert on the module and on the import.
* test(cms): wait for the Test modal impression before switching language
The locale case only passed while the impression frame never fired: on a
fast machine the next language switch unmounted the modal before its
requestAnimationFrame recorded the impression. CI is slow enough for the
frame to land, and the switch that follows then closes the modal for good.
Waiting for the recorded impression makes that order deterministic.
* fix(cms): keep the open Test modal across a same-deployment reload
A language switch (or lease renewal) reloads the selected Test deployment.
While the new decisions are in flight the runtime publishes a session
without decisions, and the modal treated that gap as the presentation
ending: it dropped its "open" marker, then the returning decision looked
like a new offer of an activity this account had already seen and stayed
closed.
Key the open presentation by the selected deployment and snapshot. A
reload of the same selection continues it; a redeploy, a different
account, a dismissal, or the session ending still releases it.
* test(e2e): red spec for the Home → project hand-off parity (OPEND-3334)
Two pins for the hand-off between the optimistic project frame and
ProjectView: pixel parity of the chat and workspace columns across the
hand-off (animations frozen), and a single assistant status label + class
set from the click to the first content. Expected red on main: the frame is
a hand-drawn copy of ProjectView and drifts from it (old "Preparing…" footer
vs the execution record's "Working" head, simplified composer, disabled
empty-state pills, tabs dock, switcher name).
* test(e2e): enroll the Home hand-off specs in the ui_p0 entry-settings group
home-amr-pending, home-send-single-loading and home-send-split-width were
merged (or opened) without being enrolled in uiP0Groups, so no merge lane
had ever executed them; only the prerelease full pool would have. Enroll
them with the other Home-entry files.
* test(e2e): enroll the hand-off parity spec in ui_p0 (OPEND-3334)
* feat(web): draw the Home → project hand-off frame with the real view's parts (OPEND-3334)
The optimistic creation frame was a hand-drawn copy of ProjectView and had
drifted from it, so the hand-off moved: the old assistant footer's
"Preparing…" flipped to the execution record's "Working" head, the composer
gained its accessories, the empty-state pills lit up, the tabs dock gained
the history control.
The frame now draws the same parts: the role row named through the shared
`assistantRoleNameForAgent`, the real `ExecutionShell` on an empty running
shell ("Working", its orb, its geometry), the real composer accessories
(design-system picker + agent/model menu) inert, the history control's
footprint in the dock, and live-looking, inert empty-state pills. Behind an
execution shell the old footer no longer paints its running label, so a
running turn states its status once.
App and ProjectView pass the agent name, config, agents, daemon liveness and
design systems the frame needs; the pending record carries the send's
design-system id.
* test(e2e): compare the status row's element set per hand-off phase
The record head is more than one element (its shimmer span and the summary
wrapper both carry the text), so counting distinct class sets across the
whole log flagged an identical head as a change. Compare the set the frame
drew with the set the view drew instead.
* feat(web): let the real ChatPane draw the Home hand-off's first turn (OPEND-3334)
The pending frame and ProjectView's hand-off card were hand-drawn copies of
the chat column, so every ChatPane internal they missed (the fixed composer
layer, the chat seam, the log's top inset) was a jump at the hand-off. Both
now render the real ChatPane on an optimistic first turn built from the
creation record: a user message and a running, empty assistant placeholder.
- runtime/chat/creation-handoff: pure builder for that turn; staged images
preview through object URLs until the files are in the project.
- ChatPane: `detached` mode (inert pane + composer layer) for the frame;
the composer portal target resolves at mount so the composer is portaled
before the first paint instead of one frame after it.
- ProjectView: mounts ChatPane during the hand-off and feeds it the
optimistic turn until a real message exists; the overlay card, the hidden
pane CSS and `composerLayerHidden` are gone.
- agentModelSelection: one `selectedAssistantIdentity` for the real and the
optimistic turn.
* fix(web): give the pending frame's workspace column the add-tab and project-menu controls (OPEND-3334)
The parity pin now passes on the chat column and fails on the workspace
column: the frame lacked FileWorkspace's add-tab button and the project
menu trigger, so the top bar was 4px shorter and the empty state below it
moved at the hand-off.
* test(web): decouple pending handoff assertions from CSS classes
Generated-By: looper 0.13.0 (runner=fixer, agent=codex)
* fix(web): the Home hand-off's first turn fades in once, no remount, no workspace reload (OPEND-3334)
A rAF probe of the Home send found the first turn mounted four times, each
playing the 200ms `msg-enter` fade (QA's recording shows the flashes):
the pending frame (the one intended entrance); ProjectView taking over;
the ChatPane key moving from `conversation-unavailable` to the resolved
conversation id; and the real rows replacing the optimistic ones under new
ids. The workspace went pending-empty -> "Loading..." -> empty.
- ChatPane `quietEntrance`: rows first rendered while it is on get
`msg--quiet-enter` (no fade) for their lifetime; dropping the flag never
restarts an animation. ProjectView sets it while the hand-off runs.
- ProjectView keeps the pane's key when the hand-off pane's first
conversation id resolves; a later switch still re-keys.
- A project born from the Home send (not an imported folder) shows the
empty workspace until the first listing, as the pending frame did.
* test(e2e): pin one entrance, one view pane and no workspace reload across the Home hand-off (OPEND-3334)
* fixer: address PR #8267 follow-up items
Generated-By: looper 0.13.0 (runner=fixer, agent=codex)
* fix(web): keep the file-list authority gate across the Home hand-off (OPEND-3334)
e3596b032c made a Home-created project's workspace authoritative before
its first listing was accepted, so the empty-state CTAs were live while
Home attachments were still uploading, and a failed first read looked
like a genuinely empty project (review by nettee).
Restore `filesAuthoritative={committedFilesGeneration > 0}`. Until that
first listing, `emptyLookBeforeFirstListing` draws the same empty state
the hand-off frame showed, from DesignFilesPanel's one empty-state
markup, but inert and aria-busy and without CTA test ids. The live empty
state (or the files) replaces it once a listing is accepted, so the
workspace still never detours through "Loading…".
* feat(daemon): accept a caller-minted seed conversation id on project create (OPEND-3334)
* refactor(web): mount ProjectView from the Home send and hold project reads until the create answers (OPEND-3334)
* test(web): pin the held reads and the single pane across the Home send (OPEND-3334)
* test(e2e): key the Home hand-off specs on the creation phase, pin one pane and one user row (OPEND-3334)
* test(e2e): no project-scoped request leaves before the create answers (OPEND-3334)
* test(web): type the fetch spy in the held-reads case
* fix(web): hold the pending-prompt clear, tab hydrate, folders and share-status reads until the create answers (OPEND-3334)
The e2e network assertion caught five project-scoped requests leaving
before POST /api/projects answered. A Home send's view is also an
auto-send from mount now: App writes the auto-send keys after the
create, so the prompt must not fall back to a composer draft.
* fix(web): keep the run-status feed off a project until its create answers (OPEND-3334)
The rail and the tab switcher list the optimistic row from the click, and
their shared feed polled /api/runs?projectId= for it every 4s. The read
predates this branch; the e2e network assertion caught it intermittently.
* fix(web): the optimistic first turn belongs to ProjectView, not App's creation record (OPEND-3334)
QA on bd5fe20579: App releases the creation record 8s after the create;
Home uploads outliving that made the first turn and its Working row
vanish until they finished. The view now captures the turn at mount and
retires it when the real turn owns the rows, when the auto-send is turned
down, or when the record is gone with nothing left to send. The seed
conversation id is kept for the view's life so the pane never re-keys.