relay_knowledge/application/knowledge/map/
contracts.rs1use serde::Serialize;
4
5use crate::{
6 api::{ApiMetadata, RequestContext},
7 clock::system_now_millis_or_zero,
8 domain::{
9 DirectoryLoadHint, DirectoryUpdateRule, KnowledgeMap, KnowledgeMapHistoryEntry,
10 KnowledgeMapRoute, KnowledgeMapSource, KnowledgeMapSourceKind, KnowledgeMapTopic,
11 RepositoryMapDirectory, RepositoryMapType,
12 },
13};
14
15use super::artifact::{KnowledgeMapArchiveRef, KnowledgeMapHistoryIndexRef};
16
17pub(super) struct MutableKnowledgeMap {
18 pub(super) map_type: RepositoryMapType,
19 pub(super) directories: Vec<RepositoryMapDirectory>,
20 pub(super) map: KnowledgeMap,
21 pub(super) archived_through: u64,
22 pub(super) archive: Option<KnowledgeMapArchiveRef>,
23 pub(super) history_index: Option<KnowledgeMapHistoryIndexRef>,
24 pub(super) requires_publish: bool,
25}
26
27impl MutableKnowledgeMap {
28 pub(super) fn initial(map_type: RepositoryMapType, updated_at: String) -> Self {
29 Self {
30 map: match map_type {
31 RepositoryMapType::Knowledge => KnowledgeMap::initial(updated_at),
32 RepositoryMapType::Codespec => KnowledgeMap::empty(updated_at),
33 },
34 map_type,
35 directories: baseline_directories(map_type),
36 archived_through: 0,
37 archive: None,
38 history_index: None,
39 requires_publish: false,
40 }
41 }
42}
43
44pub(super) fn baseline_directories(map_type: RepositoryMapType) -> Vec<RepositoryMapDirectory> {
45 map_type
46 .required_directories()
47 .iter()
48 .map(|directory| RepositoryMapDirectory {
49 directory: (*directory).to_owned(),
50 purpose: baseline_purpose(map_type, directory).to_owned(),
51 content_scope: vec![format!("{}/{directory}/**", map_type.as_str())],
52 key_files: vec![format!("{}/{directory}/README.md", map_type.as_str())],
53 load_hint: DirectoryLoadHint::OnDemand,
54 relations: Vec::new(),
55 update_rule: DirectoryUpdateRule::Reviewed,
56 })
57 .collect()
58}
59
60fn baseline_purpose(map_type: RepositoryMapType, directory: &str) -> &'static str {
61 match (map_type, directory) {
62 (RepositoryMapType::Codespec, "requirements") => {
63 "Product requirements and acceptance criteria."
64 }
65 (RepositoryMapType::Codespec, "design") => {
66 "Architecture and implementation design records."
67 }
68 (RepositoryMapType::Codespec, "api") => "Public interface and schema contracts.",
69 (RepositoryMapType::Codespec, "test") => "Verification strategy, fixtures, and evidence.",
70 (RepositoryMapType::Codespec, "decisions") => "Durable architecture and product decisions.",
71 (RepositoryMapType::Knowledge, "domain") => "Domain concepts, models, and business rules.",
72 (RepositoryMapType::Knowledge, "guides") => "Task-oriented repository knowledge guides.",
73 (RepositoryMapType::Knowledge, "ops") => "Operational procedures and diagnostics.",
74 (RepositoryMapType::Knowledge, "glossary") => {
75 "Business terminology, aliases, and technical mappings."
76 }
77 (RepositoryMapType::Knowledge, "best-practices") => {
78 "Reviewed engineering and knowledge-management practices."
79 }
80 _ => "Repository navigation knowledge.",
81 }
82}
83
84pub(super) fn metadata(context: &RequestContext) -> ApiMetadata {
85 ApiMetadata::graph_only(context, crate::domain::GraphVersion::ZERO)
86}
87
88pub(super) fn now_stamp() -> String {
89 let seconds = system_now_millis_or_zero() / 1_000;
90 format!("unix:{seconds}")
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
95pub struct KnowledgeMapSourceAddRequest {
96 pub id: String,
97 pub topic: String,
98 pub kind: KnowledgeMapSourceKind,
99 pub uri: String,
100 pub source_scope: Option<String>,
101 pub description: Option<String>,
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
106pub struct KnowledgeMapMutationResponse {
107 pub metadata: ApiMetadata,
108 pub path: String,
109 pub map_type: RepositoryMapType,
110 pub map_version: u64,
111 pub summary: String,
112}
113
114#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
116pub struct KnowledgeMapShowResponse {
117 pub metadata: ApiMetadata,
118 pub path: String,
119 pub map_type: RepositoryMapType,
120 pub map: KnowledgeMapView,
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
125pub struct KnowledgeMapView {
126 pub artifact_schema_version: u16,
127 pub map_version: u64,
128 pub updated_at: String,
129 pub directories: Vec<RepositoryMapDirectory>,
130 pub topics: Vec<KnowledgeMapTopic>,
131 pub sources: Vec<KnowledgeMapSource>,
132 pub routes: Vec<KnowledgeMapRoute>,
133 pub history: KnowledgeMapHistoryWindow,
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
138pub struct KnowledgeMapHistoryWindow {
139 pub archived_through: u64,
140 pub complete: bool,
141 pub recent: Vec<KnowledgeMapHistoryEntry>,
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
146pub struct KnowledgeMapHistoryResponse {
147 pub metadata: ApiMetadata,
148 pub path: String,
149 pub map_type: RepositoryMapType,
150 pub map_version: u64,
151 pub from_version: u64,
152 pub through_version: u64,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub next_from_version: Option<u64>,
155 pub entries: Vec<KnowledgeMapHistoryEntry>,
156}
157
158#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
160pub struct KnowledgeMapRouteResponse {
161 pub metadata: ApiMetadata,
162 pub path: String,
163 pub map_type: RepositoryMapType,
164 pub topic: String,
165 pub route: Option<KnowledgeMapRoute>,
166 pub sources: Vec<KnowledgeMapSource>,
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
171pub struct KnowledgeMapValidationResponse {
172 pub metadata: ApiMetadata,
173 pub path: String,
174 pub map_type: RepositoryMapType,
175 pub valid: bool,
176 pub diagnostics: Vec<String>,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
181pub struct KnowledgeMapAgentSnippetResponse {
182 pub metadata: ApiMetadata,
183 pub snippet: String,
184}