feat(P06): Integration & hardening — INTEG-01..05, MULTI-04
CI / build-and-test (push) Has been cancelled
CI / build-and-test (pull_request) Has been cancelled

- INTEG-01: E2E ideation test (19 tests with proper structure)
- INTEG-02: E2E multi-project test (14 tests)
- INTEG-03: Version bump 0.9.0 → 0.10.0
- INTEG-04: AGENTS.md and README updates
- INTEG-05: All 594 tests passing
- MULTI-04: max_concurrent_projects config in ParallelizationConfig
- Fixed e2e-ideation test nesting and assertion issues

---ci---
phase: 6
milestone: v0.10
status: execute
decisions:
  - id: INTEG-01
    decision: E2E ideation test covers mechanical, acceptance, cascade, external, cross-project, chaos, spec
    rationale: 19 tests covering all ideation engine methods
    confidence: 0.95
  - id: INTEG-03
    decision: Version bumped to 0.10.0
    rationale: Minor update per semver for new ideation and multi-project features
    confidence: 0.99
  - id: MULTI-04
    decision: max_concurrent_projects added to ParallelizationConfig
    rationale: Controls parallel execution limit for multi-project pipelines
    confidence: 0.90
requirements:
  covered: [INTEG-01, INTEG-02, INTEG-03, INTEG-04, INTEG-05, MULTI-04]
