FN-8050: cover cached dependency reconciliation seeding

Ensure raw dependency-reconciliation fixtures invalidate warmed task caches.

- Warm slim task-list caches before corrupt-row seeding in cycle reconciliation tests.
- Document the PostgreSQL-only fixture seam and cache invalidation rationale.

Files changed:
 .../engine/src/__tests__/reliability-interactions/_helpers.ts | 11 ++++++-----
 .../dependency-cycle-reconcile.test.ts                        |  7 +++++++
 2 files changed, 13 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-8050

Fusion-Task-Lineage: 5e708d58-faed-4271-a075-24c36eaa5878

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-16 07:48:12 -07:00
parent bc02b27ed9
commit 40687cb0be
2 changed files with 13 additions and 5 deletions

View File

@@ -324,11 +324,12 @@ export async function makeReliabilityFixture(input: {
},
mergeTask: async () => aiMergeTask(store, rootDir, task.id),
/*
FNXC:PgReliabilitySeeding 2026-07-16-04:48:
Reconcile tests must seed intentionally corrupt dependency/title rows that write-time guards reject.
Raw PostgreSQL updates bypass those guards, then clear both read-through snapshots: otherwise
startupSlimListMemo or taskCache can hide the corruption and reconcilers return zero. Require
exactly one persisted row so a bad fixture ID cannot make a negative-path test pass vacuously.
FNXC:ReliabilityFixtures 2026-07-16-12:00:
VAL-REMOVAL-005 made getDatabase() unusable for synchronous raw writes in PG-backed fixtures.
Reconcile tests must seed intentionally corrupt dependency/title rows that updateTask guards reject,
so this sole supported seam updates PostgreSQL directly. It then clears both read-through snapshots:
a warm startupSlimListMemo or taskCache otherwise hides corruption and reconcilers return zero.
Require exactly one persisted row so a bad fixture ID cannot make a negative-path test pass vacuously.
*/
seedRawTaskColumns: async (taskId, patch) => {
const values = {

View File

@@ -23,6 +23,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
} as any);
const child = await fx.store.createTask({ id: "FN-5256-C", title: "Foundation child", description: "child" } as any);
await fx.store.listTasks({ slim: true });
await fx.seedRawTaskColumns(umbrella.id, { dependencies: [child.id] });
await fx.seedRawTaskColumns(child.id, { dependencies: [umbrella.id] });
@@ -55,6 +56,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
const b = await fx.store.createTask({ id: "FN-5241", title: "Task B", description: "B" } as any);
const c = await fx.store.createTask({ id: "FN-5242", title: "Task C", description: "C" } as any);
await fx.store.listTasks({ slim: true });
await fx.seedRawTaskColumns(a.id, { dependencies: [b.id] });
await fx.seedRawTaskColumns(b.id, { dependencies: [c.id] });
await fx.seedRawTaskColumns(c.id, { dependencies: [a.id] });
@@ -92,6 +94,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
dependencies: [child.id],
} as any);
await fx.store.listTasks({ column: "todo", slim: true });
await fx.seedRawTaskColumns(child.id, { title: "Finalize FN-100: close loop", dependencies: ["FN-100"], column: "todo" });
expect(await fx.store.getTask(child.id)).toMatchObject({
title: "Finalize FN-100: close loop", dependencies: ["FN-100"], column: "todo",
@@ -137,6 +140,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
const c = await fx.store.createTask({ id: "FN-5432-C", title: "Task C", description: "C" } as any);
const d = await fx.store.createTask({ id: "FN-5432-D", title: "Task D", description: "D" } as any);
await fx.store.listTasks({ slim: true });
await fx.seedRawTaskColumns(a.id, { dependencies: [b.id] });
await fx.seedRawTaskColumns(b.id, { dependencies: [c.id] });
await fx.seedRawTaskColumns(c.id, { dependencies: [d.id] });
@@ -171,6 +175,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
const c = await fx.store.createTask({ id: "FN-5432-RC", title: "Task C", description: "C" } as any);
const d = await fx.store.createTask({ id: "FN-5432-RD", title: "Task D", description: "D" } as any);
await fx.store.listTasks({ slim: true });
await fx.seedRawTaskColumns(a.id, { dependencies: [b.id] });
await fx.seedRawTaskColumns(b.id, { dependencies: [c.id] });
await fx.seedRawTaskColumns(c.id, { dependencies: [d.id] });
@@ -192,6 +197,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
const p = await fx.store.createTask({ title: "Task P", description: "P" } as any);
const q = await fx.store.createTask({ title: "Task Q", description: "Q", dependencies: [p.id] } as any);
await fx.store.listTasks({ column: "todo", slim: true });
await fx.seedRawTaskColumns(p.id, { title: "Finalize FN-101: now", dependencies: ["FN-101"], column: "todo" });
expect(await fx.store.getTask(p.id)).toMatchObject({
title: "Finalize FN-101: now", dependencies: ["FN-101"], column: "todo",
@@ -228,6 +234,7 @@ describeIfGit("reliability interactions: dependency-cycle reconciliation", () =>
const c = await fx.store.createTask({ id: "FN-5432-SC", title: "Task C", description: "C" } as any);
const d = await fx.store.createTask({ id: "FN-5432-SD", title: "Task D", description: "D" } as any);
await fx.store.listTasks({ slim: true });
await fx.seedRawTaskColumns(a.id, { dependencies: [b.id] });
await fx.seedRawTaskColumns(b.id, { dependencies: [c.id] });
await fx.seedRawTaskColumns(c.id, { dependencies: [d.id] });