Skip to content

feat(v2): rebuild workspace thread, decisions, and composer - #1556

Merged
lilyshen0722 merged 13 commits into
mainfrom
feat/v2-workspace-thread-artboard
Sep 6, 2026
Merged

lilyshen0722 merged 13 commits into
mainfrom
feat/v2-workspace-thread-artboard

Conversation

@lilyshen0722

@lilyshen0722 lilyshen0722 commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

TASK-129 PR 3 — stacked on #1555 / #1549

Replaces the legacy workspace chat and bubble route with the thread artboard surface.

  • Deletes V2PodChat and V2MessageBubble; the route now composes V2Thread, V2MessageRow, V2DecisionCard, and V2Composer.
  • Adds flat 28px-avatar message rows, a pod header with muted description and working count, one bordered composer, and 2px cobalt decision cards.
  • Derives decision cards from the durable decision queue joined to their source message ID; choosing a card posts to the existing choose endpoint and settles in place.
  • Preserves threads, reactions, uploads, PR cards, replies, and agent-delivery hints.
  • Extracts transcript, starter, and message-action modules so route coordination does not own rendering details.
  • Updates static layout invariants rather than deleting retired guards.

Verification

  • Frontend typecheck passed.
  • Frontend test suite passed: 91 suites, 587 tests.
  • Frontend production build passed.
  • Focused lint has no errors; repository JSX warnings remain.

UX 1440/390 walk remains required. This is draft pending that review and the stacked cohesive cutover.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: CHANGES_REQUESTED @ 639a9ea — built and walked at 1440 + 390 beside Workspace · Main, the after-pick frame and Workspace · 390; sheet in Sprint HQ. Passing: rows with no bubbles, composer as one bordered box with mono footer and ink Send at 1440, decision card CSS with the 2px cobalt ring and cobalt primary, old bubble/inspector selectors gone, no UA controls, scroll width clean. Fixes: (1) header — pod name Bricolage Grotesque 22/28; working line as mono 11 cobalt text '● N agents working' (muted at 0), not a tint pill; a separate 28px outline-square inspector toggle at the right at 1440 AND 390 (today .v2-thread__working is the toggle and is display:none at 390, so the phone cannot open the sheet); (2) rows — avatar 28px square r4 (built v2-avatar--md 30px 50%), time mono 12 muted (built Plex Sans 11), tag slot after the time for '· telegram' / '· ruled', hover action bar r4 no shadow (built r8 + shadow); (3) card — 'Other…' as a cobalt text link without the dashed border, drop the muted hint span unless it is a count, options stack full-width 44px at 390, and a ruling unmounts the card leaving a plain human row tagged '· ruled' with the option label as body (built: settled card + status line); (4) composer at 390 — no footer, box + 44px ink square Send with the glyph; (5) 390 frame — no rail, page white edge to edge, four-tile tab bar with the cobalt needs-you badge, and opening the drawer closes the sheet. Note for the page-level cobalt invariant: the rail brand mark is a cobalt fill in the artboard too — exempt .v2-rail__brand-icon. Not walkable on the smoke account: live card, ruled row, telegram tag, working > 0.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code gate at ad64d81837a59b6b82ab793713ba8580d8c0c1c0.

The card rule is in and it discriminates. The page-level invariant ruling 3 asked for is not written, and writing it as ruled fails today on exactly one element.

What passes

the pending human decision is the sole cobalt-filled action exception: one primary choice, bordered alternatives, and a text-only Other action is real. Mutation: change .v2-root button.v2-decision-card__choice--primary from var(--v2-accent) to var(--v2-ink) → 1 red, that test. 92/92 across v2-layout-invariants, V2DecisionCard and V2ThreadDecisionCard at this head.

The retirement is genuine, not a flag: V2PodChat.tsx, V2MessageBubble.tsx and V2PodInspector.tsx are absent from the tree, and :227, :228, :349 assert their absence with fs.existsSync(...) rather than a grep — that is the right instrument for "deleted, not kept behind a flag".

The ruled page-level invariant is missing

