70f9f720e6
---ci---
project: ci
phase: 6
milestone: v0.8
status: complete
decisions:
- id: D-037
decision: v0.8.0 release with 6 phases complete
rationale: All verification layers now deliver what they claim
confidence: 0.95
requirements:
covered: [INT-01, INT-02, INT-03, INT-04, INT-05, INT-06, INT-07, INT-08]
---/ci---
INT-06: Version bumped to 0.8.0 in package.json and src/version.ts.
INT-07: New test suites for SecurityAuditorAgent (5 tests), DocWriterAgent
(5 tests), DebuggerAgent (5 tests), ChallengerAgent (4 tests).
INT-08: Zod validation test suite with 9 cases: valid input, missing
fields, path traversal, absolute paths, contradictory success+error,
invalid operation, negative tokens, fail+error, emptyBackendResult.
INT-04: ciagent review command now has mechanical fallback — runs
CodeReviewerAgent regex review without backend.
INT-05: ciagent debug command now has mechanical fallback — runs
DebuggerAgent stack trace parsing + git bisect without backend.
INT-01: E2E verification test — fixture with defects fails L3/L4; clean
project passes all 4 layers.
INT-02: AGENTS.md updated — removed 'not yet implemented' caveats for
L2/L3/L4; updated test count to 44 suites, 454 tests.
INT-03: PROJECT.md updated — removed Out of Scope for STRIDE,
multi-persona review, and behavioral test generation.
75 lines
3.2 KiB
TypeScript
75 lines
3.2 KiB
TypeScript
import * as fs from "node:fs";
|
|
import * as path from "node:path";
|
|
import * as os from "node:os";
|
|
import { VerificationPipeline } from "../verification/index.js";
|
|
|
|
describe("E2E Verification Pipeline", () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-e2e-test-"));
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it("passes all 4 layers on a clean project", async () => {
|
|
const srcDir = path.join(tempDir, "src");
|
|
fs.mkdirSync(srcDir, { recursive: true });
|
|
fs.writeFileSync(path.join(srcDir, "app.ts"), "export function main() { return 1; }");
|
|
fs.writeFileSync(path.join(tempDir, "package.json"), JSON.stringify({
|
|
name: "test-project",
|
|
version: "1.0.0",
|
|
devDependencies: { jest: "^29.0.0" },
|
|
scripts: { test: "echo 'no tests yet'" },
|
|
}));
|
|
fs.writeFileSync(path.join(tempDir, "tsconfig.json"), JSON.stringify({
|
|
compilerOptions: { target: "ES2022", module: "Node16", strict: true, outDir: "dist" },
|
|
include: ["src"],
|
|
}));
|
|
fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\ndist\n");
|
|
|
|
const ciDir = path.join(tempDir, ".ciagent");
|
|
fs.mkdirSync(ciDir, { recursive: true });
|
|
fs.writeFileSync(path.join(ciDir, "ROADMAP.md"), "# Roadmap\n\n| 1 | Init | complete | setup |\n");
|
|
fs.writeFileSync(path.join(ciDir, "REQUIREMENTS.md"), "# Requirements\n\n| REQ-01 | Must work | P0 | 1 | covered |\n");
|
|
fs.writeFileSync(path.join(ciDir, "config.json"), JSON.stringify({ autonomy: { level: "full" } }));
|
|
fs.writeFileSync(path.join(ciDir, "PROJECT.md"), "# Test\n\n## Requirements\n\n- [ ] Must work\n");
|
|
|
|
const pipeline = new VerificationPipeline(tempDir);
|
|
const result = await pipeline.run(1);
|
|
|
|
expect(result.all_passed).toBe(true);
|
|
expect(result.structural.passed).toBe(true);
|
|
expect(result.behavioral.passed).toBe(true);
|
|
expect(result.security.passed).toBe(true);
|
|
expect(result.quality.passed).toBe(true);
|
|
});
|
|
|
|
it("fails security layer on hardcoded password", async () => {
|
|
const srcDir = path.join(tempDir, "src");
|
|
fs.mkdirSync(srcDir, { recursive: true });
|
|
fs.writeFileSync(path.join(srcDir, "app.ts"), 'export const password = "secret123";');
|
|
fs.writeFileSync(path.join(tempDir, "package.json"), JSON.stringify({ name: "test", version: "1.0.0" }));
|
|
fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n");
|
|
|
|
const pipeline = new VerificationPipeline(tempDir);
|
|
const result = await pipeline.run(1);
|
|
|
|
expect(result.security.passed).toBe(false);
|
|
});
|
|
|
|
it("fails quality layer on P0 finding (empty catch)", async () => {
|
|
const srcDir = path.join(tempDir, "src");
|
|
fs.mkdirSync(srcDir, { recursive: true });
|
|
fs.writeFileSync(path.join(srcDir, "app.ts"), 'try { work(); } catch(e) {}\nexport function main() { return 1; }');
|
|
fs.writeFileSync(path.join(tempDir, "package.json"), JSON.stringify({ name: "test", version: "1.0.0" }));
|
|
fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n");
|
|
|
|
const pipeline = new VerificationPipeline(tempDir);
|
|
const result = await pipeline.run(1);
|
|
|
|
expect(result.quality.passed).toBe(false);
|
|
});
|
|
}); |