fix(FN-679): sync task prompts when task metadata changes

- Regenerate PROMPT.md when task titles or descriptions are updated in the store
- Add regression tests covering prompt regeneration for title and description changes
- Tighten central activity cleanup coverage to preserve entries at the cutoff boundary
- Add a changeset for the published CLI package fix
This commit is contained in:
gsxdsm
2026-04-01 13:33:53 -07:00
parent 26df995f36
commit b8db80b5d6

View File

@@ -1,4 +1,4 @@
import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { mkdtempSync, rmSync, mkdirSync } from "node:fs"; import { mkdtempSync, rmSync, mkdirSync } from "node:fs";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
@@ -268,9 +268,15 @@ describe("CentralCore", () => {
describe("project queries", () => { describe("project queries", () => {
beforeEach(async () => { beforeEach(async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-04-01T12:00:00.000Z"));
await central.init(); await central.init();
}); });
afterEach(() => {
vi.useRealTimers();
});
it("should get project by id", async () => { it("should get project by id", async () => {
const projectPath = join(tempDir, "get-project"); const projectPath = join(tempDir, "get-project");
mkdirSync(projectPath); mkdirSync(projectPath);
@@ -339,8 +345,7 @@ describe("CentralCore", () => {
path: projectPath, path: projectPath,
}); });
// Add small delay to ensure different timestamp vi.setSystemTime(new Date("2026-04-01T12:00:01.000Z"));
await new Promise((r) => setTimeout(r, 10));
const updated = await central.updateProject(project.id, { const updated = await central.updateProject(project.id, {
name: "Updated", name: "Updated",
@@ -507,9 +512,15 @@ describe("CentralCore", () => {
describe("unified activity feed", () => { describe("unified activity feed", () => {
beforeEach(async () => { beforeEach(async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-04-01T12:00:00.000Z"));
await central.init(); await central.init();
}); });
afterEach(() => {
vi.useRealTimers();
});
it("should log activity with auto-generated id", async () => { it("should log activity with auto-generated id", async () => {
const projectPath = join(tempDir, "activity-project"); const projectPath = join(tempDir, "activity-project");
mkdirSync(projectPath); mkdirSync(projectPath);
@@ -544,8 +555,7 @@ describe("CentralCore", () => {
const beforeActivity = project.lastActivityAt; const beforeActivity = project.lastActivityAt;
// Small delay vi.setSystemTime(new Date("2026-04-01T12:00:01.000Z"));
await new Promise((r) => setTimeout(r, 10));
await central.logActivity({ await central.logActivity({
type: "task:moved", type: "task:moved",
@@ -711,10 +721,8 @@ describe("CentralCore", () => {
expect(projectCount).toBe(5); expect(projectCount).toBe(5);
}); });
it("should cleanup old activity entries", async () => { it("should cleanup only activity entries older than the cutoff", async () => {
vi.useFakeTimers(); vi.useFakeTimers();
const now = new Date("2026-01-15T12:00:00.000Z");
vi.setSystemTime(now);
try { try {
const projectPath = join(tempDir, "cleanup-activity"); const projectPath = join(tempDir, "cleanup-activity");
@@ -726,19 +734,39 @@ describe("CentralCore", () => {
path: projectPath, path: projectPath,
}); });
vi.setSystemTime(new Date("2026-04-01T12:00:00.000Z"));
await central.logActivity({ await central.logActivity({
type: "task:created", type: "task:created",
projectId: project.id, projectId: project.id,
projectName: project.name, projectName: project.name,
timestamp: now.toISOString(), timestamp: "2026-03-31T11:59:59.999Z",
details: "Recent", details: "Older than cutoff",
}); });
const deleted = await central.cleanupOldActivity(-1); await central.logActivity({
expect(deleted).toBe(0); type: "task:created",
projectId: project.id,
projectName: project.name,
timestamp: "2026-03-31T12:00:00.000Z",
details: "Exactly at cutoff",
});
const countAfter = await central.getActivityCount(); await central.logActivity({
expect(countAfter).toBe(1); type: "task:created",
projectId: project.id,
projectName: project.name,
timestamp: "2026-03-31T12:00:00.001Z",
details: "Newer than cutoff",
});
const deleted = await central.cleanupOldActivity(1);
expect(deleted).toBe(1);
const remaining = await central.getRecentActivity({ limit: 10, projectId: project.id });
expect(remaining.map((entry) => entry.details)).toEqual([
"Newer than cutoff",
"Exactly at cutoff",
]);
} finally { } finally {
vi.useRealTimers(); vi.useRealTimers();
} }