feat(FN-1690): add RoadmapStore with SQLite persistence
- Implement RoadmapStore with CRUD operations for roadmaps, milestones, and features - Add roadmap schema migration v32 with roadmaps, roadmap_milestones, and roadmap_features tables - Add covering indexes for deterministic ordering within roadmaps and milestones - Wire RoadmapStore access via TaskStore.getRoadmapStore() - Update architecture.md documentation with RoadmapStore persistence - Add comprehensive tests for RoadmapStore CRUD and ordering - Update db.test.ts with schema v32 assertions - Add UpdateInput type imports to task-documents.test.ts - Export RoadmapStore from core index.ts
This commit is contained in:
@@ -59,7 +59,7 @@ export function fromJson<T>(json: string | null | undefined): T | undefined {
|
||||
|
||||
// ── Schema Definition ────────────────────────────────────────────────
|
||||
|
||||
const SCHEMA_VERSION = 31;
|
||||
const SCHEMA_VERSION = 32;
|
||||
|
||||
function normalizeTaskComments(
|
||||
steeringComments: SteeringComment[] | undefined,
|
||||
@@ -1176,6 +1176,66 @@ export class Database {
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxFixLineageRunId ON mission_fix_feature_lineage(runId)`);
|
||||
});
|
||||
}
|
||||
|
||||
// Roadmap persistence tables (FN-1690)
|
||||
// Standalone roadmap: Roadmap → RoadmapMilestone → RoadmapFeature
|
||||
// with deterministic ordering indexes and FK cascade integrity
|
||||
if (version < 32) {
|
||||
this.applyMigration(32, () => {
|
||||
// Roadmaps table
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS roadmaps (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL
|
||||
)
|
||||
`);
|
||||
|
||||
// Roadmap milestones table
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS roadmap_milestones (
|
||||
id TEXT PRIMARY KEY,
|
||||
roadmapId TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
orderIndex INTEGER NOT NULL,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (roadmapId) REFERENCES roadmaps(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// Roadmap features table
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS roadmap_features (
|
||||
id TEXT PRIMARY KEY,
|
||||
milestoneId TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
orderIndex INTEGER NOT NULL,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (milestoneId) REFERENCES roadmap_milestones(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// Covering index for deterministic milestone ordering within a roadmap
|
||||
// Covers: WHERE roadmapId = ? ORDER BY orderIndex ASC, createdAt ASC, id ASC
|
||||
this.db.exec(`
|
||||
CREATE INDEX IF NOT EXISTS idxRoadmapMilestonesRoadmapOrder
|
||||
ON roadmap_milestones(roadmapId, orderIndex, createdAt, id)
|
||||
`);
|
||||
|
||||
// Covering index for deterministic feature ordering within a milestone
|
||||
// Covers: WHERE milestoneId = ? ORDER BY orderIndex ASC, createdAt ASC, id ASC
|
||||
this.db.exec(`
|
||||
CREATE INDEX IF NOT EXISTS idxRoadmapFeaturesMilestoneOrder
|
||||
ON roadmap_features(milestoneId, orderIndex, createdAt, id)
|
||||
`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user