From 56512d852bac0e1f35470ac9c391bba2039bd135 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sun, 12 Apr 2026 10:40:14 +0700 Subject: [PATCH] Run Biome formatter and add formatting guidance to CLAUDE.md --- CLAUDE.md | 3 ++ .../__tests__/split-markdown-blocks.test.ts | 17 ++++--- .../app/src/utils/split-markdown-blocks.ts | 5 +-- .../session.workspace-git-watch.test.ts | 12 +++-- .../src/server/session.workspaces.test.ts | 18 ++++---- .../src/server/workspace-git-service.test.ts | 45 ++++++++----------- .../src/server/workspace-git-service.ts | 15 +++++-- 7 files changed, 60 insertions(+), 55 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 78020044a..dfb9b88d0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,6 +35,8 @@ npm run dev # Start daemon + Expo in Tmux npm run cli -- ls -a -g # List all agents npm run cli -- daemon status # Check daemon status npm run typecheck # Always run after changes +npm run format # Auto-format with Biome +npm run format:check # Check formatting without writing ``` See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for full setup, build sync requirements, and debugging. @@ -45,6 +47,7 @@ See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for full setup, build sync requir - **NEVER assume a timeout means the service needs restarting** — timeouts can be transient. - **NEVER add auth checks to tests** — agent providers handle their own auth. - **Always run typecheck after every change.** +- **Run `npm run format` before committing.** This repo uses Biome for formatting. Do not manually fix formatting — let the formatter handle it. - **NEVER make breaking changes to WebSocket or message schemas.** The primary compatibility path is old mobile app clients talking to newly updated daemons. Users update desktop and daemon first, then keep running the old app for a while. Every schema change MUST be backward-compatible for old clients against new daemons: - New fields: always `.optional()` with a sensible default or `.transform()` fallback. - Never change a field from optional to required. diff --git a/packages/app/src/utils/__tests__/split-markdown-blocks.test.ts b/packages/app/src/utils/__tests__/split-markdown-blocks.test.ts index a014708fa..2a12f80e4 100644 --- a/packages/app/src/utils/__tests__/split-markdown-blocks.test.ts +++ b/packages/app/src/utils/__tests__/split-markdown-blocks.test.ts @@ -37,18 +37,17 @@ describe("splitMarkdownBlocks", () => { it("splits mixed paragraph, code fence, and paragraph content into three blocks", () => { expect( - splitMarkdownBlocks("Intro paragraph\n\n```ts\nconst a = 1;\n\nconst b = 2;\n```\n\nOutro paragraph"), - ).toEqual([ - "Intro paragraph", - "```ts\nconst a = 1;\n\nconst b = 2;\n```", - "Outro paragraph", - ]); + splitMarkdownBlocks( + "Intro paragraph\n\n```ts\nconst a = 1;\n\nconst b = 2;\n```\n\nOutro paragraph", + ), + ).toEqual(["Intro paragraph", "```ts\nconst a = 1;\n\nconst b = 2;\n```", "Outro paragraph"]); }); it("keeps everything from an unclosed fence start as one block for streaming content", () => { - expect( - splitMarkdownBlocks("Before fence\n\n```ts\nconst a = 1;\n\nconst b = 2;"), - ).toEqual(["Before fence", "```ts\nconst a = 1;\n\nconst b = 2;"]); + expect(splitMarkdownBlocks("Before fence\n\n```ts\nconst a = 1;\n\nconst b = 2;")).toEqual([ + "Before fence", + "```ts\nconst a = 1;\n\nconst b = 2;", + ]); }); it("returns an empty array for empty input", () => { diff --git a/packages/app/src/utils/split-markdown-blocks.ts b/packages/app/src/utils/split-markdown-blocks.ts index 4a6942872..3d7e831ad 100644 --- a/packages/app/src/utils/split-markdown-blocks.ts +++ b/packages/app/src/utils/split-markdown-blocks.ts @@ -43,10 +43,7 @@ export function splitMarkdownBlocks(text: string): string[] { continue; } - if ( - fenceDelimiter[0] === activeFenceCharacter && - fenceDelimiter.length >= activeFenceLength - ) { + if (fenceDelimiter[0] === activeFenceCharacter && fenceDelimiter.length >= activeFenceLength) { activeFenceCharacter = null; activeFenceLength = 0; } diff --git a/packages/server/src/server/session.workspace-git-watch.test.ts b/packages/server/src/server/session.workspace-git-watch.test.ts index 541c35857..a528cfba4 100644 --- a/packages/server/src/server/session.workspace-git-watch.test.ts +++ b/packages/server/src/server/session.workspace-git-watch.test.ts @@ -47,11 +47,11 @@ function createWorkspaceRuntimeSnapshot( ...overrides?.github, pullRequest: overrides?.github && "pullRequest" in overrides.github - ? overrides.github.pullRequest ?? null + ? (overrides.github.pullRequest ?? null) : base.github.pullRequest, error: overrides?.github && "error" in overrides.github - ? overrides.github.error ?? null + ? (overrides.github.error ?? null) : base.github.error, }, }; @@ -309,7 +309,9 @@ describe("workspace git watch targets", () => { }); expect(workspaceGitService.getSnapshot).toHaveBeenCalledWith("/tmp/repo"); - expect(emitted.find((message) => message.type === "checkout_pr_status_response")?.payload).toEqual({ + expect( + emitted.find((message) => message.type === "checkout_pr_status_response")?.payload, + ).toEqual({ cwd: "/tmp/repo", status: { url: "https://github.com/acme/repo/pull/456", @@ -366,7 +368,9 @@ describe("workspace git watch targets", () => { expect(workspaceGitService.refresh).toHaveBeenCalledWith("/tmp/repo", { priority: "high", }); - expect(emitted.find((message) => message.type === "checkout_pr_status_response")?.payload).toEqual({ + expect( + emitted.find((message) => message.type === "checkout_pr_status_response")?.payload, + ).toEqual({ cwd: "/tmp/repo", status: { url: "https://github.com/acme/repo/pull/457", diff --git a/packages/server/src/server/session.workspaces.test.ts b/packages/server/src/server/session.workspaces.test.ts index 7398497df..36d8cb1de 100644 --- a/packages/server/src/server/session.workspaces.test.ts +++ b/packages/server/src/server/session.workspaces.test.ts @@ -165,20 +165,22 @@ function createWorkspaceRuntimeSnapshot( ...overrides?.github, pullRequest: overrides?.github && "pullRequest" in overrides.github - ? overrides.github.pullRequest ?? null + ? (overrides.github.pullRequest ?? null) : base.github.pullRequest, error: overrides?.github && "error" in overrides.github - ? overrides.github.error ?? null + ? (overrides.github.error ?? null) : base.github.error, }, }; } -function createSessionForWorkspaceTests(options: { - appVersion?: string | null; - workspaceGitService?: ReturnType; -} = {}): Session { +function createSessionForWorkspaceTests( + options: { + appVersion?: string | null; + workspaceGitService?: ReturnType; + } = {}, +): Session { const logger = { child: () => logger, trace: vi.fn(), @@ -238,8 +240,8 @@ function createSessionForWorkspaceTests(options: { checkoutDiffWatcherCount: 0, checkoutDiffFallbackRefreshTargetCount: 0, }), - dispose: () => {}, - } as any, + dispose: () => {}, + } as any, workspaceGitService: (options.workspaceGitService ?? createNoopWorkspaceGitService()) as any, mcpBaseUrl: null, stt: null, diff --git a/packages/server/src/server/workspace-git-service.test.ts b/packages/server/src/server/workspace-git-service.test.ts index 4bbbf2ef6..97baf930c 100644 --- a/packages/server/src/server/workspace-git-service.test.ts +++ b/packages/server/src/server/workspace-git-service.test.ts @@ -1,8 +1,5 @@ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; -import type { - CheckoutStatusGit, - PullRequestStatusResult, -} from "../utils/checkout-git.js"; +import type { CheckoutStatusGit, PullRequestStatusResult } from "../utils/checkout-git.js"; import { WorkspaceGitServiceImpl, type WorkspaceGitRuntimeSnapshot, @@ -65,11 +62,11 @@ function createSnapshot( ...overrides?.github, pullRequest: overrides?.github && "pullRequest" in overrides.github - ? overrides.github.pullRequest ?? null + ? (overrides.github.pullRequest ?? null) : base.github.pullRequest, error: overrides?.github && "error" in overrides.github - ? overrides.github.error ?? null + ? (overrides.github.error ?? null) : base.github.error, }, }; @@ -139,7 +136,7 @@ function createService(options?: { logger: createLogger() as any, paseoHome: "/tmp/paseo-test", deps: { - watch: options?.watch ?? (((() => createWatcher()) as unknown) as any), + watch: options?.watch ?? ((() => createWatcher()) as unknown as any), getCheckoutStatus: options?.getCheckoutStatus ?? vi.fn(async (cwd: string) => createCheckoutStatus(cwd)), getCheckoutShortstat: @@ -149,8 +146,7 @@ function createService(options?: { deletions: 0, })), getPullRequestStatus: - options?.getPullRequestStatus ?? - vi.fn(async () => createPullRequestStatusResult()), + options?.getPullRequestStatus ?? vi.fn(async () => createPullRequestStatusResult()), resolveGhPath: options?.resolveGhPath ?? vi.fn(async () => "/usr/bin/gh"), resolveAbsoluteGitDir: options?.resolveAbsoluteGitDir ?? vi.fn(async () => "/tmp/repo/.git"), hasOriginRemote: options?.hasOriginRemote ?? vi.fn(async () => false), @@ -325,10 +321,7 @@ describe("WorkspaceGitServiceImpl", () => { }), ); - const nowValues = [ - new Date("2026-04-12T00:00:00.000Z"), - new Date("2026-04-12T00:05:00.000Z"), - ]; + const nowValues = [new Date("2026-04-12T00:00:00.000Z"), new Date("2026-04-12T00:05:00.000Z")]; const service = createService({ getPullRequestStatus, now: () => nowValues.shift() ?? new Date("2026-04-12T00:05:00.000Z"), @@ -383,20 +376,18 @@ describe("WorkspaceGitServiceImpl", () => { aheadOfOrigin: 2, }), ); - const getPullRequestStatus = vi - .fn<() => Promise>() - .mockResolvedValue( - createPullRequestStatusResult({ - status: { - url: "https://github.com/acme/repo/pull/123", - title: "Runtime payloads", - state: "open", - baseRefName: "main", - headRefName: "feature/runtime-payloads", - isMerged: false, - }, - }), - ); + const getPullRequestStatus = vi.fn<() => Promise>().mockResolvedValue( + createPullRequestStatusResult({ + status: { + url: "https://github.com/acme/repo/pull/123", + title: "Runtime payloads", + state: "open", + baseRefName: "main", + headRefName: "feature/runtime-payloads", + isMerged: false, + }, + }), + ); const service = createService({ getCheckoutStatus, diff --git a/packages/server/src/server/workspace-git-service.ts b/packages/server/src/server/workspace-git-service.ts index a134072ba..07f29fc88 100644 --- a/packages/server/src/server/workspace-git-service.ts +++ b/packages/server/src/server/workspace-git-service.ts @@ -258,7 +258,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService { this.scheduleWorkspaceRefresh(target); }); } catch (error) { - this.logger.warn({ err: error, cwd: target.cwd, watchPath }, "Failed to start workspace git watcher"); + this.logger.warn( + { err: error, cwd: target.cwd, watchPath }, + "Failed to start workspace git watcher", + ); } if (!watcher) { @@ -332,7 +335,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService { const snapshot = await this.refreshSnapshot(target.cwd); this.rememberSnapshot(target, snapshot, { notify: true }); } catch (error) { - this.logger.warn({ err: error, cwd: target.cwd }, "Failed to refresh workspace git snapshot"); + this.logger.warn( + { err: error, cwd: target.cwd }, + "Failed to refresh workspace git snapshot", + ); } } while (target.refreshQueued); })(); @@ -378,7 +384,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService { } target.fetchInFlight = true; - this.logger.debug({ repoGitRoot: target.repoGitRoot, cwd: target.cwd }, "Running background git fetch"); + this.logger.debug( + { repoGitRoot: target.repoGitRoot, cwd: target.cwd }, + "Running background git fetch", + ); try { await this.deps.runGitFetch(target.cwd);