@lamentis/naome 1.4.3 → 1.4.4
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/task_commands/agent_snapshot.rs +68 -10
- package/crates/naome-cli/tests/task_cli_fast_flow.rs +43 -1
- package/crates/naome-core/Cargo.toml +1 -1
- package/native/darwin-arm64/naome +0 -0
- package/native/linux-x64/naome +0 -0
- package/package.json +1 -1
package/Cargo.lock
CHANGED
|
@@ -76,7 +76,7 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
|
76
76
|
|
|
77
77
|
[[package]]
|
|
78
78
|
name = "naome-cli"
|
|
79
|
-
version = "1.4.
|
|
79
|
+
version = "1.4.4"
|
|
80
80
|
dependencies = [
|
|
81
81
|
"naome-core",
|
|
82
82
|
"serde_json",
|
|
@@ -84,7 +84,7 @@ dependencies = [
|
|
|
84
84
|
|
|
85
85
|
[[package]]
|
|
86
86
|
name = "naome-core"
|
|
87
|
-
version = "1.4.
|
|
87
|
+
version = "1.4.4"
|
|
88
88
|
dependencies = [
|
|
89
89
|
"serde",
|
|
90
90
|
"serde_json",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use std::collections::{BTreeMap, BTreeSet};
|
|
1
2
|
use std::path::Path;
|
|
2
3
|
|
|
3
4
|
use naome_core::{
|
|
@@ -77,23 +78,80 @@ pub(super) fn agent_snapshot(
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
fn merge_commands(left: Value, right: Vec<Value>) -> Vec<Value> {
|
|
80
|
-
let
|
|
81
|
+
let commands = left
|
|
81
82
|
.as_array()
|
|
82
83
|
.cloned()
|
|
83
84
|
.unwrap_or_default()
|
|
84
85
|
.into_iter()
|
|
85
86
|
.chain(right)
|
|
86
87
|
.collect::<Vec<_>>();
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
let mut merged = BTreeMap::<String, Value>::new();
|
|
89
|
+
for command in commands {
|
|
90
|
+
let Some(check_id) = command
|
|
91
|
+
.get("checkId")
|
|
89
92
|
.and_then(Value::as_str)
|
|
90
|
-
.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
.map(ToString::to_string)
|
|
94
|
+
else {
|
|
95
|
+
continue;
|
|
96
|
+
};
|
|
97
|
+
if let Some(existing) = merged.get_mut(&check_id) {
|
|
98
|
+
merge_command(existing, &command);
|
|
99
|
+
} else {
|
|
100
|
+
merged.insert(check_id, command);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
merged.into_values().collect()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fn merge_command(existing: &mut Value, incoming: &Value) {
|
|
107
|
+
merge_csv_field(existing, incoming, "reason");
|
|
108
|
+
existing["selectionReason"] = existing["reason"].clone();
|
|
109
|
+
merge_string_array_field(existing, incoming, "impactedPaths");
|
|
110
|
+
let safe = existing
|
|
111
|
+
.get("safeToExecute")
|
|
112
|
+
.and_then(Value::as_bool)
|
|
113
|
+
.unwrap_or(false)
|
|
114
|
+
&& incoming
|
|
115
|
+
.get("safeToExecute")
|
|
116
|
+
.and_then(Value::as_bool)
|
|
117
|
+
.unwrap_or(false);
|
|
118
|
+
existing["safeToExecute"] = json!(safe);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fn merge_csv_field(existing: &mut Value, incoming: &Value, field: &str) {
|
|
122
|
+
let mut values = BTreeSet::new();
|
|
123
|
+
collect_csv(existing.get(field), &mut values);
|
|
124
|
+
collect_csv(incoming.get(field), &mut values);
|
|
125
|
+
existing[field] = json!(values.into_iter().collect::<Vec<_>>().join(","));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fn collect_csv(value: Option<&Value>, values: &mut BTreeSet<String>) {
|
|
129
|
+
if let Some(raw) = value.and_then(Value::as_str) {
|
|
130
|
+
values.extend(
|
|
131
|
+
raw.split(',')
|
|
132
|
+
.map(str::trim)
|
|
133
|
+
.filter(|part| !part.is_empty())
|
|
134
|
+
.map(ToString::to_string),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fn merge_string_array_field(existing: &mut Value, incoming: &Value, field: &str) {
|
|
140
|
+
let mut values = BTreeSet::new();
|
|
141
|
+
collect_string_array(existing.get(field), &mut values);
|
|
142
|
+
collect_string_array(incoming.get(field), &mut values);
|
|
143
|
+
existing[field] = json!(values.into_iter().collect::<Vec<_>>());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fn collect_string_array(value: Option<&Value>, values: &mut BTreeSet<String>) {
|
|
147
|
+
values.extend(
|
|
148
|
+
value
|
|
149
|
+
.and_then(Value::as_array)
|
|
150
|
+
.into_iter()
|
|
151
|
+
.flatten()
|
|
152
|
+
.filter_map(Value::as_str)
|
|
153
|
+
.map(ToString::to_string),
|
|
154
|
+
);
|
|
97
155
|
}
|
|
98
156
|
|
|
99
157
|
fn snapshot_state(status: &naome_core::TaskStatusReportV1) -> &'static str {
|
|
@@ -7,7 +7,7 @@ mod task_cli_support;
|
|
|
7
7
|
|
|
8
8
|
use task_cli_support::{
|
|
9
9
|
active_task, fixture_root, git, init_git, run_json, task_state, task_state_with_active_task,
|
|
10
|
-
write_fixture_file, write_json,
|
|
10
|
+
write_fixture_file, write_json, write_verification_checks,
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
#[test]
|
|
@@ -24,6 +24,48 @@ fn agent_snapshot_reports_missing_proof_and_safe_commands() {
|
|
|
24
24
|
assert_eq!(snapshot["checks"]["safeToRun"][0]["checkId"], "diff-check");
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
#[test]
|
|
28
|
+
fn agent_snapshot_merges_duplicate_check_reasons_from_proof_and_impact_plans() {
|
|
29
|
+
let root = fixture_root(task_state_with_active_task(active_task(json!({
|
|
30
|
+
"allowedPaths": ["src/lib.rs"],
|
|
31
|
+
"requiredCheckIds": ["repository-quality-check"],
|
|
32
|
+
"proofResults": []
|
|
33
|
+
}))));
|
|
34
|
+
write_verification_checks(
|
|
35
|
+
&root,
|
|
36
|
+
json!([{
|
|
37
|
+
"id": "repository-quality-check",
|
|
38
|
+
"command": "node .naome/bin/naome.js quality check --changed",
|
|
39
|
+
"cwd": ".",
|
|
40
|
+
"purpose": "Validate changed-file quality.",
|
|
41
|
+
"cost": "fast",
|
|
42
|
+
"source": "NAOME",
|
|
43
|
+
"evidence": [".naome/repository-quality.json"],
|
|
44
|
+
"lastVerified": null
|
|
45
|
+
}]),
|
|
46
|
+
);
|
|
47
|
+
init_git(&root);
|
|
48
|
+
write_fixture_file(&root, "src/lib.rs", "pub fn changed() {}\n");
|
|
49
|
+
|
|
50
|
+
let snapshot = run_json(&root, ["task", "agent-snapshot", "--json"]);
|
|
51
|
+
let commands = snapshot["checks"]["recommended"].as_array().unwrap();
|
|
52
|
+
let quality_commands = commands
|
|
53
|
+
.iter()
|
|
54
|
+
.filter(|command| command["checkId"] == "repository-quality-check")
|
|
55
|
+
.collect::<Vec<_>>();
|
|
56
|
+
|
|
57
|
+
assert_eq!(quality_commands.len(), 1);
|
|
58
|
+
assert_eq!(
|
|
59
|
+
quality_commands[0]["reason"],
|
|
60
|
+
"changed_source,missing-proof"
|
|
61
|
+
);
|
|
62
|
+
assert_eq!(
|
|
63
|
+
quality_commands[0]["selectionReason"],
|
|
64
|
+
"changed_source,missing-proof"
|
|
65
|
+
);
|
|
66
|
+
assert_eq!(quality_commands[0]["impactedPaths"], json!(["src/lib.rs"]));
|
|
67
|
+
}
|
|
68
|
+
|
|
27
69
|
#[test]
|
|
28
70
|
fn preflight_reports_path_policy_and_check_plan() {
|
|
29
71
|
let root = fixture_root(task_state_with_active_task(active_task(json!({
|
|
Binary file
|
package/native/linux-x64/naome
CHANGED
|
Binary file
|