1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// SPDX-FileCopyrightText: 2025 Knitli Inc. <knitli@knit.li>
// SPDX-License-Identifier: AGPL-3.0-or-later
//! # Incremental Update System
//!
//! This module implements Thread's incremental update system for dependency-aware
//! invalidation and targeted re-analysis. It adapts patterns from ReCoco's
//! `FieldDefFingerprint` design to Thread's AST analysis domain.
//!
//! ## Architecture
//!
//! The system consists of four integrated subsystems:
//!
//! - **Types** ([`types`]): Core data structures for fingerprints, dependency edges,
//! and the dependency graph.
//! - **Graph** ([`graph`]): Dependency graph traversal algorithms including BFS
//! affected-file detection, topological sort, and cycle detection.
//! - **Storage** ([`storage`]): Trait definitions for persisting dependency graphs
//! and fingerprints across sessions.
//! - **Backends** ([`backends`]): Concrete storage implementations (Postgres, D1, InMemory)
//! with factory pattern for runtime backend selection.
//!
//! ## Design Pattern
//!
//! Adapted from ReCoco's `FieldDefFingerprint` (analyzer.rs:69-84):
//! - **Source tracking**: Identifies which files contribute to each analysis result
//! - **Fingerprint composition**: Detects content AND logic changes via Blake3 hashing
//! - **Dependency graph**: Maintains import/export relationships for cascading invalidation
//!
//! ## Examples
//!
//! ### Basic Dependency Graph Operations
//!
//! ```rust
//! use thread_flow::incremental::types::{
//! AnalysisDefFingerprint, DependencyEdge, DependencyType,
//! };
//! use thread_flow::incremental::graph::DependencyGraph;
//! use std::path::PathBuf;
//! use std::collections::HashSet;
//!
//! // Create a dependency graph
//! let mut graph = DependencyGraph::new();
//!
//! // Add a dependency edge: main.rs imports utils.rs
//! graph.add_edge(DependencyEdge {
//! from: PathBuf::from("src/main.rs"),
//! to: PathBuf::from("src/utils.rs"),
//! dep_type: DependencyType::Import,
//! symbol: None,
//! });
//!
//! // Find files affected by a change to utils.rs
//! let changed = HashSet::from([PathBuf::from("src/utils.rs")]);
//! let affected = graph.find_affected_files(&changed);
//! assert!(affected.contains(&PathBuf::from("src/main.rs")));
//! ```
//!
//! ### Runtime Backend Selection
//!
//! ```rust
//! use thread_flow::incremental::{create_backend, BackendType, BackendConfig};
//!
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! // Select backend based on deployment environment
//! let backend = if cfg!(feature = "postgres-backend") {
//! create_backend(
//! BackendType::Postgres,
//! BackendConfig::Postgres {
//! database_url: std::env::var("DATABASE_URL")?,
//! },
//! ).await?
//! } else if cfg!(feature = "d1-backend") {
//! create_backend(
//! BackendType::D1,
//! BackendConfig::D1 {
//! account_id: std::env::var("CF_ACCOUNT_ID")?,
//! database_id: std::env::var("CF_DATABASE_ID")?,
//! api_token: std::env::var("CF_API_TOKEN")?,
//! },
//! ).await?
//! } else {
//! // Fallback to in-memory for testing
//! create_backend(BackendType::InMemory, BackendConfig::InMemory).await?
//! };
//! # Ok(())
//! # }
//! ```
//!
//! ### Persistent Storage with Incremental Updates
//!
//! ```rust,ignore
//! use thread_flow::incremental::{
//! create_backend, BackendType, BackendConfig,
//! StorageBackend, AnalysisDefFingerprint, DependencyGraph,
//! };
//! use std::path::Path;
//!
//! async fn incremental_analysis(backend: &dyn StorageBackend) -> Result<(), Box<dyn std::error::Error>> {
//! // Load previous dependency graph
//! let mut graph = backend.load_full_graph().await?;
//!
//! // Check if file changed
//! let file_path = Path::new("src/main.rs");
//! let new_fp = AnalysisDefFingerprint::new(b"new content");
//!
//! if let Some(old_fp) = backend.load_fingerprint(file_path).await? {
//! if !old_fp.content_matches(b"new content") {
//! // File changed - invalidate and re-analyze
//! let affected = graph.find_affected_files(&[file_path.to_path_buf()].into());
//! for affected_file in affected {
//! // Re-analyze affected files...
//! }
//! }
//! }
//!
//! // Save updated state
//! backend.save_fingerprint(file_path, &new_fp).await?;
//! backend.save_full_graph(&graph).await?;
//! Ok(())
//! }
//! ```
//!
//! ## Migration Guide
//!
//! ### From Direct Storage Usage to Backend Factory
//!
//! **Before (direct backend instantiation):**
//! ```rust,ignore
//! #[cfg(feature = "postgres-backend")]
//! use thread_flow::incremental::backends::postgres::PostgresIncrementalBackend;
//!
//! let backend = PostgresIncrementalBackend::new(database_url).await?;
//! ```
//!
//! **After (factory pattern):**
//! ```rust,ignore
//! use thread_flow::incremental::{create_backend, BackendType, BackendConfig};
//!
//! let backend = create_backend(
//! BackendType::Postgres,
//! BackendConfig::Postgres { database_url },
//! ).await?;
//! ```
//!
//! ### Feature Flag Configuration
//!
//! **CLI deployment (Postgres):**
//! ```toml
//! [dependencies]
//! thread-flow = { version = "*", features = ["postgres-backend", "parallel"] }
//! ```
//!
//! **Edge deployment (D1):**
//! ```toml
//! [dependencies]
//! thread-flow = { version = "*", features = ["d1-backend", "worker"] }
//! ```
//!
//! **Testing (InMemory):**
//! ```toml
//! [dev-dependencies]
//! thread-flow = { version = "*" } # InMemory always available
//! ```
// Re-export core types for ergonomic use
pub use ;
pub use DependencyGraph;
pub use ;
pub use ;
// Re-export backend factory and configuration for runtime backend selection
pub use ;
// Re-export storage trait for custom backend implementations
pub use ;
// Re-export concurrency layer for parallel execution - TODO: Phase 4.3
// pub use concurrency::{create_executor, ConcurrencyMode, ExecutionError, Executor};
// Feature-gated backend re-exports
pub use PostgresIncrementalBackend;
pub use D1IncrementalBackend;