Files
Codewalkers/apps/server/test/integration/agent-workdir-verification.test.ts
Lukas May 34578d39c6 refactor: Restructure monorepo to apps/server/ and apps/web/ layout
Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt
standard monorepo conventions (apps/ for runnable apps, packages/
for reusable libraries). Update all config files, shared package
imports, test fixtures, and documentation to reflect new paths.

Key fixes:
- Update workspace config to ["apps/*", "packages/*"]
- Update tsconfig.json rootDir/include for apps/server/
- Add apps/web/** to vitest exclude list
- Update drizzle.config.ts schema path
- Fix ensure-schema.ts migration path detection (3 levels up in dev,
  2 levels up in dist)
- Fix tests/integration/cli-server.test.ts import paths
- Update packages/shared imports to apps/server/ paths
- Update all docs/ files with new paths
2026-03-03 11:22:53 +01:00

203 lines
7.2 KiB
TypeScript

/**
* Agent Working Directory Verification Tests
*
* Tests that verify agents actually run in their intended working directories.
* These tests use simple shell commands to prove the agent execution location.
*
* IMPORTANT: These tests spawn real CLI processes and may incur API costs.
* They are SKIPPED by default to prevent accidental charges.
*
* To run these tests:
* ```bash
* REAL_WORKDIR_TESTS=1 npm test -- src/test/integration/agent-workdir-verification.test.ts --test-timeout=120000
* ```
*/
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { mkdtemp, rm, readFile } from 'node:fs/promises';
import { existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { MultiProviderAgentManager } from '../../agent/manager.js';
import { createTestDatabase } from '../../db/repositories/drizzle/test-helpers.js';
import {
DrizzleAgentRepository,
DrizzleProjectRepository,
DrizzleAccountRepository,
DrizzleInitiativeRepository,
} from '../../db/repositories/drizzle/index.js';
import { EventEmitterBus } from '../../events/bus.js';
const SHOULD_SKIP = !process.env.REAL_WORKDIR_TESTS;
const TEST_TIMEOUT = 60000;
describe.skipIf(SHOULD_SKIP)('Agent Working Directory Verification', () => {
let tempDir: string;
let agentManager: MultiProviderAgentManager;
let agentRepository: DrizzleAgentRepository;
beforeAll(async () => {
if (SHOULD_SKIP) return;
console.log('\n=== Running Agent Working Directory Tests ===');
console.log('These tests verify agents run in correct working directories.\n');
// Create temp directory for test workspace
tempDir = await mkdtemp(join(tmpdir(), 'cw-workdir-test-'));
// Set up test database and repositories
const db = await createTestDatabase();
const eventBus = new EventEmitterBus();
agentRepository = new DrizzleAgentRepository(db);
const projectRepository = new DrizzleProjectRepository(db);
const accountRepository = new DrizzleAccountRepository(db);
agentManager = new MultiProviderAgentManager(
agentRepository,
tempDir,
projectRepository,
accountRepository,
eventBus,
);
});
afterAll(async () => {
if (SHOULD_SKIP || !tempDir) return;
try {
await rm(tempDir, { recursive: true });
} catch (err) {
console.warn('Failed to cleanup temp directory:', err);
}
});
it('spawns agent in correct standalone working directory', async () => {
const prompt = `
Write your current working directory to a file called 'verify-pwd.txt'.
Use this exact bash command:
pwd > verify-pwd.txt
Then output the signal: {"done": true}
`.trim();
// Spawn standalone agent
const agent = await agentManager.spawn({
taskId: null,
prompt,
mode: 'execute',
provider: 'claude',
});
expect(agent.id).toBeTruthy();
expect(agent.status).toBe('running');
// Wait for completion (poll agent status)
let attempts = 0;
const maxAttempts = 60; // 60 seconds timeout
while (attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 1000));
attempts++;
const currentAgent = await agentRepository.findById(agent.id);
if (!currentAgent || currentAgent.status !== 'running') {
break;
}
}
// Verify final agent state
const completedAgent = await agentRepository.findById(agent.id);
expect(completedAgent).toBeTruthy();
expect(completedAgent!.status).not.toBe('running');
// Get the agent's expected working directory
const expectedWorkdir = join(tempDir, 'agent-workdirs', agent.name, 'workspace');
// Read diagnostic files
const diagnosticFile = join(expectedWorkdir, '.cw', 'spawn-diagnostic.json');
const expectedPwdFile = join(expectedWorkdir, '.cw', 'expected-pwd.txt');
const verifyPwdFile = join(expectedWorkdir, 'verify-pwd.txt');
// Verify diagnostic files exist
expect(existsSync(diagnosticFile), 'spawn diagnostic file should exist').toBe(true);
expect(existsSync(expectedPwdFile), 'expected pwd file should exist').toBe(true);
// Read diagnostic data
const diagnostic = JSON.parse(await readFile(diagnosticFile, 'utf-8'));
const expectedPwd = (await readFile(expectedPwdFile, 'utf-8')).trim();
console.log('Diagnostic data:', diagnostic);
console.log('Expected working directory:', expectedPwd);
// Verify diagnostic consistency
expect(diagnostic.intendedCwd).toBe(expectedWorkdir);
expect(diagnostic.cwdExistsAtSpawn).toBe(true);
expect(expectedPwd).toBe(expectedWorkdir);
// The critical test: verify the agent actually wrote the file in the expected location
if (existsSync(verifyPwdFile)) {
const actualPwd = (await readFile(verifyPwdFile, 'utf-8')).trim();
console.log('Agent reported working directory:', actualPwd);
// This is the key verification: the pwd reported by the agent should match expected
expect(actualPwd).toBe(expectedWorkdir);
} else {
// If the file doesn't exist, the agent either failed or ran somewhere else
console.warn('Agent did not create verify-pwd.txt file');
console.log('Expected at:', verifyPwdFile);
// Let's check if it was created elsewhere (debugging)
const alternativeLocations = [
join(tempDir, 'verify-pwd.txt'),
join(process.cwd(), 'verify-pwd.txt'),
];
for (const loc of alternativeLocations) {
if (existsSync(loc)) {
const content = await readFile(loc, 'utf-8');
console.log(`Found verify-pwd.txt at unexpected location ${loc}:`, content.trim());
}
}
throw new Error('Agent did not create pwd verification file in expected location');
}
}, TEST_TIMEOUT);
it('creates diagnostic files with correct metadata', async () => {
const prompt = `Output the signal: {"done": true}`;
const agent = await agentManager.spawn({
taskId: null,
prompt,
mode: 'execute',
provider: 'claude',
});
// Wait a bit for spawn to complete
await new Promise(resolve => setTimeout(resolve, 2000));
const expectedWorkdir = join(tempDir, 'agent-workdirs', agent.name, 'workspace');
const diagnosticFile = join(expectedWorkdir, '.cw', 'spawn-diagnostic.json');
const expectedPwdFile = join(expectedWorkdir, '.cw', 'expected-pwd.txt');
// Verify files exist immediately after spawn
expect(existsSync(diagnosticFile), 'diagnostic file should be created after spawn').toBe(true);
expect(existsSync(expectedPwdFile), 'expected pwd file should be created').toBe(true);
// Verify diagnostic content
const diagnostic = JSON.parse(await readFile(diagnosticFile, 'utf-8'));
const expectedPwd = (await readFile(expectedPwdFile, 'utf-8')).trim();
expect(diagnostic.agentId).toBe(agent.id);
expect(diagnostic.alias).toBe(agent.name);
expect(diagnostic.intendedCwd).toBe(expectedWorkdir);
expect(diagnostic.provider).toBe('claude');
expect(diagnostic.cwdExistsAtSpawn).toBe(true);
expect(diagnostic.customCwdProvided).toBe(false);
expect(typeof diagnostic.timestamp).toBe('string');
expect(Array.isArray(diagnostic.args)).toBe(true);
expect(expectedPwd).toBe(expectedWorkdir);
});
});