foundry_mcp/types/
spec.rs1use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5
6use crate::core::backends::ResourceLocator;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct SpecContentData {
11 pub spec: String,
12 pub notes: String,
13 pub tasks: String,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Spec {
19 pub name: String,
20 pub created_at: String,
21 pub path: PathBuf, pub project_name: String,
23
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub location_hint: Option<String>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub locator: Option<ResourceLocator>,
29
30 pub content: SpecContentData,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct SpecConfig {
37 pub project_name: String,
38 pub feature_name: String,
39 pub content: SpecContentData,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct SpecMetadata {
45 pub name: String,
46 pub created_at: String,
47 pub feature_name: String,
48 pub project_name: String,
49}
50
51#[derive(Debug, Clone, Default, Serialize, Deserialize)]
53pub struct SpecFilter {
54 pub feature_name_contains: Option<String>,
55 pub created_after: Option<String>,
56 pub created_before: Option<String>,
57 pub limit: Option<usize>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(rename_all = "lowercase")]
63pub enum SpecFileType {
64 Spec,
65 Notes,
66 TaskList,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct ContentValidationStatus {
72 pub spec_valid: bool,
73 pub notes_valid: bool,
74 pub task_list_valid: bool,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct SpecValidationResult {
80 pub spec_name: String,
81 pub project_name: String,
82 pub spec_file_exists: bool,
83 pub notes_file_exists: bool,
84 pub task_list_file_exists: bool,
85 pub content_validation: ContentValidationStatus,
86 pub validation_errors: Vec<String>,
87}
88
89impl SpecValidationResult {
90 pub fn is_valid(&self) -> bool {
92 self.spec_file_exists
93 && self.notes_file_exists
94 && self.task_list_file_exists
95 && self.content_validation.spec_valid
96 && self.content_validation.notes_valid
97 && self.content_validation.task_list_valid
98 && self.validation_errors.is_empty()
99 }
100
101 pub fn summary(&self) -> String {
103 if self.is_valid() {
104 "Spec is valid".to_string()
105 } else {
106 format!(
107 "Spec validation failed: {} errors",
108 self.validation_errors.len()
109 )
110 }
111 }
112}