Skip to content

feat(cloud-sync): Runtime Sync tab, per-repo sync coverage, Channels-first sidebar - #650

Merged
beruro merged 3 commits into
developfrom
feat/cloud-org-sync-tab-coverage
Aug 2, 2026
Merged

feat(cloud-sync): Runtime Sync tab, per-repo sync coverage, Channels-first sidebar#650
beruro merged 3 commits into
developfrom
feat/cloud-org-sync-tab-coverage

Conversation

@sudomaggie

Copy link
Copy Markdown
Collaborator

Summary

Adds a Sync tab to Runtime → cloud org (same content as org management → Sync), plus a Session coverage section on that shared tab showing one row per repo with the share of sessions synced to the org. Also moves cloud Channels above Team Sessions in the sidebar.

Problem

  • Sync diagnostics (last-sync, manual trigger, connection health, journal) existed only in org management — Runtime users had to leave the surface to check whether sync worked.
  • Nothing answered "how much of my work in this repo is in this org?" A repo could be mostly unpushed with no way to notice.
  • Channels rendered below the unbounded Team Sessions list, so they got pushed off-screen.

Solution

One shared tab. New CloudOrgSyncTab wires useCloudOrgSyncStatus to CloudOrgSyncSection; both surfaces mount it, so they can't drift. Probes now fire when the tab opens rather than on every panel mount.

Per-repo coverage. New pure module org2CloudSyncCoverage.ts renders one row per org repo scope — scope string, synced/syncable, meter, percentage — with totals in the section title. Sessions resolve through the same path the push pass uses (getSessionScopeKeyspeekMatchingOrgRepoScope), so rows carry the exact scope string the engine pushes as repoScopeKey. Sessions outside every org scope are excluded from rows and totals, so the percentage means "of the work this org can receive."

Denominators reuse the engine's own filters — isPrimarySessionListSession (drops subagents/workers) and isCloudPushCandidate (drops teammate copies). Numerator is the durable push marker, so counts survive restarts.

Also: manual-sync outcome note moved left of the primary button. i18n across all 13 locales.

Sidebar (separate commit, unrelated): Channels lead Team Sessions; merge extracted to mergeCloudSidebarSections for test coverage.

Potential risks

  • Coverage is local evidence, not a server read — sessions pushed from another machine aren't counted; clearing local storage resets it until the next pass.
  • Rows depend on async scope-key resolution; the section can be briefly sparse on a cold cache (hook subscribes via useShareableScopeKeyVersion).
  • An unhydrated repo-scope mirror shows the empty state rather than a wrong number — deliberate, but looks empty for a moment after launch.
  • The tab now subscribes to sessionsAtom (hot); O(sessions) per change while open.
  • Sidebar reorder is a visible behavior change. Neither change was exercised against a live app.

Validation / Test plan

  • tsc --noEmit clean · eslint clean, no new suppressions
  • 1213 tests / 133 files pass across Org2Cloud/, CloudOrgPanelView/, dataSource/
  • 84 tests / 14 files pass across WorkstationSidebarConnector/
  • New: 18 coverage unit tests (grouping, org-scope-only, in-flight skip, ordering, rounding), section-render tests (rows, empty state, bar edges, note/button order), hook tests through the real resolver, Runtime tab-switch test, sidebar ordering test

Manual before merge: open Runtime → cloud org → Sync wit

sudomaggie and others added 3 commits August 2, 2026 14:59
Runtime → cloud org gains a Sync tab rendering the same content as org
management → Sync. Both surfaces now mount one wired CloudOrgSyncTab so
they cannot drift apart.

Adds a Session coverage section to that shared tab: one row per repo scope
the org has configured, showing synced/syncable and a percentage, with the
device-wide total in the section title.

Rows are scoped to the org's own repos. A session is resolved through the
same path the push pass uses (getSessionScopeKeys → peekMatchingOrgRepoScope
against the org's repo-scope mirror), so a row is labelled with the exact
org-side scope string the engine pushes as repoScopeKey. Sessions outside
every org scope are excluded from both the rows and the totals, so the
percentage means "of the work this org can receive".

Denominators reuse the engine's own candidate filters: subagent and worker
transcripts are dropped (isPrimarySessionListSession), as are teammate
copies pulled down from an org (isCloudPushCandidate). The numerator is the
durable push marker, so counts survive a restart.

The manual-sync outcome note now renders before the primary button so it
sits to its left in the right-aligned control cell.

Pre-commit hook ran. Total eslint: 1, total circular: 0
Channels rows now sort above Team Sessions instead of below. Both are
org-scoped server data, but Channels is the smaller, stable set and reads
better as the section header of the cloud scope; Team Sessions grows
without bound and pushed Channels off-screen.

Extracts the merge into mergeCloudSidebarSections so the ordering is
covered by a unit test rather than only observable through the assembled
sidebar. The My Sessions separator is still appended downstream by
buildCloudScopedMenuItems.

Pre-commit hook ran. Total eslint: 0, total circular: 0
@beruro
beruro merged commit 038e18c into develop Aug 2, 2026
3 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.

2 participants