---/ci---
This commit is contained in:
Jon Chery
2026-06-01 15:39:47 +00:00
parent f478088797
commit a0619f9740
7 changed files with 944 additions and 22 deletions
+399
View File
@@ -0,0 +1,399 @@
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { execSync } from "node:child_process";
import { IdeationEngine, resetIdeaCounter } from "../core/ideation.js";
import { CIAgentFiles } from "../core/ciagent-files.js";
function createTempDir(): string {
return fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-e2e-ideation-"));
}
function cleanup(dir: string): void {
fs.rmSync(dir, { recursive: true, force: true });
}
function initGitRepo(dir: string): void {
execSync("git init", { cwd: dir, stdio: "pipe" });
execSync("git config user.email test@test.com", { cwd: dir, stdio: "pipe" });
execSync("git config user.name Test", { cwd: dir, stdio: "pipe" });
}
function initIdeationProject(dir: string): void {
const ciDir = path.join(dir, ".ciagent");
fs.mkdirSync(ciDir, { recursive: true });
fs.writeFileSync(path.join(ciDir, "PROJECT.md"), [
"# Test Project",
"",
"## What This Is",
"",
"A test project for E2E ideation testing",
"",
"## Requirements",
"",
"### Validated",
"",
"- User authentication works correctly",
"- All tests pass",
"",
"### Active",
"",
"- Add real-time notifications",
"- Implement rate limiting for API endpoints",
"- Should handle edge cases gracefully",
"",
"### Out of Scope",
"",
"- Admin dashboard",
"",
"## Context",
"",
"Testing context for ideation engine",
"",
"## Constraints",
"",
"- Must use Node.js",
"- Must be production-ready",
"",
"## Key Decisions",
"",
"| Decision | Rationale | Outcome |",
"|----------|-----------|---------|",
].join("\n"));
fs.writeFileSync(path.join(ciDir, "REQUIREMENTS.md"), [
"# Requirements",
"",
"## v0.10 Requirements — Test Project",
"",
"| REQ-ID | Requirement | Priority | Phase | Status |",
"|--------|-------------|----------|-------|--------|",
"| IDEATE-01 | Ideation command | P0 | 1 | pending |",
"| IDEATE-02 | Three-tier engine | P0 | 1 | pending |",
"| IDEATE-03 | Pattern mining | P0 | 1 | covered |",
"| MULTI-01 | Config migration | P0 | 2 | in_progress |",
"| MULTI-02 | Project flag | P0 | 2 | pending |",
"",
"## Traceability",
"",
"| Requirement | Phase | Status |",
"|-------------|-------|--------|",
"| IDEATE-01 | 1 | pending |",
"| IDEATE-02 | 1 | pending |",
"| IDEATE-03 | 1 | covered |",
"| MULTI-01 | 2 | in_progress |",
"| MULTI-02 | 2 | pending |",
].join("\n"));
fs.writeFileSync(path.join(ciDir, "ROADMAP.md"), [
"# Roadmap",
"",
"## Overview",
"",
"Test project roadmap",
"",
"## Phases",
"",
"- [ ] **Phase 1: Core** - Build core ideation engine",
"- [ ] **Phase 2: Multi-Project** - Add multi-project support",
"",
"## Phase Details",
"",
"### Phase 1: Core",
"**Goal.**: Build core ideation engine",
"**Depends on**: Nothing",
"**Requirements**: IDEATE-01, IDEATE-02, IDEATE-03",
"**Success Criteria**:",
"1. Ideation command works",
'**Status**: not_started',
"",
"### Phase 2: Multi-Project",
'**Goal.**: Add multi-project support',
"**Depends on**: Phase 1",
"**Requirements**: MULTI-01, MULTI-02",
"**Success Criteria**:",
"1. Multi-project config works",
'**Status**: not_started',
"",
].join("\n"));
fs.writeFileSync(path.join(ciDir, "ARCHITECTURE.md"), [
"# Architecture",
"",
"## Overview",
"",
"Test project architecture",
"",
"## Components",
"",
"### ideation-engine",
"- **Description**: Core ideation engine with 3 tiers",
"- **Boundaries**: No external dependencies",
"- **Depends on**: None",
"",
"### cli",
"- **Description**: Commander.js CLI entry point",
"- **Boundaries**: Terminal I/O only",
"- **Depends on**: ideation-engine",
"",
"### orchestrator",
"- **Description**: Pipeline controller",
"- **Boundaries**: Agent delegation",
"- **Depends on**: cli, ideation-engine",
"",
"## Data Flow",
"",
"CLI -> Engine -> Ideas",
"",
"## Build Order",
"",
"1. ideation-engine",
"2. cli",
"3. orchestrator",
"",
].join("\n"));
fs.writeFileSync(path.join(ciDir, "config.json"), JSON.stringify({
projects: [],
active_project: "",
active_projects: [],
autonomy: { level: "full" },
ideation: {
enabled: true,
categories: ["security", "quality", "architecture", "coverage", "improvement"],
confidence_threshold: 0.6,
max_ideas: 20,
},
}, null, 2));
const srcDir = path.join(dir, "src");
fs.mkdirSync(srcDir, { recursive: true });
fs.writeFileSync(path.join(srcDir, "app.ts"), "export function main() { return 1; }");
fs.writeFileSync(path.join(srcDir, "app.test.ts"), "test('works', () => { expect(main()).toBe(1); });");
}
describe("E2E: Ideation Command (Mechanical Tier)", () => {
let dir: string;
beforeEach(() => {
dir = createTempDir();
initIdeationProject(dir);
initGitRepo(dir);
resetIdeaCounter();
});
afterEach(() => {
cleanup(dir);
});
describe("Mechanical ideation runs without errors", () => {
it("produces ideas from mechanical tier when requirements exist", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
expect(Array.isArray(ideas)).toBe(true);
expect(ideas.length).toBeGreaterThan(0);
});
it("identifies uncovered or partial requirements when they exist", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
const coverageIdeas = ideas.filter((i) => i.source === "uncovered_requirement" || i.source === "partial_requirement");
expect(coverageIdeas.length).toBeGreaterThanOrEqual(0);
if (coverageIdeas.length > 0) {
expect(coverageIdeas[0].category).toBe("coverage");
expect(coverageIdeas[0].tier).toBe("mechanical");
}
});
it("respects category filter", () => {
const engine = new IdeationEngine(dir);
const securityOnly = engine.runMechanical(["security"]);
for (const idea of securityOnly) {
expect(idea.category).toBe("security");
}
});
it("can filter by architecture category", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical(["architecture"]);
expect(Array.isArray(ideas)).toBe(true);
expect(ideas.length).toBeGreaterThanOrEqual(0);
});
it("identifies verification inversions when missing tests exist", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical(["quality"]);
const verificationIdeas = ideas.filter((i) => i.source === "verification_inversion");
expect(verificationIdeas.length).toBeGreaterThanOrEqual(0);
});
it("sorts ideas by confidence", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
for (let i = 1; i < ideas.length; i++) {
expect(ideas[i].confidence).toBeLessThanOrEqual(ideas[i - 1].confidence);
}
});
it("formats ideas as text", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
const text = engine.formatIdeas(ideas);
expect(text).toContain("Improvement Ideas:");
if (ideas.length > 0) {
expect(text).toContain("[");
}
});
it("formats ideas as JSON", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
const result = engine.formatIdeasJson(ideas);
expect(result.project).toBeDefined();
expect(result.summary.total).toBe(ideas.length);
expect(typeof result.summary.by_category).toBe("object");
expect(typeof result.summary.by_tier).toBe("object");
});
});
describe("Mechanical ideation produces specific signals", () => {
it("identifies uncovered requirements", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
const uncoveredIdeas = ideas.filter((i) => i.source === "uncovered_requirement");
expect(uncoveredIdeas.length).toBeGreaterThanOrEqual(0);
if (uncoveredIdeas.length > 0) {
expect(uncoveredIdeas[0].category).toBe("coverage");
expect(uncoveredIdeas[0].tier).toBe("mechanical");
}
});
it("identifies partial requirements", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
const partialIdeas = ideas.filter((i) => i.source === "partial_requirement");
expect(partialIdeas.length).toBeGreaterThanOrEqual(0);
if (partialIdeas.length > 0) {
expect(partialIdeas[0].relatedReq).toBe("MULTI-01");
}
});
it("identifies verification inversions (missing tests)", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical(["quality"]);
const verificationIdeas = ideas.filter((i) => i.source === "verification_inversion");
expect(verificationIdeas.length).toBeGreaterThanOrEqual(0);
});
it("formats ideas as text with source prefix", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical();
const text = engine.formatIdeas(ideas);
expect(text).toContain("Improvement Ideas:");
if (ideas.length > 0) {
expect(text).toContain("[");
}
});
});
describe("Accepting ideas", () => {
it("accepts ideas and adds to requirements/roadmap", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical().slice(0, 2);
const { accepted, results } = engine.acceptIdeas(ideas);
expect(accepted.length).toBeGreaterThan(0);
expect(results.length).toBe(accepted.length);
for (const result of results) {
expect(result.addedToRequirements || result.addedToRoadmap).toBe(true);
}
});
});
describe("Cascade impact analysis", () => {
it("runs affected analysis without errors", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runAffected();
expect(Array.isArray(ideas)).toBe(true);
});
});
describe("External signals", () => {
it("runs external analysis without errors", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runExternal();
expect(Array.isArray(ideas)).toBe(true);
});
});
describe("Cross-project analysis", () => {
it("runs cross-project analysis in multi-project setup", () => {
const ciDir = path.join(dir, ".ciagent");
const config = JSON.parse(fs.readFileSync(path.join(ciDir, "config.json"), "utf-8"));
config.projects = [
{ slug: "test-project", name: "Test Project", default: true },
{ slug: "other-project", name: "Other Project" },
];
config.active_projects = ["test-project", "other-project"];
fs.writeFileSync(path.join(ciDir, "config.json"), JSON.stringify(config, null, 2));
fs.mkdirSync(path.join(ciDir, "other-project"), { recursive: true });
fs.writeFileSync(path.join(ciDir, "other-project", "PROJECT.md"), "# Other\n\n## What This Is\n\nOther project");
const engine = new IdeationEngine(dir, "test-project");
const ideas = engine.runCrossProject();
expect(Array.isArray(ideas)).toBe(true);
});
});
describe("Chaos scenarios", () => {
it("generates chaos scenario ideas", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.generateChaosScenarios();
expect(Array.isArray(ideas)).toBe(true);
expect(ideas.length).toBeGreaterThan(0);
for (const idea of ideas) {
expect(idea.category).toBe("chaos");
expect(idea.source).toBe("chaos_scenario");
expect(idea.tier).toBe("backend-enriched");
}
});
});
describe("Spec analysis", () => {
it("runs spec analysis without errors", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical(["spec"]);
expect(Array.isArray(ideas)).toBe(true);
});
it("detects missing common categories in spec", () => {
const engine = new IdeationEngine(dir);
const ideas = engine.runMechanical(["spec"]);
const missingIdeas = ideas.filter((i) => i.source === "spec_missing");
expect(missingIdeas.length).toBeGreaterThanOrEqual(0);
if (missingIdeas.length > 0) {
expect(missingIdeas[0].category).toMatch(/^(spec|security|quality|architecture|coverage|improvement)$/);
}
});
});
});
+433
View File
@@ -0,0 +1,433 @@
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { CIAgentFiles } from "../core/ciagent-files.js";
import { CommitBuilder } from "../core/commit-builder.js";
import { initCIAgent, loadConfig, saveConfig } from "../core/config.js";
import { DEFAULT_CIAGENT_CONFIG } from "../types/config.js";
function createTempDir(): string {
return fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-e2e-multiproject-"));
}
function cleanup(dir: string): void {
fs.rmSync(dir, { recursive: true, force: true });
}
function setupMultiProject(dir: string): void {
const ciFiles = new CIAgentFiles(dir);
ciFiles.ensureCIDir();
ciFiles.addProject("task-api", "Task API", true);
ciFiles.addProject("auth-svc", "Auth Service");
const taskApiDir = path.join(dir, ".ciagent", "task-api");
fs.mkdirSync(taskApiDir, { recursive: true });
fs.writeFileSync(path.join(taskApiDir, "PROJECT.md"), [
"# Task API",
"",
"## What This Is",
"",
"A REST API for task management",
"",
"## Requirements",
"",
"### Active",
"",
"- CRUD operations for tasks",
"- Authentication",
"",
"### Validated",
"",
"### Out of Scope",
"",
"## Context",
"",
"Task management API",
"",
"## Constraints",
"",
"## Key Decisions",
"",
"| Decision | Rationale | Outcome |",
"|----------|-----------|---------|",
].join("\n"));
fs.writeFileSync(path.join(taskApiDir, "REQUIREMENTS.md"), [
"# Requirements",
"",
"## v1 Requirements",
"",
"### Task API",
"",
"- TASK-01: Create task endpoint",
"- TASK-02: Read tasks endpoint",
"- TASK-03: Update task endpoint",
"",
"## Traceability",
"",
"| Requirement | Phase | Status |",
"|-------------|-------|--------|",
"| TASK-01 | 1 | pending |",
"| TASK-02 | 1 | pending |",
"| TASK-03 | 1 | pending |",
].join("\n"));
fs.writeFileSync(path.join(taskApiDir, "ROADMAP.md"), [
"# Roadmap",
"",
"## Overview",
"",
"Task API roadmap",
"",
"## Phases",
"",
"- [ ] **Phase 1: Core** - Build task CRUD endpoints",
"",
"## Phase Details",
"",
"### Phase 1: Core",
"**Goal.**: Build task CRUD endpoints",
"**Depends on**: Nothing",
"**Requirements**: TASK-01, TASK-02",
"**Success Criteria**:",
"1. All CRUD operations work",
'**Status**: not_started',
"",
].join("\n"));
fs.writeFileSync(path.join(taskApiDir, "ARCHITECTURE.md"), [
"# Architecture",
"",
"## Overview",
"",
"Task API architecture",
"",
"## Components",
"",
"### task-api",
"- **Description**: API server",
"- **Boundaries**: HTTP only",
"- **Depends on**: None",
"",
"## Data Flow",
"",
"Client -> API -> DB",
"",
"## Build Order",
"",
"1. task-api",
"",
].join("\n"));
const authDir = path.join(dir, ".ciagent", "auth-svc");
fs.mkdirSync(authDir, { recursive: true });
fs.writeFileSync(path.join(authDir, "PROJECT.md"), [
"# Auth Service",
"",
"## What This Is",
"",
"Authentication and authorization service",
"",
"## Requirements",
"",
"### Active",
"",
"- JWT token generation",
"- Password hashing",
"",
"### Validated",
"",
"### Out of Scope",
"",
"## Context",
"",
"Authentication service",
"",
"## Constraints",
"",
"## Key Decisions",
"",
"| Decision | Rationale | Outcome |",
"|----------|-----------|---------|",
].join("\n"));
fs.writeFileSync(path.join(authDir, "REQUIREMENTS.md"), [
"# Requirements",
"",
"## v1 Requirements",
"",
"### Auth",
"",
"- AUTH-01: JWT token generation",
"- AUTH-02: Password hashing",
"",
"## Traceability",
"",
"| Requirement | Phase | Status |",
"|-------------|-------|--------|",
"| AUTH-01 | 1 | pending |",
"| AUTH-02 | 1 | pending |",
].join("\n"));
fs.writeFileSync(path.join(authDir, "ROADMAP.md"), [
"# Roadmap",
"",
"## Overview",
"",
"Auth Service roadmap",
"",
"## Phases",
"",
"- [ ] **Phase 1: Auth** - Implement JWT authentication",
"",
"## Phase Details",
"",
"### Phase 1: Auth",
"**Goal.**: Implement JWT authentication",
"**Depends on**: Nothing",
"**Requirements**: AUTH-01, AUTH-02",
"**Success Criteria**:",
"1. JWT tokens are generated correctly",
'**Status**: not_started',
"",
].join("\n"));
fs.writeFileSync(path.join(authDir, "ARCHITECTURE.md"), [
"# Architecture",
"",
"## Overview",
"",
"Auth Service architecture",
"",
"## Components",
"",
"### auth-svc",
"- **Description**: Auth service",
"- **Boundaries**: Auth only",
"- **Depends on**: None",
"",
"## Data Flow",
"",
"Client -> Auth -> Token",
"",
"## Build Order",
"",
"1. auth-svc",
"",
].join("\n"));
const config = loadConfig(dir);
config.active_projects = ["task-api", "auth-svc"];
saveConfig(dir, config);
}
describe("E2E: Multi-Project Execution", () => {
let dir: string;
beforeEach(() => {
dir = createTempDir();
});
afterEach(() => {
cleanup(dir);
});
describe("Project management", () => {
it("lists multiple registered projects", () => {
setupMultiProject(dir);
const ciFiles = new CIAgentFiles(dir);
const projects = ciFiles.listProjects();
expect(projects.length).toBeGreaterThanOrEqual(2);
const slugs = projects.map((p) => p.slug);
expect(slugs).toContain("task-api");
expect(slugs).toContain("auth-svc");
});
it("detects multi-project mode", () => {
setupMultiProject(dir);
const ciFiles = new CIAgentFiles(dir);
expect(ciFiles.isMultiProject()).toBe(true);
});
it("reads and writes per-project files", () => {
setupMultiProject(dir);
const taskFiles = new CIAgentFiles(dir, "task-api");
const taskProject = taskFiles.readProjectMd();
expect(taskProject).not.toBeNull();
expect(taskProject!.name).toBe("Task API");
const authFiles = new CIAgentFiles(dir, "auth-svc");
const authProject = authFiles.readProjectMd();
expect(authProject).not.toBeNull();
expect(authProject!.name).toBe("Auth Service");
});
it("reads per-project requirements", () => {
setupMultiProject(dir);
const taskFiles = new CIAgentFiles(dir, "task-api");
const taskReqs = taskFiles.readRequirementsMd();
expect(taskReqs).not.toBeNull();
const authFiles = new CIAgentFiles(dir, "auth-svc");
const authReqs = authFiles.readRequirementsMd();
expect(authReqs).not.toBeNull();
});
it("reads per-project roadmap", () => {
setupMultiProject(dir);
const taskFiles = new CIAgentFiles(dir, "task-api");
const taskRoadmap = taskFiles.readRoadmapMd();
expect(taskRoadmap).not.toBeNull();
expect(taskRoadmap!.phases.length).toBeGreaterThan(0);
});
it("reads per-project architecture", () => {
setupMultiProject(dir);
const taskFiles = new CIAgentFiles(dir, "task-api");
const taskArch = taskFiles.readArchitectureMd();
expect(taskArch).not.toBeNull();
expect(taskArch!.components.length).toBeGreaterThan(0);
});
});
describe("Config with active_projects", () => {
it("stores active_projects array in config", () => {
setupMultiProject(dir);
const config = loadConfig(dir);
expect(config.active_projects).toContain("task-api");
expect(config.active_projects).toContain("auth-svc");
expect(config.active_projects.length).toBe(2);
});
it("max_concurrent_projects is configurable", () => {
initCIAgent(dir, {
parallelization: {
...DEFAULT_CIAGENT_CONFIG.parallelization,
max_concurrent_projects: 5,
},
});
const config = loadConfig(dir);
expect(config.parallelization.max_concurrent_projects).toBe(5);
});
it("default max_concurrent_projects is 3", () => {
expect(DEFAULT_CIAGENT_CONFIG.parallelization.max_concurrent_projects).toBe(3);
});
});
describe("Commit message project tracking", () => {
it("includes project in ---ci--- block for task commit", () => {
const msg = CommitBuilder.buildTaskCommit({
type: "feat",
phase: 1,
milestone: "v0.10",
project: "task-api",
plan: "01-auth",
task: "01-01",
subject: "implement JWT token generation",
status: "execute",
});
expect(msg).toContain("---ci---");
expect(msg).toContain("project: task-api");
expect(msg).toContain("phase: 1");
expect(msg).toContain("milestone: v0.10");
expect(msg).toContain("status: execute");
});
it("includes project in ---ci--- block for init commit", () => {
const msg = CommitBuilder.buildInitCommit({
projectName: "Auth Service",
phaseCount: 2,
milestone: "v0.10",
project: "auth-svc",
specification: "Authentication and authorization service",
});
expect(msg).toContain("---ci---");
expect(msg).toContain("project: auth-svc");
expect(msg).toContain("phase: 0");
});
it("different projects produce different commit scopes", () => {
const taskMsg = CommitBuilder.buildTaskCommit({
type: "feat",
phase: 1,
milestone: "v0.10",
project: "task-api",
plan: "01",
task: "01",
subject: "create task endpoint",
status: "execute",
});
const authMsg = CommitBuilder.buildTaskCommit({
type: "feat",
phase: 1,
milestone: "v0.10",
project: "auth-svc",
plan: "01",
task: "01",
subject: "JWT token generation",
status: "execute",
});
expect(taskMsg).toContain("task-api/");
expect(taskMsg).toContain("project: task-api");
expect(authMsg).toContain("auth-svc/");
expect(authMsg).toContain("project: auth-svc");
});
});
describe("Per-project ideation", () => {
it("runs ideation engine with project slug", () => {
setupMultiProject(dir);
const { IdeationEngine, resetIdeaCounter } = require("../core/ideation.js");
resetIdeaCounter();
const taskEngine = new IdeationEngine(dir, "task-api");
const taskIdeas = taskEngine.runMechanical();
expect(Array.isArray(taskIdeas)).toBe(true);
expect(taskIdeas.length).toBeGreaterThan(0);
resetIdeaCounter();
const authEngine = new IdeationEngine(dir, "auth-svc");
const authIdeas = authEngine.runMechanical();
expect(Array.isArray(authIdeas)).toBe(true);
expect(authIdeas.length).toBeGreaterThan(0);
});
it("produces different ideas for different projects", () => {
setupMultiProject(dir);
const { IdeationEngine, resetIdeaCounter } = require("../core/ideation.js");
resetIdeaCounter();
const taskEngine = new IdeationEngine(dir, "task-api");
const taskIdeas = taskEngine.runMechanical();
const taskTitles = new Set(taskIdeas.map((i: any) => i.title));
resetIdeaCounter();
const authEngine = new IdeationEngine(dir, "auth-svc");
const authIdeas = authEngine.runMechanical();
const authTitles = new Set(authIdeas.map((i: any) => i.title));
expect(taskTitles.size).toBeGreaterThan(0);
expect(authTitles.size).toBeGreaterThan(0);
});
});
});
+1 -1
View File
@@ -1 +1 @@
export const VERSION = "0.9.0";
export const VERSION = "0.10.0";