1use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct FafData {
14 pub faf_version: String,
16 pub project: Project,
18
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub ai_score: Option<String>,
22
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub ai_confidence: Option<String>,
26
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub ai_tldr: Option<HashMap<String, String>>,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub instant_context: Option<InstantContext>,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 pub context_quality: Option<ContextQuality>,
38
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub stack: Option<Stack>,
42
43 #[serde(skip_serializing_if = "Option::is_none")]
45 pub human_context: Option<HumanContext>,
46
47 #[serde(skip_serializing_if = "Option::is_none")]
49 pub preferences: Option<Preferences>,
50
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub state: Option<State>,
54
55 #[serde(default, skip_serializing_if = "Vec::is_empty")]
57 pub tags: Vec<String>,
58
59 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
63 pub commands: HashMap<String, String>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub security: Option<Security>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub ai_instructions: Option<AiInstructions>,
72
73 #[serde(default, skip_serializing_if = "Vec::is_empty")]
75 pub conventions: Vec<String>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct Security {
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub secrets: Option<String>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub example: Option<String>,
88
89 #[serde(default, skip_serializing_if = "Vec::is_empty")]
91 pub never: Vec<String>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct AiInstructions {
97 #[serde(default, skip_serializing_if = "Vec::is_empty")]
99 pub warnings: Vec<String>,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub working_style: Option<HashMap<String, String>>,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct Project {
109 pub name: String,
111
112 #[serde(skip_serializing_if = "Option::is_none")]
114 pub goal: Option<String>,
115
116 #[serde(skip_serializing_if = "Option::is_none")]
118 pub main_language: Option<String>,
119
120 #[serde(skip_serializing_if = "Option::is_none")]
122 pub approach: Option<String>,
123
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub version: Option<String>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
130 pub license: Option<String>,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct InstantContext {
136 #[serde(skip_serializing_if = "Option::is_none")]
138 pub what_building: Option<String>,
139
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub tech_stack: Option<String>,
143
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub deployment: Option<String>,
147
148 #[serde(default, skip_serializing_if = "Vec::is_empty")]
150 pub key_files: Vec<String>,
151
152 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
154 pub commands: HashMap<String, String>,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct Stack {
160 #[serde(skip_serializing_if = "Option::is_none")]
162 pub frontend: Option<String>,
163
164 #[serde(skip_serializing_if = "Option::is_none")]
166 pub backend: Option<String>,
167
168 #[serde(skip_serializing_if = "Option::is_none")]
170 pub database: Option<String>,
171
172 #[serde(skip_serializing_if = "Option::is_none")]
174 pub infrastructure: Option<String>,
175
176 #[serde(skip_serializing_if = "Option::is_none")]
178 pub build_tool: Option<String>,
179
180 #[serde(skip_serializing_if = "Option::is_none")]
182 pub testing: Option<String>,
183
184 #[serde(skip_serializing_if = "Option::is_none")]
186 pub cicd: Option<String>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct ContextQuality {
192 #[serde(skip_serializing_if = "Option::is_none")]
194 pub slots_filled: Option<String>,
195
196 #[serde(skip_serializing_if = "Option::is_none")]
198 pub confidence: Option<String>,
199
200 #[serde(default)]
202 pub handoff_ready: bool,
203
204 #[serde(default, skip_serializing_if = "Vec::is_empty")]
206 pub missing_context: Vec<String>,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct HumanContext {
212 #[serde(skip_serializing_if = "Option::is_none")]
214 pub who: Option<String>,
215
216 #[serde(skip_serializing_if = "Option::is_none")]
218 pub what: Option<String>,
219
220 #[serde(rename = "why", skip_serializing_if = "Option::is_none")]
222 pub why_field: Option<String>,
223
224 #[serde(skip_serializing_if = "Option::is_none")]
226 pub how: Option<String>,
227
228 #[serde(rename = "where", skip_serializing_if = "Option::is_none")]
230 pub where_field: Option<String>,
231
232 #[serde(skip_serializing_if = "Option::is_none")]
234 pub when: Option<String>,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct Preferences {
240 #[serde(skip_serializing_if = "Option::is_none")]
242 pub quality_bar: Option<String>,
243
244 #[serde(skip_serializing_if = "Option::is_none")]
246 pub testing: Option<String>,
247
248 #[serde(skip_serializing_if = "Option::is_none")]
250 pub documentation: Option<String>,
251
252 #[serde(skip_serializing_if = "Option::is_none")]
254 pub code_style: Option<String>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct State {
260 #[serde(skip_serializing_if = "Option::is_none")]
262 pub phase: Option<String>,
263
264 #[serde(skip_serializing_if = "Option::is_none")]
266 pub version: Option<String>,
267
268 #[serde(skip_serializing_if = "Option::is_none")]
270 pub focus: Option<String>,
271
272 #[serde(default, skip_serializing_if = "Vec::is_empty")]
274 pub milestones: Vec<String>,
275}