feat(P06): docs & hardening — AGENTS.md/README fixes, agent tests, Gitea tests, multi-project tests, version 0.7.0

---ci---
phase: 6
milestone: v0.7.0
plan: 06
task: P06-all
status: execute
---/ci---
This commit is contained in:
Jon Chery
2026-05-29 18:20:46 +00:00
parent e8c6c5c917
commit a416413c7d
15 changed files with 1031 additions and 21 deletions
+94
View File
@@ -0,0 +1,94 @@
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { TesterAgent } from "../agents/tester.js";
import { AgentContext } from "../agents/base.js";
import { IntelligenceBackend, BackendRequest, BackendResult } from "../backends/types.js";
import { emptyTokenUsage } from "../backends/types.js";
class MockBackend implements IntelligenceBackend {
readonly name = "mock";
readonly type = "llm" as const;
async isAvailable(): Promise<boolean> { return true; }
async execute(request: BackendRequest): Promise<BackendResult> {
return {
success: true,
output: `Mock backend executed: ${request.task.slice(0, 50)}`,
artifacts: [],
decisions: [],
escalations: [],
usage: emptyTokenUsage(),
};
}
}
function createTempDir(): string {
return fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-tester-test-"));
}
function cleanup(dir: string): void {
fs.rmSync(dir, { recursive: true, force: true });
}
function makeContext(dir: string, backend?: IntelligenceBackend): AgentContext {
return {
project_path: dir,
phase: 1,
stage: "test",
specification: "Build a REST API for task management",
config_path: path.join(dir, ".ciagent", "config.json"),
backend,
};
}
describe("TesterAgent", () => {
let dir: string;
beforeEach(() => {
dir = createTempDir();
});
afterEach(() => {
cleanup(dir);
});
it("detects test files when src directory exists", async () => {
const srcDir = path.join(dir, "src");
fs.mkdirSync(srcDir, { recursive: true });
fs.writeFileSync(path.join(srcDir, "app.integration.test.ts"), "test('integration', () => {});\n");
const tester = new TesterAgent();
const result = await tester.execute(makeContext(dir));
expect(result.success).toBeDefined();
});
it("does not write test files", async () => {
const srcDir = path.join(dir, "src");
fs.mkdirSync(srcDir, { recursive: true });
fs.writeFileSync(path.join(srcDir, "app.test.ts"), "test('unit', () => {});\n");
const testFilesBefore = fs.readdirSync(srcDir).filter(f => f.endsWith(".test.ts"));
const tester = new TesterAgent();
await tester.execute(makeContext(dir));
const testFilesAfter = fs.readdirSync(srcDir).filter(f => f.endsWith(".test.ts"));
expect(testFilesAfter.length).toBe(testFilesBefore.length);
});
it("delegates to backend when available", async () => {
const mockBackend = new MockBackend();
const tester = new TesterAgent();
const result = await tester.execute(makeContext(dir, mockBackend));
expect(result.success).toBe(true);
expect(result.output).toContain("Mock backend executed");
});
it("has correct agent name", () => {
const tester = new TesterAgent();
expect(tester.name).toBe("tester");
});
it("has correct workflow", () => {
const tester = new TesterAgent();
expect(tester.workflow).toBe("test");
});
});