63938 ruled: "cobalt fills under .v2-root are exactly the selected room and the primary option of an open decision card, nothing else; the sidebar-scoped rule stays as well." This head has the sidebar-scoped rule and the card rule. It has no rule about the page.

That is not a formality, because the page changed underneath it. Accent backgrounds in v2.css went 29 → 33 across this stack, and on the workspace route the set is now:

selector size fill or mark
.v2-pods__row--selected full-width row fill — ruled
.v2-root button.v2-decision-card__choice--primary button fill — ruled
.v2-rail__brand-icon 28×28 block fill — unruled
.v2-workspace-inspector__state--needs-you 6×6 mark
.v2-workspace-inspector__state--working 6×6 mark
.v2-thread-card__dot 6×6 mark

So written literally, the invariant fails today on one element: the rail brand mark. That is the item ux-lead's own section B parked as "artboard decides… flagged for @sam" and it is still unruled — I raised it at 12:58 and nothing has answered it.

The three 6px indicators are marks and correctly stay cobalt, which means the invariant wants a role discriminator rather than an exception list: cobalt as a background on anything larger than a mark (say ≥ 16px in either axis, or simply "not a dot/indicator class") is exactly the selected room and the card's primary choice. Written that way it passes today if the brand mark is ruled ink, and fails loudly if a fourth block appears.

Two things needed before it can be written, both one-liners from a human: is the rail brand mark cobalt or ink, and does "fill" mean any accent background or only a ground-covering block.

DoD 2, for the record

V2Thread.tsx is 50,281 B at this head — 77,673 as V2PodChat, 58,349 at 02daee55, 49,042 at 6bca87dc, now back up 1.2 KB as the 1440/390 corrections landed. V2MessageRow.tsx is 29,759 B. The trend is real but has flattened well above "small"; V2Thread remains the largest component in v2.

Instrument note

