@lamentis/naome 1.3.13 → 1.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +2 -2
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/architecture_commands.rs +1 -1
- package/crates/naome-cli/src/quality_commands.rs +4 -4
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/architecture/config/parser/sections.rs +1 -1
- package/crates/naome-core/src/architecture/config.rs +1 -1
- package/crates/naome-core/src/architecture/model.rs +19 -0
- package/crates/naome-core/src/architecture/output.rs +27 -24
- package/crates/naome-core/src/architecture/rules/budgets.rs +2 -1
- package/crates/naome-core/src/architecture/rules.rs +3 -1
- package/crates/naome-core/src/architecture/scan/cache.rs +145 -0
- package/crates/naome-core/src/architecture/scan/graph_builder.rs +31 -10
- package/crates/naome-core/src/architecture/scan.rs +232 -14
- package/crates/naome-core/src/architecture.rs +3 -3
- package/crates/naome-core/src/intent/legacy.rs +1 -1
- package/crates/naome-core/src/intent/model.rs +27 -0
- package/crates/naome-core/src/intent/resolver.rs +3 -28
- package/crates/naome-core/src/intent/resolver_baseline.rs +1 -2
- package/crates/naome-core/src/intent/resolver_policy.rs +1 -2
- package/crates/naome-core/src/intent.rs +2 -1
- package/crates/naome-core/src/quality/adapter_ios.rs +3 -1
- package/crates/naome-core/src/quality/adapter_support.rs +32 -0
- package/crates/naome-core/src/quality/adapters.rs +8 -25
- package/crates/naome-core/src/quality/analysis_model.rs +33 -0
- package/crates/naome-core/src/quality/cache.rs +1 -1
- package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +2 -1
- package/crates/naome-core/src/quality/checks/near_duplicates.rs +2 -1
- package/crates/naome-core/src/quality/mod.rs +1 -0
- package/crates/naome-core/src/quality/scanner/analysis.rs +1 -1
- package/crates/naome-core/src/quality/scanner.rs +1 -32
- package/crates/naome-core/src/quality/semantic/extract.rs +2 -1
- package/crates/naome-core/src/quality/structure/adapter_ios.rs +1 -1
- package/crates/naome-core/src/quality/structure/adapter_model.rs +23 -0
- package/crates/naome-core/src/quality/structure/adapters.rs +2 -23
- package/crates/naome-core/src/quality/structure/config.rs +2 -1
- package/crates/naome-core/src/quality/structure/defaults.rs +2 -2
- package/crates/naome-core/src/quality/structure/mod.rs +1 -0
- package/crates/naome-core/src/quality/structure/model.rs +6 -6
- package/crates/naome-core/src/repository_model.rs +6 -1
- package/crates/naome-core/src/route/builtin_checks.rs +1 -1
- package/crates/naome-core/src/route/builtin_require.rs +1 -1
- package/crates/naome-core/src/route/execution.rs +2 -34
- package/crates/naome-core/src/route/execution_baselines.rs +1 -1
- package/crates/naome-core/src/route/execution_model.rs +37 -0
- package/crates/naome-core/src/route/execution_support.rs +1 -1
- package/crates/naome-core/src/route/execution_tasks.rs +1 -1
- package/crates/naome-core/src/route/quality_gate.rs +0 -1
- package/crates/naome-core/src/route.rs +3 -1
- package/crates/naome-core/src/task_state/api.rs +5 -4
- package/crates/naome-core/src/task_state/commit_gate.rs +1 -1
- package/crates/naome-core/src/task_state/compact_proof.rs +2 -2
- package/crates/naome-core/src/task_state/completed_refresh.rs +0 -13
- package/crates/naome-core/src/task_state/completion.rs +13 -4
- package/crates/naome-core/src/task_state/mod.rs +1 -1
- package/crates/naome-core/src/task_state/progress.rs +1 -1
- package/crates/naome-core/src/task_state/proof.rs +1 -4
- package/crates/naome-core/src/task_state/proof_entry.rs +1 -1
- package/crates/naome-core/src/task_state/proof_model.rs +2 -18
- package/crates/naome-core/src/task_state/proof_sources.rs +2 -2
- package/crates/naome-core/src/task_state/proof_types.rs +17 -0
- package/crates/naome-core/src/task_state/shape.rs +1 -1
- package/crates/naome-core/src/task_state/task_diff_api.rs +1 -1
- package/crates/naome-core/src/verification_contract_policy.rs +2 -6
- package/crates/naome-core/src/workflow/agent/proof.rs +1 -1
- package/crates/naome-core/src/workflow/agent.rs +1 -1
- package/crates/naome-core/src/workflow/mod.rs +3 -1
- package/crates/naome-core/src/workflow/phase_inference.rs +1 -1
- package/crates/naome-core/src/workflow/phase_model.rs +22 -0
- package/crates/naome-core/src/workflow/phases.rs +1 -21
- package/crates/naome-core/tests/architecture_cache.rs +212 -0
- package/native/darwin-arm64/naome +0 -0
- package/native/linux-x64/naome +0 -0
- package/package.json +1 -1
- package/templates/naome-root/.naome/manifest.json +1 -1
- package/templates/naome-root/docs/naome/architecture-fitness.md +29 -8
- package/crates/naome-core/src/task_state/reconcile.rs +0 -7
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
use std::collections::BTreeMap;
|
|
2
2
|
use std::path::{Path, PathBuf};
|
|
3
3
|
|
|
4
|
-
use serde::Serialize;
|
|
4
|
+
use serde::{Deserialize, Serialize};
|
|
5
5
|
|
|
6
6
|
use crate::git;
|
|
7
7
|
use crate::models::NaomeError;
|
|
8
8
|
|
|
9
|
-
use
|
|
9
|
+
use cache::CacheStatus;
|
|
10
|
+
|
|
11
|
+
use super::config::{
|
|
12
|
+
default_architecture_config_text, read_architecture_config, ArchitectureConfig,
|
|
13
|
+
};
|
|
10
14
|
use super::model::ArchitectureGraph;
|
|
11
15
|
|
|
16
|
+
mod cache;
|
|
12
17
|
mod graph_builder;
|
|
13
18
|
mod imports;
|
|
14
19
|
mod manifest;
|
|
@@ -28,6 +33,8 @@ pub struct ArchitectureScanReport {
|
|
|
28
33
|
pub files_scanned: usize,
|
|
29
34
|
pub changed_only_requested: bool,
|
|
30
35
|
pub changed_only_degraded_to_full_scan: bool,
|
|
36
|
+
pub changed_only_mode: String,
|
|
37
|
+
pub changed_only_degradation_reason: Option<String>,
|
|
31
38
|
pub changed_paths: Vec<String>,
|
|
32
39
|
#[serde(skip_serializing)]
|
|
33
40
|
pub config: ArchitectureConfig,
|
|
@@ -37,7 +44,7 @@ pub struct ArchitectureScanReport {
|
|
|
37
44
|
pub manifest_facts: Vec<ManifestFact>,
|
|
38
45
|
}
|
|
39
46
|
|
|
40
|
-
#[derive(Debug, Clone, Serialize)]
|
|
47
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
41
48
|
#[serde(rename_all = "camelCase")]
|
|
42
49
|
pub struct FileFact {
|
|
43
50
|
pub path: String,
|
|
@@ -49,7 +56,7 @@ pub struct FileFact {
|
|
|
49
56
|
pub imports: Vec<ImportFact>,
|
|
50
57
|
}
|
|
51
58
|
|
|
52
|
-
#[derive(Debug, Clone, Serialize)]
|
|
59
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
53
60
|
#[serde(rename_all = "camelCase")]
|
|
54
61
|
pub struct ImportFact {
|
|
55
62
|
pub specifier: String,
|
|
@@ -59,7 +66,7 @@ pub struct ImportFact {
|
|
|
59
66
|
pub extractor: String,
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
|
|
69
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
63
70
|
#[serde(rename_all = "camelCase")]
|
|
64
71
|
pub enum ImportTarget {
|
|
65
72
|
File(String),
|
|
@@ -67,7 +74,7 @@ pub enum ImportTarget {
|
|
|
67
74
|
Unknown(String),
|
|
68
75
|
}
|
|
69
76
|
|
|
70
|
-
#[derive(Debug, Clone, Serialize)]
|
|
77
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
71
78
|
#[serde(rename_all = "camelCase")]
|
|
72
79
|
pub struct ManifestFact {
|
|
73
80
|
pub path: String,
|
|
@@ -78,7 +85,7 @@ pub struct ManifestFact {
|
|
|
78
85
|
pub extractor: String,
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
#[derive(Debug, Clone, Serialize)]
|
|
88
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
82
89
|
#[serde(rename_all = "camelCase")]
|
|
83
90
|
pub struct ManifestDependency {
|
|
84
91
|
pub name: String,
|
|
@@ -94,24 +101,235 @@ pub fn scan_architecture(
|
|
|
94
101
|
let config = read_architecture_config(root, options.config_path.as_deref())?;
|
|
95
102
|
let changed_paths = changed_paths(root, options.changed_only)?;
|
|
96
103
|
let files = path_scan::repository_files(root, &config)?;
|
|
104
|
+
let config_hash = cache::config_hash(
|
|
105
|
+
root,
|
|
106
|
+
options.config_path.as_deref(),
|
|
107
|
+
default_architecture_config_text(),
|
|
108
|
+
)?;
|
|
109
|
+
let file_list_hash = cache::file_list_hash(&files);
|
|
97
110
|
let manifest_facts = manifest::extract_manifests(root, &files);
|
|
98
|
-
let (mut graph, file_facts) =
|
|
99
|
-
graph_builder::build_path_graph(root, files, &config, &manifest_facts);
|
|
100
111
|
|
|
112
|
+
let scan = if options.changed_only {
|
|
113
|
+
changed_only_scan(
|
|
114
|
+
root,
|
|
115
|
+
files,
|
|
116
|
+
&config,
|
|
117
|
+
&manifest_facts,
|
|
118
|
+
&changed_paths,
|
|
119
|
+
config_hash,
|
|
120
|
+
file_list_hash,
|
|
121
|
+
)?
|
|
122
|
+
} else {
|
|
123
|
+
full_scan(
|
|
124
|
+
root,
|
|
125
|
+
files,
|
|
126
|
+
&config,
|
|
127
|
+
&manifest_facts,
|
|
128
|
+
config_hash,
|
|
129
|
+
file_list_hash,
|
|
130
|
+
false,
|
|
131
|
+
None,
|
|
132
|
+
"full_scan",
|
|
133
|
+
)?
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
Ok(scan.with_changed_paths(changed_paths))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fn changed_only_scan(
|
|
140
|
+
root: &Path,
|
|
141
|
+
files: Vec<String>,
|
|
142
|
+
config: &ArchitectureConfig,
|
|
143
|
+
manifest_facts: &[ManifestFact],
|
|
144
|
+
changed_paths: &[String],
|
|
145
|
+
config_hash: String,
|
|
146
|
+
file_list_hash: String,
|
|
147
|
+
) -> Result<ArchitectureScanReport, NaomeError> {
|
|
148
|
+
let Some(cache) = cache::read(root) else {
|
|
149
|
+
return degraded_full_scan(
|
|
150
|
+
root,
|
|
151
|
+
files,
|
|
152
|
+
config,
|
|
153
|
+
manifest_facts,
|
|
154
|
+
config_hash,
|
|
155
|
+
file_list_hash,
|
|
156
|
+
"cache_miss",
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
match cache.is_compatible(&config_hash, &file_list_hash) {
|
|
160
|
+
CacheStatus::Miss(reason) => degraded_full_scan(
|
|
161
|
+
root,
|
|
162
|
+
files,
|
|
163
|
+
config,
|
|
164
|
+
manifest_facts,
|
|
165
|
+
config_hash,
|
|
166
|
+
file_list_hash,
|
|
167
|
+
reason,
|
|
168
|
+
),
|
|
169
|
+
CacheStatus::Hit => incremental_scan(
|
|
170
|
+
root,
|
|
171
|
+
files,
|
|
172
|
+
config,
|
|
173
|
+
manifest_facts,
|
|
174
|
+
changed_paths,
|
|
175
|
+
config_hash,
|
|
176
|
+
file_list_hash,
|
|
177
|
+
cache,
|
|
178
|
+
),
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fn incremental_scan(
|
|
183
|
+
root: &Path,
|
|
184
|
+
files: Vec<String>,
|
|
185
|
+
config: &ArchitectureConfig,
|
|
186
|
+
manifest_facts: &[ManifestFact],
|
|
187
|
+
changed_paths: &[String],
|
|
188
|
+
config_hash: String,
|
|
189
|
+
file_list_hash: String,
|
|
190
|
+
cache: cache::ArchitectureCache,
|
|
191
|
+
) -> Result<ArchitectureScanReport, NaomeError> {
|
|
192
|
+
let file_set = files.iter().cloned().collect();
|
|
193
|
+
let changed = cache::changed_set(changed_paths);
|
|
194
|
+
if import_resolver_context_changed(changed_paths) {
|
|
195
|
+
return degraded_full_scan(
|
|
196
|
+
root,
|
|
197
|
+
files,
|
|
198
|
+
config,
|
|
199
|
+
manifest_facts,
|
|
200
|
+
config_hash,
|
|
201
|
+
file_list_hash,
|
|
202
|
+
"resolver_context_changed",
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
if cached_clean_content_changed(root, &files, &changed, &cache) {
|
|
206
|
+
return degraded_full_scan(
|
|
207
|
+
root,
|
|
208
|
+
files,
|
|
209
|
+
config,
|
|
210
|
+
manifest_facts,
|
|
211
|
+
config_hash,
|
|
212
|
+
file_list_hash,
|
|
213
|
+
"content_changed",
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
let mut file_facts = BTreeMap::new();
|
|
217
|
+
let mut scanned = 0;
|
|
218
|
+
|
|
219
|
+
for path in &files {
|
|
220
|
+
if changed.contains(path) || !cache.files.contains_key(path) {
|
|
221
|
+
let fact = graph_builder::scan_file_fact(root, path, config, &file_set);
|
|
222
|
+
scanned += 1;
|
|
223
|
+
file_facts.insert(path.clone(), fact);
|
|
224
|
+
} else if let Some(cached) = cache.files.get(path) {
|
|
225
|
+
file_facts.insert(path.clone(), cached.fact.clone());
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let mut graph =
|
|
230
|
+
graph_builder::build_graph_from_facts(&files, &file_facts, config, manifest_facts);
|
|
101
231
|
graph.sort_stable();
|
|
232
|
+
let _ = cache::write(root, config_hash, file_list_hash, &file_facts);
|
|
102
233
|
Ok(ArchitectureScanReport {
|
|
103
234
|
schema: "naome.arch.scan.v1".to_string(),
|
|
104
|
-
files_scanned:
|
|
235
|
+
files_scanned: scanned,
|
|
105
236
|
graph,
|
|
106
|
-
changed_only_requested:
|
|
107
|
-
changed_only_degraded_to_full_scan:
|
|
108
|
-
|
|
109
|
-
|
|
237
|
+
changed_only_requested: true,
|
|
238
|
+
changed_only_degraded_to_full_scan: false,
|
|
239
|
+
changed_only_mode: "incremental_cache".to_string(),
|
|
240
|
+
changed_only_degradation_reason: None,
|
|
241
|
+
changed_paths: Vec::new(),
|
|
242
|
+
config: config.clone(),
|
|
110
243
|
file_facts,
|
|
244
|
+
manifest_facts: manifest_facts.to_vec(),
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
fn cached_clean_content_changed(
|
|
249
|
+
root: &Path,
|
|
250
|
+
files: &[String],
|
|
251
|
+
changed: &std::collections::BTreeSet<String>,
|
|
252
|
+
cache: &cache::ArchitectureCache,
|
|
253
|
+
) -> bool {
|
|
254
|
+
files.iter().any(|path| {
|
|
255
|
+
!changed.contains(path)
|
|
256
|
+
&& cache.files.get(path).is_some_and(|cached| {
|
|
257
|
+
cache::content_hash(root, path)
|
|
258
|
+
.map(|current| current != cached.content_hash)
|
|
259
|
+
.unwrap_or(true)
|
|
260
|
+
})
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
fn import_resolver_context_changed(changed_paths: &[String]) -> bool {
|
|
265
|
+
changed_paths.iter().any(|path| {
|
|
266
|
+
Path::new(path)
|
|
267
|
+
.file_name()
|
|
268
|
+
.and_then(|value| value.to_str())
|
|
269
|
+
.is_some_and(|name| matches!(name, "go.mod" | "tsconfig.json" | "jsconfig.json"))
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
fn degraded_full_scan(
|
|
274
|
+
root: &Path,
|
|
275
|
+
files: Vec<String>,
|
|
276
|
+
config: &ArchitectureConfig,
|
|
277
|
+
manifest_facts: &[ManifestFact],
|
|
278
|
+
config_hash: String,
|
|
279
|
+
file_list_hash: String,
|
|
280
|
+
reason: &'static str,
|
|
281
|
+
) -> Result<ArchitectureScanReport, NaomeError> {
|
|
282
|
+
full_scan(
|
|
283
|
+
root,
|
|
284
|
+
files,
|
|
285
|
+
config,
|
|
111
286
|
manifest_facts,
|
|
287
|
+
config_hash,
|
|
288
|
+
file_list_hash,
|
|
289
|
+
true,
|
|
290
|
+
Some(reason),
|
|
291
|
+
"degraded_full_scan",
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
fn full_scan(
|
|
296
|
+
root: &Path,
|
|
297
|
+
files: Vec<String>,
|
|
298
|
+
config: &ArchitectureConfig,
|
|
299
|
+
manifest_facts: &[ManifestFact],
|
|
300
|
+
config_hash: String,
|
|
301
|
+
file_list_hash: String,
|
|
302
|
+
changed_only_degraded_to_full_scan: bool,
|
|
303
|
+
changed_only_degradation_reason: Option<&str>,
|
|
304
|
+
changed_only_mode: &str,
|
|
305
|
+
) -> Result<ArchitectureScanReport, NaomeError> {
|
|
306
|
+
let (mut graph, file_facts) =
|
|
307
|
+
graph_builder::build_path_graph(root, files, config, manifest_facts);
|
|
308
|
+
graph.sort_stable();
|
|
309
|
+
let files_scanned = file_facts.len();
|
|
310
|
+
let _ = cache::write(root, config_hash, file_list_hash, &file_facts);
|
|
311
|
+
Ok(ArchitectureScanReport {
|
|
312
|
+
schema: "naome.arch.scan.v1".to_string(),
|
|
313
|
+
files_scanned,
|
|
314
|
+
graph,
|
|
315
|
+
changed_only_requested: changed_only_degraded_to_full_scan,
|
|
316
|
+
changed_only_degraded_to_full_scan,
|
|
317
|
+
changed_only_mode: changed_only_mode.to_string(),
|
|
318
|
+
changed_only_degradation_reason: changed_only_degradation_reason.map(str::to_string),
|
|
319
|
+
changed_paths: Vec::new(),
|
|
320
|
+
config: config.clone(),
|
|
321
|
+
file_facts,
|
|
322
|
+
manifest_facts: manifest_facts.to_vec(),
|
|
112
323
|
})
|
|
113
324
|
}
|
|
114
325
|
|
|
326
|
+
impl ArchitectureScanReport {
|
|
327
|
+
fn with_changed_paths(mut self, changed_paths: Vec<String>) -> Self {
|
|
328
|
+
self.changed_paths = changed_paths;
|
|
329
|
+
self
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
115
333
|
fn changed_paths(root: &Path, changed_only: bool) -> Result<Vec<String>, NaomeError> {
|
|
116
334
|
if changed_only {
|
|
117
335
|
git::changed_paths(root)
|
|
@@ -13,12 +13,12 @@ pub use config::{
|
|
|
13
13
|
};
|
|
14
14
|
pub use model::{
|
|
15
15
|
ArchitectureEdge, ArchitectureEdgeKind, ArchitectureGraph, ArchitectureMetadata,
|
|
16
|
-
ArchitectureNode, ArchitectureNodeKind, SourceRange,
|
|
16
|
+
ArchitectureNode, ArchitectureNodeKind, Severity, SourceRange,
|
|
17
17
|
};
|
|
18
18
|
pub use output::{
|
|
19
19
|
format_architecture_explain, format_architecture_scan, format_architecture_validation,
|
|
20
|
-
ArchitectureAgentFeedback, ArchitectureValidation, ArchitectureViolation,
|
|
21
|
-
|
|
20
|
+
ArchitectureAgentFeedback, ArchitectureValidation, ArchitectureViolation, ViolationSummary,
|
|
21
|
+
ARCHITECTURE_RULE_IDS,
|
|
22
22
|
};
|
|
23
23
|
pub use scan::{scan_architecture, ArchitectureScanOptions, ArchitectureScanReport};
|
|
24
24
|
|
|
@@ -4,8 +4,8 @@ use crate::models::Decision;
|
|
|
4
4
|
|
|
5
5
|
use super::classifier::{has_candidate, winning_intent};
|
|
6
6
|
use super::legacy_response::response_policy;
|
|
7
|
+
use super::model::ResolvedIntent;
|
|
7
8
|
use super::model::{CanonicalIntent, IntentKind};
|
|
8
|
-
use super::resolver::ResolvedIntent;
|
|
9
9
|
|
|
10
10
|
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
|
|
11
11
|
#[serde(rename_all = "camelCase")]
|
|
@@ -75,3 +75,30 @@ pub(crate) struct CanonicalIntent {
|
|
|
75
75
|
pub has_workflow_conflict: bool,
|
|
76
76
|
pub validation_errors: Vec<String>,
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
80
|
+
pub(crate) enum CompletedTaskReadiness {
|
|
81
|
+
Valid,
|
|
82
|
+
ValidAfterHarnessRefresh,
|
|
83
|
+
ValidWithUnrelatedDirty,
|
|
84
|
+
Invalid,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
88
|
+
pub(crate) enum DirtyDiffReadiness {
|
|
89
|
+
Unclassified,
|
|
90
|
+
HarnessRefreshOnly,
|
|
91
|
+
HarnessRefreshWithUnrelatedDirty,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
95
|
+
pub(crate) struct ResolvedIntent {
|
|
96
|
+
pub prompt_intent: IntentKind,
|
|
97
|
+
pub certainty: String,
|
|
98
|
+
pub policy_action: String,
|
|
99
|
+
pub allowed: bool,
|
|
100
|
+
pub summary: String,
|
|
101
|
+
pub next_action: String,
|
|
102
|
+
pub reason_codes: Vec<String>,
|
|
103
|
+
pub risk_codes: Vec<String>,
|
|
104
|
+
}
|
|
@@ -1,37 +1,12 @@
|
|
|
1
1
|
use crate::models::Decision;
|
|
2
2
|
|
|
3
3
|
use super::classifier::winning_intent;
|
|
4
|
-
use super::model::{
|
|
4
|
+
use super::model::{
|
|
5
|
+
CanonicalIntent, CompletedTaskReadiness, DirtyDiffReadiness, IntentKind, ResolvedIntent,
|
|
6
|
+
};
|
|
5
7
|
use super::resolver_policy::state_policy;
|
|
6
8
|
use super::resolver_shared::{ambiguous_conflict, ambiguous_empty, unsafe_policy, Policy};
|
|
7
9
|
|
|
8
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
9
|
-
pub(crate) enum CompletedTaskReadiness {
|
|
10
|
-
Valid,
|
|
11
|
-
ValidAfterHarnessRefresh,
|
|
12
|
-
ValidWithUnrelatedDirty,
|
|
13
|
-
Invalid,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
17
|
-
pub(crate) enum DirtyDiffReadiness {
|
|
18
|
-
Unclassified,
|
|
19
|
-
HarnessRefreshOnly,
|
|
20
|
-
HarnessRefreshWithUnrelatedDirty,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
24
|
-
pub(crate) struct ResolvedIntent {
|
|
25
|
-
pub prompt_intent: IntentKind,
|
|
26
|
-
pub certainty: String,
|
|
27
|
-
pub policy_action: String,
|
|
28
|
-
pub allowed: bool,
|
|
29
|
-
pub summary: String,
|
|
30
|
-
pub next_action: String,
|
|
31
|
-
pub reason_codes: Vec<String>,
|
|
32
|
-
pub risk_codes: Vec<String>,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
10
|
pub(crate) fn resolve_intent(
|
|
36
11
|
decision: &Decision,
|
|
37
12
|
canonical: &CanonicalIntent,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
use super::model::IntentKind;
|
|
2
|
-
use super::resolver::DirtyDiffReadiness;
|
|
1
|
+
use super::model::{DirtyDiffReadiness, IntentKind};
|
|
3
2
|
use super::resolver_catalog::{
|
|
4
3
|
POLICY_BASELINE_BLOCK, POLICY_BASELINE_CANCEL, POLICY_BASELINE_COMMIT_UPGRADE,
|
|
5
4
|
POLICY_BASELINE_NEW_REFRESH, POLICY_BASELINE_NEW_UPGRADE, POLICY_BASELINE_NO_COMMIT,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
use crate::models::Decision;
|
|
2
2
|
|
|
3
|
-
use super::model::IntentKind;
|
|
4
|
-
use super::resolver::{CompletedTaskReadiness, DirtyDiffReadiness};
|
|
3
|
+
use super::model::{CompletedTaskReadiness, DirtyDiffReadiness, IntentKind};
|
|
5
4
|
use super::resolver_active::active_policy;
|
|
6
5
|
use super::resolver_baseline::{baseline_policy, dirty_policy};
|
|
7
6
|
use super::resolver_catalog::{
|
|
@@ -24,7 +24,8 @@ use crate::task_state::{
|
|
|
24
24
|
use classifier::canonical_intent;
|
|
25
25
|
pub(crate) use envelope::prompt_envelope_json;
|
|
26
26
|
pub use legacy::{format_intent, IntentDecision, PromptEvidence};
|
|
27
|
-
use
|
|
27
|
+
use model::{CompletedTaskReadiness, DirtyDiffReadiness};
|
|
28
|
+
use resolver::resolve_intent;
|
|
28
29
|
|
|
29
30
|
pub fn evaluate_intent(
|
|
30
31
|
root: &Path,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
use super::
|
|
1
|
+
use super::adapter_support::{
|
|
2
|
+
quality_path_rule as path_rule, quality_test_file_limits as test_file_limits,
|
|
3
|
+
};
|
|
2
4
|
use super::types::{QualityLimitOverrides, QualityPathRule};
|
|
3
5
|
|
|
4
6
|
pub(super) fn swift_path_rules() -> Vec<QualityPathRule> {
|
|
@@ -2,6 +2,8 @@ use std::collections::HashSet;
|
|
|
2
2
|
|
|
3
3
|
use crate::models::NaomeError;
|
|
4
4
|
|
|
5
|
+
use super::types::{QualityLimitOverrides, QualityPathRule};
|
|
6
|
+
|
|
5
7
|
pub(crate) struct RepoSignals<'a> {
|
|
6
8
|
paths: &'a [String],
|
|
7
9
|
}
|
|
@@ -98,6 +100,36 @@ pub(crate) fn extend_unique(target: &mut Vec<String>, values: &[&str]) {
|
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
|
|
103
|
+
pub(crate) fn quality_test_file_limits(max_top_level_symbols: usize) -> QualityLimitOverrides {
|
|
104
|
+
QualityLimitOverrides {
|
|
105
|
+
max_file_lines: Some(650),
|
|
106
|
+
max_diff_added_lines: Some(220),
|
|
107
|
+
max_function_lines: Some(140),
|
|
108
|
+
max_top_level_symbols: Some(max_top_level_symbols),
|
|
109
|
+
duplicate_block_lines: Some(14),
|
|
110
|
+
near_duplicate_similarity: Some(0.96),
|
|
111
|
+
..QualityLimitOverrides::default()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
pub(crate) fn quality_path_rule(
|
|
116
|
+
id: &str,
|
|
117
|
+
paths: &[&str],
|
|
118
|
+
limits: QualityLimitOverrides,
|
|
119
|
+
disabled_checks: &[&str],
|
|
120
|
+
) -> QualityPathRule {
|
|
121
|
+
QualityPathRule {
|
|
122
|
+
id: id.to_string(),
|
|
123
|
+
paths: string_list(paths),
|
|
124
|
+
limits,
|
|
125
|
+
disabled_checks: string_list(disabled_checks),
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fn string_list(values: &[&str]) -> Vec<String> {
|
|
130
|
+
values.iter().map(|value| (*value).to_string()).collect()
|
|
131
|
+
}
|
|
132
|
+
|
|
101
133
|
pub(crate) fn detects_rust_project(signals: &RepoSignals<'_>) -> bool {
|
|
102
134
|
signals.has_manifest("Cargo.toml") || signals.has_extension(&[".rs"])
|
|
103
135
|
}
|
|
@@ -5,10 +5,10 @@ use super::adapter_support::{
|
|
|
5
5
|
detected_ids, detects_generated_ios_project, detects_ios_app_structure_project,
|
|
6
6
|
detects_ios_resources_project, detects_javascript_typescript_project, detects_rust_project,
|
|
7
7
|
detects_swift_package_project, detects_swift_project, detects_swiftui_project,
|
|
8
|
-
detects_xcode_project, detects_xctest_project, extend_unique, find_adapter_by_id,
|
|
9
|
-
AdapterDescriptor, RepoSignals,
|
|
8
|
+
detects_xcode_project, detects_xctest_project, extend_unique, find_adapter_by_id,
|
|
9
|
+
quality_path_rule, quality_test_file_limits, validate_ids, AdapterDescriptor, RepoSignals,
|
|
10
10
|
};
|
|
11
|
-
use super::types::{
|
|
11
|
+
use super::types::{QualityPathRule, RepositoryQualityConfig};
|
|
12
12
|
|
|
13
13
|
const CONFIG_PATH: &str = ".naome/repository-quality.json";
|
|
14
14
|
|
|
@@ -163,32 +163,15 @@ fn javascript_typescript_test_paths() -> Vec<String> {
|
|
|
163
163
|
paths
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
max_file_lines: Some(650),
|
|
169
|
-
max_diff_added_lines: Some(220),
|
|
170
|
-
max_function_lines: Some(140),
|
|
171
|
-
max_top_level_symbols: Some(max_top_level_symbols),
|
|
172
|
-
duplicate_block_lines: Some(14),
|
|
173
|
-
near_duplicate_similarity: Some(0.96),
|
|
174
|
-
..QualityLimitOverrides::default()
|
|
175
|
-
}
|
|
166
|
+
fn test_file_limits(max_top_level_symbols: usize) -> super::types::QualityLimitOverrides {
|
|
167
|
+
quality_test_file_limits(max_top_level_symbols)
|
|
176
168
|
}
|
|
177
169
|
|
|
178
|
-
|
|
170
|
+
fn path_rule(
|
|
179
171
|
id: &str,
|
|
180
172
|
paths: &[&str],
|
|
181
|
-
limits: QualityLimitOverrides,
|
|
173
|
+
limits: super::types::QualityLimitOverrides,
|
|
182
174
|
disabled_checks: &[&str],
|
|
183
175
|
) -> QualityPathRule {
|
|
184
|
-
|
|
185
|
-
id: id.to_string(),
|
|
186
|
-
paths: string_list(paths),
|
|
187
|
-
limits,
|
|
188
|
-
disabled_checks: string_list(disabled_checks),
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
fn string_list(values: &[&str]) -> Vec<String> {
|
|
193
|
-
values.iter().map(|value| (*value).to_string()).collect()
|
|
176
|
+
quality_path_rule(id, paths, limits, disabled_checks)
|
|
194
177
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
use std::collections::HashSet;
|
|
2
|
+
|
|
3
|
+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
4
|
+
pub struct FileAnalysis {
|
|
5
|
+
pub path: String,
|
|
6
|
+
pub line_count: usize,
|
|
7
|
+
pub added_lines: usize,
|
|
8
|
+
pub raw_lines: Vec<String>,
|
|
9
|
+
pub normalized_lines: Vec<NormalizedLine>,
|
|
10
|
+
pub symbols: Vec<SymbolAnalysis>,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
14
|
+
pub struct NormalizedLine {
|
|
15
|
+
pub line_number: usize,
|
|
16
|
+
pub value: String,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
20
|
+
pub struct SymbolAnalysis {
|
|
21
|
+
pub kind: String,
|
|
22
|
+
pub name: String,
|
|
23
|
+
pub start_line: usize,
|
|
24
|
+
pub end_line: usize,
|
|
25
|
+
pub indent: usize,
|
|
26
|
+
pub tokens: HashSet<String>,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
impl SymbolAnalysis {
|
|
30
|
+
pub fn line_count(&self) -> usize {
|
|
31
|
+
self.end_line.saturating_sub(self.start_line) + 1
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -2,7 +2,8 @@ use std::collections::{HashMap, HashSet};
|
|
|
2
2
|
|
|
3
3
|
use sha2::{Digest, Sha256};
|
|
4
4
|
|
|
5
|
-
use super::super::
|
|
5
|
+
use super::super::analysis_model::NormalizedLine;
|
|
6
|
+
use super::super::scanner::{stable_fingerprint, QualityContext};
|
|
6
7
|
use super::super::types::QualityViolation;
|
|
7
8
|
use super::{is_code_like_path, QualityCheck};
|
|
8
9
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use std::collections::HashSet;
|
|
2
2
|
|
|
3
|
-
use super::super::
|
|
3
|
+
use super::super::analysis_model::{FileAnalysis, SymbolAnalysis};
|
|
4
|
+
use super::super::scanner::QualityContext;
|
|
4
5
|
use super::super::types::QualityViolation;
|
|
5
6
|
use super::{is_code_like_path, violation, QualityCheck};
|
|
6
7
|
|
|
@@ -4,7 +4,7 @@ use std::collections::{HashMap, HashSet};
|
|
|
4
4
|
use std::fs;
|
|
5
5
|
use std::path::Path;
|
|
6
6
|
|
|
7
|
-
use
|
|
7
|
+
use crate::quality::analysis_model::{FileAnalysis, NormalizedLine, SymbolAnalysis};
|
|
8
8
|
use crate::quality::cache::{content_hash, QualityCache};
|
|
9
9
|
use normalize::{normalize_line, token_set};
|
|
10
10
|
|
|
@@ -11,6 +11,7 @@ use crate::{git, models::NaomeError, paths};
|
|
|
11
11
|
pub(crate) use repo_paths::collect_repo_paths;
|
|
12
12
|
use repo_paths::{added_lines_by_path, regular_repo_file_path, tracked_blob_hashes};
|
|
13
13
|
|
|
14
|
+
use super::analysis_model::FileAnalysis;
|
|
14
15
|
use super::cache::QualityCache;
|
|
15
16
|
use super::types::{
|
|
16
17
|
default_generated_paths, default_ignored_paths, QualityLimits, QualityMode,
|
|
@@ -55,38 +56,6 @@ impl QualityContext {
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
59
|
-
pub struct FileAnalysis {
|
|
60
|
-
pub path: String,
|
|
61
|
-
pub line_count: usize,
|
|
62
|
-
pub added_lines: usize,
|
|
63
|
-
pub raw_lines: Vec<String>,
|
|
64
|
-
pub normalized_lines: Vec<NormalizedLine>,
|
|
65
|
-
pub symbols: Vec<SymbolAnalysis>,
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
69
|
-
pub struct NormalizedLine {
|
|
70
|
-
pub line_number: usize,
|
|
71
|
-
pub value: String,
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
75
|
-
pub struct SymbolAnalysis {
|
|
76
|
-
pub kind: String,
|
|
77
|
-
pub name: String,
|
|
78
|
-
pub start_line: usize,
|
|
79
|
-
pub end_line: usize,
|
|
80
|
-
pub indent: usize,
|
|
81
|
-
pub tokens: HashSet<String>,
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
impl SymbolAnalysis {
|
|
85
|
-
pub fn line_count(&self) -> usize {
|
|
86
|
-
self.end_line.saturating_sub(self.start_line) + 1
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
59
|
pub fn scan_repository(
|
|
91
60
|
root: &Path,
|
|
92
61
|
mode: QualityMode,
|