1use chrono::{DateTime, Utc};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::path::PathBuf;
6
7macro_rules! id_type {
8 ($name:ident) => {
9 #[derive(
10 Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
11 )]
12 pub struct $name(pub String);
13
14 impl $name {
15 pub fn new(value: impl Into<String>) -> Self {
16 Self(value.into())
17 }
18 }
19
20 impl fmt::Display for $name {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.write_str(&self.0)
23 }
24 }
25 };
26}
27
28id_type!(RepositoryId);
29id_type!(FileId);
30id_type!(FileVersionId);
31id_type!(SymbolId);
32id_type!(NodeId);
33id_type!(EdgeId);
34id_type!(PatchId);
35id_type!(EvidenceId);
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
38#[serde(rename_all = "snake_case")]
39pub enum Confidence {
40 Low,
41 Medium,
42 High,
43 Exact,
44}
45
46impl Confidence {
47 pub fn score(self) -> f32 {
48 match self {
49 Self::Low => 0.35,
50 Self::Medium => 0.6,
51 Self::High => 0.85,
52 Self::Exact => 1.0,
53 }
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
58pub struct LineRange {
59 pub start: u32,
60 pub end: u32,
61}
62
63impl LineRange {
64 pub fn single(line: u32) -> Self {
65 Self {
66 start: line,
67 end: line,
68 }
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
73pub struct FileRange {
74 pub path: PathBuf,
75 pub line_range: Option<LineRange>,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
79#[serde(rename_all = "snake_case")]
80pub enum EvidenceSourceType {
81 TreeSitter,
82 Scip,
83 Lsp,
84 Regex,
85 Lexical,
86 Semantic,
87 Runtime,
88 ExternalIntegration,
89 Heuristic,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
93pub struct Evidence {
94 pub id: EvidenceId,
95 pub source: String,
96 pub source_type: EvidenceSourceType,
97 pub file_range: Option<FileRange>,
98 pub symbol_id: Option<SymbolId>,
99 pub confidence: Confidence,
100 pub message: String,
101 pub indexed_at: DateTime<Utc>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
105pub struct Repository {
106 pub id: RepositoryId,
107 pub name: String,
108 pub root: PathBuf,
109 pub branch: Option<String>,
110 pub commit: Option<String>,
111 pub indexed_at: Option<DateTime<Utc>>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115pub struct Commit {
116 pub sha: String,
117 pub message: Option<String>,
118 pub authored_at: Option<DateTime<Utc>>,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
122pub struct Branch {
123 pub name: String,
124 pub head: Option<String>,
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
128#[serde(rename_all = "snake_case")]
129pub enum Language {
130 Rust,
131 Java,
132 TypeScript,
133 JavaScript,
134 Python,
135 Go,
136 Yaml,
137 Json,
138 Toml,
139 Sql,
140 Markdown,
141 Text,
142 Unknown,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
146pub struct File {
147 pub id: FileId,
148 pub repository_id: RepositoryId,
149 pub path: PathBuf,
150 pub language: Language,
151 pub size_bytes: u64,
152 pub content_hash: String,
153 pub is_generated: bool,
154 pub is_vendor: bool,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
158pub struct FileVersion {
159 pub id: FileVersionId,
160 pub file_id: FileId,
161 pub commit: Option<String>,
162 pub content_hash: String,
163 pub indexed_at: DateTime<Utc>,
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
167#[serde(rename_all = "snake_case")]
168pub enum SymbolKind {
169 Module,
170 Package,
171 Class,
172 Trait,
173 Interface,
174 Function,
175 Method,
176 Field,
177 Variable,
178 Constant,
179 Endpoint,
180 DatabaseTable,
181 Test,
182 Unknown,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
186pub struct Symbol {
187 pub id: SymbolId,
188 pub name: String,
189 pub qualified_name: String,
190 pub kind: SymbolKind,
191 pub file_id: FileId,
192 pub range: Option<LineRange>,
193 pub language: Language,
194 pub confidence: Confidence,
195 pub provenance: EvidenceSourceType,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
199pub struct SymbolOccurrence {
200 pub symbol_id: SymbolId,
201 pub file_id: FileId,
202 pub range: Option<LineRange>,
203 pub is_definition: bool,
204 pub confidence: Confidence,
205 pub provenance: EvidenceSourceType,
206}
207
208pub type Reference = SymbolOccurrence;
209pub type Definition = SymbolOccurrence;
210
211#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
212pub struct Import {
213 pub file_id: FileId,
214 pub imported: String,
215 pub range: Option<LineRange>,
216 pub confidence: Confidence,
217}
218
219#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
220pub struct CodeChunk {
221 pub id: String,
222 pub file_id: FileId,
223 pub range: LineRange,
224 pub language: Language,
225 pub text: String,
226 pub symbol_id: Option<SymbolId>,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
230pub struct Diagnostic {
231 pub severity: String,
232 pub message: String,
233 pub file_range: Option<FileRange>,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
237pub struct TestTarget {
238 pub id: String,
239 pub name: String,
240 pub file_id: FileId,
241 pub range: Option<LineRange>,
242 pub command: Option<String>,
243 pub confidence: Confidence,
244 pub reason: String,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
248pub struct BuildTarget {
249 pub id: String,
250 pub name: String,
251 pub command: String,
252 pub files: Vec<FileId>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
256pub struct RuntimeSignal {
257 pub id: String,
258 pub kind: String,
259 pub message: String,
260 pub file_range: Option<FileRange>,
261 pub occurred_at: Option<DateTime<Utc>>,
262 pub confidence: Confidence,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
266pub struct Owner {
267 pub name: String,
268 pub email: Option<String>,
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
272pub struct ArchitectureComponent {
273 pub id: String,
274 pub name: String,
275 pub paths: Vec<String>,
276 pub evidence: Vec<Evidence>,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
280pub struct IndexManifest {
281 pub repository: Repository,
282 pub file_count: usize,
283 pub symbol_count: usize,
284 pub chunk_count: usize,
285 pub indexed_at: DateTime<Utc>,
286 pub schema_version: u32,
287 #[serde(default)]
288 pub quality: IndexQuality,
289}
290
291#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
292pub struct IndexQuality {
293 pub scip_enabled: bool,
294 pub scip_mode: String,
295 pub scip_indexes_imported: usize,
296 pub scip_symbols: usize,
297 pub scip_occurrences: usize,
298 pub scip_exact_references: usize,
299 pub test_count: usize,
300 pub import_count: usize,
301 pub quality_notes: Vec<String>,
302}
303
304#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
305#[serde(rename_all = "snake_case")]
306pub enum GraphNodeType {
307 File,
308 Directory,
309 Module,
310 Package,
311 Class,
312 Trait,
313 Interface,
314 Function,
315 Method,
316 Field,
317 Endpoint,
318 DatabaseTable,
319 Collection,
320 Queue,
321 Topic,
322 ConfigKey,
323 Test,
324 BuildTarget,
325 RuntimeError,
326 Ticket,
327 PullRequest,
328 ArchitectureComponent,
329}
330
331#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
332#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
333pub enum GraphEdgeType {
334 Contains,
335 Defines,
336 References,
337 Calls,
338 Implements,
339 Extends,
340 Imports,
341 DependsOn,
342 ExposesEndpoint,
343 CallsEndpoint,
344 ReadsConfig,
345 WritesConfig,
346 ReadsTable,
347 WritesTable,
348 PublishesEvent,
349 ConsumesEvent,
350 Tests,
351 OwnedBy,
352 ChangedBy,
353 FailedIn,
354 MentionedIn,
355 RelatedToTicket,
356}
357
358#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
359pub struct GraphNode {
360 pub id: NodeId,
361 pub node_type: GraphNodeType,
362 pub label: String,
363 pub file_id: Option<FileId>,
364 pub symbol_id: Option<SymbolId>,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
368pub struct GraphEdge {
369 pub id: EdgeId,
370 pub from: NodeId,
371 pub to: NodeId,
372 pub edge_type: GraphEdgeType,
373 pub evidence: Evidence,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
377pub struct SearchResult {
378 pub path: PathBuf,
379 pub line_range: Option<LineRange>,
380 pub snippet: String,
381 pub symbol: Option<Symbol>,
382 pub score: f32,
383 pub match_reason: String,
384 pub evidence: Vec<String>,
385 pub confidence: f32,
386}
387
388#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
389pub struct RiskReport {
390 pub level: String,
391 pub score: f32,
392 pub reasons: Vec<String>,
393}
394
395#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
396pub struct ChangeBoundary {
397 pub allowed_files: Vec<PathBuf>,
398 pub caution_files: Vec<PathBuf>,
399 pub forbidden_files: Vec<PathBuf>,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
403pub struct ValidationPlan {
404 pub commands: Vec<String>,
405 pub tests: Vec<TestTarget>,
406 pub requires_approval: bool,
407 pub evidence: Vec<Evidence>,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
411pub struct ImpactReport {
412 pub target: String,
413 pub direct_impacts: Vec<SearchResult>,
414 pub indirect_impacts: Vec<SearchResult>,
415 pub risk_report: RiskReport,
416 pub evidence: Vec<Evidence>,
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
420pub struct ContextPack {
421 pub task: String,
422 pub intent: String,
423 pub primary_files: Vec<SearchResult>,
424 pub primary_symbols: Vec<Symbol>,
425 pub supporting_files: Vec<SearchResult>,
426 pub dependency_edges: Vec<GraphEdge>,
427 pub runtime_signals: Vec<RuntimeSignal>,
428 pub test_candidates: Vec<TestTarget>,
429 pub risk_report: RiskReport,
430 pub recommended_change_boundary: ChangeBoundary,
431 pub validation_plan: ValidationPlan,
432 pub evidence: Vec<Evidence>,
433 pub confidence_summary: String,
434}
435
436#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
437pub struct ToolCallRecommendation {
438 pub tool: String,
439 pub purpose: String,
440 pub arguments: serde_json::Value,
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
444pub struct PlanReport {
445 pub task: String,
446 pub summary: String,
447 pub primary_context: Vec<SearchResult>,
448 pub relevant_symbols: Vec<Symbol>,
449 pub impact: ImpactReport,
450 pub validation: Vec<TestTarget>,
451 pub risk: RiskReport,
452 pub recommended_change_boundary: ChangeBoundary,
453 pub recommended_next_steps: Vec<String>,
454 pub tool_calls: Vec<ToolCallRecommendation>,
455 pub evidence: Vec<Evidence>,
456 pub confidence_summary: String,
457}
458
459#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
460pub struct PatchPlan {
461 pub id: PatchId,
462 pub task: String,
463 pub allowed_files: Vec<PathBuf>,
464 pub caution_files: Vec<PathBuf>,
465 pub forbidden_files: Vec<PathBuf>,
466 pub change_steps: Vec<String>,
467 pub risks: Vec<String>,
468 pub assumptions: Vec<String>,
469 pub tests: Vec<TestTarget>,
470 pub rollback_notes: Vec<String>,
471 pub unified_diff: Option<String>,
472 pub requires_approval: bool,
473 pub evidence: Vec<Evidence>,
474}