feat(redesign): msc-redesign foundation (theme tokens + Plan tab)#37
Open
kevinthelago wants to merge 20 commits into
Open
feat(redesign): msc-redesign foundation (theme tokens + Plan tab)#37kevinthelago wants to merge 20 commits into
kevinthelago wants to merge 20 commits into
Conversation
Drops the new redesign mockups under design/msc-redesign/ so they are versioned source-of-truth for the implementation work that follows. Includes a Babel- transformed HTML preview, the shared scaffold (SessionStrip + PageHeader + BottomTabs primitives), shared CSS tokens, and five mockup screens: scaffold.jsx - shared Screen wrapper, 6 tabs incl. new Plan styles.css - CSS tokens; reads as 'marries dawn palette' screen-files-find.jsx - Files + Find mockups screen-edit-run-git.jsx - Edit + Run (multi-session) + Git mockups screen-plan.jsx - new Plan tab w/ 5 sub-screens (tunneled) screen-session-switcher.jsx - drop-down session switcher overlay Implementation lives in subsequent commits. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Foundation commit for the msc-redesign work (source in design/msc-redesign/). Adds the lowest-risk pieces so subsequent screen migrations compose against a stable base. - theme.ts: extend Theme with elev, elev2, borderStrong, accentDim, success, info, warn, danger, pink. dawn's values exactly mirror the design's styles.css :root (which the design notes 'marries dawn'); the other four themes get coherent palette-aligned values so the redesign primitives read correctly regardless of which theme is active. - TabIcons.tsx + BottomTabBar.tsx: add PlanIcon (kanban-board glyph matching the design's '▩' mark) and wire 'plan' into the ICONS/LABELS maps. The maps already had a fallback for unknown routes, so this is additive. - app/(tabs)/_layout.tsx: register the new Plan tab. - app/(tabs)/plan.tsx: minimal themed placeholder. Two states keyed on useTunnel(): 'tunnel offline → pair via Run tab' empty state, and 'coming soon' for the connected state. The full Plan surface (projects, kanban, issue/subtask, scoping) follows in later commits. - docs/redesign-status.md: tracks what landed and what remains, with a per-screen migration list and notes on stale CLAUDE.md references the reviewer caught earlier (run is no longer a placeholder; the standalone-first ethos in #12 needs to acknowledge the multi-agent pivot). tsc --noEmit green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…l, Btn) Pure additive components under src/components/ui/. Faithful port of the design's .msc-* CSS classes from design/msc-redesign/.../styles.css. No existing screen is changed yet — these are the building blocks for the per-screen migrations that follow. - PageHeader — github-style header: crumbs (mono, uppercase, fgDim, 0.6 letter-spacing) > title (large mono, ellipsised) + meta + right slot. - Card — lightweight bordered panel (surface + borderColor, radius 8). Distinct from Surface, which keeps its heavier blur/glass treatment. - Tag — monospace pill, variants default/amber/green/info/warn. The design's color-mix(in oklch, ...) tints are approximated with a small hexAlpha() helper that emits rgba() at the same 12% / 30% alpha steps. - SectionLabel — uppercase letter-spaced section header with count + optional pressable action. - Btn — sized + variant button (default / primary / ghost) × (md / sm). IconBtn is kept distinct for icon-only round buttons. Refs the design's bundled CSS at design/msc-redesign/msc-redesign/styles.css. tsc --noEmit green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
First per-screen migration. Reskins app/(tabs)/index.tsx to the redesign's github-style chrome using the new primitives; all real data wiring is preserved unchanged (useSession, buildTree, openFile, recents, filter, folder expand/collapse). - PageHeader: breadcrumb (repo > branch) + leaf title + meta line with the modified count in accent. Replaces the old 28px eyebrow/title header. - SectionLabel: 'Recent' and 'Files' headers; the Files label shows the file count and a dim 'tap folder to expand' hint (or 'N matches' when filtering). - Card: horizontal Recents cards (accent-tinted + accentDim border for the current file). - Tree: mono rows matching .msc-row — folder glyphs (▾/▸), file '·', current row gets an accent tint + 2px left border, modified files show a dirty dot. Removed the old SVG FolderChevron/FileGlyph in favor of the design's text glyphs. Also adds a prop to SectionLabel (dim, normal-case, right-aligned) so passive helper text is visually distinct from the accent affordance — the design uses fgDim for 'tap folder to expand' vs accent for 'clear'/'open ›'. Behavior change (noted in redesign-status.md): Recents now hide while a filter is active (previously always shown) — when filtering you want matches, not recents. tsc --noEmit green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Second per-screen migration. Reskins app/(tabs)/find.tsx to the redesign chrome; all real grep wiring is preserved unchanged (grepInText scan across downloaded files, scope/ext filtering, debounced run, MAX_* caps, openFile navigation to the Edit tab). - PageHeader: breadcrumb (repo > branch > search), the query as the title, and a "N matches · M files" meta line. - Search input restyled to the msc-input look; scanning spinner overlaid. - Scope chips + case-sensitive toggle now render as Tag (amber when active), with an "in: <scope>" info Tag indicating a non-"all" scope. The design's whole-word/regex tags are intentionally omitted — grepInText does not support them, so they would be dead controls. - Per-file groups: a mono, normal-case header (name · count · "open ›") rather than the uppercase SectionLabel (file paths are not section titles), and one Card per match line with the line number and an accent-highlighted match. Refactor: extracted hexAlpha into src/lib/color.ts (the design's color-mix(in oklch, ...) tint approximation) now that three call sites need it (Tag, Files, Find). Tag and Files updated to import it; no behavior change. tsc --noEmit green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Third per-screen migration, and the structural one: folds the chat into a bottom dock beneath the code viewport. All real wiring is preserved unchanged (useSession send/turns/chatBusy/saveCurrentFile/setCurrentContent, image attach/remove, tokenized code + plain editor, save/edit-mode toggle). - PageHeader: breadcrumb (path dirs) + filename title + "lang · ● modified" meta; right slot keeps the existing save (when dirty) / edit-mode toggle. - Chat dock: a status header (dot + "Claude · idle/working" + "N tools used" Tag), a height-capped scroll of recent turns, the image-preview strip, and a "›"-prefixed input bar in the msc-input style. - ChatTurnView reskin: Claude replies get an accent ◉ marker; tool calls render as compact "→ name(args) … ✓/✗" Cards (design's .msc-chat-tool) using the new success/danger theme tokens instead of hardcoded colors. - Dropped the Surface/TopPill/ClaudeAvatar chrome in favor of PageHeader + the dock; removed those now-unused imports. tsc --noEmit green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Fourth per-screen migration. Reskins app/(tabs)/git.tsx; all real wiring is preserved unchanged (pull/push/pulling/pushing, anthropicDraftCommitMessage, linked-issue ref composition, conflict reporting, M/A derivation from manifest). - PageHeader: breadcrumb (repo > branch) + branch title + "N changed"/"clean" meta + a push Btn in the right slot. - Action row: pull + switch-repo ghost Btns. - Changes: a SectionLabel + one Card per modified file (M/A badge tinted via hexAlpha, tap to open in Edit). - Commit message: SectionLabel whose action slot drives draft/regenerate (the former "Draft with Claude"; shows "add API key to draft" / "drafting…" hints), an editable message Card, linked-issue ref modes (refs/fixes/none) as Tags, and a commit Btn. - Dropped the Surface/ClaudeAvatar/SVG chrome. Honest omissions: the design's per-file +adds/-dels and "stage all" are not implemented — this app tracks neither line diffs nor a staging area (CLAUDE.md known issues), so rendering them would be fake controls. tsc --noEmit green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Bump expo-updates/expo-camera/expo-image-picker to their SDK 54 versions (expo install --fix); the mismatched majors crashed the iOS build at expo-updates' "Generate updates resources" script (@expo/cli MODULE_NOT_FOUND). - Call messaging().registerDeviceForRemoteMessages() before getToken() in initFcm — iOS throws [messaging/unregistered] otherwise. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…unpair Onboarding & credentials - Remove the blocking setup screen; app loads straight into the tabs. - Anthropic key is optional; prompt for it just-in-time via a modal (ApiKeyContext + ApiKeyModal) when the on-device agent is invoked. - GitHub PAT entered just-in-time in Settings. Settings (app/settings.tsx) - New grouped Settings screen (account/GitHub, AI key, tunnel, repo, theme, about/sign-out), reached via the ▦ button in SessionStrip. Navigation & visuals - Tunnel-first launch: tabs anchor on Run (initialRouteName), which is the QR pairing view when disconnected. - Unified background: ThemedFrame paints t.bg + Orbs + a BlurView frost; all screens render transparent on top (tab scenes set transparent). Tunnel (#16) - unpair() forgets the desktop (clears tunnel secrets, returns to standalone with repo state intact); disconnect() stays transient. - ConnectingView gains a Cancel escape. - Tagged tunnel logging (tunnelLog / [tunnel-tls]). Also includes a native cert-pinning module (TlsWebSocket) + QR cert fingerprint plumbing — superseded by the Noise-relay architecture and removed in the following commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The tunnel pivoted to a Noise-IK end-to-end layer over a real-TLS relay (WAN) and plain ws:// (LAN), so trust comes from Noise rather than the transport cert. Removes the now-dead pieces: - delete the native TlsWebSocket module (modules/tls-websocket/) - revert TunnelClient to the plain JS WebSocket; drop the fingerprint field/param - drop fingerprint from connect()/auto-connect/unpair and the TUNNEL_FINGERPRINT secret - remove QrPairingPayload (fingerprint shape) and revert the QR parser The Noise pairing payload + transport land next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pivot the mobile tunnel to the Noise-relay architecture (epic #210):
trust comes from a Noise IK end-to-end session, not the transport.
- src/lib/noise/noise.ts — Noise_IK_25519_ChaChaPoly_BLAKE2s state
machine (initiator + responder) on @noble/curves/ciphers/hashes;
injectable RNG so it stays pure/testable. MUST interop with Rust
`snow` — verify against the live relay before trusting it.
- scripts/noise-selftest.ts + `npm run test:noise` — JS round-trip
test: handshake, bidirectional transport, nonce increment, and
imposter-responder-key rejection. (Proves internal consistency, not
snow interop.)
- src/lib/types.ts — TunnelPairing payload {relayUrl, room, hostPubKey,
psk, lanUrl?}; src/lib/tunnelPairing.ts — pure QR parser.
- src/lib/noise/random.ts — on-device CSPRNG via expo-crypto.
- deps: @noble/curves+ciphers+hashes, expo-crypto.
- tsconfig: exclude scripts/ from the app typecheck.
Next: TunnelTransport interface + WAN relay impl (binary ws frames),
session controller, then UI — pending a proven handshake vs the desktop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Retire the snow-interop risk before building the transport/session/UI: a fixed-key Noise test vector (cacophony format) so the desktop's Rust `snow` can prove byte-compatibility with no live connection. - scripts/noise-vectors.ts → src/lib/noise/noise-vectors.json (msg1/msg2 + transport, both directions, from fixed static+ephemeral keys) - scripts/noise-interop.ts — replays the vector through the JS impl and asserts byte-equality (passes); the desktop mirrors this against snow - src/lib/noise/README.md — protocol params + what the desktop must assert + coordination points (prologue, framing, associated data) - npm: test:noise:interop, test:noise:vectors Handoff: base-studio-code asserts snow reproduces noise-vectors.json (and confirms the empty prologue). Mobile transport/session/UI follow a green interop on both sides. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…o-pair (#16) Wire the mobile tunnel to connect to the desktop through the zero-knowledge Cloudflare relay over an end-to-end Noise IK session, replacing the plaintext LAN-only client. The Noise machinery, relay-shaped TunnelPairing type, and QR parser already existed; this lands the transport that uses them (the gap from #197, the desktop half of which shipped in #240–#243/#251/#253). - `noiseSession.ts` (new): framing helpers — base64→bytes (QR hostPubKey), binary-frame coercion, a dependency-free UTF-8 codec, and sealFrame/openFrame that wrap one app JSON message in one Noise transport frame (raw ciphertext, empty AD — byte-matching the desktop's serde_json→write_message→Binary). - `TunnelClient` (tunnel.ts): dial `…/connect?room=<room>&role=guest`, receive ArrayBuffer frames, run the Noise IK initiator handshake (msg1 out → msg2 in → transport split), then send `auth { token: psk }` and carry every frame encrypted. Fresh handshake per (re)connect; a crypto/parse failure drops the socket so reconnect re-handshakes. - `connect()` now takes a `TunnelPairing` (relayUrl/room/hostPubKey/psk). The context persists/restores it as one JSON blob (`TUNNEL_PAIRING`) and unpair clears it; the pairing screen parses the QR via `parseTunnelPairing` and the manual fallback pastes the pairing JSON (long base64 keys can't be hand-typed). - `scripts/tunnel-selftest.ts` + `npm run test:tunnel`: in-process handshake + framing round-trip (auth frame, UTF-8 pane_output, nonce advance, tamper rejection, base64 hostPubKey decode). README coordination notes confirmed. Transport is relay-only (no LAN), matching docs/tunnel-protocol.md. Interop with the desktop `snow` responder still needs a live handshake to fully verify. Test: npm run typecheck (clean), test:tunnel (7/7), test:noise + interop (green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build the Plan tab (M-plan-*) under src/screens/plan/, hosted by app/(tabs)/plan.tsx via PlanRoot — an in-tab stack navigator gated on useTunnel(). The Plan surface mirrors the desktop project-planning views over the Noise relay; with no live tunnel it renders the pairing screen. - PlanProjects: on-host/other-host grouping, filter, new-project CTA - PlanBoard: horizontal column pager + in-progress card list - PlanIssue: labels/assignees, description, Claude subtask breakdown, activity feed, comment composer - PlanScoping: @Planner chat, progress strip, draft-milestone preview - PlanPairing: tunnel-offline state wired to useTunnel().connect Connection gating and pairing are real; the data-bearing screens use the design's fixtures (planData.ts) as a ready-to-wire presentation layer, since the tunnel protocol carries only PTY panes today. Shared primitives in planShared.tsx; design oklch hues approximated as hex. Added an optional style prop to Btn for composer flex layout. tsc --noEmit clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M-sessionstrip. Restyle the SessionStrip chips to the redesign vocabulary (theme tokens, accent-tinted active chip, success/idle/warn/error status dots, awaiting pip) and add the pulsing tunnel-connected indicator (design's .msc-strip-tunnel). Add SessionSwitcher — a drawer overlay (drops from top) that groups live PTY panes by project (cwd basename), shows all/awaiting/running/idle counts, and focuses a pane on tap (→ Run tab). The ▦ button now opens this hub instead of navigating straight to Settings; Settings stays reachable from the switcher header. tsc --noEmit clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M-run-align. Rebuild PaneGridView on the redesign primitives: PageHeader (base-studio-code › tunnel · 'N active · M awaiting input' · disconnect), an all/running/awaiting/idle Tag count row, and Card-based session rows with a status dot, project Tag, and a 2-line preview box. Awaiting-input sessions get the warn border + thicker left edge per the design mockup. Status colors now resolve from theme tokens (shared by the terminal header). Unpair preserved as a danger affordance in the tag row / empty state. All tunnel wiring unchanged. tsc --noEmit clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M-font. Add @expo-google-fonts/jetbrains-mono and point every theme's fontMono at 'JetBrains Mono' (the design's --msc-mono), replacing Menlo. The tab surface gates render on the font load (no fallback flash) and theme.ts kicks off a best-effort app-wide load for the onboarding screens. Pin expo-font to ~14.0.12 to match Expo SDK 54 (npm had pulled 56.x). tsc --noEmit clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Correct the authoritative agent reference to the architecture that shipped: - Frame MSC's two modes — standalone (GitHub REST) and tunneled (paired desktop over an end-to-end-encrypted Noise IK tunnel relayed through a blind Cloudflare Worker, NOT a direct desktop WebSocket server). - Add a 'Tunnel & multi-session' section (transport, pairing, sessions, Plan, disconnect/unpair) and a tunnel pairing/mirroring data-flow. - Update the ethos + folder tree for the 6-tab nav, the Plan tab, the tunnel libs (TunnelContext/tunnel/noiseSession/noise), the new ui primitives (PageHeader/Card/Tag/SectionLabel/Btn/SessionStrip/ SessionSwitcher), and src/screens/plan. - Add the Noise/tunnel test scripts to Commands. - Remove the stale 'Run tab is a placeholder' note; clarify Plan renders a ready-to-wire fixture layer until the relay carries planning state. Sync docs/redesign-status.md (Run/SessionStrip/font/CLAUDE.md done) and flag PROJECT_PLAN.md's obsolete WS-server line for the planner. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(redesign): mobile redesign & Plan tab — v0.2.0 tail
Owner
Author
|
Director triage: this branch (feature/msc-redesign) is DIRTY/diverged vs develop (ahead 20, behind 10, 64 files) and conflicts, so it cannot be merged as-is. The redesign work is now carried by the fleet mobile-redesign stream (branch mobile-redesign, issues #46-54). Please either (a) rebase feature/msc-redesign onto current develop and resolve conflicts if it still carries unique work, or (b) close this PR if the fleet mobile-redesign stream supersedes it. Holding off on merge until clarified. |
Owner
Author
|
This branch has merge conflicts with develop and needs a rebase before it can land. The work looks good — rebase on develop, resolve any conflicts, and re-push. |
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.
Foundation commit for the msc-redesign work. Source mockups live under
design/msc-redesign/(committed inb8abbe2).This PR lands the lowest-risk layer so subsequent screen migrations compose against a stable base. Per-screen migrations are deliberately deferred to follow-up PRs — see
docs/redesign-status.mdfor the full per-screen list.What's here
src/theme.ts—Themegainselev,elev2,borderStrong,accentDim,success,info,warn,danger,pink.dawnexactly mirrorsdesign/msc-redesign/.../styles.css :root(which the design notes "marries dawn"). The other four themes get palette-coherent values so primitives read correctly regardless of which theme is active.src/components/TabIcons.tsx+src/components/ui/BottomTabBar.tsx— newPlanIcon(kanban-board glyph matching the design's▩mark) + wiredplaninto the ICONS/LABELS maps.app/(tabs)/_layout.tsx— registered the 6th tab (Files · Find · Edit · Run · Git · Plan).app/(tabs)/plan.tsx— minimal themed placeholder, two states keyed onuseTunnel(): atunnel offline → pair via Run tabempty state, and acoming soonstate when connected.docs/redesign-status.md— per-screen migration list + open items.What's not here (and where it lives)
run.tsxis the redesigned Run; only needs visual alignmentdevelopalreadyMenloVerification
tsc --noEmitis green.planto the existingBottomTabBarmaps is additive; the maps already had?? FilesIconfallback for unknown routes, so this can't break the other 5 tabs.Notes
run.tsxas a placeholder is stale;run.tsxalready ships the full pairing + pane grid + terminal view that the redesign mockup shows.🤖 Generated with Claude Code