1use std::collections::BTreeMap;
8
9use serde::{Deserialize, Serialize};
10use tokmd_types::{ScanStatus, ToolInfo};
11
12pub const ANALYSIS_SCHEMA_VERSION: u32 = 2;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct AnalysisReceipt {
17 pub schema_version: u32,
18 pub generated_at_ms: u128,
19 pub tool: ToolInfo,
20 pub mode: String,
21 pub status: ScanStatus,
22 pub warnings: Vec<String>,
23 pub source: AnalysisSource,
24 pub args: AnalysisArgsMeta,
25 pub archetype: Option<Archetype>,
26 pub topics: Option<TopicClouds>,
27 pub entropy: Option<EntropyReport>,
28 pub predictive_churn: Option<PredictiveChurnReport>,
29 pub corporate_fingerprint: Option<CorporateFingerprint>,
30 pub license: Option<LicenseReport>,
31 pub derived: Option<DerivedReport>,
32 pub assets: Option<AssetReport>,
33 pub deps: Option<DependencyReport>,
34 pub git: Option<GitReport>,
35 pub imports: Option<ImportReport>,
36 pub dup: Option<DuplicateReport>,
37 pub fun: Option<FunReport>,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct AnalysisSource {
42 pub inputs: Vec<String>,
43 pub export_path: Option<String>,
44 pub base_receipt_path: Option<String>,
45 pub export_schema_version: Option<u32>,
46 pub export_generated_at_ms: Option<u128>,
47 pub base_signature: Option<String>,
48 pub module_roots: Vec<String>,
49 pub module_depth: usize,
50 pub children: String,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct AnalysisArgsMeta {
55 pub preset: String,
56 pub format: String,
57 pub window_tokens: Option<usize>,
58 pub git: Option<bool>,
59 pub max_files: Option<usize>,
60 pub max_bytes: Option<u64>,
61 pub max_commits: Option<usize>,
62 pub max_commit_files: Option<usize>,
63 pub max_file_bytes: Option<u64>,
64 pub import_granularity: String,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct Archetype {
73 pub kind: String,
74 pub evidence: Vec<String>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct TopicClouds {
83 pub per_module: BTreeMap<String, Vec<TopicTerm>>,
84 pub overall: Vec<TopicTerm>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct TopicTerm {
89 pub term: String,
90 pub score: f64,
91 pub tf: u32,
92 pub df: u32,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct EntropyReport {
101 pub suspects: Vec<EntropyFinding>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct EntropyFinding {
106 pub path: String,
107 pub module: String,
108 pub entropy_bits_per_byte: f32,
109 pub sample_bytes: u32,
110 pub class: EntropyClass,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
114#[serde(rename_all = "snake_case")]
115pub enum EntropyClass {
116 Low,
117 Normal,
118 Suspicious,
119 High,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct PredictiveChurnReport {
128 pub per_module: BTreeMap<String, ChurnTrend>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct ChurnTrend {
133 pub slope: f64,
134 pub r2: f64,
135 pub recent_change: i64,
136 pub classification: TrendClass,
137}
138
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
140#[serde(rename_all = "snake_case")]
141pub enum TrendClass {
142 Rising,
143 Flat,
144 Falling,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct CorporateFingerprint {
153 pub domains: Vec<DomainStat>,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct DomainStat {
158 pub domain: String,
159 pub commits: u32,
160 pub pct: f32,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct LicenseReport {
169 pub findings: Vec<LicenseFinding>,
170 pub effective: Option<String>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct LicenseFinding {
175 pub spdx: String,
176 pub confidence: f32,
177 pub source_path: String,
178 pub source_kind: LicenseSourceKind,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
182#[serde(rename_all = "snake_case")]
183pub enum LicenseSourceKind {
184 Metadata,
185 Text,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct DerivedReport {
194 pub totals: DerivedTotals,
195 pub doc_density: RatioReport,
196 pub whitespace: RatioReport,
197 pub verbosity: RateReport,
198 pub max_file: MaxFileReport,
199 pub lang_purity: LangPurityReport,
200 pub nesting: NestingReport,
201 pub test_density: TestDensityReport,
202 pub boilerplate: BoilerplateReport,
203 pub polyglot: PolyglotReport,
204 pub distribution: DistributionReport,
205 pub histogram: Vec<HistogramBucket>,
206 pub top: TopOffenders,
207 pub tree: Option<String>,
208 pub reading_time: ReadingTimeReport,
209 pub context_window: Option<ContextWindowReport>,
210 pub cocomo: Option<CocomoReport>,
211 pub todo: Option<TodoReport>,
212 pub integrity: IntegrityReport,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct DerivedTotals {
217 pub files: usize,
218 pub code: usize,
219 pub comments: usize,
220 pub blanks: usize,
221 pub lines: usize,
222 pub bytes: usize,
223 pub tokens: usize,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct RatioReport {
228 pub total: RatioRow,
229 pub by_lang: Vec<RatioRow>,
230 pub by_module: Vec<RatioRow>,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct RatioRow {
235 pub key: String,
236 pub numerator: usize,
237 pub denominator: usize,
238 pub ratio: f64,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct RateReport {
243 pub total: RateRow,
244 pub by_lang: Vec<RateRow>,
245 pub by_module: Vec<RateRow>,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct RateRow {
250 pub key: String,
251 pub numerator: usize,
252 pub denominator: usize,
253 pub rate: f64,
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct MaxFileReport {
258 pub overall: FileStatRow,
259 pub by_lang: Vec<MaxFileRow>,
260 pub by_module: Vec<MaxFileRow>,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
264pub struct MaxFileRow {
265 pub key: String,
266 pub file: FileStatRow,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct FileStatRow {
271 pub path: String,
272 pub module: String,
273 pub lang: String,
274 pub code: usize,
275 pub comments: usize,
276 pub blanks: usize,
277 pub lines: usize,
278 pub bytes: usize,
279 pub tokens: usize,
280 pub doc_pct: Option<f64>,
281 pub bytes_per_line: Option<f64>,
282 pub depth: usize,
283}
284
285#[derive(Debug, Clone, Serialize, Deserialize)]
286pub struct LangPurityReport {
287 pub rows: Vec<LangPurityRow>,
288}
289
290#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct LangPurityRow {
292 pub module: String,
293 pub lang_count: usize,
294 pub dominant_lang: String,
295 pub dominant_lines: usize,
296 pub dominant_pct: f64,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct NestingReport {
301 pub max: usize,
302 pub avg: f64,
303 pub by_module: Vec<NestingRow>,
304}
305
306#[derive(Debug, Clone, Serialize, Deserialize)]
307pub struct NestingRow {
308 pub key: String,
309 pub max: usize,
310 pub avg: f64,
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct TestDensityReport {
315 pub test_lines: usize,
316 pub prod_lines: usize,
317 pub test_files: usize,
318 pub prod_files: usize,
319 pub ratio: f64,
320}
321
322#[derive(Debug, Clone, Serialize, Deserialize)]
323pub struct BoilerplateReport {
324 pub infra_lines: usize,
325 pub logic_lines: usize,
326 pub ratio: f64,
327 pub infra_langs: Vec<String>,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct PolyglotReport {
332 pub lang_count: usize,
333 pub entropy: f64,
334 pub dominant_lang: String,
335 pub dominant_lines: usize,
336 pub dominant_pct: f64,
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct DistributionReport {
341 pub count: usize,
342 pub min: usize,
343 pub max: usize,
344 pub mean: f64,
345 pub median: f64,
346 pub p90: f64,
347 pub p99: f64,
348 pub gini: f64,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct HistogramBucket {
353 pub label: String,
354 pub min: usize,
355 pub max: Option<usize>,
356 pub files: usize,
357 pub pct: f64,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct TopOffenders {
362 pub largest_lines: Vec<FileStatRow>,
363 pub largest_tokens: Vec<FileStatRow>,
364 pub largest_bytes: Vec<FileStatRow>,
365 pub least_documented: Vec<FileStatRow>,
366 pub most_dense: Vec<FileStatRow>,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
370pub struct ReadingTimeReport {
371 pub minutes: f64,
372 pub lines_per_minute: usize,
373 pub basis_lines: usize,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct TodoReport {
378 pub total: usize,
379 pub density_per_kloc: f64,
380 pub tags: Vec<TodoTagRow>,
381}
382
383#[derive(Debug, Clone, Serialize, Deserialize)]
384pub struct TodoTagRow {
385 pub tag: String,
386 pub count: usize,
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize)]
390pub struct ContextWindowReport {
391 pub window_tokens: usize,
392 pub total_tokens: usize,
393 pub pct: f64,
394 pub fits: bool,
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
398pub struct CocomoReport {
399 pub mode: String,
400 pub kloc: f64,
401 pub effort_pm: f64,
402 pub duration_months: f64,
403 pub staff: f64,
404 pub a: f64,
405 pub b: f64,
406 pub c: f64,
407 pub d: f64,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize)]
411pub struct IntegrityReport {
412 pub algo: String,
413 pub hash: String,
414 pub entries: usize,
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize)]
422pub struct AssetReport {
423 pub total_files: usize,
424 pub total_bytes: u64,
425 pub categories: Vec<AssetCategoryRow>,
426 pub top_files: Vec<AssetFileRow>,
427}
428
429#[derive(Debug, Clone, Serialize, Deserialize)]
430pub struct AssetCategoryRow {
431 pub category: String,
432 pub files: usize,
433 pub bytes: u64,
434 pub extensions: Vec<String>,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
438pub struct AssetFileRow {
439 pub path: String,
440 pub bytes: u64,
441 pub category: String,
442 pub extension: String,
443}
444
445#[derive(Debug, Clone, Serialize, Deserialize)]
450pub struct DependencyReport {
451 pub total: usize,
452 pub lockfiles: Vec<LockfileReport>,
453}
454
455#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct LockfileReport {
457 pub path: String,
458 pub kind: String,
459 pub dependencies: usize,
460}
461
462#[derive(Debug, Clone, Serialize, Deserialize)]
467pub struct GitReport {
468 pub commits_scanned: usize,
469 pub files_seen: usize,
470 pub hotspots: Vec<HotspotRow>,
471 pub bus_factor: Vec<BusFactorRow>,
472 pub freshness: FreshnessReport,
473 pub coupling: Vec<CouplingRow>,
474}
475
476#[derive(Debug, Clone, Serialize, Deserialize)]
477pub struct HotspotRow {
478 pub path: String,
479 pub commits: usize,
480 pub lines: usize,
481 pub score: usize,
482}
483
484#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct BusFactorRow {
486 pub module: String,
487 pub authors: usize,
488}
489
490#[derive(Debug, Clone, Serialize, Deserialize)]
491pub struct FreshnessReport {
492 pub threshold_days: usize,
493 pub stale_files: usize,
494 pub total_files: usize,
495 pub stale_pct: f64,
496 pub by_module: Vec<ModuleFreshnessRow>,
497}
498
499#[derive(Debug, Clone, Serialize, Deserialize)]
500pub struct ModuleFreshnessRow {
501 pub module: String,
502 pub avg_days: f64,
503 pub p90_days: f64,
504 pub stale_pct: f64,
505}
506
507#[derive(Debug, Clone, Serialize, Deserialize)]
508pub struct CouplingRow {
509 pub left: String,
510 pub right: String,
511 pub count: usize,
512}
513
514#[derive(Debug, Clone, Serialize, Deserialize)]
519pub struct ImportReport {
520 pub granularity: String,
521 pub edges: Vec<ImportEdge>,
522}
523
524#[derive(Debug, Clone, Serialize, Deserialize)]
525pub struct ImportEdge {
526 pub from: String,
527 pub to: String,
528 pub count: usize,
529}
530
531#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct DuplicateReport {
537 pub groups: Vec<DuplicateGroup>,
538 pub wasted_bytes: u64,
539 pub strategy: String,
540}
541
542#[derive(Debug, Clone, Serialize, Deserialize)]
543pub struct DuplicateGroup {
544 pub hash: String,
545 pub bytes: u64,
546 pub files: Vec<String>,
547}
548
549#[derive(Debug, Clone, Serialize, Deserialize)]
554pub struct FunReport {
555 pub eco_label: Option<EcoLabel>,
556}
557
558#[derive(Debug, Clone, Serialize, Deserialize)]
559pub struct EcoLabel {
560 pub score: f64,
561 pub label: String,
562 pub bytes: u64,
563 pub notes: String,
564}