mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 16:03:49 +00:00
split-github-client
37
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7705415fc2 | refactor(github-client): reorganize client into lifecycle folders | ||
|
|
a3a2c44edf |
Split browser pane (#14861)
* refactor: split BrowserPane.tsx under 400 lines * rm plan * refactor(browser-pane): reorganize into lifecycle folders Cut/paste + import rewrites only; no intentional behavior change. - annotate/, assemble-chrome/, host-guest/, navigate/, stream-remote/, describe-page/ (foundation sink, zero outgoing edges) - BrowserPane.tsx is now a pure re-export barrel; its component body moved verbatim to assemble-chrome/browser-workspace-pane.tsx so no dest file imports the barrel - browser-runtime.ts -> describe-page/live-browser-url-registry.ts (banned name; relocating the contract collapsed the host-guest/navigate mutual pair) - repath browser-pane test paths in config/reliability-gates.jsonc * refactor: sync addressBarValueRef with useEffect Move ref synchronization into useEffect hook with proper dependency tracking to ensure the ref updates are handled through React's lifecycle. Consolidate related imports from browser-page-types. * refactor(browser-pane): fix React lifecycle and external store patterns - Replace local state + effects with useSyncExternalStore for external subscriptions (draw hint, address bar, slot viewport) - Fix React StrictMode double-invoke issues in pointer handlers and state updates - Add keyboard navigation to context menu (arrows, Home, End, Escape) with focus management - Improve error handling for mobile driver reclaim and grab action IPC failures - Add test coverage for BrowserFind session flags, keyboard behavior, viewport lifecycle - Remove react-doctor/no-adjust-state-on-prop-change lint disables (root causes now fixed) * i18n: extract grab and download UI messages Move hardcoded toast notifications and error messages to translation system for both grab annotations and file drop handling. Also apply lazy initialization to address bar value and remove duplicate event recording. * fix(browser-pane): stop mutating refs during render React Doctor fails static analysis when refs are written in render. Mirror latest values in useLayoutEffect, and read the current page id from the latest grab callbacks. * fix(browser-pane): drop unused grab-mode exit dependency exit already reads the page id from a ref, so listing browserPageId trips the changed-code exhaustive-deps gate. * test(e2e): hide the window when Linux minimize is a no-op Xvfb has no window manager, so BrowserWindow.minimize() never sets isMinimized() on the frameless Linux CI window. Hide still occludes the guest compositor so restore coverage can run. |
||
|
|
81d7f9b24e |
refactor: split db.ts under 400 lines (#14979)
* refactor: split db.ts under 400 lines * rm plan * fix(orchestration-db): add safety guards to database operations Add status guards to UPDATE statements to prevent late operations from overwriting changes made by concurrent requests. Validate mutation results to surface silent no-ops. Extract circuit-break threshold, add transaction wrapping, and sanitize untrusted input. Bump schema version to v28. * Add transactional safety to dispatch and message operations Wrap dispatch failures and batched message updates with SAVEPOINTs to ensure atomicity and idempotency: - Dispatch failures now check status guards and roll back if the related task update fails, preventing partial state corruption - Message batches (across multiple 500-id chunks) roll back entirely if any batch fails, avoiding partial mutations - Add tests verifying idempotency and atomicity under failure conditions * Handle concurrent writes and improve transactional safety - Remote question answering: add classification check before and after UPDATE to safely detect concurrent modifications. Prevents false success when the UPDATE loses a race. - Transaction rollback: wrap in try-catch to prevent errors from masking the original failure. - Question thread reset: use status update instead of deletion to preserve message references. * test: add answer replay and race condition edge case coverage Add test cases for answer replay idempotency, conflict detection, and a race condition between concurrent answer updates in federation relay. Also verify local question state transitions during orchestration reset. |
||
|
|
84784f5393 |
Split pull request page (#14853)
* refactor: split PullRequestPage.tsx under 400 lines Move the 5888-line PR page into nested domain modules under src/renderer/src/components/pull-request-page/ and leave a thin public barrel. No intentional behavior change. * rm plan * Improve React stability and remove manual ref caching - Stabilize React keys in CheckDetailsPanel using content fields instead of array indices to prevent unnecessary remounting - Remove manual ref-based entries cache in PRFilesCombinedDiffViewer, rely on useMemo dependency (diffEntrySignature) instead - Move sectionsRef assignment to useLayoutEffect to avoid render-phase ref writes - Refactor usePRFileSectionLoader to destructure args for readability * Improve PR page stability: add error handling and fix race conditions - Add error handling with user feedback (toast notifications) for comment submission, review comments, diff loading, and file view syncing - Internationalize hardcoded strings for PR state labels and error messages - Fix race condition in reviewer submission by using a ref-based guard instead of render-time state - Fix scroll restoration to avoid overwriting target positions with intermediate clamp values - Add effectiveRepoId parameter for proper repo context in review operations - Disable reviewer picker during submission to prevent concurrent requests * Improve PR page stability: add timeout and stable list keys - Add 45s timeout for diff loading to prevent indefinite hangs - Fix React list key generation for annotations/jobs using content-based keys with occurrence tracking - Refactor scroll position caching to properly handle mid-restore teardown - Replace interpolated error messages with full locale-specific strings for close/reopen actions * Fix PR diff viewer cache isolation and list key collisions - Changed list key generation from string concatenation to JSON serialization to avoid collisions with actual content keys - Added host-aware scoping to diff view caches so local and remote execution don't share entries - Optimized virtualizer keys to use lightweight revision counter instead of full serialized signature * Extract PR file state into entry-scoped hooks Replace manual state resets with custom hooks that automatically clear section heights and active section when switching PR entries. This prevents state leakage between files and simplifies the diff viewer component. Also validates the active section key exists before passing it to child components. * Improve PR page error messages, accessibility, and stability - Show actual error messages from failed operations instead of generic fallbacks - Add aria attributes for combobox/listbox patterns and proper option identifiers - Consolidate duplicate label/assignee update logic and fix event listener passive mode - Memoize GitHub source runtime to prevent stale closure in checks callbacks - Extract filled state badge tone for reuse and fix workspace attachment type - Guard textarea shortcuts against concurrent saves and add mention query test * Add explicit PR file content cache eviction Extract PRFileContentRequestArgs type and create evictPRFileContentRequest function to handle cache eviction explicitly. Call eviction on load timeout so retries fetch fresh content. Adds tests for cache behavior. |
||
|
|
9c4627d1c6 |
Refactor: split GitHubItemDialog into lifecycle-organized modules (#14931)
* refactor: split GitHubItemDialog.tsx under 400 lines No intentional behavior change. * refactor: group github-item-dialog into lifecycle folders Reorganize the 50 flat files under src/renderer/src/components/ github-item-dialog/ into six lifecycle folders: load-item-details/ shared types, both caches, fetch/settle, state badge open-dialog/ dialog shell, headers, body, tabs, link copy discuss-item/ conversation tab, comments, composer, timeline edit-item-fields/ GH edit section, labels, assignees, status inspect-pull-request/ combined diff viewer, checks tab land-pull-request/ PR actions, merge menu, reviewers No intentional behavior change. All 50 files moved verbatim; the only edits are relative-import specifiers (sibling paths plus a depth bump for ../../../../shared) and the hardcoded module paths in the two source-boundary tests. Import graph stays acyclic: zero mutual folder pairs, no file importing 4+ sibling folders, no dest file importing the public barrel, and no per-folder index barrels. * refactor: split item references and improve diff-viewer remount logic - Break down full `GitHubWorkItem` props into discrete `itemId`, `itemNumber`, and `itemRepoId` in mutation and action functions to prevent over-memoization of callbacks and improve dependency clarity. - Extract `getPRFilesCombinedDiffSignature()` and use it as a component key to safely remount the diff viewer when the PR revision changes, replacing generationRef tracking. - Add `getKeyedCheckAnnotations()` and `getKeyedCheckJobs()` to generate stable, collision-resistant keys for check arrays that may contain duplicates. - Consolidate interpreter timeouts into a single `SPAWNED_INTERPRETER_TIMEOUT_MS` constant and apply it via describe options rather than per-test values. * refactor: improve github-item-dialog repo context and i18n coverage - Add repoId prop to ConversationTab for explicit repo context override - Internationalize UI strings in diff viewer and PR action components - Improve error handling with cache rollback and guard cleanup on sync failure - Enhance cache key validation for cross-window invalidation by repoPath - Add repository access validation before rendering diff viewer - Fix cross-platform issues: skip symlink test on Windows, normalize CRLF in test assertions * Refactor check button i18n key and update text - Replace hash-based key with semantic name for maintainability - Change button label to "Open in browser" for broader context |
||
|
|
31e9f4af30 |
Refactor: split editor.ts into modular state actions (#14847)
* refactor: split editor.ts under 400 lines Move editor slice types, file-id/tab helpers, and action factories under src/renderer/src/store/slices/editor/. The source file is now a public barrel. No intentional behavior change. * refactor: split editor-chrome-slice into state modules - Move EditorDraftState, ExplorerDirState, and RightSidebarState type definitions into their respective action files - Simplify state creator return types from Pick<EditorSlice, ...> to specific state types - Improve modularity by colocating types with implementations |
||
|
|
8b04e060fa |
refactor(persistence): extract modules to half persistence.ts (#14252)
* refactor(persistence): extract modules to half persistence.ts * refactor(persistence): tighten the extracted operations seam Review follow-ups on the module extraction, all behavior-neutral. The extracted operations read and mutate the Store's state object in place, but every seam typed it as a bare PersistedState, so nothing at the boundary said a caller must pass the live reference — a future caller handing over a clone would have its writes silently dropped. Name that contract: StoreOwnedPersistedState carries it to every operations interface and every mutating free function. normalizePersistedPaneIdentityState and backfillFolderScopeConnectionIds stay on PersistedState; they build a fresh state rather than mutating the Store's. The six *PersistenceOperations wrappers were constructed per delegate call. They are stateless today, so this was inert, but any future instance state would be lost between calls. Memoize them, and mark state and gitUsernameCache readonly so the compiler enforces the single-assignment invariant memoizing them relies on. Also: restore flushSshPtyConsumerRecovery, whose inlining left its rationale duplicated at both call sites; document that migrateWorktreeIdentity's boolean gates the caller's save, since the extracted function kept no docs of its own; and merge a duplicate shared/types import that was failing lint under --deny-warnings. * delete plan doc * refactor(persistence): add error recovery and improve field cleanup - Rollback failed migrations to prevent corrupted state that blocks retry - Gracefully skip malformed entries in normalization instead of aborting - Strip retired fields to prevent orphaned state and sync issues * refactor(persistence): drop the redundant persistence- filename prefix The extracted modules already live in src/main/persistence/, so name them after the domain they own. Point leftover shared/types imports at the real type modules while touching those files. * refactor(persistence): optimize lookups and fix unsanitized updates - Use Maps instead of repeated array searches for O(1) lookups - Apply sanitized updates instead of raw input in ui-state-update - Compare fields directly rather than JSON strings to avoid false dirty states from persisted key ordering differences * refactor(persistence): group modules into lifecycle folders Move the 42 flat persistence modules into six folders named for what the module does, and lift the Store class out of the barrel so persistence.ts becomes an 8-line public surface. Bodies are unchanged: every moved file diffs clean against HEAD once import blocks are excluded. Only import specifiers were rewritten, by resolving each one to an absolute path and mapping it through the move map. Store keeps its existing max-lines suppression; its baseline entry is repathed rather than re-added. Its 119-method public API sets a ~525-line floor, so it cannot meet the 400-line cap without breaking the API for 153 importers. * Sanitize worktree visibility sources and preferences on hydration Ensure invalid or corrupted data from disk (untracked whitespace, relative paths, bogus preference values) is cleaned during load rather than corrupting the in-memory store. |
||
|
|
306c5d545f |
refactor(source-control): split the dropdown action resolver under the max-lines budget (#14835)
`source-control-dropdown-items.ts` was 524 counted lines behind an `eslint-disable max-lines`. It splits along the seams the resolver already had: - `source-control-dropdown-item-types` — the row union, consumed by CommitArea, the composer and the action dispatcher without pulling in the state machine. - `source-control-dropdown-labels` — count/label/title wording. - `source-control-dropdown-action-context` — the branch, upstream and review facts every row reads, derived once so rows cannot disagree about them. - `source-control-dropdown-commit-items` / `-remote-items` / `-review-items` — the three row groups, each keeping its own disabled-reason ladder intact. `resolveDropdownItems` is now just the entry order plus the conflict-abort and hosted-review-busy passes. Verified output-identical to the pre-split resolver: a differential harness ran both implementations over 16,380 generated input combinations (every upstream shape × PR state × conflict operation × blocked reason × staged count × provider) and compared entries deeply. The harness was scaffolding and is not committed. |
||
|
|
73aa5d0ca7 |
refactor(daemon,runtime): split daemon, pty and rpc modules under the max-lines budget (#14834)
Splits the nine oversized modules in the daemon/provider/runtime domain into focused per-concern files and drops their max-lines baseline entries. - daemon: `Session` decomposes into an output plane (emulator, pending-output buffer, client fan-out), a producer-pause controller, a shell-ready barrier and a termination controller; `DaemonClient` into socket connect, hello handshake, ndjson readers, pending-request settlement, listener registry and notify settlement; `daemon-health` into pid-file parsing, process identity, stale-kill, TCC attribution and bundle staleness; `shell-ready` into the marker constant and the bash/zsh rcfile generators. - providers: local-pty shell-ready wrapper generation, wrapper root, startup command and bash rcfile split out of local-pty-shell-ready. - runtime: `Coordinator` sheds DAG convergence, decision gates, escalation triage, the runtime contract, the stale-base flag and task dispatch; the files/git/github rpc modules split into per-domain method groups. Behavior-preserving: the extracted units keep their original construction order, guards and timer lifetimes, and every RPC method name is still registered. Test `vi.mock` surfaces were re-partitioned to follow the moved symbols. |
||
|
|
6854cceb90 |
refactor(panes,tabs): split pane manager and tab-group modules under the max-lines budget (#14760)
The two tab-group hooks, the pane manager, worktree activation, and the terminal pane context menu each carried a file-level `eslint-disable max-lines` and ran 461-745 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all five suppressions and prunes their entries (341 -> 335). Pure move, no behavior change. useTabDragSplit is cut into gesture lifecycle, hover preview and drop commit; useTabGroupWorkspaceModel into item projections plus the tab-close, close-scope, activation and creation command sets; the pane manager into host, tree mutations, pane creation, drag wiring, reparent frame tracking, layout sweeps and rendering diagnostics. react-hooks exhaustive-deps stays at zero warnings, matching HEAD. Dependency additions are only stable identifiers -- refs and callbacks that became parameters -- and no `.current` dereference was added to any dependency array. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (the three remaining failures are pre-existing load flakes in untouched files, each green when re-run serially), no new runtime import cycles among 1020 modules, no barrel files, and no lint suppression added anywhere. |
||
|
|
cc19692f93 |
refactor(editor): split Monaco, autosave and notebook modules under the max-lines budget (#14748)
The four editor modules, the diff-comment decorator and the file-type icon table each carried a file-level `eslint-disable max-lines` and ran 319-806 counted lines against 300/400-line budgets. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all six suppressions and prunes their entries (341 -> 334). Pure move, no behavior change. MonacoEditor is cut along its own seams -- mount, input bindings, markdown annotations, decorations, content sync, view-state persistence and reveal scheduling -- with the markdown overlay becoming its own component. useEditorPanelContentState splits into file and diff content loaders plus the active-tab load and reload triggers. When the mount module came in at 370 counted lines, over the 300 ceiling, it was split again into its parameter types and its input bindings rather than carrying a suppression. Hook usage is identical to HEAD across all three React split families: the same counts of every hook type between each original and its extracted modules, so no hook was added, dropped, or converted to a plain function. react-hooks exhaustive-deps stays at zero warnings, matching HEAD. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (the four remaining failures are pre-existing load flakes in untouched files, each green when re-run serially), no new runtime import cycles among 884 modules, and no lint suppression added anywhere. |
||
|
|
98450718f7 |
refactor(right-sidebar): split file explorer and sidebar under the max-lines budget (#14741)
The six right-sidebar modules and the remote file browser each carried a file-level `eslint-disable max-lines` and ran 347-797 counted lines against 300/400-line budgets. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all seven suppressions and prunes their entries (341 -> 333). Pure move, no behavior change. Two renderer-specific hazards were found and fixed rather than shipped. First, effect and ref LIFETIME. FileExplorer's `if (!worktreePath) return` sits above the files pane, so moving the worktree-reset effect into that pane made its guard ref `lastResetWorktreePathRef` die on any render where worktreePath was transiently null (workspace-list refresh, store rehydrate, remote worktree reload). On remount the guard read null, so the reset fired even when returning to the SAME worktree -- wiping dirCache, collapsing every expanded directory, clearing the name filter and undo history, and forcing a full re-read over SSH. The tree-load effects now live in a hook called from FileExplorer above the early return, and the pane is purely presentational with zero hooks. That also restores the original parent-effect ordering, which had shifted because React flushes child effects before parent effects. Second, extracting a hook silently degrades dependency analysis: `setX` setters that the linter knew were stable when created locally become opaque parameters, producing 8 new react-hooks/exhaustive-deps warnings where src/renderer had zero. Those are fixed by listing the genuinely stable identifiers (useState setters and ref OBJECTS). No `.current` dereference was added to any dependency array, since that would change callback identity as the ref mutates. Verified: oxlint clean with exhaustive-deps back to zero, ratchet passes, typecheck clean, full unit suite green on the first pass, no new runtime import cycles, no lint suppression added, and hook usage identical to HEAD across both split families. |
||
|
|
97b71c2285 |
refactor(usage): split AI-usage scanners and stores under the max-lines budget (#14668)
The three usage scanners and their stores, plus the renderer usage-overview model, each carried a file-level `eslint-disable max-lines` and had grown to 338-769 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all seven suppressions and prunes their entries (341 -> 334). Each file is cut along the seams it already had -- and that several of the suppression comments named out loud: filesystem discovery / record parsing / attribution / aggregation for the scanners, and pricing policy / scope filters / rollups / session rows / automation attribution for the stores. Pure move, no behavior change. Code is relocated verbatim; the only edits are import plumbing and, where a private class method became a free function, the mechanical `this.state` -> `state` parameter threading. Every converted call site passes `this.state` at call time and the automation path takes a live `getState: () => this.state` getter, so no state is snapshotted. No barrel exports: each new module owns real logic and importers point at the owner. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (remaining failures are pre-existing load flakes in untouched files, each green when re-run serially), no import cycles among the 64 affected modules, and a statement-level diff of every split confirms the moves are verbatim. |
||
|
|
bc28107864 |
refactor(hooks,relay): split agent hook services and relay under the max-lines budget (#14725)
The four agent hook services, the main hooks module, and the two relay modules each carried a file-level `eslint-disable max-lines` and ran 365-628 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all seven suppressions and prunes their entries (341 -> 334). Pure move, no behavior change. Each hook service splits into its managed script source, its config/bundle serialization, and its remote-install path, keeping the per-agent integrations independent: copilot, amp, antigravity and hermes each retain their own getManagedScript rather than sharing one, because each emits a different script body for a different agent. Merging them by name would have been a behavior change, not a refactor. For antigravity the suppression's stated rationale -- that local install, Windows wrapper generation, status cleanup, and SSH remote install must share one event list and managed-command matcher so stale-hook cleanup cannot drift by platform -- is now enforced structurally instead: both install paths call buildInstalledConfig + createAntigravityManagedCommandMatcher over the single ANTIGRAVITY_EVENTS catalog, with the graph a strict DAG. Also registers the six new antigravity/ and copilot/ modules in config/tsconfig.cli.json. That project uses a curated `include` list rather than a glob, so an unlisted module fails `tsc -p config/tsconfig.tc.cli.json` with TS6307 even though the entire unit suite passes. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (remaining failures are pre-existing load flakes in untouched files, green when re-run serially), no new runtime import cycles, and no lint suppression added. |
||
|
|
83117f2860 |
refactor(integrations): split issue-tracker clients under the max-lines budget (#14704)
The GitLab, GitHub, Jira and Linear integration modules, their two IPC registrars, and the shared GitHub project types each carried a file-level `eslint-disable max-lines` and ran 351-614 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all eight suppressions and prunes their entries (341 -> 333). Pure move, no behavior change. Each client is cut along the seam it already had: per-operation modules for the issue APIs (create / update / comment / field options), and for Jira the request queue, site credential store, authenticated request, and site identity. The two IPC registrars keep their own handlers and delegate the rest to per-domain sub-registrars, so they remain real entry points rather than re-export shims. The IPC surface is proved intact rather than assumed: comparing (method, channel) multisets between HEAD and the split gives 52 registrations across 52 distinct channels on both sides. Provider-neutrality is preserved -- GitLab and GitHub keep separate, parallel module layouts rather than being merged behind a shared abstraction. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (the one remaining failure is a pre-existing load flake in an untouched file, green when re-run serially), no new runtime import cycles among 744 modules, and no lint suppression added anywhere. |
||
|
|
15e1ba3f84 |
refactor(ipc): split main-process IPC modules under the max-lines budget (#14703)
The six oversized src/main/ipc modules each carried a file-level `eslint-disable max-lines` and ran 427-671 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all six suppressions and prunes their entries (341 -> 335). Pure move, no behavior change. Each file is cut along the seams it already had: pet splits into format allowlist / storage paths / symlink-safe copy / bundle manifest + import; filesystem-auth into path-containment primitives, the config-derived allow-list, and the git-registered root cache; notifications into sound selection, native lifecycle, permission probe, and burst cooldown; crash-reporting into renderer error reports, breadcrumbs, and sender. The IPC surface is proved intact rather than assumed: comparing (method, channel) multisets between HEAD and the split gives 49 registrations across 49 distinct channels on both sides. filesystem-auth's security boundary keeps its acyclic layering -- containment primitives, then allow-list, then root cache, then path-resolution orchestration -- with no layer gaining a back-edge. Also keeps clipboard-ipc-handlers.test.ts under the 800-line test budget. The split had briefly added a redundant vi.mock for isENOENT (byte-identical to the real implementation) that pushed it to 801; the mock is dropped in favor of the real function, with realpath added to the existing node:fs/promises mock. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (the one remaining failure is a pre-existing load flake in an untouched file, green when re-run serially), no new runtime import cycles among 617 modules, and no lint suppression added anywhere. |
||
|
|
c8fe5fc8c1 |
refactor(browser): split browser and browser-IPC modules under the max-lines budget (#14697)
The five oversized src/main/browser modules and src/main/ipc/browser.ts each carried a file-level `eslint-disable max-lines` and ran 377-654 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all six suppressions and prunes their entries (341 -> 335). Pure move, no behavior change. cdp-ws-proxy is decomposed into collaborating objects rather than free functions because its state is genuinely per-connection: every collaborator is a private readonly instance field built in the constructor with live closures over `this`, so per-connection state stays per-connection. Likewise the screencast pacer's isClosed/isStopping and snapshot capture's getSeq are live thunks, not values captured at wiring time, so guards inside already-armed timers still observe a later stop(). browser-guest-ui.ts is renamed to browser-guest-shortcut-forwarding.ts: after the split it exports exactly one function, setupGuestShortcutForwarding, so the old name no longer described its contents. Also restores a single `webContents.debugger` read in the screencast path. The extraction had left three reads where the original had one; the accessor is stable today, so this is not a behavior fix but it removes a latent divergence. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (remaining failures are pre-existing load flakes in untouched files, each green when re-run serially), no new runtime import cycles, and the IPC channel set diffed identical before/after with all 23 handlers still trust-gated. |
||
|
|
93ab6e142e |
refactor(source-control): extract modules to half SourceControl.tsx (#14396)
* docs(source-control): plan half-size extraction * refactor(source-control): extract modules to half SourceControl.tsx * move git decoration token comment to correct component * delete plan doc * test: add useSourceControlBranchCompare and git-history hook tests Comprehensive unit tests covering the scheduling, stale response filtering, and visibility logic of the extracted branch-compare and git-history hooks. * refactor(source-control): internationalize UI strings Add translate() support for all hardcoded strings throughout source control UI, extract reusable SourceControlTreeDirectoryHeader component, improve error handling in bulk operations with logging and user-facing toasts, and add proper return type annotations to hooks. * fix(source-control): satisfy react-doctor rules in extracted modules Reset worktree-scoped hook state during render instead of in an effect, and give dropdown separators stable ids so the changed-code quality gate stops flagging the extracted SourceControl modules. * docs: add JSDoc comments to source-control hooks and components Clarify the purpose, behavior, and constraints of test-harness functions, directory-row components, and the git-history hook to help maintainers understand the extracted and refactored source-control module. * refactor: organize source-control into lifecycle dest folders * fix(source-control): clear remaining react-doctor findings Reset worktree- and history-scoped state during render, keep Cmd/Ctrl selection updates free of setter side effects, and key graph paths by swimlane/parent id. Also add the PR LoC helper scripts the quality workflow fetches from the branch head. * fix(source-control): refetch git history when owner host changes Track activeRuntimeEnvironmentId as a stable key in useSourceControlGitHistory so that when the owner host changes but the worktree and path remain the same, the git history panel correctly refetches from the new host instead of keeping stale commits from the previous one. Add ownerHostKey to the useEffect dependency array to trigger refetch on host changes. Include JSDoc documentation for related components and expand test coverage to verify the host-change scenario. * fix(source-control): refetch git history when owner host changes Track activeRuntimeEnvironmentId as a stable key in useSourceControlGitHistory so that when the owner host changes but the worktree and path remain the same, the git history panel correctly refetches from the new host instead of keeping stale commits from the previous one. Add ownerHostKey to the useEffect dependency array to trigger refetch on host changes. Include JSDoc documentation for related components and expand test coverage to verify the host-change scenario. * refactor(source-control): consolidate bulk mutation error handling Extracts repeated error reporting into a dedicated helper function and applies it consistently across all bulk stage/unstage handlers, including two that were previously missing error handling. |
||
|
|
7aaa7c6f5b |
refactor(sidebar): group worktree-list files by domain (#14486)
* refactor(sidebar): group worktree-list files by domain Follow-up to #14465 / #14467. Keep the landed extract and reorganize the flat worktree-list dump into drag/, headers/, reveal/, rows/, scroll/, and viewport/. Fold tiny modules into their owners, move leftover sidebar-root files into the module, and retarget imports and source-path tests. Layout-only; no behavior change. * fix(sidebar): merge duplicate virtual-rows imports Inlining virtual-row-dom-attributes left a second import from the same module, which fails audit:code-quality:native --deny-warnings. * refactor(sidebar): condense indentation comments Shorten explanations to focus on the essential why, removing redundant detail and improving readability without changing functionality. * refactor: organize worktree-list into lifecycle dest folders * fix react doctor * fix: update reliability-gates path after worktree-list reorg host-filtering.test.ts moved from viewport/ to listing/; keep the runtime-routing.active-server-preference gate pointing at the real file. * Extract workspace status colors to design tokens Define theme-aware color tokens for workspace PR-state indicators (done, in-review, in-progress) to ensure consistent identity across theme switches. Update references to use the new tokens and refactor EmptyState button to use the Button component. * fix(sidebar): stop mutating refs during worktree-list render React Doctor fails static analysis when refs are written in render. Commit reused array identity and the Smart live-signal latch after paint, and return the attention map from the sort memo instead of stashing it on a render-time ref. |
||
|
|
9367169888 |
refactor(tests): split every oversized test file off the max-lines suppression list (#14728)
* refactor(tests): split oversized test files off the max-lines suppression list Every `*.test.ts`/`*.spec.ts` that carried an `eslint/oxlint-disable max-lines` directive is now split into focused, behavior-scoped suites that fit the 800-line test budget, with shared setup extracted into co-located `*-test-harness.ts` / `*-test-fixtures.ts` modules (300-line budget). 83 files became ~930; the largest output is 797 effective lines. `orca-runtime.test.ts` is intentionally untouched. Test bodies were moved by scripted line-range slicing rather than retyped, so assertions are byte-identical. The only permitted body edits were mechanical rebinding where a shared value moved into a harness (e.g. `tmpHome` -> `homes.tmpHome`). Registries that enumerate test files were updated in lockstep: - config/max-lines-baseline.txt: pruned 341 -> 258 entries (all 83 removed). - config/reliability-gates.jsonc: 33 gates repointed at the split files, with assertionRefs split per file where a gate's coverage now spans several. - .github/workflows/pr.yml: the real-zsh lane now lists the 4 split files that actually exercise zsh, so they keep running in the dedicated shell lane. Also renamed agent-hooks `server-test-fixtures.ts` to `server.test-fixtures.ts` so the global-fetch call-site audit keeps skipping it, and added `.js` extensions to the CLI suites' dynamic harness imports (node16 resolution) to unbreak `build:cli`. Verification: full suite 52,449 passing vs 52,448 at baseline with zero assertions lost; `pnpm lint`, `pnpm typecheck`, and `pnpm build:cli` all exit 0; the terminal-pane e2e spec runs 31/31 headless. * refactor(tests): split hook-idle arbitration suite that oxfmt pushed over budget The pre-commit oxfmt pass reflowed pty-connection-hook-idle-arbitration.test.ts to 811 effective lines, 11 over the test budget. Split the hook-completion side effect and replacement-agent veto cases into their own suite; both files now sit well under the cap and the 15 tests are unchanged. * test: port upstream test changes into the split files after rebase Rebasing onto main surfaced 27 tests that main had added to files this branch deleted, plus edits to tests that had already moved. Taking the deletion side of those modify/delete conflicts would have dropped that coverage silently, so each upstream change is ported into the split file that now owns the behavior — for example main's six orchestration mailbox tests land across orchestration-runs, -send, and -check. Also repoints `orchestration.notification-mailbox-consistency`, a gate main added after this branch's gate remap, at those same three split files, and re-prunes the max-lines baseline against main's (257 entries). Verified: all 27 upstream test titles present; full suite 52,761 passing with the only diff vs baseline being 12 tests main itself removed and 3 that moved from skipped to passing; lint and typecheck exit 0. * fix(test): flush pending continuations before tearing down terminal test globals CI shard 5/16 failed on both Node 24 and 26 with `ReferenceError: window is not defined` from pty-connection.ts, surfacing through pty-connection-daemon-snapshot-replay.test.ts. The reattach/settle chains `await` a real promise and then touch `window.api`. Under fake timers those continuations cannot run, so they only become schedulable once restoreTerminalTestGlobals() switches back to real timers — which previously happened immediately before `delete globalThis.window`, so a late continuation threw and failed the whole file. Flush async ticks in that window instead. This is latent in the source rather than new: the pre-split 25k-line file kept running other tests after these, which gave the chains time to settle before teardown. Splitting the file moved teardown directly behind them. * fix(test): keep an inert window after terminal test teardown instead of deleting it The async-tick flush was not enough: the reattach/settle chain can resolve after teardown regardless of how long we drain, so CI shard 5/16 still failed with `ReferenceError: window is not defined` from pty-connection.ts. A real renderer never loses `window`, so deleting it was the artificial part. Swap in an inert proxy whose properties resolve to callables and whose calls resolve to undefined, making a late `window.api.pty.*` call a harmless no-op. The next test replaces it wholesale via installTerminalTestGlobals(), and no test asserts that `window` is absent. |
||
|
|
8b31910ac1 |
Split worktrees slice (#14643)
* refactor: split worktrees.ts under 400 lines Move the worktree slice into dest modules under store/slices/worktrees/ and leave a thin public barrel so existing imports keep working. * refactor: nest worktrees dest modules by domain Group the extracted slice files into catalog, refresh, create, remove, and related domain folders instead of a flat dest dump. * refactor: group worktrees dest modules by lifecycle Collapse the 12 noun folders into listing, create, teardown, metadata, and session so dest layout matches the slice methods. * rm duplicated mport |
||
|
|
a3b472d050 |
refactor(renderer): decompose App.tsx into an app-shell module (#14607)
* refactor(renderer): decompose App.tsx into an app-shell module App.tsx was 2831 lines behind an `eslint-disable max-lines` and a grandfathered entry in the max-lines ratchet baseline. It is now 92 lines: a root element, the shared providers, and three children. The body is split by concern into src/renderer/src/app-shell/: - use-app-chrome-layout — titlebar/sidebar/workbench layout derivations - use-floating-workspace-panel — overlay open state, persistence, return focus - use-app-startup-hydration — the boot chain (order preserved verbatim) - use-app-session-persistence — session writer + shutdown checkpoint - use-persisted-ui-writer / use-document-appearance / use-runtime-graph-sync / use-window-visibility-effects - use-onboarding-and-feature-tips — first-run education gating - use-global-keybindings + app-command-handlers — window shortcut dispatch - use-app-shell-services — app-level subscriptions that outlive any surface - AppWorkspaceShell / AppRootSurfaces / AppBackgroundServices / titlebar parts Two startup branches that no longer needed to sit inline moved to src/renderer/src/startup/: startup-ssh-connection-restore and startup-degraded-recovery. No behavior change. Sibling order of root overlays and modals is preserved so stacking is unchanged; the sidebar's virtualized scroll refs still live above the sidebar's remount boundary. The source-assertion tests in app-startup-routing.test.ts follow the code to its new files. The one that claimed to check "first-window startup services before terminal reconnect" was matching the degraded-recovery block, not the success path; it now asserts the success path, and the degraded ordering keeps its own dedicated test. Removes the disable comment and drops App.tsx from config/max-lines-baseline.txt. * refactor(renderer): move app-shell ref writes out of render React Doctor's changed-lines purity gate flags three render-phase ref writes in the new app-shell files. The patterns predate the split, but moving them into new files brings them into the gate. - use-app-chrome-layout: the terminal-workbench latch becomes state set during render (the pattern use-lazy-modal-mounts already uses). The `canMountTerminalWorkbenchNow ||` term keeps the current render correct, so the latch only has to be visible to the next one. - use-app-startup-hydration: the onboarding callback ref syncs in an effect declared before the boot chain, so it lands first on mount. The callback is a `useCallback([])`, so its identity never actually changes. - use-global-keybindings: the shortcut-state mirror syncs in useLayoutEffect, which commits before any key event can read it. Key events are discrete, so handlers always observe committed state. All three now hold committed state only, so nothing can leak from a render React discards — the behavior the gate is protecting. pnpm run check:react-doctor:changed: 0 errors (was 3). |
||
|
|
9e5ee5ef8e |
feat(workspaces): rework cleanup discovery and dialog (#13413)
* fix(workspaces): support full cleanup scans * feat(workspaces): persist cleanup snapshots * feat(workspaces): add cleanup filter model * refactor(workspaces): remove cleanup presets * feat(workspaces): rework cleanup dialog * fix(workspaces): keep cleanup row ordering render-pure * refactor(workspaces): simplify cleanup browsing * refactor(workspaces): show cleanup facts * refactor(workspaces): surface cleanup row facts * fix(workspaces): remove misleading cleanup count * fix(workspaces): preserve full scan semantics * fix(workspaces): scope snapshot persistence * fix(workspaces): preserve cleanup browse compatibility * fix(workspaces): reconcile cleanup dialog state * test(workspaces): update snapshot store fixtures * test(workspaces): preserve cleanup scan modes * perf(workspace-cleanup): stream scan progress and size results * fix(workspace-cleanup): address review feedback * fix(workspace-cleanup): preserve host-scoped cleanup metadata * fix(workspace-cleanup): declare review source dependencies * fix(workspace-cleanup): align size scan banner * fix(workspace-cleanup): shorten scan action * perf(workspace-cleanup): avoid redundant scan IO * perf(workspace-cleanup): bound restarted evidence scans * fix(workspace-cleanup): satisfy scan queue lint * perf(workspace-cleanup): bound scan and snapshot work * perf(workspace-cleanup): serialize final enrichment * test(workspace-cleanup): assert final enrichment drain * fix(workspace-cleanup): stop progress after renderer teardown * perf: batch workspace cleanup git evidence scans * perf(workspace-cleanup): stop redundant snapshot and scan work * fix(workspace-cleanup): resolve review findings across scan, store, and dialog Correctness: - Chunk git-evidence dispatches at the shared 500-target limit and exclude queued/in-flight ids from target selection, so fleets past the limit can no longer strand rows permanently mislabeled as checked-but-unknown. - Key destructive selection pruning on the user's filter state instead of the per-tick matched-set identity; streaming reclassification no longer silently deselects rows. - Clamp the facet clock to max(scannedAt, open time): a stale hydrated snapshot no longer misbuckets idle thresholds or keeps dead agents fresh; row labels use the same clock. - Supersede and cancel the previous broad scan when a new one starts (renderer registry and same-sender guard in main) instead of racing two fleet scans. - Gate snapshot persistence on hasTargetedWorkspaceCleanupScan so worktreeIds: [] can never persist an empty fleet snapshot. - Re-apply dismissals at set-time in progress application so a dismissal landing mid-enrichment is not clobbered. - Record a one-off local snapshot prune for single (unbatched) remote deletes so removed workspaces cannot resurrect from cache. - Strip .exe when normalizing foreground process names so Windows agent processes match. Performance: - Cache per-candidate facet and review-info objects on candidate identity; no-op streaming ticks reuse the previous rows array and skip every downstream pass; matched-set identity is stable under equal membership. - Compute facet counts/options only while the filter popover is open. - Equality-bail git-evidence publishes; structural (non-stringify) facet-group comparison memoized in the toolbar. - Identity-token fast path for the enrichment cache (cache hits skip both JSON.stringify signatures); prune viewed/dismissal records on removal and expiry; bound the superseded-scan-id set. - Restore the no-op bail in removeWorkspaceSpaceWorktrees (regression). - Abort main-side scans when the renderer is destroyed; module-scope controller maps survive handler re-registration. - Batch removal preflight into one targeted scan (with refreshActivity) per 500 ids instead of one scan per row. - Scan repos at concurrency 2, report discovered counts upfront for honest progress, share fs-activity probes per path (folder workspaces), read only the reflog tail, and skip the snapshot read-before-write via a remembered scannedAt. Split workspace-cleanup-worktree-listing, workspace-cleanup-facet-row-caches, and workspace-cleanup-selection-model out of files that crossed max-lines. * fix(workspace-cleanup): address verifier findings - Fall back to a full reflog read when the newest record exceeds the 8KB tail window, so an oversized subject cannot hide recent ref activity. - Bound the single-removal snapshot prune batch id with a UUID; embedding the unbounded worktreeId silently failed main's 128-char validation and skipped the prune for long remote ids. - Key the main-side broad-scan supersession by sender AND scan mode so legacy suggestion-only and full-workspace scans stay isolated, matching the renderer registry. * fix(workspace-cleanup): own facet caches with useMemo instead of render-time ref writes React Doctor (CI changed-lines gate) correctly flagged the three cache refs written during render. Each per-candidate cache now lives in one memo with the derived context it is keyed on, so the memo deps are the invalidation and interior fills stay content-addressed; the matched-set identity stabilization is dropped since its only consumer reads through a useEffectEvent and never keys on identity. |
||
|
|
08027d0d23 |
refactor(sidebar): split WorktreeList into a worktree-list module (#14465)
WorktreeList.tsx was 6.8k lines behind an `eslint-disable max-lines`. Break it into `sidebar/worktree-list/`: the container keeps store wiring and composition, the virtualized viewport keeps layout, and the drag, reveal, virtualization, row-model, and row-render concerns each get their own file. Every file now fits the oxlint budget, so the suppression and its baseline entry are gone. Behaviour-preserving. The only deliberate cleanups are duplicate branches folded into shared helpers (drop-preview state updates, status-hover fallback, the two identical scroll-to-index reveal branches) and a dead sticky-header-index ref. Tests that asserted on WorktreeList.tsx source text or imported its named helpers now point at the module that owns them. |
||
|
|
4221f8d429 |
refactor(preload): split the preload contract into per-domain api modules (#14403)
`src/preload/api-types.ts` was 3,752 raw lines (3,533 counted, 11.8x the 300-line budget) behind an `eslint-disable max-lines`. Almost all of it was a single `PreloadApi` object type whose ~83 namespace properties were declared inline, so any IPC surface change meant editing one 2,600-line type. Give each namespace a named type in its own module under `src/preload/api/` (`pty-api.ts`, `filesystem-api.ts`, `github-pull-request-api.ts`, ...) and recompose `PreloadApi` from those names. `api-types.ts` keeps the `declare global` Window augmentation and re-exports every moved name, so all 52 import sites are untouched. Two shapes needed care to stay type-identical rather than merely compatible: - Three keys (`gh`, `git`, `ui`) are composed from two modules each. A plain intersection is NOT identical to the original flat object literal, so those use a `Merged<T>` mapped type; a negative control confirmed that dropping it fails the parity assertion. - Keys whose module groups several namespaces use indexed access (`fs: FilesystemApi['fs']`) to preserve exact identity and source order. `config/tsconfig.web.json` and `tsconfig.tc.web.json` enumerate files by path, so they need `src/preload/api/**/*` alongside the existing `api-types.ts` seed or the web projects fail TS6307. Verified by exact type identity, not assignability: 41 assertions of the form `Equals<Now.X, Before.X>` against a frozen pre-split snapshot, covering every exported name, plus a per-key pass over all 83 `PreloadApi` keys. All three projects typecheck clean with those assertions active. Verification note: these tsconfigs are `composite: true`, and `tsc --noEmit` will reuse a stale `.tsbuildinfo` and report clean for a state that genuinely fails. Every result above was produced after deleting the buildinfo, including a negative control confirming the gate still fails on deliberate drift. Drops the `max-lines` bypass and its baseline entry (ratchet 346 -> 345). |
||
|
|
583ab1601b |
refactor(shared): group worktree, github, and linear modules into folders (#14437)
`src/shared` is a flat directory of ~1,150 entries. The worktree, github, and
linear domains accounted for 71 of them, so finding the module you wanted meant
scanning a wall of same-prefixed filenames.
Move each domain into its own folder and drop the now-redundant prefix:
src/shared/github-pr-types.ts -> src/shared/github/pull-request-types.ts
src/shared/worktree-id.ts -> src/shared/worktree/id.ts
src/shared/linear-links.ts -> src/shared/linear/links.ts
This follows the existing `network/` and `new-workspace/` convention in the
same directory, which also drop the prefix inside the folder.
Whole clusters move, including tests. Foldering only part of a domain would be
worse than flat: a reader would have to check both `github/` and the flat
directory, and `github-auth-types.ts` / `github-project-types.ts` are type
modules that belong with the rest. No files with these prefixes remain flat.
Import specifiers were rewritten by resolving each one to an absolute path and
recomputing it, not by string substitution, so the `@/../../shared/...` alias
forms are handled correctly. 501 specifiers across 298 files.
Two things `tsc` cannot catch, handled explicitly:
- `github-project-types.ts` carries its own `max-lines` bypass, so its baseline
entry is REPOINTED to the new path rather than pruned. Pruning would drop the
bypass and then flag the new path as a fresh violation. Ratchet stays at 345.
- `mobile/` is outside `pnpm typecheck` and cannot be typechecked here
(`mobile/node_modules` is empty). Instead every relative specifier in the repo
was resolved against the filesystem: 174 unresolved before this change and 174
after — identical, so nothing broke in mobile either.
The pinned `tests/e2e/.cross-version-checkouts` fixtures are deliberately NOT
rewritten; they are a snapshot of an older release and still reference the old
paths.
Verified: cold `tsc --noEmit` green on node, cli, and web (buildinfo deleted
first — these projects are `composite: true` and reuse stale caches).
|
||
|
|
070572bfd7 |
refactor(shared): split shared/types.ts into per-domain type modules (#14397)
`src/shared/types.ts` was 3,981 raw lines (2,825 counted, 9.4x the 300-line budget) behind an `eslint-disable max-lines`, and is imported by 2,092 files — the single widest contract surface in the repo. Move all 320 top-level declarations into 46 per-domain modules (`repo-types.ts`, `worktree-types.ts`, `github-pr-types.ts`, ...) and reduce `types.ts` to an explicit re-export barrel, so the 2,092 import sites are untouched. `HostSettingOverrides` moves into the pre-existing `host-setting-overrides.ts` alongside the accessors that operate on it, which also removes that module's circular import back into `types.ts`. Named re-exports only, never `export type *`: with star re-exports a name exported by two modules is silently dropped, which would surface as a confusing "has no exported member" at a random call site. Verified lossless mechanically, not by inspection: - export parity — the module's resolved export set through the TS checker is identical before and after (396 names, no additions, no removals) - declaration parity — all 320 declarations compare character-identical modulo comments and whitespace, so no optionality, union order, or generic parameter drifted - `tsc --noEmit` green on the node, cli, and web projects - `oxfmt --write` is byte-identical, so the barrel is format-stable Drops the `max-lines` bypass and its baseline entry (ratchet 346 -> 345). |
||
|
|
c86418eaad |
rm git shim (#14141)
* rm git shim Drops the terminal git/gh PATH wrapper and its settings toggle. Renames the no-marker shell-ready launch config after what it does. Co-authored-by: Orca <help@stably.ai> * rm git shim: clear stale state from older installs Deletes the orphaned wrapper dir and scrubs inherited env/PATH, so a daemon that outlives the upgrade cannot keep seeding it. Drops a now-unread spawn option. Co-authored-by: Orca <help@stably.ai> * rm git shim: cover the daemon and headless paths Scrub after the PATH prepends (they re-read process.env on the sparse daemon env) and run the cleanup above the serve branch so remote hosts get it too. Retry a locked removal; match PATH case-insensitively. Co-authored-by: Orca <help@stably.ai> * rm git shim: keep the scrub final Refuse to re-prepend a legacy entry during agent-teams PATH promotion, which runs after the scrub. Cover the removal guard. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai> |
||
|
|
0345d71214 | refactor(renderer): split oversized TabBar module (#13739) | ||
|
|
fdaafc93dd | refactor(renderer): split SettingsFormControls below max-lines limit (#13747) | ||
|
|
6964f75cd0 | refactor(renderer): share metadata list request lifecycle (#13524) | ||
|
|
600b0b1c15 | refactor(renderer): split WorktreeCard (#13715) | ||
|
|
96c2cebfa6 | refactor(mobile): extract terminal settings styles (#13706) | ||
|
|
5e9186f5ff |
chore(mobile): import the shared marine-creature corpus instead of mirroring it (#12090)
mobile/src/constants/marine-creatures.ts was a hand-maintained copy of src/shared/marine-creatures.ts, identical except for a comment header. The copy existed because Metro only watched mobile/ and could not resolve repo-root modules; mobile/metro.config.js:11 added src/shared to watchFolders five weeks later, and ~195 mobile files already import from src/shared. The renderer collapsed its copy to a re-export at the same time; mobile was the leftover. Point the one consumer at the shared corpus and delete the mirror, the bespoke regex-scraping parity test that policed it, and the now-stale max-lines baseline entry. No behavior change: same exported symbol, byte-identical name list. |
||
|
|
6f3845baa4 |
fix(checks): rank successful checks above skipped and neutral (#11337)
* fix(checks): rank successful checks above skipped and neutral Checks were ordered with `skipped` (4) and `neutral` (3) ahead of `success` (5), so a PR with a long tail of skipped jobs pushed every passing check below the fold — you scroll past a wall of "Skipped" to find out whether anything actually ran. Rank the no-signal conclusions last (`success` 3, `neutral` 4, `skipped` 5) and pull the order out of its three duplicated copies (checks-panel-content, PullRequestPage, GitHubItemDialog) into `src/shared/pr-check-severity-order.ts`. Unknown conclusions now sink to the bottom instead of silently ranking as `neutral`. * fix(checks): look up check ranks through a Map, not an object literal An object-literal rank table resolves `constructor`, `toString`, and `__proto__` off Object.prototype, so those keys returned a function instead of falling through to UNKNOWN_CHECK_RANK — the comparator then subtracted functions, went NaN, and left the list in arbitrary order. Conclusions come from provider payloads, so keep the lookup on a Map and cover prototype property names in the test. * test(checks): cover provider-neutral ordering states * fix(checks): preserve actionable provider states * fix(checks): preserve unresolved provider rollups * fix(checks): keep unknown GitLab rollups neutral * fix: preserve neutral review check summaries * fix: complete provider-neutral check ordering remediation * fix: use provider-neutral mobile review status input * fix: hydrate GitLab mobile review status * fix: type mobile GitLab review hydration --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
624c8d4120 |
Make plain-text file:// links clickable in the terminal (#9467)
* Make plain-text file:// links clickable in the terminal Printed file:// URIs (e.g. a report path echoed by a tool or agent) were neither http links nor bare filesystem paths, so the terminal's URL and local-path detectors both skipped them and the link was dead. Orca already resolves and opens file:// URIs for OSC 8 hyperlinks. Reuse that exact resolver for plain-text URIs so a printed file:// behaves the same whether or not the emitter wrapped it in an escape sequence: - Promote the (dependency-pure) file-url target resolver into src/shared so the OSC path and the new plain-text path share one implementation. - Add a file:// detector that decodes the URI to a filesystem path and routes it through the existing file-link pipeline (existence probe + openDetectedFilePath), so line/col anchors, %20, Windows drive paths, html-in-browser, editor reveal, and SSH/runtime resolution all just work. Lines without file:// are unchanged: the pass short-circuits to the prior result, so only file://-bearing lines gain a link. - Add unit + integration coverage for detection, decoding, and no-double-link. * Harden plain-text file URI detection * Split terminal file link detection modules |
||
|
|
f311307560 |
Add max-lines ratchet CI gate to block new line-limit bypasses (#7608)
oxlint already fails any file over max-lines that is not suppressed, so the only way to grow past the budget is to add an eslint/oxlint-disable max-lines comment or a per-file max-lines bump in mobile/.oxlintrc.json. This adds a CI gate that freezes the current set of suppressions (config/max-lines-baseline.txt, 355 grandfathered entries) and fails the build when a NEW one appears — with a loud, actionable message pointing at 'split the file'. Existing oversized files are untouched; the baseline may only shrink (pnpm check:max-lines-ratchet --prune). Wired into the root lint script and as a dedicated pr.yml step. Unit-tested (15 cases) and verified against all three failure paths + clean-tree pass. Co-authored-by: Orca <help@stably.ai> |