Repository navigation
Batch 2026-10-01 (2): drive-unreachable screen, view tabs, row comments, AI fixes, presence order, vault quiet, canvas selection (12 PRs) - #1966
Merged
Conversation
A table row is a resource of its own, so its comment thread is already the ordinary one — Messages whose `about` points at the row. What was missing was a way to reach it: the Comments panel could only ever be about the page's own resource, and a row is never that. Two pieces: - The grid takes a `RowHeaderAddonComponent`, rendered in each row's gutter left of the row number. It knows rows only by index, so the table page supplies the index -> subject mapping (`getRowSubject`) and the component. The gutter is widened to hold a bubble beside the row number, and row-scoped affordances marked `data-row-affordance` are revealed by hovering anywhere in the row rather than only over the gutter. - The panel gains a target. `commentSubject` says which resource the thread is about, `undefined` meaning the page's own — what the NavBar button opens. Aiming it at another resource switches threads instead of toggling, so clicking row 3's bubble while row 1's thread is up does what it looks like. A close request carries no target and so cannot be expressed as a toggle: `closePanelState` closes the panel whatever it is aimed at, which is what a deleted target, a navigation and the drawer's own dismiss all need. The bubble stays put, with its count, for a row that has comments (highlighted while some are unseen) and appears on hover for one that has none. Not covered: reaching the bubble by keyboard. It shares the gutter's mouse-only reachability with the existing expand button, because the grid owns Tab for cell navigation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SooZ4RQshFY8YncRNq6Qpe
The gutter bubble never appeared for the rows it most needed to: the ones you had just typed. It asked the collection for every row's subject and treated `index >= memberCount` as "no resource yet", which is not what that boundary means. A row added this session keeps its local `_new:` key for its whole life on the page — materializing persists it but deliberately does NOT turn it into a collection member, so react-window never remounts it mid-edit. Past the member count sat real, saved rows, reported as having nothing to point at. So the context now reports which of the two kinds a row is (`rowSource`), mirroring what `TablePage/TableRow.tsx` itself renders, and the bubble uses the matching hook for each: `useMemberFromCollection` for a member, `useResource` on the `_new:` key for a session row, which the store aliases to the real subject once it materializes. The two cases genuinely need different hooks — a session row has no subject at all until then — which is why this reports the source rather than resolving to a subject. Caught by `table-row-comments.spec.ts`, which now passes end to end against a real server. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SooZ4RQshFY8YncRNq6Qpe
Choosing Calendar from the menu of a table's only view tab turned that view into a calendar, and the table layout was gone (#1806). The user should always be able to switch between all the applicable views. - A tab's menu now has an "Add a view" section (built-in kinds and apps), the same as the + tab: it adds a view named after the type and switches to it, leaving the tab's view intact. - "Change this view to" is offered only while another view of the current type remains, so the last table view (or the only view of an app) can never be converted away. setViewKind enforces the same rule and adds a view instead. - Delete is disabled on the last table view while other views exist. - A converted view whose name was a default ("Default View", a type label, a template view name, or an "All <rows>" table name) takes the new type's name; a name a person chose is kept. Closes #1806 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
useDriveApps published nothing until its whole mount chain had finished:
findSchema, the local app query, then an awaited getResource per app, one
after the other. Live events that landed meanwhile were held back too. After
a reload, an app whose sync delta could not apply to the page's copy
("incomplete Loro import ... missing base state") sits as a placeholder under
repair, and getResource waits up to 10 s on it, which is as long as the
money e2e waits for the "New app" menu item.
- Attach the listeners before anything else and fold every answer in as it
arrives, reading the live resource each time, so no answer overrules a
newer one and no slow read holds back the others.
- Read the query's members in parallel.
- Expose refresh(), and call it when "+ Add view" and a view tab's menu
open, so opening a menu re-runs the query and re-reads what it knows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sets up a fresh Claude Code on the web container so agents can lint, test and run the stack straight away: the pinned Rust toolchain and WASM targets, wasm-pack, wasm-opt, pnpm install, the @Tomic package builds, Playwright's browsers for @tomic/e2e and a warm debug build of atomic-server (which also builds data-browser and the WASM). Two sandbox workarounds: - The proxy blocks cdn.playwright.dev, so the Chrome for Testing builds come from the storage.googleapis.com mirror. - Containers have no IPv6, so ATOMIC_IP=0.0.0.0 is exported for the session; atomic-server binds to :: by default and fails otherwise. Only runs when CLAUDE_CODE_REMOTE=true. .gitignore now tracks the shared hook and settings while keeping local .claude state ignored, and AGENTS.md says to keep the hook in sync with the environment requirements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168N2XS6KXcewxhP3XTwDa6
The 45 second stall notice is a fixed deadline, so a machine that is slow and one that is stuck report the same thing. Sentry ATOMIC-BROWSER-1J holds twelve of them across four releases, spread over every step (identity 7, workspace 3, storage 2, and one that never left the sign-in check), from Chrome on Windows and Mac alike, and nothing in them says which kind it was. Setup measures 17 to 28 seconds on a desktop CPU, so 45 seconds is under twice the ordinary time, and a slow laptop could reach it while still making progress. The report now carries how long each step took and whether the tab was in the background, which browsers throttle. And a run that does finish after the notice sends a second, informational report with its total time and its slowest step, so a stall that ends is a slow machine, and one with no such follow-up is a hang. That is all this changes: what to fix depends on which of the two the reports turn out to be, and twelve events do not say.
The message was the same for the status check, both start calls and both finish calls, and dropped the HTTP status. It now ends with the request and status, for example (/use/finish: 401).
Only a cloud environment's setup script is cached between sessions; hooks run every session on a fresh clone. The previous hook redid the whole cold setup, server build included (10-20 min), while blocking the session. Split it in three: - cloud-setup.sh installs toolchains, node_modules, Playwright browsers and crates, skipping what is present. It fits the setup script's five-minute cache limit (about a minute from cold), so AGENTS.md suggests calling it from there; the hook also runs it, so sessions work without that. - cloud-build.sh builds the @Tomic packages and the debug atomic-server, writing packages.done / server.done markers under /tmp/atomic-setup. - session-start.sh exports ATOMIC_IP, runs cloud-setup.sh, starts cloud-build.sh in the background and tells the agent, through additionalContext, how to wait for it. With a cached environment the hook now blocks for about a minute (mostly linking node_modules) instead of the full build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168N2XS6KXcewxhP3XTwDa6
A second tab signing in as a different account takes over the shared portal cookie. A backup pass the first tab already had in flight then reaches the control plane as that account and is told the enrollment does not exist, which was logged as a failed backup. When the signed-in account no longer matches the one the pass started for, it is now skipped quietly, like the 401 case.
A drive with no copy here and nothing to fetch it from (a local-only drive while no other device is open, or no server at all) now gets its own page: what is going on, the Cloud Vault restore first when a backup exists, a device diagram, automatic retries every 10 seconds, and the raw error under Technical details. The open drive counts as a drive even before this device registered it as local-only.
subscribePresence() is deferred behind authenticate().then(), while the presence manager sends its first update (and reSubscribeAll() its rebroadcast) synchronously. The update reached the server ahead of the subscribe frame and was dropped as 'presence update from non-subscriber'. Hold presence updates for a drive while its subscribe is pending and send them right behind it. Nothing is held before authentication, and a withdrawn subscription drops what was held, so the server's subscribe-time read check stays the only gate.
# Conflicts: # browser/CHANGELOG.md
…ng a raw error # Conflicts: # browser/data-browser/src/locales/de.po # browser/data-browser/src/locales/en.po # browser/data-browser/src/locales/es.po # browser/data-browser/src/locales/fr.po
…e the last one # Conflicts: # browser/data-browser/src/locales/de.po # browser/data-browser/src/locales/en.po # browser/data-browser/src/locales/es.po # browser/data-browser/src/locales/fr.po
# Conflicts: # browser/data-browser/src/chunks/AppPage/useDriveApps.live.test.tsx # browser/data-browser/src/chunks/TablePage/TableViewTabs.tsx
Resolved: RightPanelContext keeps develop's overlay block and adds commentSubject. Fixed: an unsaved draft row (develop now pre-mints drafts with their final subject) no longer shows a comment bubble; it is hidden while resource.new.
Resolved against develop's #1876 startRun: the step callback keeps the performance.mark and now also records stepStarts. DemoManifest is no longer used here.
…de-less return link
…witched account
); HANDLE_HIT_RADIUS gets its doc comment back (#1962)
…f a type from being converted
This was referenced Oct 1, 2026
…can call (e2eTestResults was 'unknown command')
… ten millisecond tests at 5 s
- CanvasPage: the develop merge declared FAN_DRAG_THRESHOLD twice (#1962 landed on develop and in this batch); keep it once, each constant with its comment. - #1960: usageMetadata/compactionTokens as a pure module with tests, including that the last tool step's input wins once the SDK merges every part. - #1523: rowIsCommentable, tested with a real deferred-genesis draft from the store (final subject, still new) and the legacy _new: key. - #1941: DriveUnavailable test: the 10 s retry and Retry now must not leak a rejection (fails with an unhandled rejection without the fix).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Joep
Before: finished PRs by Joep, Polle and Michiel each waited for a Mancave run. Some were behind develop, and some had small bugs that only show up combined with current develop.
After: they sit together on one branch off develop (1f892aa, after #1947), decided by one full run. Squash-merge this, then close the included PRs. Every PR was read before it went in; big or impactful ones stay out with a review comment.
Included:
onboarding-existing-tab)Fixes made while batching:
newResource({ deferGenesis: true })), so the_new:prefix check no longer caught them. The bubble is now hidden whileresource.new.RightPanelContextkeeps develop's overlay block and addscommentSubject.kanban.spec.ts"view tab menu…" andtimer.spec.ts"the duration is view config…" converted the only view of a type, which Add a view when choosing a type from a tab, never replace the last one #1902 now refuses (the reason they failed in Batch 2026-10-01: table quick filter, proxy return, commit extenders, e2e traces, Android menus, demo tooling, docs (11 PRs) #1947). Both now duplicate the view and convert the copy, so they still test conversion and config carry-over.TableViewTabskeeps Add a view when choosing a type from a tab, never replace the last one #1902'stypesBySubjectand Ask the drive for its apps again when a view menu opens (#1846) #1904's{apps, refresh}. Add a view when choosing a type from a tab, never replace the last one #1902's test mock returns that shape, and the live test keeps develop'sconnect: false.DriveUnavailableletfetchResourceFromServerrejections escape, both the 10 s retry and Retry now (a local-only subject throws every time). They are now caught.startRun. The step callback keepsperformance.markand recordsstepStarts. The unusedDemoManifestimport is gone.HANDLE_HIT_RADIUSgets its doc comment back.de.pokeeps its 12 translations.Left out, with reasons on the PRs:
Superseded: List a drive once across did:ad: and atomic: spellings #1943 (by List a drive once when its address is spelled two ways #1937), Correct client clock skew for commits and auth proofs #1942 (by Batch 2026-09-30: clock skew, vault restore, connect dialog, twin agent, Google sign-in #1946), Better unavailable-drive screen and fix Cloud Vault restore for large vaults #1939 (by Batch 2026-09-30: clock skew, vault restore, connect dialog, twin agent, Google sign-in #1946 and Explain a drive this device can't reach instead of showing a raw error #1941).
Review needed: Open big drives and busy chats fast: sparse sync, batched writes, capped sidebar, paged chat #1921, Move the browser workspace to pnpm 11 (split out of #1281) #1931, AI chat: Try again continues a failed reply instead of discarding it #1963, AI chat: keep the reply running when leaving the chat page #1961, Stop running out of peer sessions with many tabs and drives #1959, Trust vanity hosts the server has a drive mapping for #1958, Live updates and full lists for things shared out of other drives #1949, Link the device's identity to the signed-in account #1948.
Needs a fix first: Table: quick text filter across all columns (#1881) #1894 (table-refresh reload hang), Faster branch runs and no silent frontend rebuilds #1956 (the build stamp can embed a stale frontend), Use one profile form for signup, share and invite #1953 (paired with an atomic-saas branch).
In another batch: Hosted builds open on sign-in, not the welcome screen #1911–Stop the sync page repeating account requests every five seconds #1914, Report writes that keep failing to Sentry #1918, Fix Cloud Server setup leaving the node without the drive #1919.
Run 36906311895 failed only on 10
@tomic/libunit tests that all hit vitest's 5 s timeout together (for example "signs any string correctly", which takes milliseconds) while Mancave was saturated.browser/lib/vitest.config.tsnow setstestTimeout: 20_000.The trace collector is renamed to
failedTestResults. The Dagger CLI couldn't calle2eTestResults("unknown command"), so develop's Batch 2026-10-01: table quick filter, proxy return, commit extenders, e2e traces, Android menus, demo tooling, docs (11 PRs) #1947 run collected nothing.Develop merged in again (85163ab): Canvas: stronger selection, recolor the selection, reliable color taps #1962 landed there separately, plus the demo-test reload budget and table-reload diagnostics.
Checked locally: data-browser and e2e
tsc,pnpm run -r lint, and data-browser vitest 1519/1519. The only@tomic/libfailure isgenesis-roundtrip.integration, which needs atomicdata.dev'sloroUpdateproperty; that currently 404s from outside CI.