Skip to content

v0.7.58: styling improvements, files dimensions - #6303

Merged
waleedlatif1 merged 9 commits into
mainfrom
staging
Aug 6, 2026
Merged

v0.7.58: styling improvements, files dimensions#6303
waleedlatif1 merged 9 commits into
mainfrom
staging

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

icecrasher321 and others added 9 commits August 5, 2026 11:44
… Platform (#6286)

* feat(library): Sim vs Dify: Open-Source AI Workspace vs LLM App / RAG Platform

* feat(library): Sim vs Dify: Open-Source AI Workspace vs LLM App / RAG Platform

---------

Co-authored-by: Sim Pi Agent <pi@sim.ai>
* feat(tables): support plain predicates in v2 queries

* fix(tables): regenerate tool metadata

* fix(tables): bound predicate validation
…ip to Chat (#6296)

Sidebar: 11 separator groups become 5, with each module a collapsible folder
that auto-opens on the active page. 61 always-visible rows drop to 16. Groups
mirror the app's own nav (Chats/Workspace/Workflows) rather than inventing a
taxonomy; Enterprise and Self-Hosting are hoisted out of Platform.

Chrome: register the `hover-hover` variant, without which every @sim/emcn hover
state silently compiled to nothing; restore the sidebar's Geist font stack; add
11 emcn tokens that were falling back to currentColor; adopt the named type
scale; align row geometry, hover tokens and group labels with the app.

Rename: mothership/ -> chat/ with redirects for the old URLs. Asset paths,
the @mothership.sim.ai domain and the `mothership` log-trigger enum value are
deliberately left alone -- they are CDN objects, a real domain, and a live
product value.

Also removes the page-type badge, drops the "Next" heading from the ToC, and
lets FAQ rows open independently so expanding one no longer shifts the page.
…6293)

* fix(files): stop a cached collab snapshot resurrecting blank lines

A collaborative markdown file's cold-start seed can come from a cached Yjs
snapshot (workspace_file_collab_state.doc_state) rather than a fresh markdown
re-parse. The snapshot is a raw CRDT binary, so it preserves top-level empty
paragraphs that parseMarkdownToDoc/stripEmptyParagraphs strips from every parse
target. The static placeholder always re-parses (clean); a warm seed replays the
snapshot verbatim, so a stray blank line appears once the doc settles — and only
intermittently, since a stale/cold cache falls through to the clean re-parse.

Enforce the same no-top-level-empty-paragraph invariant on the Yjs side:
- normalize.ts: stripEmptyTopLevelParagraphs(doc) shared helper.
- seed.ts: repair the cached snapshot on read (self-heals legacy snapshots,
  preserving CRDT client ids; no data migration).
- persist.ts: normalize before caching so new snapshots are clean by construction.

* refactor(collab-doc): make COLLAB_DOC_FIELD a single canonical constant

converter.ts had a duplicate 'default' fragment-name constant; import the now-exported one from normalize.ts so the value TipTap's Collaboration binding depends on lives in exactly one place. Fold the back-to-front loop note into the helper's TSDoc.
…ss the panel (#6297)

* fix(editor): restore caret alignment and the intended type scale across the panel

Four distinct defects, all surfaced while testing the workflow editor.

**Caret drift in the Start block's Description field.** Its overlay mirror was
built differently from every sibling field: `overflow-hidden` + `truncate` and
no scroll synchronisation, where the working fields use `overflow-x-auto` +
`whitespace-pre` + `syncOverlayScroll`. Once the value passed the visible width
the input scrolled and carried the caret with it while the overlay stayed pinned
at the first character, so the gap grew as you typed. It now has the same
plumbing as its siblings, on its own ref maps so it cannot collide with the value
overlay.

**Overlay mirrors left at 500 over 400 inputs.** #6291 dropped emcn Input and
Textarea to the inherited weight, but the canvas files that mirror them were
reverted from that PR, so 11 overlays kept a hardcoded `font-medium`. A mirror
that renders heavier than the input beneath it misaligns by the weight delta on
every character. All 11 realigned.

**Input text tracking differently from its label.** The UA stylesheet resets form
controls to `letter-spacing: normal`, so inside `.workspace-root` (0.02em) an
input diverged from surrounding text — and from its own overlay — by 0.28px per
character. emcn Input and Textarea now carry `[letter-spacing:inherit]`, which
fixes every mirrored input at the source rather than per call site.

**Weights and type sizes that changed meaning under #6241.** That PR deleted the
tailwind remap of `font-medium` (440 light / 480 dark) without migrating the
~505 call sites written against it, so untouched code jumped to a stock 500. The
panel's editor, toolbar, chat and connections surfaces are swept back to the
inherited weight. The Chat header was also visibly taller than Toolbar and Editor
purely because it used `text-[14px]` — font-size with no paired line-height —
against otherwise byte-identical containers; it and the panel's two other
arbitrary sizes now use named tokens.

Also fixes five JSX conditionals in the workflow MCP settings page that had lost
their braces, so `canManage && ()` rendered as literal text under the server
detail tab.

Verified: typecheck 0, biome clean, 18644/18645 vitest passing (the one failure
is a missing `rg` binary and predates this branch).

* fix(emcn): give chip text fields the same tracking as their mirrors

An audit of the previous commit found the letter-spacing fix was incomplete: it
landed on `Input`/`Textarea` but not on the chip family, so `ChipInput` and
`ChipTextarea` kept the UA `letter-spacing: normal` while any overlay mirroring
them inherited the ambient tracking.

The MCP server form modal is a live instance — its shared `FormattedInput` layers
a transparent `ChipInput` under a visible div, across the server URL and both
header fields, whose values are long by nature. The caret separated from the text
by roughly 0.28px per character.

Fixed on `chipFieldTextClass` rather than the call site, so every chip field
matches its mirror the way `Input`/`Textarea` already do.

* fix(editor): restore the strong-text variant a class sweep welded together

The font-weight sweep in 94c9f1f used a blanket sed, which turned

  [&_strong]:font-medium [&_strong]:text-[var(--text-primary)]

into [&_strong]:[&_strong]:text-[var(--text-primary)] — a chained variant
matching a <strong> inside a <strong>, so ordinary strong text in trigger setup
instructions lost its color.

The removed weight was also load-bearing rather than decorative. Preflight sets
b/strong to font-weight: bolder, so against a 400 body a bare <strong> lands near
700; the class was holding it down to 500. Deleting it made that text heavier,
the inverse of the sweep's intent — the same UA-default trap as <th>. Both
variants are restored.

Swept for the same damage: no chained [&…]:[&…] variants remain across apps/sim
or packages, and this was the only variant-scoped weight the sed touched.

Found independently by Greptile and Cursor Bugbot.
Bumps TABLE_LIMITS.MAX_COLUMNS_PER_TABLE from 50 to 1000. Every validation site (schema validation, add-column, bulk add, workflow output columns, and the boundary contract) already derives from this constant.
* fix(docs): stop the sidebar drifting when page content resizes

The sidebar used fumadocs' `sticky` positioning, and a sticky box is
bottom-limited by its containing block. #nd-docs-layout ends ~660px above the
document bottom because the site footer is a sibling of the layout rather than
a grid child, so across the whole footer the sidebar was pushed progressively
upward. Any content-height change while the reader sat in that zone then moved
it: expanding one FAQ row shifted the sidebar 16.8px at a fixed scroll offset,
and collapsing it shifted it back.

Pin the sidebar and its divider to the viewport instead. A fixed box ignores
both the container's end and the document height, so neither the drift nor the
jump can happen. The grid columns are explicit (`0px 300px 1fr 268px 0px`), so
taking the placeholder out of flow leaves its track intact and the content
column does not move. The footer is already opaque and now out-stacks both, so
it slides over them at the end of the page.

Measured with Playwright before and after: sidebar delta on expand/collapse
16.8px/-16.8px -> 0px/0px, content column left and width unchanged, and the
sidebar holds top:92px at the page bottom on the docs, API-reference, academy
and integrations layouts. Mobile is untouched (the rule is desktop-only).

* refactor(docs): drop dead grid placement, move footer stacking to the component

Review follow-ups. The divider's `grid-row`/`grid-column` stopped doing anything
the moment it became `position: fixed` — a fixed box is out of grid layout
entirely — so they and the comment explaining the grid span were describing
positioning that no longer happens. Verified inert: the divider still computes
to left 300px / width 1px / z-index 21 without them.

The footer's stacking context also belongs on the footer, not in a global rule
matching every desktop `footer` element, so it moves to the component as
`relative z-[22]` with the reason in its TSDoc.
…ad (#6299)

* fix(files): reserve image layout space so images stop reflowing on load

A markdown image with no stored dimensions reserved zero vertical space until
it downloaded, then snapped to its natural height and pushed content below it
down (cumulative layout shift). Reserve the box up front from the image's
intrinsic aspect ratio instead.

Store intrinsic width/height as workspace_file metadata (not in the markdown —
it stays clean `![](src)`), read it synchronously from the already-loaded file
list to reserve a responsive aspect-ratio box on first render, and lazily
backfill it once per image on first view via a write-gated, idempotent PATCH.
The node view falls back to on-load measurement for the first-ever view and for
external images. Images stay fluid (max-width:100%, height:auto).

* fix(files): address review — reserve on stale memo, clear dims on content swap

- onLoad guards on the memoized storedDimensions the render uses (not a fresh
  cache read), so a sibling's non-reactive backfill can't leave a view unreserved.
- updateWorkspaceFileContent clears width/height when it swaps bytes, so stale
  dimensions can't be reserved for new content (and the null re-enables backfill).
- Keep optimistically-cached dimensions when the PATCH fails (correct measurement;
  a 403/transient error shouldn't wipe sibling reservations).
- Test imports the sibling via the absolute @/ path.

* fix(files): re-derive image dimensions on content swap instead of clearing

Clearing width/height to NULL on a content swap reopened the width IS NULL
backfill path, so a late fire-and-forget PATCH for the previous image could
write its stale size onto the new content. Instead, measure the new bytes'
intrinsic dimensions server-side (image-size, headers only) and store those
(or null for a non-image), so the row always matches the current content and a
stale backfill can't apply.

* fix(files): self-heal image dimensions from the browser instead of server-measuring

Round-3 review: server-side image-size returns raw (non-EXIF) dimensions, and
clearing dims on content swap reopened the stale-PATCH race for non-image or
unmeasurable content. Move authority to the browser's own naturalWidth/Height
(EXIF-correct): the node view reserves from it and reports on any mismatch, and
updateWorkspaceFileDimensions overwrites (no width IS NULL gate) so stale values
self-correct on the next view. Reverts the server-side measurement and the
content-swap dimension touch entirely.

* fix(files): clear image dimensions on content swap (completes self-heal)

The self-heal rework left the old image's dimensions in the row after a content
replacement, so the next view of the new bytes reserved a wrong-sized box before
correcting. Clear width/height on the content-swap write so the row never
describes stale content: the next view falls back to the baseline first-load
reflow and the browser's measurement backfills the correct size. No server-side
decode (EXIF-safe), and the client's overwrite-on-mismatch handles a late PATCH.

* fix(files): guard dimension writes by content key so a stale PATCH can't persist

Ties the dimensions write to the storage key the client measured. The key is
regenerated on every content replacement, so an in-flight PATCH measured against
superseded bytes is rejected at the DB (WHERE key = measured key) instead of
persisting the old aspect ratio for new content. Closes the last stale-ordering
window Greptile flagged — the write is now content-version-conditioned, not just
corrected on the next render.

* chore(files): fix stale route TSDoc and hoist a regex literal (cleanup pass)

Post-review /cleanup: the dimensions route TSDoc still described backfill-once
behavior (now overwrite-on-mismatch via the content-key CAS); the bare-pixel
width regex is hoisted to module scope. No behavior change.

* fix(files): reflect the content-version guard outcome in the dimensions response

The route returned success:true even when updateWorkspaceFileDimensions matched
0 rows (the CAS rejected a write whose measured key no longer matches the row).
Return success:<whether a row was written> and widen the contract response to
{ success: boolean }. Not an error path — the client's next measurement persists
once its file list has the new key; this just stops the API claiming a persist
that did not happen.

* fix(files): reconcile the cache when a dimension write is content-version-rejected

Previously the client discarded a success:false (CAS-rejected) response, leaving
its optimistic patch — which is for superseded bytes — lingering in the file-list
cache. On rejection, invalidate the list so the cache reconciles with the new
content (whose real size persists on its next load). Deliberately NOT a retry:
re-sending the old measurement under the new key would write the wrong size. A
transport error / read-only 403 still keeps the optimistic value (it's the real
displayed size).

* docs(files): align stale dimension docs with the overwrite/self-heal behavior

Cleanup audit: the ImageDimensionsSource/reportImageDimensions interface docs and
one route log string still said backfill-once/no-op; the mechanism overwrites on
mismatch to self-correct. Wording only, no behavior change.
@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review (173 files, 100 file limit).

Bypass the limit by tagging @greptile-apps to review.

@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Building Building Preview Aug 6, 2026 12:55am

Request Review

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New file-dimensions PATCH and table predicate normalization are API behavior changes; the large docs URL rename depends on redirects being complete so external links do not break.

Overview
This release is mostly docs site work: Mothership is renamed to Chat across content and routes (/mothership/chat, plus /copilot redirects), the English nav is regrouped into Build / Workspace / Administration, and Diátaxis pageType badges are removed from frontmatter and the UI.

Docs chrome changes pin the sidebar and divider with position: fixed so the nav does not jump when long pages (e.g. FAQs) change height; footer stacking (z-[22]) covers the fixed sidebar. Sidebar styling aligns with the app (chip-sized rows, sentence-case section labels, no nested left border). TOC filters out ## Next / ## Next steps headings, and the clerk TOC active dot is hidden. hover-hover is registered in global.css so @sim/emcn hover utilities work under Tailwind v4. Page footer prev/next links drop redundant labels and social icons; FAQ rows can stay open independently.

Product/API (in diff): PATCH /api/workspaces/[id]/files/[fileId]/dimensions stores width/height keyed to the file’s storage key (write permission; success: false if content swapped). Table query routes accept a single root predicate and normalize it to the canonical { all: [...] } shape (covered by new tests).

Other items listed in the PR description (editor caret, collab blank lines, knowledge chunk scroll, column limit 1000, library page) are not in the attached diff.

Reviewed by Cursor Bugbot for commit 5dbe95e. Configure here.

@waleedlatif1
waleedlatif1 merged commit 54a3262 into main Aug 6, 2026
42 of 43 checks passed
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.

3 participants