@@ -16,13 +16,6 @@ use flowctl_core::types::{
1616
1717use super :: get_flow_dir;
1818
19- /// Open DB connection (hard error on failure, DB is sole source of truth).
20- fn require_db ( ) -> crate :: commands:: db_shim:: Connection {
21- crate :: commands:: db_shim:: require_db ( )
22- . unwrap_or_else ( |e| {
23- crate :: output:: error_exit ( & format ! ( "Cannot open database: {e}" ) ) ;
24- } )
25- }
2619
2720// ── Status command ──────────────────────────────────────────────────
2821
@@ -156,13 +149,10 @@ pub fn cmd_status(json: bool, interrupted: bool) {
156149 }
157150}
158151
159- /// Try to get status counts from SQLite database .
152+ /// Try to get status counts from JSON files .
160153fn status_from_db ( ) -> Option < ( serde_json:: Value , serde_json:: Value ) > {
161- let cwd = env:: current_dir ( ) . ok ( ) ?;
162- let conn = crate :: commands:: db_shim:: open ( & cwd) . ok ( ) ?;
163-
164- let epic_repo = crate :: commands:: db_shim:: EpicRepo :: new ( & conn) ;
165- let epics = epic_repo. list ( None ) . ok ( ) ?;
154+ let flow_dir = crate :: commands:: helpers:: get_flow_dir ( ) ;
155+ let epics = flowctl_core:: json_store:: epic_list ( & flow_dir) . ok ( ) ?;
166156
167157 let mut epic_open = 0u64 ;
168158 let mut epic_done = 0u64 ;
@@ -173,8 +163,7 @@ fn status_from_db() -> Option<(serde_json::Value, serde_json::Value)> {
173163 }
174164 }
175165
176- let task_repo = crate :: commands:: db_shim:: TaskRepo :: new ( & conn) ;
177- let tasks = task_repo. list_all ( None , None ) . ok ( ) ?;
166+ let tasks = flowctl_core:: json_store:: task_list_all ( & flow_dir) . ok ( ) ?;
178167
179168 let mut todo = 0u64 ;
180169 let mut in_progress = 0u64 ;
@@ -219,29 +208,21 @@ fn is_daemon_heartbeat_alive(flow_dir: &Path) -> bool {
219208 . unwrap_or ( false )
220209}
221210
222- /// Find open epics with undone tasks (interrupted work) from DB .
223- fn find_interrupted_epics ( _flow_dir : & Path ) -> Vec < serde_json:: Value > {
211+ /// Find open epics with undone tasks (interrupted work) from JSON files .
212+ fn find_interrupted_epics ( flow_dir : & Path ) -> Vec < serde_json:: Value > {
224213 let mut interrupted = Vec :: new ( ) ;
225214
226- let conn = match crate :: commands:: db_shim:: require_db ( ) {
227- Ok ( c) => c,
228- Err ( _) => return interrupted,
229- } ;
230-
231- let epic_repo = crate :: commands:: db_shim:: EpicRepo :: new ( & conn) ;
232- let epics = match epic_repo. list ( None ) {
215+ let epics = match flowctl_core:: json_store:: epic_list ( flow_dir) {
233216 Ok ( e) => e,
234217 Err ( _) => return interrupted,
235218 } ;
236219
237- let task_repo = crate :: commands:: db_shim:: TaskRepo :: new ( & conn) ;
238-
239220 for epic in epics {
240221 if epic. status != flowctl_core:: types:: EpicStatus :: Open {
241222 continue ;
242223 }
243224
244- let tasks = match task_repo . list_by_epic ( & epic. id ) {
225+ let tasks = match flowctl_core :: json_store :: task_list_by_epic ( flow_dir , & epic. id ) {
245226 Ok ( t) => t,
246227 Err ( _) => continue ,
247228 } ;
@@ -337,26 +318,24 @@ pub(super) fn validate_epic(flow_dir: &Path, epic_id: &str) -> (Vec<String>, Vec
337318 let mut errors = Vec :: new ( ) ;
338319 let mut warnings = Vec :: new ( ) ;
339320
340- // Read tasks from DB (sole source of truth)
321+ // Read tasks from JSON files
341322 let mut tasks: std:: collections:: HashMap < String , flowctl_core:: types:: Task > =
342323 std:: collections:: HashMap :: new ( ) ;
343324
344- let conn = require_db ( ) ;
345- let task_repo = crate :: commands:: db_shim:: TaskRepo :: new ( & conn) ;
346- if let Ok ( task_list) = task_repo. list_by_epic ( epic_id) {
325+ if let Ok ( task_list) = flowctl_core:: json_store:: task_list_by_epic ( flow_dir, epic_id) {
347326 for task in task_list {
348327 tasks. insert ( task. id . clone ( ) , task) ;
349328 }
350329 }
351330
352331 // Validate each task
353332 for ( task_id, task) in & tasks {
354- // Validate task body has required headings (read from DB )
333+ // Validate task body has required headings (read from JSON )
355334 {
356- match task_repo . get_with_body ( task_id) {
357- Ok ( ( _t , body) ) => {
335+ match flowctl_core :: json_store :: task_spec_read ( flow_dir , task_id) {
336+ Ok ( body) => {
358337 if body. is_empty ( ) {
359- warnings. push ( format ! ( "Task {}: no body in DB " , task_id) ) ;
338+ warnings. push ( format ! ( "Task {}: no spec body " , task_id) ) ;
360339 } else {
361340 for heading in flowctl_core:: types:: TASK_SPEC_HEADINGS {
362341 if !body. contains ( heading) {
@@ -366,7 +345,7 @@ pub(super) fn validate_epic(flow_dir: &Path, epic_id: &str) -> (Vec<String>, Vec
366345 }
367346 }
368347 Err ( _) => {
369- errors. push ( format ! ( "Task {}: could not read body from DB " , task_id) ) ;
348+ errors. push ( format ! ( "Task {}: could not read spec " , task_id) ) ;
370349 }
371350 }
372351 }
@@ -430,9 +409,7 @@ pub fn cmd_validate(json_mode: bool, epic: Option<String>, all: bool) {
430409 // Validate all epics
431410 let root_errors = validate_flow_root ( & flow_dir) ;
432411
433- let conn = require_db ( ) ;
434- let epic_repo = crate :: commands:: db_shim:: EpicRepo :: new ( & conn) ;
435- let mut epic_ids: Vec < String > = epic_repo. list ( None )
412+ let mut epic_ids: Vec < String > = flowctl_core:: json_store:: epic_list ( & flow_dir)
436413 . unwrap_or_default ( )
437414 . into_iter ( )
438415 . map ( |e| e. id )
@@ -553,9 +530,7 @@ pub fn cmd_doctor(json_mode: bool) {
553530 let mut validate_errors = root_errors. clone ( ) ;
554531
555532 {
556- let conn = require_db ( ) ;
557- let epic_repo = crate :: commands:: db_shim:: EpicRepo :: new ( & conn) ;
558- if let Ok ( epics) = epic_repo. list ( None ) {
533+ if let Ok ( epics) = flowctl_core:: json_store:: epic_list ( & flow_dir) {
559534 for epic in & epics {
560535 let ( errors, _, _) = validate_epic ( & flow_dir, & epic. id ) ;
561536 validate_errors. extend ( errors) ;
0 commit comments