@@ -167,40 +167,37 @@ fn validate_epic_id(id: &str) {
167167 }
168168}
169169
170- /// Load epic document from DB (sole source of truth) .
170+ /// Load epic document from JSON files .
171171fn load_epic ( id : & str ) -> Document < Epic > {
172- let conn = require_db ( )
173- . unwrap_or_else ( |e| error_exit ( & format ! ( "DB required: {e}" ) ) ) ;
174- let repo = crate :: commands:: db_shim:: EpicRepo :: new ( & conn) ;
175- match repo. get_with_body ( id) {
176- Ok ( ( epic, body) ) => Document { frontmatter : epic, body } ,
177- Err ( _) => error_exit ( & format ! ( "Epic {id} not found" ) ) ,
178- }
172+ let flow_dir = get_flow_dir ( ) ;
173+ let epic = flowctl_core:: json_store:: epic_read ( & flow_dir, id)
174+ . unwrap_or_else ( |_| error_exit ( & format ! ( "Epic {id} not found" ) ) ) ;
175+ let body = flowctl_core:: json_store:: epic_spec_read ( & flow_dir, id)
176+ . unwrap_or_default ( ) ;
177+ Document { frontmatter : epic, body }
179178}
180179
181- /// Write an epic document to DB (sole source of truth, no MD export) .
180+ /// Write an epic document to JSON files .
182181fn save_epic ( doc : & Document < Epic > ) {
183- let conn = require_db ( )
184- . unwrap_or_else ( |e| error_exit ( & format ! ( "DB required: {e}" ) ) ) ;
185- let repo = crate :: commands:: db_shim:: EpicRepo :: new ( & conn) ;
186- if let Err ( e) = repo. upsert_with_body ( & doc. frontmatter , & doc. body ) {
187- error_exit ( & format ! ( "DB write failed for {}: {e}" , doc. frontmatter. id) ) ;
182+ let flow_dir = get_flow_dir ( ) ;
183+ if let Err ( e) = flowctl_core:: json_store:: epic_write ( & flow_dir, & doc. frontmatter ) {
184+ error_exit ( & format ! ( "Failed to write epic {}: {e}" , doc. frontmatter. id) ) ;
185+ }
186+ if let Err ( e) = flowctl_core:: json_store:: epic_spec_write ( & flow_dir, & doc. frontmatter . id , & doc. body ) {
187+ error_exit ( & format ! ( "Failed to write epic spec {}: {e}" , doc. frontmatter. id) ) ;
188188 }
189189}
190190
191- /// Open DB connection (hard error if unavailable).
192- fn require_db ( ) -> Result < crate :: commands:: db_shim:: Connection , crate :: commands:: db_shim:: DbError > {
193- crate :: commands:: db_shim:: require_db ( )
191+ /// Get max epic number from JSON files.
192+ fn find_max_epic_number ( ) -> u32 {
193+ let flow_dir = get_flow_dir ( ) ;
194+ flowctl_core:: json_store:: epic_max_num ( & flow_dir) . unwrap_or ( 0 )
194195}
195196
196- /// Get max epic number from DB. Returns 0 if none exist.
197- fn find_max_epic_number ( ) -> u32 {
198- let conn = require_db ( )
199- . unwrap_or_else ( |e| error_exit ( & format ! ( "DB required: {e}" ) ) ) ;
200- match crate :: commands:: db_shim:: max_epic_num ( & conn) {
201- Ok ( n) => n as u32 ,
202- Err ( _) => 0 ,
203- }
197+ /// Bridge: DB connection for functions not yet migrated to json_store.
198+ /// TODO(fn-24): Remove once all epic commands use json_store.
199+ fn require_db ( ) -> Result < crate :: commands:: db_shim:: Connection , crate :: commands:: db_shim:: DbError > {
200+ crate :: commands:: db_shim:: require_db ( )
204201}
205202
206203/// Create default epic spec Markdown body.
@@ -610,11 +607,9 @@ fn cmd_close(id: &str, skip_gap_check: bool, json_mode: bool) {
610607
611608 let mut doc = load_epic ( id) ;
612609
613- // Check all tasks are done/skipped via DB
614- let conn = require_db ( )
615- . unwrap_or_else ( |e| error_exit ( & format ! ( "DB required: {e}" ) ) ) ;
616- let task_repo = crate :: commands:: db_shim:: TaskRepo :: new ( & conn) ;
617- let tasks = task_repo. list_by_epic ( id) . unwrap_or_default ( ) ;
610+ // Check all tasks are done/skipped via JSON files
611+ let flow_dir = get_flow_dir ( ) ;
612+ let tasks = flowctl_core:: json_store:: task_list_by_epic ( & flow_dir, id) . unwrap_or_default ( ) ;
618613
619614 let incomplete: Vec < String > = tasks
620615 . iter ( )
@@ -632,14 +627,13 @@ fn cmd_close(id: &str, skip_gap_check: bool, json_mode: bool) {
632627 ) ) ;
633628 }
634629
635- // Gap registry gate — check DB gaps table
636- let gap_repo = crate :: commands:: db_shim:: GapRepo :: new ( & conn) ;
630+ // Gap registry gate — check JSON gaps
637631 let mut open_blocking_count = 0 ;
638632 let mut gap_list_parts: Vec < String > = Vec :: new ( ) ;
639633
640- if let Ok ( gaps) = gap_repo . list ( id , Some ( "open" ) ) {
634+ if let Ok ( gaps) = flowctl_core :: json_store :: gaps_read ( & flow_dir , id ) {
641635 for gap in & gaps {
642- if GAP_BLOCKING_PRIORITIES . contains ( & gap. priority . as_str ( ) ) {
636+ if !gap . resolved && GAP_BLOCKING_PRIORITIES . contains ( & gap. priority . as_str ( ) ) {
643637 open_blocking_count += 1 ;
644638 gap_list_parts. push ( format ! ( "[{}] {}" , gap. priority, gap. capability) ) ;
645639 }
0 commit comments