From 7f2ee1e6ab88f04f6c80772e5e20e82b724d7e94 Mon Sep 17 00:00:00 2001 From: "Sakamoto, Kazunori" Date: Sat, 2 May 2026 17:25:11 +0900 Subject: [PATCH 1/3] fix: run wb through yarn in playwright web server Co-authored-by: WillBooster (Codex CLI) --- packages/wbfy/src/fixers/playwrightConfig.ts | 7 ++++--- packages/wbfy/src/generators/agents.ts | 2 +- packages/wbfy/test/agentInstructions.test.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/wbfy/src/fixers/playwrightConfig.ts b/packages/wbfy/src/fixers/playwrightConfig.ts index 95a66b14..5ab6219b 100644 --- a/packages/wbfy/src/fixers/playwrightConfig.ts +++ b/packages/wbfy/src/fixers/playwrightConfig.ts @@ -40,7 +40,7 @@ const defaultConfig = toParsedObject({ video: literal("process.env.CI ? 'on-first-retry' : 'retain-on-failure'"), }), webServer: asObject({ - command: literal("'wb start --mode test'"), + command: literal("'yarn wb start --mode test'"), url: literal('process.env.NEXT_PUBLIC_BASE_URL'), reuseExistingServer: literal('!!process.env.CI'), timeout: literal('300_000'), @@ -158,8 +158,9 @@ function setWebServerCommand(object: ParsedObject): void { if (webServer?.kind !== 'object') return; // wb owns the canonical test-server startup path; keep custom Playwright - // server settings while normalizing the command itself. - webServer.value.properties.command = literal("'wb start --mode test'"); + // server settings while normalizing the command itself. Invoke wb through + // Yarn because target repos install wb as a package dependency. + webServer.value.properties.command = literal("'yarn wb start --mode test'"); } function extractDefineConfigObjectLiteral(content: string): ExtractedObjectLiteral | undefined { diff --git a/packages/wbfy/src/generators/agents.ts b/packages/wbfy/src/generators/agents.ts index 0614c231..d7b0ee8f 100644 --- a/packages/wbfy/src/generators/agents.ts +++ b/packages/wbfy/src/generators/agents.ts @@ -74,7 +74,7 @@ function generateAgentInstruction( - If not specified, make sure to add a new line at the end of your commit message${rootConfig.isWillBoosterRepo ? ` with: \`Co-authored-by: WillBooster (${toolName}) \`` : ''}. - Always create new commits. Avoid using \`--amend\`. - Always use heredoc syntax when passing multi-line content to any command. -${hasPlaywrightTestServer(allConfigs) ? `- Use \`wb start --mode test\` to launch a web server for debugging or testing.` : ''} +${hasPlaywrightTestServer(allConfigs) ? `- Use \`yarn wb start --mode test\` to launch a web server for debugging or testing.` : ''} ${generateAgentCodingStyle(allConfigs)} ` diff --git a/packages/wbfy/test/agentInstructions.test.ts b/packages/wbfy/test/agentInstructions.test.ts index 498d427b..54f4e96e 100644 --- a/packages/wbfy/test/agentInstructions.test.ts +++ b/packages/wbfy/test/agentInstructions.test.ts @@ -35,7 +35,7 @@ test('mentions wb test server startup for Playwright projects on the first run', await promisePool.promiseAll(); const content = await fs.promises.readFile(path.join(dirPath, 'AGENTS.md'), 'utf8'); - expect(content).toContain('Use `wb start --mode test` to launch a web server for debugging or testing.'); + expect(content).toContain('Use `yarn wb start --mode test` to launch a web server for debugging or testing.'); }); function createTempDir(): string { From 5c7385b63568a7297f9b54e6eb1c58bf26206c76 Mon Sep 17 00:00:00 2001 From: "Sakamoto, Kazunori" Date: Sat, 2 May 2026 17:32:05 +0900 Subject: [PATCH 2/3] fix: respect package manager for wb test server command Co-authored-by: WillBooster (Codex CLI) --- packages/wbfy/src/fixers/playwrightConfig.ts | 57 +++++++++++--------- packages/wbfy/src/generators/agents.ts | 2 +- packages/wbfy/test/agentInstructions.test.ts | 2 +- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/packages/wbfy/src/fixers/playwrightConfig.ts b/packages/wbfy/src/fixers/playwrightConfig.ts index 5ab6219b..b12b90f3 100644 --- a/packages/wbfy/src/fixers/playwrightConfig.ts +++ b/packages/wbfy/src/fixers/playwrightConfig.ts @@ -30,32 +30,33 @@ const asObject = (properties: Record, extraMembers: string[ value: toParsedObject(properties, extraMembers), }); -const defaultConfig = toParsedObject({ - forbidOnly: literal('!!process.env.CI'), - retries: literal('process.env.PWDEBUG ? 0 : process.env.CI ? 5 : 1'), - use: asObject({ - baseURL: literal('process.env.NEXT_PUBLIC_BASE_URL'), - trace: literal("process.env.CI ? 'on-first-retry' : 'retain-on-failure'"), - screenshot: literal("process.env.CI ? 'only-on-failure' : 'on'"), - video: literal("process.env.CI ? 'on-first-retry' : 'retain-on-failure'"), - }), - webServer: asObject({ - command: literal("'yarn wb start --mode test'"), - url: literal('process.env.NEXT_PUBLIC_BASE_URL'), - reuseExistingServer: literal('!!process.env.CI'), - timeout: literal('300_000'), - stdout: literal("'pipe'"), - stderr: literal("'pipe'"), - env: literal(`{ +const createDefaultConfig = (config: PackageConfig): ParsedObject => + toParsedObject({ + forbidOnly: literal('!!process.env.CI'), + retries: literal('process.env.PWDEBUG ? 0 : process.env.CI ? 5 : 1'), + use: asObject({ + baseURL: literal('process.env.NEXT_PUBLIC_BASE_URL'), + trace: literal("process.env.CI ? 'on-first-retry' : 'retain-on-failure'"), + screenshot: literal("process.env.CI ? 'only-on-failure' : 'on'"), + video: literal("process.env.CI ? 'on-first-retry' : 'retain-on-failure'"), + }), + webServer: asObject({ + command: literal(`'${getPackageManagerCommand(config)} wb start --mode test'`), + url: literal('process.env.NEXT_PUBLIC_BASE_URL'), + reuseExistingServer: literal('!!process.env.CI'), + timeout: literal('300_000'), + stdout: literal("'pipe'"), + stderr: literal("'pipe'"), + env: literal(`{ ...process.env, PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION: 'true', }`), - gracefulShutdown: literal(`{ + gracefulShutdown: literal(`{ signal: 'SIGTERM', timeout: 500, }`), - }), -}); + }), + }); function toParsedObject(properties: Record, extraMembers: string[] = []): ParsedObject { return { @@ -83,8 +84,8 @@ export async function fixPlaywrightConfig(config: PackageConfig): Promise if (!parsed) return; // Keep filling missing defaults, but don't overwrite local adjustments on every regeneration. - const merged = mergeParsedObjects(defaultConfig, parsed); - setWebServerCommand(merged); + const merged = mergeParsedObjects(createDefaultConfig(config), parsed); + setWebServerCommand(merged, config); const newObjectLiteral = stringifyValue({ kind: 'object', value: merged }, 0); const start = extractedObjectLiteral.node.getStart(extractedObjectLiteral.source); @@ -153,14 +154,18 @@ function getEnvFilePaths(dirPath: string): string[] { return envFilePaths; } -function setWebServerCommand(object: ParsedObject): void { +function setWebServerCommand(object: ParsedObject, config: PackageConfig): void { const webServer = object.properties.webServer; if (webServer?.kind !== 'object') return; // wb owns the canonical test-server startup path; keep custom Playwright - // server settings while normalizing the command itself. Invoke wb through - // Yarn because target repos install wb as a package dependency. - webServer.value.properties.command = literal("'yarn wb start --mode test'"); + // server settings while normalizing the command itself. Invoke wb through the + // package manager because target repos install wb as a package dependency. + webServer.value.properties.command = literal(`'${getPackageManagerCommand(config)} wb start --mode test'`); +} + +function getPackageManagerCommand(config: PackageConfig): 'bun' | 'yarn' { + return config.isBun ? 'bun' : 'yarn'; } function extractDefineConfigObjectLiteral(content: string): ExtractedObjectLiteral | undefined { diff --git a/packages/wbfy/src/generators/agents.ts b/packages/wbfy/src/generators/agents.ts index d7b0ee8f..83b7b1a2 100644 --- a/packages/wbfy/src/generators/agents.ts +++ b/packages/wbfy/src/generators/agents.ts @@ -74,7 +74,7 @@ function generateAgentInstruction( - If not specified, make sure to add a new line at the end of your commit message${rootConfig.isWillBoosterRepo ? ` with: \`Co-authored-by: WillBooster (${toolName}) \`` : ''}. - Always create new commits. Avoid using \`--amend\`. - Always use heredoc syntax when passing multi-line content to any command. -${hasPlaywrightTestServer(allConfigs) ? `- Use \`yarn wb start --mode test\` to launch a web server for debugging or testing.` : ''} +${hasPlaywrightTestServer(allConfigs) ? `- Use \`${packageManager} wb start --mode test\` to launch a web server for debugging or testing.` : ''} ${generateAgentCodingStyle(allConfigs)} ` diff --git a/packages/wbfy/test/agentInstructions.test.ts b/packages/wbfy/test/agentInstructions.test.ts index 54f4e96e..708cf075 100644 --- a/packages/wbfy/test/agentInstructions.test.ts +++ b/packages/wbfy/test/agentInstructions.test.ts @@ -35,7 +35,7 @@ test('mentions wb test server startup for Playwright projects on the first run', await promisePool.promiseAll(); const content = await fs.promises.readFile(path.join(dirPath, 'AGENTS.md'), 'utf8'); - expect(content).toContain('Use `yarn wb start --mode test` to launch a web server for debugging or testing.'); + expect(content).toContain('Use `bun wb start --mode test` to launch a web server for debugging or testing.'); }); function createTempDir(): string { From 20ade8bd2907f3969c120612018849b881254a5a Mon Sep 17 00:00:00 2001 From: "Sakamoto, Kazunori" Date: Sat, 2 May 2026 17:38:36 +0900 Subject: [PATCH 3/3] refactor: share package manager command detection Co-authored-by: WillBooster (Codex CLI) --- packages/wbfy/src/fixers/playwrightConfig.ts | 9 +++++---- packages/wbfy/src/generators/agents.ts | 3 ++- packages/wbfy/src/utils/packageCapabilities.ts | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/wbfy/src/fixers/playwrightConfig.ts b/packages/wbfy/src/fixers/playwrightConfig.ts index b12b90f3..686a7b27 100644 --- a/packages/wbfy/src/fixers/playwrightConfig.ts +++ b/packages/wbfy/src/fixers/playwrightConfig.ts @@ -6,6 +6,7 @@ import ts from 'typescript'; import { logger } from '../logger.js'; import type { PackageConfig } from '../packageConfig.js'; import { fsUtil } from '../utils/fsUtil.js'; +import { getPackageManagerCommand } from '../utils/packageCapabilities.js'; import { promisePool } from '../utils/promisePool.js'; type ParsedValue = @@ -41,7 +42,7 @@ const createDefaultConfig = (config: PackageConfig): ParsedObject => video: literal("process.env.CI ? 'on-first-retry' : 'retain-on-failure'"), }), webServer: asObject({ - command: literal(`'${getPackageManagerCommand(config)} wb start --mode test'`), + command: literal(getWbStartTestCommand(config)), url: literal('process.env.NEXT_PUBLIC_BASE_URL'), reuseExistingServer: literal('!!process.env.CI'), timeout: literal('300_000'), @@ -161,11 +162,11 @@ function setWebServerCommand(object: ParsedObject, config: PackageConfig): void // wb owns the canonical test-server startup path; keep custom Playwright // server settings while normalizing the command itself. Invoke wb through the // package manager because target repos install wb as a package dependency. - webServer.value.properties.command = literal(`'${getPackageManagerCommand(config)} wb start --mode test'`); + webServer.value.properties.command = literal(getWbStartTestCommand(config)); } -function getPackageManagerCommand(config: PackageConfig): 'bun' | 'yarn' { - return config.isBun ? 'bun' : 'yarn'; +function getWbStartTestCommand(config: PackageConfig): string { + return `'${getPackageManagerCommand(config)} wb start --mode test'`; } function extractDefineConfigObjectLiteral(content: string): ExtractedObjectLiteral | undefined { diff --git a/packages/wbfy/src/generators/agents.ts b/packages/wbfy/src/generators/agents.ts index 83b7b1a2..ebab3e01 100644 --- a/packages/wbfy/src/generators/agents.ts +++ b/packages/wbfy/src/generators/agents.ts @@ -3,6 +3,7 @@ import path from 'node:path'; import { logger } from '../logger.js'; import type { PackageConfig } from '../packageConfig.js'; import { fsUtil } from '../utils/fsUtil.js'; +import { getPackageManagerCommand } from '../utils/packageCapabilities.js'; import { promisePool } from '../utils/promisePool.js'; export async function generateAgentInstructions(rootConfig: PackageConfig, allConfigs: PackageConfig[]): Promise { @@ -45,7 +46,7 @@ function generateAgentInstruction( toolName: string, extraContent?: string ): string { - const packageManager = rootConfig.isBun ? 'bun' : 'yarn'; + const packageManager = getPackageManagerCommand(rootConfig); const baseContent = ` ## Project Information diff --git a/packages/wbfy/src/utils/packageCapabilities.ts b/packages/wbfy/src/utils/packageCapabilities.ts index 68e2b125..3f5f00a5 100644 --- a/packages/wbfy/src/utils/packageCapabilities.ts +++ b/packages/wbfy/src/utils/packageCapabilities.ts @@ -12,3 +12,7 @@ export function doesContainJsOrTs(config: PackageConfig): boolean { export function doesContainJava(config: PackageConfig): boolean { return config.doesContainJava || config.doesContainJavaInPackages; } + +export function getPackageManagerCommand(config: Pick): 'bun' | 'yarn' { + return config.isBun ? 'bun' : 'yarn'; +}