Skip to main content

faf_kernel/
types.rs

1//! Type definitions for the FAF format.
2//!
3//! These structs are the in-memory shape of a parsed `.faf` file. Field names
4//! map directly to the YAML keys; most are `Option` because `.faf` is
5//! progressive — a project fills in as much context as it has, and the score
6//! reflects how complete that picture is.
7
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11/// A complete parsed `.faf` file — the root of the context document.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct FafData {
14    /// The `.faf` format version this file was written against (e.g. `"2.5.0"`).
15    pub faf_version: String,
16    /// Core project identity (name, goal, language). Always present.
17    pub project: Project,
18
19    /// Cached AI-readiness score, if one was written by a generator.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub ai_score: Option<String>,
22
23    /// Cached confidence band for the score, if present.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub ai_confidence: Option<String>,
26
27    /// Short, AI-facing summary lines keyed by topic.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub ai_tldr: Option<HashMap<String, String>>,
30
31    /// The fast-path context an assistant reads first (what/stack/files).
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub instant_context: Option<InstantContext>,
34
35    /// Self-reported completeness metrics for the context.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub context_quality: Option<ContextQuality>,
38
39    /// The technical stack (frontend, backend, database, build, …).
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub stack: Option<Stack>,
42
43    /// The human side — the 6 W's (who/what/why/how/where/when).
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub human_context: Option<HumanContext>,
46
47    /// Working preferences (quality bar, testing, docs, code style).
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub preferences: Option<Preferences>,
50
51    /// Where the project is right now (phase, version, focus, milestones).
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub state: Option<State>,
54
55    /// Free-form classification tags.
56    #[serde(default, skip_serializing_if = "Vec::is_empty")]
57    pub tags: Vec<String>,
58}
59
60/// Core project identity — the one block every `.faf` file has.
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Project {
63    /// The project's name.
64    pub name: String,
65
66    /// One sentence on what the project is for — the seed for the 6 W's.
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub goal: Option<String>,
69
70    /// Primary implementation language (e.g. `"Rust"`).
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub main_language: Option<String>,
73
74    /// How the project is built or approached (architecture, methodology).
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub approach: Option<String>,
77
78    /// The project's own version string.
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub version: Option<String>,
81
82    /// SPDX license identifier (e.g. `"MIT"`).
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub license: Option<String>,
85}
86
87/// The fast-path context an AI assistant reads first.
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct InstantContext {
90    /// A one-line description of what is being built.
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub what_building: Option<String>,
93
94    /// The stack in brief, as a single human-readable line.
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub tech_stack: Option<String>,
97
98    /// How and where the project is deployed.
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub deployment: Option<String>,
101
102    /// The files most worth reading first to understand the project.
103    #[serde(default, skip_serializing_if = "Vec::is_empty")]
104    pub key_files: Vec<String>,
105
106    /// Named commands (e.g. `build`, `test`) → their shell invocations.
107    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
108    pub commands: HashMap<String, String>,
109}
110
111/// The technical stack — one field per layer.
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct Stack {
114    /// Frontend framework or library.
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub frontend: Option<String>,
117
118    /// Backend framework or runtime.
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub backend: Option<String>,
121
122    /// Database or data store.
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub database: Option<String>,
125
126    /// Hosting / infrastructure platform.
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub infrastructure: Option<String>,
129
130    /// Build tool or bundler.
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub build_tool: Option<String>,
133
134    /// Test framework or runner.
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub testing: Option<String>,
137
138    /// CI/CD platform.
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub cicd: Option<String>,
141}
142
143/// Self-reported metrics on how complete the context is.
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct ContextQuality {
146    /// How many of the 33 slots are filled, as reported by the generator.
147    #[serde(skip_serializing_if = "Option::is_none")]
148    pub slots_filled: Option<String>,
149
150    /// Confidence band for the reported completeness.
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub confidence: Option<String>,
153
154    /// Whether the context is considered ready to hand off to an AI.
155    #[serde(default)]
156    pub handoff_ready: bool,
157
158    /// Slots the author knows are still missing.
159    #[serde(default, skip_serializing_if = "Vec::is_empty")]
160    pub missing_context: Vec<String>,
161}
162
163/// The human side of the project — the 6 W's.
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct HumanContext {
166    /// Who the project is for / who works on it.
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub who: Option<String>,
169
170    /// What the project is.
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub what: Option<String>,
173
174    /// Why it exists. Serialized as `why` (`why_field` avoids the keyword).
175    #[serde(rename = "why", skip_serializing_if = "Option::is_none")]
176    pub why_field: Option<String>,
177
178    /// How it works or is built.
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub how: Option<String>,
181
182    /// Where it runs / lives. Serialized as `where`.
183    #[serde(rename = "where", skip_serializing_if = "Option::is_none")]
184    pub where_field: Option<String>,
185
186    /// When — timeline, stage, or cadence.
187    #[serde(skip_serializing_if = "Option::is_none")]
188    pub when: Option<String>,
189}
190
191/// Working preferences that shape how the project should be developed.
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct Preferences {
194    /// The quality bar to hold (e.g. zero-errors, championship-grade).
195    #[serde(skip_serializing_if = "Option::is_none")]
196    pub quality_bar: Option<String>,
197
198    /// Testing expectations.
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub testing: Option<String>,
201
202    /// Documentation expectations.
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub documentation: Option<String>,
205
206    /// Code-style conventions.
207    #[serde(skip_serializing_if = "Option::is_none")]
208    pub code_style: Option<String>,
209}
210
211/// Where the project is right now.
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct State {
214    /// Current phase (e.g. `"production"`, `"prototype"`).
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub phase: Option<String>,
217
218    /// Version associated with the current state.
219    #[serde(skip_serializing_if = "Option::is_none")]
220    pub version: Option<String>,
221
222    /// What the work is focused on right now.
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub focus: Option<String>,
225
226    /// Recent or upcoming milestones.
227    #[serde(default, skip_serializing_if = "Vec::is_empty")]
228    pub milestones: Vec<String>,
229}