diff --git a/src/resources/extensions/sf/sf-db.ts b/src/resources/extensions/sf/sf-db.ts index 1c7fe8a9a..f5ee72d2b 100644 --- a/src/resources/extensions/sf/sf-db.ts +++ b/src/resources/extensions/sf/sf-db.ts @@ -332,6 +332,8 @@ function initSchema(db: DbAdapter, fileBacked: boolean): void { planning_meeting_json TEXT NOT NULL DEFAULT '', sequence INTEGER DEFAULT 0, -- Ordering hint: tools may set this to control execution order replan_triggered_at TEXT DEFAULT NULL, + is_sketch INTEGER NOT NULL DEFAULT 0, -- ADR-011: 1 = slice is a sketch awaiting refine-slice + sketch_scope TEXT NOT NULL DEFAULT '', -- ADR-011: 2-3 sentence scope hint from plan-milestone PRIMARY KEY (milestone_id, id), FOREIGN KEY (milestone_id) REFERENCES milestones(id) ) @@ -1396,6 +1398,31 @@ function migrateSchema(db: DbAdapter): void { }); } + if (currentVersion < 22) { + // ADR-011: progressive planning. is_sketch=1 means the slice is a 2-3 + // sentence sketch awaiting refine-slice expansion; refine fills in the + // real plan and clears the flag. sketch_scope holds the milestone + // planner's stored scope hint that refine treats as a hard boundary. + ensureColumn( + db, + "slices", + "is_sketch", + `ALTER TABLE slices ADD COLUMN is_sketch INTEGER NOT NULL DEFAULT 0`, + ); + ensureColumn( + db, + "slices", + "sketch_scope", + `ALTER TABLE slices ADD COLUMN sketch_scope TEXT NOT NULL DEFAULT ''`, + ); + db.prepare( + "INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)", + ).run({ + ":version": 22, + ":applied_at": new Date().toISOString(), + }); + } + db.exec("COMMIT"); } catch (err) { db.exec("ROLLBACK"); @@ -2355,6 +2382,8 @@ function rowToSlice(row: Record): SliceRow { planning_meeting: parsePlanningMeeting(row["planning_meeting_json"]), sequence: (row["sequence"] as number) ?? 0, replan_triggered_at: (row["replan_triggered_at"] as string) ?? null, + sketch_scope: (row["sketch_scope"] as string) ?? "", + is_sketch: (row["is_sketch"] as number) ?? 0, }; }