My first run of this file reported two failures at :228 and :349. That was my own working tree: git checkout <ref> -- frontend/ adds the PR's files but does not delete files the PR removed, so the three retired components were still on disk and their existsSync assertions correctly said true. Removing them gives 92/92. Worth recording because those two invariants are precisely the ones designed to catch a leftover file, and a reviewer's stale checkout makes them fire on a correct PR.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: CHANGES_REQUESTED @ ad64d81 — re-walked at 1440 + 390 beside the Workspace frames (sheet in Sprint HQ). Closed since 639a9ea: separate 28px outline inspector toggle at both widths (the phone opens the sheet again), working line as mono text with the cobalt dot, name 22/28 with the description inline, no rail at 390, white page at 390, four-tile tab bar with the ink active tile, phone composer = box + 44px ink square Send, Other… as cobalt text, ruling unmounts the card and leaves a '· ruled' row. Remaining: (1) .v2-thread__title h1 uses var(--v2-font) — the artboard face is Bricolage, use var(--v2-font-display); (2) row avatars are V2Avatar size=md = 30px circles with a white ring + shadow — 28px square r4, no chrome, as the inspector/sidebar already do; (3) .v2-msg__time is 11px Plex Sans (legacy rule ~v2.css:2980) — mono 12 muted; author 14/600; '· telegram' in the same tag slot as '· ruled' when a message carries a channel source (if no source field exists, say so in the body and it's a follow-up); (4) .v2-msg__actions r8 + shadow (legacy ~v2.css:2864) — r4, 1px border, no shadow; (5) no 760px rule stacks .v2-decision-card__options — full-width 44px options at 390; drop the muted hint span unless it is a count; (6) opening the drawer while the sheet is open leaves both up — each closes the other; (7) the drawer toggle is a borderless glyph — the artboard draws the same 28px outline square as the inspector toggle. Not walkable on smoke: live card, ruled row, telegram tag, working > 0, tab badge.

@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from ad64d81 to c6c782f Compare September 5, 2026 14:01
@samxu01
samxu01 force-pushed the feat/v2-workspace-inspector-artboard branch from 74e24f9 to 199e905 Compare September 5, 2026 14:09
@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from c6c782f to 089c990 Compare September 5, 2026 14:10

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Joint code gate: #1549 82fa5ef8 · #1555 199e9054 · #1556 089c9902.

The cobalt role allowlist is in and it discriminates. One finding, and it is invisible to both gates as currently defined.

The allowlist is better than what I proposed

I suggested a hand-written selector list. This is stronger: activeAccentBackgroundSelectors derives the active class set from the route's own components (navRail, podsSidebar, thread, threadCard, workspaceInspector, decisionCard, composer, messageRow) and intersects it with the stylesheet, so a class that gains an accent background joins the set automatically instead of hiding in a stale rule. The two generated inspector state classes are added explicitly, with a comment saying why.

It also corrects my count. I enumerated six selectors and missed .v2-pods__channel-dot--live; the real set is seven — two blocks (.v2-pods__row--selected, .v2-root button.v2-decision-card__choice--primary) and five marks. Their enumeration was right and mine was the incomplete one.

Verified rather than read. Baseline 93/93. Mutation: add .v2-composer__send-extra { background: var(--v2-accent) } and put that class on the composer's send button — a realistic eighth fill on a class the route actually uses. Result 1 red, that test. It fails on arrival, which is the property ruling 3 wanted.

Also confirmed the rail geometry survived the resize: --v2-rail-w is still 56px and only .v2-rail__brand-icon went 28 → 32. "The rail is now 32px" in the pod reads like a column change; it isn't one.

Finding: the column tokens inflate as the window narrows

The desktop values were updated to the ruled grid. The breakpoint overrides were not, and they still carry the pre-Signal numbers:

context --v2-rail-w --v2-pods-w --v2-inspector-w
root 56 232 300
@media (max-width: 1279px) 72 248 300
@media (max-width: 1023px) 64 236 —

So between 1024px and 1279px the rail is 72px — wider than at 1440 — and the sidebar is 248px against the ruled 232. The layout drifts back toward the geometry TASK-129 exists to replace, and it gets wider as the viewport shrinks, which is the opposite of what a responsive step should do.

Nothing catches it. #1549's grid invariant asserts cssVariable(v2, '--v2-rail-w') === '56px', and cssVariable matches the first declaration, so the root value satisfies it while two overrides sit 5,500 lines below. The UX walk is 1440 and 390, and both breakpoints fall between them.

Two lines fix it — delete the three stale declarations, or restate them deliberately if the rail is meant to change at tablet width. The invariant then wants to assert the count of --v2-rail-w declarations, the same shape as the .v2-shell one-head cleanup already agreed for this pass.

Carried

DoD 2: V2Thread.tsx is the number to re-read at the final head; it was 50,281 B at ad64d818, from 77,673 as V2PodChat.

Instrument note: git checkout <ref> -- frontend/ does not delete files the PR removed, so the three retired components must be deleted from the working tree before running — otherwise their existsSync invariants fire on a correct PR. That cost me a false red earlier today and it will cost the next reviewer the same.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: CHANGES_REQUESTED @ 089c990 — re-walked at 1440 + 390 (sheet in Sprint HQ). Closed since ad64d81: pod name in Bricolage Grotesque Variable 22/28 (font loads), drawer toggle as a 28px outline square, sheet and drawer mutually exclusive both ways, 760px rule stacks the card options full-width at 44px, cobalt allowlist pinned. Still open — the message rows did not move: (1) V2MessageRow still renders V2Avatar size=md → 30px, border-radius 50%, 2px white ring; the artboard row avatar is 28px square r4 with no chrome (as the inspector now does); (2) .v2-msg__time is still 11px Plex Sans (legacy rule ~v2.css:2983) → mono 12 muted; author .v2-msg__author-btn 13/700 → 14/600; (3) .v2-msg__actions still r8 + shadow (legacy ~v2.css:2867) → r4, 1px border, no shadow. Three CSS/props changes; I re-walk on the next head. Non-blocking: option.description renders as a muted 11px span beside each option — data-driven, fine; '· telegram' tag when a source field exists stays a follow-up unless the row already carries one.

@samxu01
samxu01 force-pushed the feat/v2-workspace-inspector-artboard branch from 199e905 to a8f9449 Compare September 5, 2026 14:21

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code re-gate at 43243593. The binding guard works, and I swept for the same failure elsewhere — the blast radius is one.

The guard discriminates

93/93 at this head. Mutation: drop v2-thread from the root's className="v2-chat v2-thread" — the exact bug this commit fixes — gives 1 red, on workspace thread rows retain the artboard grammar at desktop and phone widths. So the binding is pinned, not just the rules.

The interesting part is what the bug says about every other invariant here

This file's guards read v2.css as text. A rule can be present, correct, and reach nothing, and the guard still passes — which is what happened: the .v2-thread rules existed and the element never carried the class, so legacy row styles won and every .v2-thread … assertion stayed green through three UX walks. That is the same shape as the two 2026-08-24 CSS incidents, in a new place.

So I swept for it rather than assuming it was unique. Extracted every descendant selector asserted via ruleBody/selectorRuleBody/lastRuleBody, took the scoping class of each — 13 of them — and checked each against the class names v2 components actually emit.

Ten are literal className attributes. Three looked absent and are not:

  • v2-activity__queue-row--decision — built by interpolation, V2ActivityPage.tsx:420 `…queue-row--${item.kind}…`
  • v2-connector-row__dot--live — V2ConnectorsPage.tsx:486 `…dot--${row.dot}…`
  • v2-thread-card--addressed — V2ThreadCard.tsx:80, literal inside a template

All three are genuinely applied; my extractor could not resolve the interpolation. Reporting them as unbound would have been the same false-absence error the sweep exists to catch, so: no other asserted scoping class is unbound at this head. The .v2-thread case was the only one.

The standing weakness, for whoever adds the next invariant

The new guard is hand-written and per-class. Nothing detects the general case, and the general case is cheap to hit: add a scoped rule block, forget the class on the element, and the invariant passes forever while the page renders the old thing.

The mechanical version of what I just did by hand would close it — for every asserted descendant selector, require its scoping class to appear in a component's class output, with interpolated names handled by matching the prefix before ${. Worth considering when the .v2-shell and duplicate-rule cleanup lands, since that pass is already touching this file's helpers.

Carried

V2Thread.tsx size and the five stale breakpoint declarations are unchanged at this head; both are tracked in my earlier reviews.

@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from 4324359 to cc519cc Compare September 5, 2026 14:21

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: CHANGES_REQUESTED @ 4324359 — rows re-walked at 1440 + 1200 + 390 (sheet in Sprint HQ). The three row items are closed in kind: avatar 28px square r4 with no ring or shadow, time in IBM Plex Mono, author 600, hover bar r4 with a 1px border and no shadow (the .v2-thread binding did it). Two left: (1) desktop row meta is one size under the artboard — time mono 11 → 12 muted, author 13 → 14/600 (the phone already renders 12 and 15); (2) the stale breakpoint tokens agreed in 64009/64011 are still present, so at 1200 the grid is 72 / 248 / 516 / 300 instead of 56 / 232 / 776 / 300 — delete --v2-rail-w: 72px; --v2-pods-w: 248px (≤1279) and --v2-rail-w: 64px; --v2-pods-w: 236px (≤1023). Both are CSS-only; I re-stamp on the next head after a 1440 + 1200 + 390 recapture.

@samxu01
samxu01 force-pushed the feat/v2-workspace-inspector-artboard branch from a8f9449 to a6f10d4 Compare September 5, 2026 14:22
@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from cc519cc to 255c6a0 Compare September 5, 2026 14:22
@samxu01
samxu01 force-pushed the feat/v2-workspace-inspector-artboard branch from a6f10d4 to b6adfa3 Compare September 5, 2026 14:24
@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from 255c6a0 to e76651c Compare September 5, 2026 14:24

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: CHANGES_REQUESTED @ 255c6a0 — one line left. Re-walked at 1440, 1200, 1024 and 390 (sheet in Sprint HQ): grid fixed at 56 / 232 / 300 down to 1024 with the chat absorbing the width; rows are 28px square r4 avatars with no ring, mono time, 600 author, r4 bordered hover bar with no shadow; everything else unchanged from 089c990 and matching. Still under the artboard on desktop only: .v2-msg__time mono 11 → 12 muted, .v2-msg__author-btn 13/600 → 14/600 (the phone already renders 12 and 15). That is the last visible delta I have; I re-stamp APPROVED on the head that carries it.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code gate at 7ef104e3 — note this is #1556's head as GitHub reports it now; e76651c0 in the pod message is already superseded, the fourth sha drift in this stack today. Content is what was described, so this is a gate on the right thing under a different name.

The guard now catches the case that defeated its predecessor.

--v2-rail-w, --v2-pods-w and --v2-inspector-w are each declared exactly once. Baseline 94/94.

Mutation, the one that mattered: re-add --v2-rail-w: 72px; --v2-pods-w: 248px inside @media (max-width: 940px) — outside the old 29-line slice, which is where the previous guard let it through green. Result 1 red, on the workspace keeps each artboard column width declared exactly once. The guard is now positionless and catches a re-add anywhere in the file.

One consequence of the routing, stated once

The deletion and the guard now live in #1556 only. #1549 stays at 82fa5ef8, which carries the 56/232 roots and the five stale overrides. That is a deliberate choice and it preserves ux-lead's approvals, which is what I suggested — but it makes merge order load-bearing rather than cosmetic:

  • #1549 alone on main = the inversion I reported, live.
  • #1549 + #1555 = same, since b6adfa35 also carries 8 declarations.
  • All three = correct.

Under the ruled press — three within an hour, one deploy — that is fine. It stops being fine if #1556 is held for any reason after the first two land, and #1556 is the PR most likely to be held, since it is the one still taking UX rounds.

Cheapest insurance if that risk is unwelcome: cherry-pick the five deletions into #1549 as well. They are idempotent with the guard, and #1556 would then be a no-op for that file. Not asking for it — flagging it so the order is chosen rather than assumed.

Standing items, unchanged

V2Thread.tsx against DoD 2's "small components"; the .v2-shell duplicate rule heads and the two-accessor situation in the invariants file; and the mechanical class-binding sweep that would generalise the .v2-thread fix. All three are follow-ups, none blocks this head.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: APPROVED @ 7ef104e — built the stack top and walked at 1440, 1200 and 390 (sheet in Sprint HQ). The last item is closed: desktop row meta now author 14/600 and time IBM Plex Mono 12 muted (phone 15 / 12). Grid 56 / 232 / 788 / 300 at 1440 and 56 / 232 / 548 / 300 at 1200 with the stale tablet tokens deleted here; rows 28px square r4 avatars with no ring, r4 bordered hover bar; Bricolage name 22/28 with inline description; mono working line with the cobalt dot; 28px outline toggles at both widths; no rail, white page, four-tile tab bar and box + 44px ink square Send at 390; sheet and drawer exclusive; cobalt fills = brand + selected room (+ card primary when open). Not walkable on the smoke account: live decision card, ruled row, telegram tag, working > 0, tab badge — Sam's whole-workspace look needs Sharpen. Clear to press with #1549 82fa5ef and #1555 b6adfa3 within the hour.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: APPROVED @ b7dd542 — diff read against the walked 7ef104e (lily-shen's three pre-press deltas, no new walk per 64030). (1) Phone: inspectorCollapsed initialises true under (max-width: 760px) and a matchMedia change listener re-collapses it, so the sheet starts closed and opens only from the control. (2) Inspector label: shortRoomName() takes the leading segment before · — – : |, lowercased; .v2-workspace-inspector__label is one line (nowrap, overflow hidden, text-overflow clip) in mono 11. (3) Working dot: ::before muted by default, cobalt only with .v2-thread__working--active when onlineAgentCount > 0; guards added for all three. One non-blocking note: at ≤760 the mobile working TEXT stays cobalt (.v2-thread__working--mobile color: var(--v2-accent-text)) while the dot goes grey at 0 — if you want the phone line fully quiet at zero, move that colour under --active too. Stack stands approved: #1549 82fa5ef, #1555 b6adfa3, #1556 b7dd542.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code gate at b7dd5429. Both behavioural guards discriminate. One observation about the phone fix that no test covers.

Baseline 114/114 across v2-layout-invariants, V2LayoutSelection, V2Inspector and V2ThreadDeliveryHint.

Delta 3 — the working dot

Mutation: force workingClass to always be ' v2-thread__working--active', i.e. cobalt at zero agents, the exact defect. 2 red — the thread header is the artboard's name, muted description, and working count and V2Composer send button › uses the artboard's compact working count in the thread header. Two independent readers, one on the stylesheet and one on the rendered header. Good.

Delta 1 — the phone sheet, and a redundancy worth knowing about

a phone starts with its inspector sheet closed even when desktop left it open is real, but it took two mutations to characterise:

  • Revert only the lazy initializer (isPhoneViewport() ? true : readInspectorCollapsed()) → 7 passed.
  • Revert the initializer and the closeInspectorOnPhone() effect → 1 red, that test.

So the property is enforced twice and the test pins the property, not either mechanism. That is not a vacuous guard — after the first mutation the behaviour is still correct, so green is the right answer.

The gap is what the two mechanisms do differently. The effect closes the sheet after first render; the initializer prevents it opening at all. With only the effect, a phone entering the route with v2.inspectorCollapsed = '0' renders one frame with the sheet up, then it snaps closed. The test cannot see that — RTL asserts the settled DOM — so if someone later removes the initializer as "redundant", the suite stays green and the flash returns.

Same shape as the v2 dark-flash and the login-payload badge: correct end state, wrong first frame, invisible to the tier that guards it. Not asking for a fix — the initializer is there and correct. Worth a one-line comment on it saying it exists to prevent the first-frame flash and is not redundant with the effect, since that is the note that stops the next reader deleting it.

Delta 2

uses the short lowercase room name in the single-line agents label is a straightforward render assertion and covered.

Confirmation requested

No invariant moved: the stylesheet guards are unchanged in count and content apart from the two additions above, and the token, cobalt-allowlist and class-binding guards all still pass at this head.

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: APPROVED @ 1d9b274 — re-stamp of b7dd542: the only delta is a comment in V2Layout.tsx (no non-comment lines change outside tests). Stack stands approved: #1549 82fa5ef · #1555 b6adfa3 · #1556 1d9b274.

@samxu01
samxu01 force-pushed the feat/v2-workspace-inspector-artboard branch from b6adfa3 to bcb58d7 Compare September 6, 2026 01:40
@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from 1d9b274 to f8721f9 Compare September 6, 2026 01:40

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: APPROVED @ f8721f9 — restack of the approved 1d9b274 onto #1555 bcb58d7: the PR's non-test patch against its base is line-identical to the approved one (the sidebar-attention conflict resolved to the same lines). Thread / card / composer walk from 7ef104e and the b7dd542 diff-read stand. Stack clear: #1549 43e237c · #1555 bcb58d7 · #1556 f8721f9.

@lilyshen0722
lilyshen0722 changed the base branch from feat/v2-workspace-inspector-artboard to main September 6, 2026 01:49
@samxu01
samxu01 force-pushed the feat/v2-workspace-thread-artboard branch from f8721f9 to fe5358f Compare September 6, 2026 02:12

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: APPROVED @ fe5358f — carried from f8721f9: rebased onto main b0b4759 (#1555 merged); the PR's patch against its base is line-identical to the approved one, both with tests excluded (nothing that renders changed) and with all files included (nothing at all changed). Clear to press 3; I walk commonly.me live at 1440 + 390 after the single Deploy Dev.

@lilyshen0722
lilyshen0722 marked this pull request as ready for review September 6, 2026 02:24
@lilyshen0722
lilyshen0722 merged commit f2640bc into main Sep 6, 2026
15 checks passed
@lilyshen0722
lilyshen0722 deleted the feat/v2-workspace-thread-artboard branch September 6, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant