Conversation
Introduce a background PR polling service and end-to-end support for PR notifications, plus several related improvements. Key changes: - Add new prPollingService to poll PRs, compute notifications, backoff on failures/rate limits, and broadcast IPC prs events. - Integrate polling into main app lifecycle and ensure disposal on shutdown. - Expose prs.onEvent in preload/global types and renderer IPC to receive notifications. - Add UI toast notifications in AppShell for PR events with actions to view lane or open PR in GitHub. - Add Settings UI to control github.prPollingIntervalSeconds (local project config) and validate/save it. - Extend projectConfigService to parse/serialize github.prPollingIntervalSeconds, merge effective config, and validate interval bounds. - Enhance prService to fetch check-runs, compute richer checks status, and produce detailed PrCheck entries (merge with combined status fallback). - Add githubService rate-limit handling by attaching rateLimitResetAtMs to thrown errors so callers can schedule retries. - Add getCommitMessage to gitOperationsService and expose it over IPC; increase recent commits limit upper bound. - ConflictService: read lane pack bodies, generate truncated overlap diffs for proposals, and include pack context when present. - IPC additions: appOpenExternal handler (http(s) only), gitGetCommitMessage handler, ptyDispose accepts optional sessionId, and AppContext updated. - PtyService: allow disposing orphaned PTYs by sessionId (marks stale sessions disposed and broadcasts exit). - SessionService: reconcileStaleRunningSessions to mark running sessions as disposed on startup; main now calls this and logs reconciliations. Also includes various type updates, small UI/layout tweaks, and removal of a stray test.txt file.
Multiple improvements across BYOK, hosted agent, job engine, pack service and UI themes: - byokLlmService: fix regex spacing issues; add normalizeGeminiModel to validate/normalize Gemini model names (removes optional "models/" prefix and enforces "gemini-" prefix); stricter BYOK provider validation and clearer error messages. - hostedAgentService: add fetchWithTimeout, stableStringify, makeRequestKey and sleep utilities; introduce request deduplication maps for lane narrative, conflict proposals and PR descriptions; robust pollJob with exponential backoff, stall detection, and better error handling; default/constant timeouts and improved fetch usage. - jobEngine: avoid unnecessary hosted narrative refreshes by comparing previous and refreshed head SHAs and only syncing/making requests when needed; reorder pack refresh logic and logging. - packService: update descriptive text about narrative behavior to reflect AI-assisted narratives when Hosted/BYOK is available. - SettingsPage & renderer: normalize BYOK provider input, add Gemini model validation, expand theme metadata (additional color tokens and UI tweaks) and adjust theme swatches to use muted/accent secondary colors. - index.css: update theme variables (new surface/secondary/muted tokens), tweak colors for several themes and add a subtle background gradient for body. Overall these changes improve validation, reliability, request deduplication, UX messaging and theming consistency.
arul28
added a commit
that referenced
this pull request
Mar 14, 2026
arul28
added a commit
that referenced
this pull request
Mar 14, 2026
arul28
added a commit
that referenced
this pull request
Apr 14, 2026
Part A — fix 22 branch-introduced test failures: - TerminalView: add DEFAULT_TERMINAL_FONT_FAMILY to appStore mock + fontFamily to terminalPreferences (8 tests) - AgentChatMessageList: update bubble max-w assertion to match widened responsive class (1 test) - appStore: include fontFamily in terminalPreferences expectations; switch persistence assertions to unified store (2 tests) - CtoSettingsPanel: navigate to correct sub-tab in 4 tests, drop 3 tests for removed UI (Configured/Needs work badges, CTO runtime header), update tag/button assertions (11 tests) Part B — apply 5 low-risk optimizations from docs/OPTIMIZATION_OPPORTUNITIES.md: - #2 Pause renderer watchdog when tab hidden (main.tsx): start/stop the 1s event-loop-stall interval based on document.visibilityState. - #10 Combine warmup timers (appStore.ts): merge warmLaneStatusTimer + warmProviderModeTimer into a single warmupTimer firing both refreshes after max(1200, 1800) ms. - #13 Hoist inline config objects (IntegrationTab.tsx): OutcomeDot config moved to module-scope OUTCOME_DOT_CONFIG. AppShell was already module-scoped. - #19 Atomic UserPreferences store (appStore.ts): theme / terminalPreferences / smartTooltipsEnabled now persist as one ade.userPreferences.v1 JSON; legacy per-key reads kept as one-time migration. - #20 Compact JSON for machine files: preload.ts audited — no pretty-printed JSON.stringify remained, no-op for this pass. Doc: append "## Applied" section to docs/OPTIMIZATION_OPPORTUNITIES.md describing the five changes. Verified: typecheck clean; all 8 vitest shards pass; npm run build succeeded. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4 tasks
arul28
added a commit
that referenced
this pull request
Apr 14, 2026
* Improve Tasks and Subagents panel typography and sizing Bump text sizes across BottomDrawerSection, ChatTasksPanel, ChatSubagentsPanel, and ChatSubagentStrip to be more readable (e.g. 9px→11px, 10px→12px, 11px→13px). Switch labels, descriptions, and buttons from font-mono to the system sans font, keeping monospace only where it belongs (timestamps, task IDs, tool names, status badges). Slightly increase icon sizes and padding for better visual weight. * Widen assistant message cards on large screens Change max-width from 78ch to min(96ch, 75%) so messages use more horizontal space on wide displays while still staying readable and not stretching edge-to-edge. * Fix drifted tests and apply safe renderer optimizations Part A — fix 22 branch-introduced test failures: - TerminalView: add DEFAULT_TERMINAL_FONT_FAMILY to appStore mock + fontFamily to terminalPreferences (8 tests) - AgentChatMessageList: update bubble max-w assertion to match widened responsive class (1 test) - appStore: include fontFamily in terminalPreferences expectations; switch persistence assertions to unified store (2 tests) - CtoSettingsPanel: navigate to correct sub-tab in 4 tests, drop 3 tests for removed UI (Configured/Needs work badges, CTO runtime header), update tag/button assertions (11 tests) Part B — apply 5 low-risk optimizations from docs/OPTIMIZATION_OPPORTUNITIES.md: - #2 Pause renderer watchdog when tab hidden (main.tsx): start/stop the 1s event-loop-stall interval based on document.visibilityState. - #10 Combine warmup timers (appStore.ts): merge warmLaneStatusTimer + warmProviderModeTimer into a single warmupTimer firing both refreshes after max(1200, 1800) ms. - #13 Hoist inline config objects (IntegrationTab.tsx): OutcomeDot config moved to module-scope OUTCOME_DOT_CONFIG. AppShell was already module-scoped. - #19 Atomic UserPreferences store (appStore.ts): theme / terminalPreferences / smartTooltipsEnabled now persist as one ade.userPreferences.v1 JSON; legacy per-key reads kept as one-time migration. - #20 Compact JSON for machine files: preload.ts audited — no pretty-printed JSON.stringify remained, no-op for this pass. Doc: append "## Applied" section to docs/OPTIMIZATION_OPPORTUNITIES.md describing the five changes. Verified: typecheck clean; all 8 vitest shards pass; npm run build succeeded. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
arul28
added a commit
that referenced
this pull request
Apr 16, 2026
Ports items #2 and #3 from .factory/library/mobile-chat-port-plan.md. - WorkActivityIndicator.swift: new view that scans the transcript tail for the most recent running command / tool call / file change / named activity / web search / subagent event and renders a one-line pill ("Running: ls -la", "Editing .../foo.ts", "Searching", etc.) with a pulsing dot. Falls back to "Thinking" when nothing specific is streaming. Respects Reduce Motion. Drop-in for WorkChatSessionView.streamingStatusSection. - WorkChatHeaderAndMessageViews.swift: WorkChatMessageBubble now picks up the active session's provider from a new `workChatProvider` environment value and renders a compact provider chip (icon + label tinted by providerTint) next to the "Assistant" role label. No change to call sites — ancestor views opt in via .environment(\.workChatProvider, chatSummary?.provider).
arul28
added a commit
that referenced
this pull request
Apr 17, 2026
* Add sticky commit bar to lane detail * WIP: lanes tab, sync pairing, and settings refactor Staging in-progress work on mobile lanes tab, desktop sync pairing (PIN store), iOS design system/haptics, and connection settings screen before merging in work tab branch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * mobile work tab Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fixing review agent comments * Sync active lane presence across devices * Restore the green iOS baseline validation path Make PR list hydration tolerate older/local test schemas, restore lane list ordering, and fix the manifest desktop test command so baseline validation can run again. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Promote shared iOS glass primitives and cache code highlighting * Polish cached Lanes state and gating Keep cached lane context visible while making offline, hydrating, and syncing states explicit so live git actions never fail silently on iPhone. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Restore cached lane diff inspection offline * Synthesize foundation scrutiny rerun Record the passing foundation scrutiny rerun after restoring the iOS-only hard gate and verifying the offline lane diff regression fix. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Extend Work sync parity metadata Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Prioritize mobile Work session triage and chat creation Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Split mobile Work session detail views Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Synthesize work scrutiny findings Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Fix Work follow-up parity gaps Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Synthesize work scrutiny rerun Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Add read-only Files mobile cache contracts Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Rebuild the iOS Files mobile browser Split the Files tab into focused browser/detail slices so workspace switching, breadcrumbs, root-state messaging, and search flows stay readable and explicit on iPhone. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * Fix Work crash on duplicate transcript merge keys The cached base transcript can occasionally hold two envelopes with the same merge key (hosts replay activity events during resume), and the previous Dictionary(uniqueKeysWithValues:) init fatal-errors on that. Replace it with an in-place dedupe that keeps the later envelope and harden laneById against duplicate lane ids with uniquingKeysWith. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Rework Files detail around content-first layout Replaces the five-stacked-glass-cards surface with a pinned thin header (icon + name + language/size/read-only chips), an inline mode and diff picker, and a content-hero region that lets the code/diff/image fill the screen instead of competing with metadata chrome. Metadata and history move into a Details sheet (info.circle in the toolbar) so they stay one tap away without dominating the read flow. Compact banners replace ADENoticeCard for disconnected / load-failure states, and the binary and image-pending fallbacks share a single centered FilesContentFallback. Transition IDs (files-container / -icon / -title) stay stable so the zoom-push from FilesDirectoryScreen keeps working. All read-only framing is preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Reshape Settings into a mobile shell with grouped sections Split the 1156-line ConnectionSettingsView.swift into focused sub-files under Views/Settings/ (all < 500 lines), and reorganize the screen into a proper settings shell: connection status header with inline reconnect/ disconnect quick action, pairing section (Discover/Scan/Manual), theme tiles, and a diagnostics/about section with app version and paired-host details. Preserves Bonjour discovery, QR scanning, manual entry, and PIN pairing flows end-to-end via the existing SyncService API — no new service methods. - ConnectionSettingsView.swift: top-level shell + aurora background - SettingsSupportTypes.swift: PinPreset, PairSheetRoute, status tint helpers - SettingsConnectionHeader.swift: live indicator + host + Reconnect action - SettingsPairingSection.swift: pair rows + Discover/QR/Manual sheets - SettingsPinSheet.swift: PIN entry + digit box + keypad - SettingsAppearanceSection.swift: theme tiles - SettingsDiagnosticsSection.swift: version, paired host, last sync * Cache Work activity transcripts and flatten filter chips - Memoize parseWorkChatTranscript per session + buffer fingerprint so activityFeed stops re-parsing every localStateRevision tick - Split WorkChatSessionView timeline switch into @ViewBuilder helpers in a new WorkChatSessionView+Timeline.swift (keeps parent under 500 lines and lets the compiler skip card branches that haven't changed) - Replace LaneMicroChip glass chips inside the filter card with a flat WorkFlatCountChip to avoid glass-on-glass nesting * Add PR mobile snapshot sync contract for iOS parity Introduce prs.getMobileSnapshot: a single viewer-allowed sync command that returns stack metadata, create-PR eligibility, workflow cards (queue/integration/rebase), and per-PR capability gates in one payload so the iOS PRs rebuild can render its list/detail/workflow surfaces without fanning out across several commands. Contract is additive — existing desktop consumers of the PR service and sync registry are untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Harden Dictionary merges and drop duplicate matched-geometry sources Part A — replace Dictionary(uniqueKeysWithValues:) with coalescing merges so sync reconciliation overlaps cannot fatal the app: - Database.swift lane-row keying - LaneTreeView.swift lane-by-id memo Part B — remove the destination-side matchedGeometryEffect emissions in LaneDetailHeaderCard and WorkSessionHeader. The container's navigationTransition(.zoom(sourceID:)) interpolates child layouts during the push, so having the detail header ALSO emit isSource=true for lane-icon/title/status and work-icon/title/status groups is what SwiftUI warns about ("Multiple inserted views ... have isSource: true, results are undefined"). The list rows remain the sole source. Init signatures are preserved for call-site compatibility. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Split PRsTabView.swift into per-file view modules Pure mechanical file split of the 2480-line monolith into 14 focused files under apps/ios/ADE/Views/PRs/ so the PRs mobile rebuild can operate on clean per-file surfaces. No behavior, type, data-access, or UI changes. Visibility narrowed from private to internal where types are shared across the new files. New files (all under 500 lines): - PrModels.swift — shared structs/enums - PrHelpers.swift — free functions + ISO date parsing - PrListRowModifier.swift — .prListRow() modifier - PrFiltersCard.swift — filters card + signal chip - PrRowCard.swift — list row card - PrsRootScreen.swift — PRsTabView root - PrDetailScreen.swift — PrDetailView root - PrDetailOverviewTab.swift — overview tab, header, section card, chip wrap, cleanup banner - PrDetailFilesTab.swift — files tab, file diff card, unified diff view - PrDetailChecksTab.swift — checks tab, check row - PrDetailActivityTab.swift — activity tab, timeline row - PrWorkflowCards.swift — integration/queue/rebase workflow cards - PrStackSheet.swift — stack members sheet - CreatePrWizardView.swift — wizard + step indicator + markdown renderer PRsTabView.swift is emptied to a forwarding comment to preserve the pbxproj reference without further edits. * Wire PrMobileSnapshot into PRs root screen and unified workflow cards Adopt the new prs.getMobileSnapshot contract (commit ad17c74) on the root PRs surface. The snapshot replaces the three-fan-out fetch for queue/integration/rebase state with a single unified `workflowCards` array, and its per-PR capability map drives the row swipe actions so Close/Reopen respect the host's actual gating instead of guessing from the stored PR state. Create PR is now disabled when createCapabilities reports canCreateAny=false, and the previously dead status notice for disconnected / hydrating / failed phases finally renders at the top of the list. Adds a new PrMobileWorkflowCardView that dispatches on card.kind (queue | integration | rebase) so one ForEach covers all three. Legacy per-kind fetches remain as a fallback so the list still renders when a paired host predates the mobile-snapshot command. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Gate PR detail actions and Create wizard by host capabilities Thread PrActionCapabilities through PrDetailScreen → PrOverviewTab so merge/close/reopen/request-reviewers/rerun-checks/comment gates come from the host snapshot when available, and fall back to the legacy supportsRemoteAction probe + PrActionAvailability when the mobile snapshot hasn't arrived (offline / pre-contract host). Surface mergeBlockedReason under the merge button so users see the specific blocker (draft, failing checks, closed) instead of a silent disabled state. Accept optional PrCreateCapabilities in CreatePrWizardView. When present, the lane picker shows only eligible lanes, the target branch defaults from the host, and blocked lanes are listed separately with their blockedReason. Nil fallback keeps the existing LaneSummary flow intact so offline create still works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Forward createCapabilities from root into Create PR wizard The wizard's new createCapabilities prop was landed with a nil default so the root-screen wire-up could follow. Pass mobileSnapshot?.create Capabilities through so the wizard actually filters to canCreate lanes, fills the default base branch from host metadata, and surfaces each lane's blockedReason. With a nil snapshot the wizard still falls back to the raw lanes list unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Polish PR stack sheet, workflow cards, and create wizard Stack sheet: join PrGroupMemberSummary with snapshot.stacks data so the chain renders with role badges (BASE/BODY/HEAD), depth indentation (capped at 4 levels to stay readable on iPhone), dirty-worktree warnings per lane, and live PR state pills. Each member with a PR is now a tap target that pushes PrDetailView inside the sheet's own NavigationStack — users no longer have to dismiss + re-navigate from the root to open a stack member. Falls back to position-derived depth when the snapshot is unavailable so offline stacks still render. Workflow cards: - queue: position chip (3/5) now renders next to the title instead of at the bottom, so progress is visible before the action buttons - integration: "Open linked PR" upgraded from ghost glass to prominent glass with a full-width label + icon so the escape hatch reads as a primary action - rebase: the CONFLICT badge is a new PrConflictBadge with a solid red background and warning icon so a predicted conflict can't be glanced past alongside the other tinted status pills Create wizard: - PrStepIndicator: active step title shown beside the counter, segment labels align to segments and highlight up-to-current-step so users see where they are at a glance - Blocked-lane list got a lock icon header, per-row minus-circle icons, and a subtle warning-tinted background so "not eligible" reads as a deliberate state, not greyed-out content Tests: two new cases for buildStackRows covering snapshot-joined and fallback paths. Build + targeted tests green on iPhone 17 Pro. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add chat activity indicator pill + per-turn provider badge Ports items #2 and #3 from .factory/library/mobile-chat-port-plan.md. - WorkActivityIndicator.swift: new view that scans the transcript tail for the most recent running command / tool call / file change / named activity / web search / subagent event and renders a one-line pill ("Running: ls -la", "Editing .../foo.ts", "Searching", etc.) with a pulsing dot. Falls back to "Thinking" when nothing specific is streaming. Respects Reduce Motion. Drop-in for WorkChatSessionView.streamingStatusSection. - WorkChatHeaderAndMessageViews.swift: WorkChatMessageBubble now picks up the active session's provider from a new `workChatProvider` environment value and renders a compact provider chip (icon + label tinted by providerTint) next to the "Assistant" role label. No change to call sites — ancestor views opt in via .environment(\.workChatProvider, chatSummary?.provider). * Add reasoning card and smart-autoscroll jump-to-latest pill to Work chat Ports items #1 and #5 from the desktop chat port plan. A new WorkReasoningCard replaces the generic event-card rendering for reasoning entries: brain icon pulses while a turn is streaming, the body stays open, three staggered dots signal live thinking, and once the turn settles the card auto-collapses behind a "Reasoning" label so it stops competing with the final assistant message. Smart autoscroll now tracks an unreadBelowCount instead of always yanking the view: when the user scrolls up and new entries arrive, the count accumulates and a floating WorkJumpToLatestPill appears at the bottom-trailing edge showing "N new" with the accent tint. Tap it or naturally scroll back to the end to clear the count. Reduce-motion is honored throughout via ADEMotion + static-dot fallbacks. Also lands .factory/library/mobile-chat-port-plan.md so future work on the other eight port-plan items has the same inventory to work from. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Upgrade queued-steer strip with collapsible rows and haptic cancel Chat composer plan item #7 — queued-steer strip. The mobile strip now mirrors desktop's PendingSteerItem treatment: - Header collapses by default to a compact "N queued · preview" row with a chevron; taps toggle the list. Strip auto-expands whenever a row enters edit mode so edits aren't hidden behind a collapse tap. - Each row ribbon starts with a discreet "Queued" pill (accent tint) and a relative timestamp so the queued state reads at a glance without competing with the body text. - Body text now clips at 2 lines with tail truncation. Long messages stay reachable through the Edit button's inline TextEditor. - Cancel drives a light-weight .sensoryFeedback(.impact) so the strip confirms destructive actions through haptics, not just visuals. File stays under the 500-line ceiling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Rebuild Work sidebar to match desktop SessionListPane architecture Replaces the phone-only filter card + hard-coded section stack with the same information architecture the desktop uses: a compact toolbar (Search + New Chat accent button + Filter funnel toggle), an expandable Group/Lane filter panel, and a grouped session list driven by the user's chosen organization — byLane / byStatus / byTime — with collapsible section headers showing icon, label, and count badge. Organization and per-section collapse state persist via @AppStorage so the sidebar reopens the way it was left. Iconography matches desktop: magnifyingglass for search, line.3.horizontal.decrease.circle for the funnel, plus for New Chat, arrow.triangle.branch for lane grouping, and colored status dots for the byStatus sections. Removes the always-on status chip strip and the standalone "0 live" chip in favor of the filter-panel-scoped live/waiting count chips that only appear when the panel is open. Session row logic extracted into a reusable WorkSessionListRow so the new grouped loop can render any organization with consistent swipe and context-menu actions. New WorkSessionGrouping.swift holds the pure grouping helpers (byStatus / byLane / byTime bucketers plus the AppStorage serialization for collapsed-section ids). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Wire WorkActivityIndicator + provider env into the chat session view Drops the spinner-only streamingStatusSection in favor of the activity indicator settings-worker shipped at 24db48b, so the tail of the transcript always surfaces the current tool/command/file edit as a "Label · detail" pill when a turn is streaming. Also injects \.workChatProvider down the transcript ForEach so every assistant bubble can render the per-turn provider chip without each row having to resolve it independently. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Chat polish: streaming shimmer, tool result truncation, compact divider Ports items #6, #8, and #10 from .factory/library/mobile-chat-port-plan.md. #6 — Streaming shimmer on the active assistant bubble: - New ADEStreamingShimmer view modifier (Views/Components/): gentle one-direction gradient sweep + accent glow + stroke, gated on isActive and respecting Reduce Motion (becomes a no-op). - WorkChatMessageBubble gains an `isLive: Bool = false` prop; the timeline call site passes `isLatestAssistantMessageLive(message)` so only the newest assistant bubble of an active session shimmers. - Liveness derivation lives in WorkChatSessionView+MessageLiveness.swift (scans visibleTimeline tail for the most recent assistant message id). #8 — Tool-result truncation, preview, and show-all toggle: - WorkToolCardView now shows a first-line preview in the collapsed header. - Long results (> 500 chars) render truncated with a "Show all (N chars)" toggle; copy affordance is already provided by WorkOutputBlockHeader. - Helpers: workToolResultPreview, workToolResultTruncate, workToolResultByteLabel. #10 — Context-compact divider: - WorkEventCardView special-cases kind == "contextCompact" and renders the new WorkContextCompactDivider: a horizontal hairline flanking a warning-tinted chip with the rectangle.compress.vertical icon, tokens freed (when parseable) and an AUTO/MANUAL trigger tag. - Parsing handled by WorkContextCompactSummary. Tests (appended to the end of ADETests.swift per coordination rule): 8 new unit tests covering the truncation boundary, preview extraction, byte-label formatting, and context-compact summary parsing. * Use branded provider logos + fix Work sidebar row and chat header layout User flagged three concrete problems in the mobile Work surface: the session rows all shared a generic grey brain icon instead of the branded model logos the desktop uses, timestamps leaked as raw ISO strings (`2026-04-16T07:40:08.095Z`) because the parser did not accept fractional seconds, and the chat detail header wrapped its chip row off-screen while showing a useless "—" duration and a truncated "Summa..." column on mobile. Bundle the LobeHub static SVGs (claude-color, codex-color, cursor, opencode + anthropic / openai family marks) into Assets.xcassets as Provider* imagesets with preserves-vector-representation. A new WorkProviderLogo view renders the branded asset when one exists and falls back to the tinted SF Symbol we already had. Rewrite WorkSessionRow around the desktop SessionListPane cadence: one line for status-dot + title + relative time, an optional preview line, and a horizontal-scrolling chip strip (status pill, lane, model, device presence). Drop the standalone duration column that was only ever rendering "—" on ended sessions. Rewrite WorkSessionHeader to a single collapsed meta line ("3h ago · sonnet"), a horizontal chip ScrollView so "Claude / sonnet / Primary" never clips past the edge again, and a summary line that only renders when there is a real summary — no more empty "Duration —" placeholder. Session starts now parse cleanly thanks to workDateFormatterFractional, so "Started" reads as relative time everywhere else too. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Polish Work logo avatar container + row chip strip + ended-session control bar Wrap the branded provider SVG in a tinted rounded-card container so the mobile mark reads the way desktop's Claude.Avatar / Codex.Avatar do — logo centered on a tinted squircle with a hairline border — instead of a raw glyph floating on the background. Drop the redundant ENDED / closed status pill from session rows whose status matches the section they already live in. Needs-input, running, idle, and archived rows keep their pill because those differ from the group header. Rewrite WorkSessionControlBar around the actual session states. On an ENDED session the only sensible action is Resume, so the old "Close session" filled button (closing an already-closed session) is gone and Resume chat takes the whole row as the prominent CTA. On active turns Interrupt is the prominent action; End is the small escape hatch. Idle and awaiting-input get a Resume + End pair. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Drop the Turn finished card that dumped raw usage JSON into the transcript The Turn status card already marks completion and the session usage summary card at the top of the chat aggregates token spend. Rendering a second "Turn finished" event card for every .done envelope just dumped the host's raw summary string — usually a JSON usage blob — into the transcript alongside the real messages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add inline model picker to the chat composer Composer chip strip now surfaces Model / Access / Profile as three labeled pills with the branded provider logo on the model chip, and tapping the model chip opens a WorkModelPickerSheet that mirrors the desktop ProviderModelSelector mobile variant — grouped by provider, branded logos inline, tier badge, one-line tagline, and a checkmark for the currently applied model. Committing a selection calls updateChatSession on the paired host and marks the change with a light haptic. Unknown models (e.g. a freshly released id the mobile catalog doesn't know about yet) still render as the active entry so the picker never hides the live host model. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Replace New Chat modal with a pushed welcome screen Desktop's "+ New Chat" flows straight into a dedicated welcome page: big ADE word-mark, tagline, workspace pill, and a prominent composer at the bottom. Typing and sending turns the page into the live chat without bouncing back to a sidebar. Mobile currently opens a six-step slide-up sheet for the same intent, which the user called out as wrong for this flow. Add WorkNewChatScreen and a WorkNewChatRoute hashable value. The "+" toolbar button, the inline "New Chat" button in the sidebar toolbar, and the empty-state CTA now push the route onto the NavigationStack path instead of opening WorkNewChatSheet. Inside the screen the composer defaults to claude-sonnet-4-6 but the same WorkModelPickerSheet the chat composer uses is one tap away, so users can still switch provider/model before sending. Submitting creates the host chat session and replaces the path with the live session route — Back goes to the sidebar, not to an empty form. The old WorkNewChatSheet stays in the codebase for now so the sync surfaces it still references keep compiling; it can be pulled once nothing else presents it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Streamline Work chat composer, picker, and chrome Drop the bulky two-line composer chips for a single-row strip of compact desktop-style pills (access dot + runtime label, model logo + short name). The access pill flips runtime modes through an inline menu instead of routing users through a separate Chat Settings sheet, which is removed from the UI entirely. Redesign the model picker to match the desktop ProviderModelSelector — "Select Model" title, search field, provider tab strip with count badges, and grouped rows with active/Ready chips. Hide the tab bar once a session is pushed so the transcript and composer get the full screen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Collapse Work composer into a single desktop-style container Fold the text field, pill strip, and send button into one rounded container so the composer reads as one unit like the desktop "Type to vibecode…" box. Drop the redundant ENDED/RUNNING status pill row with its inline play/stop button — the session control bar above the transcript already owns the Resume/Interrupt CTA and the "Resume this chat before sending another message." feedback line below communicates status in prose. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Flow Work chat transcript like a document Drop the heavy card chrome the timeline used on every message, turn status, and system notice. User messages stay right-aligned with a small tinted bubble; assistant messages shed the box entirely and render as provider-chipped prose. Low-value event kinds (status / activity / notice / todo / autoApproval / webSearch / promptSuggestion / toolUseSummary / pendingInputResolved) collapse into a single-line ribbon instead of a full card, matching the desktop's document-style feel. The session header drops its adeListCard chrome for a compact status dot · lane · meta line, and the reasoning card now defaults to collapsed with a slimmer background so it stops competing with the final assistant turn for attention. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Tune composer typing, markdown pills, and model catalog - Composer now accepts keystrokes while the session is ended so the user can draft before hitting Resume. The feedback line below still explains why send is blocked, and Send itself stays disabled via a new canSend gate. - Give inline markdown code runs the desktop pill treatment — tinted accent background, monospaced font, accent foreground — so identifiers, branch names, and file paths pop out of prose like they do on desktop. - Expand the mobile model catalog to mirror apps/desktop/src/shared/modelRegistry.ts: Claude Opus 4.6 / Opus 4.6 1M / Sonnet 4.6 / Haiku 4.5; the seven shipping Codex CLI tiers; Cursor Auto/Sonnet-thinking/Sonnet/GPT-5/Codex; and a broad OpenCode row set (Anthropic / OpenAI / Google / xAI / DeepSeek / LM Studio / Ollama). Ids match the sync-contract shape the host accepts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Ship a properly defined composer card Rewrite composerInset so the composer reads as one bold rounded container rather than a faint tinted rectangle. The new card gets a deeper recessedBackground fill, a 22pt radius, a visible border stroke, and a subtle drop shadow so it sits cleanly over the chat surface. The send button shows a visible disabled state (accent ring outline + secondary glyph) instead of fading into the background, and takes on an accent fill with a soft purple halo the moment typing begins, mirroring the desktop "Send" affordance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Give composer desktop-shaped Send pill and full model name The composer now renders the model pill with the desktop display name ("Claude Sonnet 4.6" instead of just "Sonnet"), and replaces the icon-only circle with a desktop-shaped Send pill — paperplane glyph plus a "Send" label in a capsule that fills with accent and halos purple the moment the draft has content. Wrap the card in ultra-thin material over a darker tint so the composer sits cleanly against the transcript background and reads as one container. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Drop outer composer inset bubble The composerInset used to paint a faint glass rectangle around the whole bottom area (composer card + feedback text), which read as a second "bubble" overlapping the composer card itself. Since the composerCard now owns its own clearly-defined rounded surface we can drop the outer background + glassEffect and let the feedback text sit plainly below the card. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Move composer feedback above the composer card The "Resume this chat before sending another message." (and similar status-blocked messages) now render above the composer card instead of below, and the bottom padding is dropped to zero so the card sits flush with the safe-area edge. Feedback text is also centered to read as a banner hint rather than a footnote. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Match desktop model picker organization and new chat composer - Model picker now uses the desktop ModelCatalogPanel's 2-level hierarchy: CLAUDE / CODEX / CURSOR / OPENCODE group tab strip, then a provider badge row inside the active group. OpenCode exposes its full provider ladder (Anthropic, OpenAI, Google, xAI, DeepSeek, LM Studio, Ollama) as horizontal badges just like the desktop panel, with count chips on each. Search mode flattens results and renders them grouped by group header, mirroring desktop behavior. - New chat welcome page composer rebuilt to share the same rounded glass card, model pill logic (full "Claude Sonnet 4.6" name), and desktop-shaped Send capsule as the in-session composer, dropping the prior ad-hoc chip + round-button layout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: in-progress mobile droid work before merging main Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: iOS chat redesign + unified per-provider chat accent iOS: - New chatSurfaceAccent with per-provider table (Claude amber, Codex warm-white, etc.) mirroring the shared desktop mapping so each chat reads the same on both surfaces. - Per-model reasoningTiers lookup matching MODEL_REGISTRY — effort pill only renders for models that advertise tiers (Opus: low/med/high/max, Sonnet: low/med/high, Haiku hides entirely, Codex tiers: low/med/high/xhigh, mini: med/high). - Compact "…" nav toolbar menu (lane name + Go to lane) replacing the inline status row under the chat title. - Stop button folded into the composer Send slot while the assistant streams; removed the full-width yellow WorkSessionControlBar. - Turn-separator pill between user turns, assistant message card surface, dropped redundant model-badge chip above each response and inside the USAGE row, compact Thought pill, k/M-abbreviated usage numbers with separate Cache / New cache. - Retired unused LaneChatSessionView and its pbxproj references. Desktop: - PROVIDER_CHAT_ACCENTS + providerChatAccent() in chatSurfaceTheme.ts; AgentChatPane's draftAccent routes through provider first so Claude/Codex chats share a single tone across model variants. - resolveModelAlias now falls back to bySdkModelId so provider-model-id forms like "claude-sonnet-4-6" or "gpt-5.4-codex" resolve — fixes mid-turn model switches from iOS which sends that form. Known build issue (pre-existing, not mine): apps/ios PRs area has uncommitted WIP referencing PrSingleLineEditSheet / PrMultilineEditSheet / PrSubmitReviewSheet (files don't exist) and ADEColor.surface (field doesn't exist — should be surfaceBackground). Chat work compiles fine in isolation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Finalize pass: simplify sync/chat services, align iOS schema, docs - Drop dead code across sync host/remote-command/pairing services, chat message builder, agent chat service, registerIpc, and PackedSessionGrid - Mirror iOS files-cache schema (files_workspaces + 4 snapshot tables) into desktop kvDb migrations so generate-ios-bootstrap-sql stays in sync - Stabilize CommandPalette test by making getDetail's default resolved value survive mockClear between tests - Refresh internal docs for chat slash-command discovery, provider accents, PackedSessionGrid resize model, lane device presence, Linear dispatch replay, and sync pairing/pin stores Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix PR review and CI issues * Retry buffered sync updates on transient failures * Include project root in PTY broadcast tests * Preserve local Claude commands and orchestrator compaction --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
arul28
added a commit
that referenced
this pull request
Apr 25, 2026
- adeCliService: distinguish "added vs already present" install message via
ShellPathResult { profilePath, modified }; handle fish shell explicitly
with fish_add_path in ~/.config/fish/config.fish (Greptile P2 #1, #3)
- DeepLinkRouter.swift: return nil from resolvePrId when numeric lookup
misses the workspace snapshot, so PrsRootScreen can degrade gracefully
instead of silently dropping the deep-link nav (Greptile P2 #2 / CR #7)
- firstJourneyTour.test.ts: drop tautological waitForSelector self-compare;
assert string + non-empty length directly (CR #1)
- firstJourneyTour.ts: swap "Act 6 — PRs" / "Act 7 — History" comments to
match underlying act7Intro/act6Intro IDs already referenced by tests (CR #3)
- lanesTour.ts: change "Switch between lanes" fallback selector from
lanes.newLane (overlapping prior step) to lanes.statusChips (CR #4)
- prsTour.test.ts: rename test description from stale "Path to Merge" to
current "What's blocking me?" step title (CR #5)
Tests: 29/29 scoped pass (adeCliService + firstJourney + prsTour).
Typecheck: clean. Swift parse: clean.
Addressed comment ids: 3141711542, 3141711558, 3141711581, 3141713614,
3141713631, 3141713638, 3141713642, 3141713651
arul28
added a commit
that referenced
this pull request
Apr 25, 2026
…#197) * ship: checkpoint before automate/finalize * test: pin prsTour fallback + tab-switch invariants Detail-drawer steps now carry fallback skip paths and dispatch ade:tour-pr-detail-tab to switch tabs in-flight. These invariants are load-bearing for the "user can never get stuck on a tutorial step" contract and easy to break in future edits, so pin them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ship: iter 1 — rebase on main + address Greptile P2 + CodeRabbit review - adeCliService: distinguish "added vs already present" install message via ShellPathResult { profilePath, modified }; handle fish shell explicitly with fish_add_path in ~/.config/fish/config.fish (Greptile P2 #1, #3) - DeepLinkRouter.swift: return nil from resolvePrId when numeric lookup misses the workspace snapshot, so PrsRootScreen can degrade gracefully instead of silently dropping the deep-link nav (Greptile P2 #2 / CR #7) - firstJourneyTour.test.ts: drop tautological waitForSelector self-compare; assert string + non-empty length directly (CR #1) - firstJourneyTour.ts: swap "Act 6 — PRs" / "Act 7 — History" comments to match underlying act7Intro/act6Intro IDs already referenced by tests (CR #3) - lanesTour.ts: change "Switch between lanes" fallback selector from lanes.newLane (overlapping prior step) to lanes.statusChips (CR #4) - prsTour.test.ts: rename test description from stale "Path to Merge" to current "What's blocking me?" step title (CR #5) Tests: 29/29 scoped pass (adeCliService + firstJourney + prsTour). Typecheck: clean. Swift parse: clean. Addressed comment ids: 3141711542, 3141711558, 3141711581, 3141713614, 3141713631, 3141713638, 3141713642, 3141713651 --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
arul28
added a commit
that referenced
this pull request
Apr 26, 2026
Now that AutomationActionType includes "lane-setup" (7e7390c), the per-row narrowing in RunDetailPanel no longer needs to cast through `typeof action.actionType`. Bundles the renderer's run-detail redesign that landed alongside task #2: lane-setup rows render with a GitBranch icon and accent border, all hex colors swapped for CSS variables + cardCls/labelCls, error_message in text-error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
arul28
added a commit
that referenced
this pull request
Apr 26, 2026
* feat(automations): add laneMode + laneNamePreset to AutomationExecution
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(tests): remove dead tests for ripped-out features
Verified-orphaned: sibling source files no longer exist for any of the
removed test files. Cleaned up the orchestrator/, prs/, missions/, and a
handful of other directories. Also rewrote a no-op `expect(true).toBe(true)`
assertion in usageTrackingService.test.ts to a proper not.toThrow() check.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(automations): laneMode 'create' path with createLaneForRun + lane-setup row
- presetToTemplate util maps lane-name presets to {{trigger.*}} templates.
- createLaneForRun resolves the preset/template, disambiguates collisions
with #issueNumber (or short timestamp), then a 4-char random suffix.
- resolveExecutionLaneId branches on rule.execution.laneMode; on "create"
it allocates a fresh lane and emits a synthetic 'lane-setup' action_results
row so failures surface in run history. No silent fallback to primary.
- normalizeRuntimeRule preserves laneMode/laneNamePreset/laneNameTemplate.
- projectConfigService migrates legacy create-lane-as-first-action rules
into laneMode: 'create' on load, carrying the template forward as 'custom'.
- listRuns already accepts {status} (no schema change needed); adeActions
registry already passes args through.
- Tests cover preset mapping, happy/collision/random-suffix paths, run-failed
semantics, and the legacy migration shape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(automations): widen AutomationActionType with synthetic 'lane-setup'
Adds "lane-setup" to the union so RunDetailPanel and friends can render the
runtime-emitted row without a cast. Adds a no-op draft mapping in
RuleEditorPanel so the action-to-draft switch stays exhaustive.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(automations): drop lane-setup type cast in RunDetailPanel
Now that AutomationActionType includes "lane-setup" (7e7390c),
the per-row narrowing in RunDetailPanel no longer needs to cast
through `typeof action.actionType`. Bundles the renderer's run-detail
redesign that landed alongside task #2: lane-setup rows render with a
GitBranch icon and accent border, all hex colors swapped for CSS
variables + cardCls/labelCls, error_message in text-error.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(automations): redesign rule editor lane controls + design-token migration
Renderer-side companion to the laneMode backend work:
- New designTokens.ts re-exports the CTO panel tokens (inputCls, selectCls,
labelCls, textareaCls, cardCls, etc.) as the single source of truth for
the automations surface.
- shared.ts: legacy INPUT_CLS / INPUT_STYLE / CARD_STYLE collapse to thin
aliases over the new tokens so existing call sites inherit the new chrome
with zero churn.
- ActionList: drops "Create lane" from the +Add menu (lane creation is now
a first-class EXECUTION setting), Button + token chrome.
- ActionRow: removes the per-action targetLaneId override on agent-session
rows; legacy create-lane rows render read-only with a "now in Execution"
pill so unmigrated rules still display sensibly.
- RulesTab: "Last run: failed" pill on the rule list with click-through to
history, empty-state card uses cardCls.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(tests): consolidate PR-service tests from 10 → 5 feature suites
Group PR-service tests by contract instead of one file per source module.
All 180 unique it() cases preserved; no behavioral coverage loss.
- prService.test.ts (kept) — main PR service entry points (22 tests)
- prMergeQueue.test.ts ← queueLandingService + integrationPlanning +
integrationValidation (10 tests)
- prRebase.test.ts ← prRebaseResolver + resolverUtils via vi.importActual
(26 tests)
- prAsync.test.ts ← prPollingService + prSummaryService (16 tests)
- prIssueResolution.test.ts ← issueInventoryService + prIssueResolver
(106 tests)
Rationale per merge:
- prMergeQueue groups everything that drives merging/integration mechanics.
- prRebase keeps resolver-utils tests next to the rebase resolver that
consumes them; the resolver block uses vi.importActual to exercise the
real module while the rebase block keeps its replica mock.
- prAsync groups background services (polling + summary cache).
- prIssueResolution merges the inventory service with the chat-launch
resolver since both implement the issue tracking + remediation flow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(tests): consolidate CTO tests from 26 -> 7 feature suites
Group 26 fragmented files (226 cases) into 7 colocated, feature-scoped
suites with no behavioral coverage loss:
Main:
- ctoState.test.ts (ctoStateService + flowPolicyService)
- linearAuth.test.ts (linearOAuthService + linearCredentialService + linearClient)
- linearSync.test.ts (linearSyncService + linearDispatcherService + linearOutboundService + linearTemplateService + linearWorkflowFileService)
- linearIntake.test.ts (linearIntakeService + linearIngressService + linearRoutingService + linearCloseoutService)
- ctoWorkerLifecycle.test.ts (workerHeartbeat + workerAdapterRuntime + workerAgent + workerBudget + workerRevision + workerTaskSession + openclawBridge)
Renderer:
- pipeline/pipeline.test.ts (pipelineHelpers + pipelineLabels)
- ctoUi.test.tsx (CtoSettingsPanel + LinearSyncPanel + ctoSessionViewState)
Each merged file scopes per-source helpers/fixtures inside an outer
`describe("<source> (file group)", ...)` block to avoid identifier
collisions between distinct issueFixture/createLogger definitions
across sources. Imports are deduped at file top.
All 226 source `it(` cases are preserved verbatim. No tests dropped.
No mocks-of-module-under-test removed (none existed). No trivial
toBeDefined-only tests found. Total runtime: 141 main + 86 renderer
= 227 tests, all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(tests): consolidate orchestrator tests from 17 -> 12 subsystem suites
Merge nine fragmented orchestrator test files into three feature-level
suites without dropping any behavioral coverage:
- orchestratorAdapters.test.ts <- baseOrchestratorAdapter +
providerOrchestratorAdapter + permissionMapping + modelConfigResolver
(13 it cases)
- mission.test.ts <- missionLifecycle + missionBudgetService +
missionStateDoc (35 it cases)
- orchestratorPlanning.test.ts <- orchestratorContext +
delegationContracts (14 it cases)
Kept separate (genuinely different concerns / file size):
orchestratorService, aiOrchestratorService, executionPolicy,
promptInspector, adaptiveRuntime, runtimeEventRouter,
workerDeliveryService, coordinatorAgent, coordinatorTools.
All 463 tests in the consolidated orchestrator suite pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fixing mobiel ui
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
No description provided.