feat(P03): multi-project support, NFR milestone versioning, phase context reset, install scripts (v0.3.0)

This commit is contained in:
CI
2026-05-29 15:13:45 +00:00
parent e4bb3a9970
commit ddf04792c7
57 changed files with 1748 additions and 59 deletions
+51
View File
@@ -45,6 +45,37 @@ describe("CI Config", () => {
expect(config.autonomy.max_revision_iterations).toBe(3);
expect(config.autonomy.escalation_hooks).toEqual(["deploy", "delete_data", "merge_to_main"]);
});
it("initializes with project slug", () => {
const config = initCI(tempDir, undefined, "task-api", "Task API");
expect(config.projects).toHaveLength(1);
expect(config.projects[0].slug).toBe("task-api");
expect(config.projects[0].name).toBe("Task API");
expect(config.projects[0].default).toBe(true);
expect(config.active_project).toBe("task-api");
});
it("does not re-add existing project slug", () => {
initCI(tempDir, undefined, "task-api", "Task API");
const config = initCI(tempDir, undefined, "task-api", "Task API V2");
expect(config.projects).toHaveLength(1);
});
it("defaults projects and active_project when no slug provided", () => {
const config = initCI(tempDir);
expect(config.projects).toEqual([]);
expect(config.active_project).toBe("");
});
it("preserves existing projects when adding new one", () => {
const config1 = initCI(tempDir, undefined, "task-api", "Task API");
const config2 = initCI(tempDir, {
...config1,
projects: [...config1.projects, { slug: "auth-svc", name: "Auth Service" }],
}, "auth-svc", "Auth Service");
expect(config2.projects).toHaveLength(2);
expect(config2.active_project).toBe("auth-svc");
});
});
describe("loadConfig", () => {
@@ -68,6 +99,13 @@ describe("CI Config", () => {
expect(config.git.auto_commit).toBe(true);
expect(config.git.branching_strategy).toBe("phase");
});
it("loads projects array from config", () => {
initCI(tempDir, undefined, "task-api", "Task API");
const config = loadConfig(tempDir);
expect(config.projects).toHaveLength(1);
expect(config.active_project).toBe("task-api");
});
});
describe("saveConfig", () => {
@@ -81,6 +119,19 @@ describe("CI Config", () => {
const loaded = loadConfig(tempDir);
expect(loaded.autonomy.level).toBe("guided");
});
it("saves and reloads config with projects", () => {
ensureCIDir(tempDir);
const config = {
...DEFAULT_CI_CONFIG,
projects: [{ slug: "my-app", name: "My App", default: true }],
active_project: "my-app",
};
saveConfig(tempDir, config);
const loaded = loadConfig(tempDir);
expect(loaded.projects).toHaveLength(1);
expect(loaded.active_project).toBe("my-app");
});
});
describe("isCIInitialized", () => {