@lamentis/naome 1.3.1 → 1.3.3

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.
Files changed (37) hide show
  1. package/Cargo.lock +2 -2
  2. package/crates/naome-cli/Cargo.toml +1 -1
  3. package/crates/naome-core/Cargo.toml +1 -1
  4. package/crates/naome-core/src/intent/resolver_catalog/active.rs +38 -0
  5. package/crates/naome-core/src/intent/resolver_catalog/baseline.rs +44 -0
  6. package/crates/naome-core/src/intent/resolver_catalog/completed.rs +56 -0
  7. package/crates/naome-core/src/intent/resolver_catalog/dirty.rs +32 -0
  8. package/crates/naome-core/src/intent/resolver_catalog/ready.rs +32 -0
  9. package/crates/naome-core/src/intent/resolver_catalog/system.rs +20 -0
  10. package/crates/naome-core/src/intent/resolver_catalog.rs +12 -166
  11. package/crates/naome-core/src/lib.rs +1 -0
  12. package/crates/naome-core/src/route/quality_gate_config.rs +18 -0
  13. package/crates/naome-core/src/task_state/diff.rs +2 -2
  14. package/crates/naome-core/src/task_state/git_io.rs +5 -2
  15. package/crates/naome-core/src/task_state/types.rs +4 -0
  16. package/crates/naome-core/src/verification_contract.rs +3 -1
  17. package/crates/naome-core/src/verification_contract_policy.rs +52 -0
  18. package/crates/naome-core/tests/harness_health.rs +29 -40
  19. package/crates/naome-core/tests/repo_support/mod.rs +5 -2
  20. package/crates/naome-core/tests/repo_support/verification.rs +28 -42
  21. package/crates/naome-core/tests/repo_support/verification_values.rs +106 -1
  22. package/crates/naome-core/tests/route_user_diff.rs +52 -4
  23. package/crates/naome-core/tests/task_state.rs +12 -26
  24. package/crates/naome-core/tests/task_state_support/mod.rs +2 -1
  25. package/crates/naome-core/tests/task_state_support/states.rs +28 -11
  26. package/crates/naome-core/tests/verification.rs +2 -20
  27. package/crates/naome-core/tests/verification_contract.rs +42 -52
  28. package/crates/naome-core/tests/workflow_integrity.rs +2 -20
  29. package/crates/naome-core/tests/workflow_support/mod.rs +59 -20
  30. package/native/darwin-arm64/naome +0 -0
  31. package/native/linux-x64/naome +0 -0
  32. package/package.json +1 -1
  33. package/templates/naome-root/.naome/bin/check-harness-health.js +1 -1
  34. package/templates/naome-root/.naome/bin/check-task-state.js +1 -1
  35. package/templates/naome-root/.naome/manifest.json +1 -1
  36. package/templates/naome-root/docs/naome/first-run.md +1 -1
  37. package/templates/naome-root/docs/naome/testing.md +1 -1
@@ -156,50 +156,13 @@ impl HarnessFixture {
156
156
  write_file(
157
157
  &root,
158
158
  ".naome/manifest.json",
159
- &format!(
160
- "{}\n",
161
- serde_json::to_string_pretty(&json!({
162
- "name": "naome",
163
- "harnessVersion": "0.6.1",
164
- "profile": "standard",
165
- "installedAt": "2026-05-05T00:00:00.000Z",
166
- "machineOwned": MACHINE_OWNED_PATHS,
167
- "projectOwned": PROJECT_OWNED_PATHS,
168
- "integrity": integrity
169
- }))
170
- .unwrap()
171
- ),
172
- );
173
- write_file(
174
- &root,
175
- ".naome/task-state.json",
176
- &format!(
177
- "{}\n",
178
- serde_json::to_string_pretty(&json!({
179
- "schema": "naome.task-state.v1",
180
- "version": 1,
181
- "status": "idle",
182
- "activeTask": null,
183
- "blocker": null,
184
- "updatedAt": null
185
- }))
186
- .unwrap()
187
- ),
159
+ &pretty_json(manifest_fixture(&integrity)),
188
160
  );
161
+ write_file(&root, ".naome/task-state.json", "{}\n");
189
162
  write_file(
190
163
  &root,
191
164
  ".naome/upgrade-state.json",
192
- &format!(
193
- "{}\n",
194
- serde_json::to_string_pretty(&json!({
195
- "status": "complete",
196
- "fromVersion": null,
197
- "toVersion": "0.6.1",
198
- "pending": [],
199
- "completed": []
200
- }))
201
- .unwrap()
202
- ),
165
+ &pretty_json(complete_upgrade_state_fixture()),
203
166
  );
204
167
 
205
168
  Self { root, integrity }
@@ -214,6 +177,32 @@ impl HarnessFixture {
214
177
  }
215
178
  }
216
179
 
180
+ fn manifest_fixture(integrity: &HashMap<String, String>) -> serde_json::Value {
181
+ json!({
182
+ "name": "naome",
183
+ "harnessVersion": "0.6.1",
184
+ "profile": "standard",
185
+ "installedAt": "2026-05-05T00:00:00.000Z",
186
+ "machineOwned": MACHINE_OWNED_PATHS,
187
+ "projectOwned": PROJECT_OWNED_PATHS,
188
+ "integrity": integrity
189
+ })
190
+ }
191
+
192
+ fn complete_upgrade_state_fixture() -> serde_json::Value {
193
+ json!({
194
+ "status": "complete",
195
+ "fromVersion": null,
196
+ "toVersion": "0.6.1",
197
+ "pending": [],
198
+ "completed": []
199
+ })
200
+ }
201
+
202
+ fn pretty_json(value: serde_json::Value) -> String {
203
+ format!("{}\n", serde_json::to_string_pretty(&value).unwrap())
204
+ }
205
+
217
206
  fn machine_content(relative_path: &str) -> String {
218
207
  match relative_path {
219
208
  "AGENTS.md" => [
@@ -14,7 +14,10 @@ pub use routes::{
14
14
  try_route_readme_task,
15
15
  };
16
16
  pub use verification_values::{
17
- change_type, diff_check, quality_check, repository_quality_config_source,
18
- repository_quality_config_value, semantic_repository_quality_fixture_source,
17
+ change_type, check_missing_last_verified_fixture, diff_check,
18
+ placeholder_verification_contract_fixture, quality_check, repo_docs_verification_fixture,
19
+ repository_quality_config_source,
20
+ repository_quality_config_value, repository_semantic_check,
21
+ semantic_repository_quality_fixture_source,
19
22
  verification_value,
20
23
  };
@@ -2,7 +2,8 @@ use serde_json::{json, Value};
2
2
 
3
3
  use super::repo::TestRepo;
4
4
  use super::verification_values::{
5
- change_type, diff_check, mutating_diff_check, repository_quality_check, verification_value,
5
+ change_type, diff_check, mutating_diff_check, repository_quality_check,
6
+ repository_semantic_check, verification_value,
6
7
  };
7
8
 
8
9
  impl TestRepo {
@@ -33,54 +34,39 @@ impl TestRepo {
33
34
  ) {
34
35
  let mut checks = vec![diff_check(vec!["README.md"])];
35
36
  checks.extend(extra_checks);
36
-
37
37
  self.write_naome_json(
38
38
  "verification.json",
39
- json!({
40
- "schema": "naome.verification.v1",
41
- "version": 1,
42
- "status": "ready",
43
- "checks": checks,
44
- "changeTypes": [
45
- {
46
- "id": "readme",
47
- "description": "README changes.",
48
- "paths": ["README.md"],
49
- "requiredChecks": required_checks,
50
- "recommendedChecks": [],
51
- "humanReview": false
52
- }
53
- ],
54
- "releaseGates": []
55
- }),
39
+ verification_value(
40
+ "ready",
41
+ checks,
42
+ vec![change_type(
43
+ "readme",
44
+ "README changes.",
45
+ vec!["README.md"],
46
+ required_checks,
47
+ )],
48
+ ),
56
49
  );
57
50
  }
58
51
 
59
52
  pub fn write_product_quality_verification(&self) {
60
53
  self.write_naome_json(
61
54
  "verification.json",
62
- json!({
63
- "schema": "naome.verification.v1",
64
- "version": 1,
65
- "status": "ready",
66
- "checks": product_quality_checks(),
67
- "changeTypes": [
68
- {
69
- "id": "product-installer-or-template",
70
- "description": "NAOME product changes.",
71
- "paths": ["packages/naome/**", "scripts/**"],
72
- "requiredChecks": [
73
- "installer-tests",
74
- "rust-build",
75
- "decision-engine-tests",
76
- "package-dry-run"
77
- ],
78
- "recommendedChecks": [],
79
- "humanReview": false
80
- }
81
- ],
82
- "releaseGates": []
83
- }),
55
+ verification_value(
56
+ "ready",
57
+ product_quality_checks(),
58
+ vec![change_type(
59
+ "product-installer-or-template",
60
+ "NAOME product changes.",
61
+ vec!["packages/naome/**", "scripts/**"],
62
+ vec![
63
+ "installer-tests",
64
+ "rust-build",
65
+ "decision-engine-tests",
66
+ "package-dry-run",
67
+ ],
68
+ )],
69
+ ),
84
70
  );
85
71
  }
86
72
 
@@ -89,7 +75,7 @@ impl TestRepo {
89
75
  "verification.json",
90
76
  verification_value(
91
77
  "ready",
92
- vec![repository_quality_check()],
78
+ vec![repository_quality_check(), repository_semantic_check()],
93
79
  vec![change_type(
94
80
  "source",
95
81
  "Source changes.",
@@ -1,4 +1,4 @@
1
- use serde_json::json;
1
+ use serde_json::{json, Value};
2
2
 
3
3
  pub fn completed_task_state(admission_head: &str) -> serde_json::Value {
4
4
  json!({
@@ -67,6 +67,7 @@ pub fn verification_value(
67
67
  "schema": "naome.verification.v1",
68
68
  "version": 1,
69
69
  "status": status,
70
+ "lastUpdated": null,
70
71
  "checks": checks,
71
72
  "changeTypes": change_types,
72
73
  "releaseGates": []
@@ -118,6 +119,97 @@ pub fn change_type(
118
119
  })
119
120
  }
120
121
 
122
+ pub fn repo_docs_verification_fixture() -> Value {
123
+ json!({
124
+ "schema": "naome.verification.v1",
125
+ "version": 1,
126
+ "status": "ready",
127
+ "lastUpdated": "2026-05-05",
128
+ "checks": [
129
+ {
130
+ "id": "repo-docs",
131
+ "command": "npm run docs:test",
132
+ "cwd": ".",
133
+ "purpose": "Validate repository documentation.",
134
+ "cost": "fast",
135
+ "source": "repository intake",
136
+ "evidence": ["package.json"],
137
+ "lastVerified": null
138
+ }
139
+ ],
140
+ "changeTypes": [
141
+ {
142
+ "id": "repo-docs",
143
+ "description": "Repository documentation changes.",
144
+ "paths": ["docs/**"],
145
+ "requiredChecks": ["repo-docs"],
146
+ "recommendedChecks": [],
147
+ "humanReview": false
148
+ }
149
+ ],
150
+ "releaseGates": [
151
+ {
152
+ "checkId": "repo-docs",
153
+ "requiredWhen": "Before merging repository documentation changes."
154
+ }
155
+ ]
156
+ })
157
+ }
158
+
159
+ pub fn placeholder_verification_contract_fixture() -> Value {
160
+ json!({
161
+ "schema": "naome.verification.v1",
162
+ "version": 1,
163
+ "status": "ready",
164
+ "lastUpdated": "2026-05-05",
165
+ "checks": [
166
+ {
167
+ "id": "example-check",
168
+ "command": "replace with real command",
169
+ "cwd": ".",
170
+ "purpose": "Replace with what this proves.",
171
+ "cost": "fast",
172
+ "source": "replace with evidence source",
173
+ "evidence": [],
174
+ "lastVerified": null
175
+ }
176
+ ],
177
+ "changeTypes": [
178
+ {
179
+ "id": "docs",
180
+ "description": "Documentation changes.",
181
+ "paths": ["docs/**"],
182
+ "requiredChecks": ["missing-check"],
183
+ "recommendedChecks": [],
184
+ "humanReview": false
185
+ }
186
+ ],
187
+ "releaseGates": []
188
+ })
189
+ }
190
+
191
+ pub fn check_missing_last_verified_fixture() -> Value {
192
+ json!({
193
+ "schema": "naome.verification.v1",
194
+ "version": 1,
195
+ "status": "uninitialized",
196
+ "lastUpdated": null,
197
+ "checks": [
198
+ {
199
+ "id": "diff-check",
200
+ "command": "git diff --check",
201
+ "cwd": ".",
202
+ "purpose": "Reject whitespace errors.",
203
+ "cost": "fast",
204
+ "source": "git",
205
+ "evidence": []
206
+ }
207
+ ],
208
+ "changeTypes": [],
209
+ "releaseGates": []
210
+ })
211
+ }
212
+
121
213
  pub fn quality_check(
122
214
  id: &str,
123
215
  command: &str,
@@ -150,6 +242,19 @@ pub fn repository_quality_check() -> serde_json::Value {
150
242
  })
151
243
  }
152
244
 
245
+ pub fn repository_semantic_check() -> serde_json::Value {
246
+ json!({
247
+ "id": "repository-semantic-check",
248
+ "command": "naome semantic check --changed",
249
+ "cwd": ".",
250
+ "purpose": "Validate changed files against repository semantic rules.",
251
+ "cost": "fast",
252
+ "source": "NAOME built-in",
253
+ "evidence": ["src/**"],
254
+ "lastVerified": null
255
+ })
256
+ }
257
+
153
258
  pub fn semantic_repository_quality_fixture_source(name: &str) -> String {
154
259
  [
155
260
  format!("const {name} = {{"),
@@ -73,14 +73,14 @@ fn execute_route_runs_repository_quality_check_without_shelling_to_repo_command(
73
73
  }
74
74
 
75
75
  #[test]
76
- fn execute_route_refuses_semantic_changed_findings_through_repository_quality_gate() {
77
- let repo = TestRepo::new("route-semantic-quality-gate");
76
+ fn execute_route_requires_semantic_gate_with_repository_quality_gate() {
77
+ let repo = TestRepo::new("route-repository-quality-requires-semantic");
78
78
  repo.init_git();
79
79
  repo.write_file(
80
80
  ".naome/repository-quality.json",
81
81
  &repository_quality_config_source(),
82
82
  );
83
- repo.write_file("scripts/baseline.test.js", "const ok = { value: 1 };\n");
83
+ repo.write_file("src/clean.js", "export const clean = true;\n");
84
84
  repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
85
85
  repo.write_naome_json(
86
86
  "verification.json",
@@ -91,8 +91,56 @@ fn execute_route_refuses_semantic_changed_findings_through_repository_quality_ga
91
91
  "naome quality check --changed",
92
92
  "Validate changed files against repository quality rules.",
93
93
  "fast",
94
- vec!["scripts/**"],
94
+ vec!["src/**"],
95
95
  )],
96
+ vec![change_type(
97
+ "source",
98
+ "Source changes.",
99
+ vec!["src/**"],
100
+ vec!["repository-quality-check"],
101
+ )],
102
+ ),
103
+ );
104
+ repo.commit_all("baseline");
105
+ repo.write_file("src/clean.js", "export const clean = false;\n");
106
+ let before_head = repo.git_stdout(&["rev-parse", "HEAD"]);
107
+
108
+ let route = route_commit_request(&repo);
109
+
110
+ assert_quality_gate_blocked(&repo, &route, before_head, "src/clean.js");
111
+ assert!(route.user_message.contains("repository-semantic-check"));
112
+ }
113
+
114
+ #[test]
115
+ fn execute_route_refuses_semantic_changed_findings_through_repository_quality_gate() {
116
+ let repo = TestRepo::new("route-semantic-quality-gate");
117
+ repo.init_git();
118
+ repo.write_file(
119
+ ".naome/repository-quality.json",
120
+ &repository_quality_config_source(),
121
+ );
122
+ repo.write_file("scripts/baseline.test.js", "const ok = { value: 1 };\n");
123
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
124
+ repo.write_naome_json(
125
+ "verification.json",
126
+ verification_value(
127
+ "ready",
128
+ vec![
129
+ quality_check(
130
+ "repository-quality-check",
131
+ "naome quality check --changed",
132
+ "Validate changed files against repository quality rules.",
133
+ "fast",
134
+ vec!["scripts/**"],
135
+ ),
136
+ quality_check(
137
+ "repository-semantic-check",
138
+ "naome semantic check --changed",
139
+ "Validate changed files against repository semantic rules.",
140
+ "fast",
141
+ vec!["scripts/**"],
142
+ ),
143
+ ],
96
144
  vec![change_type(
97
145
  "scripts",
98
146
  "Script changes.",
@@ -8,8 +8,8 @@ use naome_core::{
8
8
  };
9
9
  use serde_json::json;
10
10
  use task_state_support::{
11
- active_task, complete_task_state, idle_task_state, strict_health_options, successful_admission,
12
- successful_proof, TaskFixture,
11
+ active_task, complete_task_state, idle_task_state, ready_empty_verification_fixture,
12
+ strict_health_options, successful_admission, successful_proof, TaskFixture,
13
13
  };
14
14
 
15
15
  #[test]
@@ -137,15 +137,7 @@ fn commit_gate_allows_install_baseline_with_gitignore_and_project_owned_paths()
137
137
  repo.write("docs/naome/testing.md", "# Testing\n");
138
138
  repo.write_json(
139
139
  ".naome/verification.json",
140
- json!({
141
- "schema": "naome.verification.v1",
142
- "version": 1,
143
- "status": "ready",
144
- "lastUpdated": "2026-05-05",
145
- "checks": [],
146
- "changeTypes": [],
147
- "releaseGates": []
148
- }),
140
+ ready_empty_verification_fixture(),
149
141
  );
150
142
 
151
143
  let report = commit_gate_report(&repo);
@@ -292,7 +284,7 @@ fn commit_gate_ignores_unstaged_user_edits_outside_completed_task_scope() {
292
284
 
293
285
  #[test]
294
286
  fn progress_accepts_implementing_task_with_scoped_diff_without_proof() {
295
- let repo = TaskFixture::new(implementing_readme_task());
287
+ let repo = TaskFixture::new(implementing_readme_task_fixture());
296
288
  repo.init_git();
297
289
  repo.write("README.md", "# In progress\n");
298
290
 
@@ -303,7 +295,7 @@ fn progress_accepts_implementing_task_with_scoped_diff_without_proof() {
303
295
 
304
296
  #[test]
305
297
  fn progress_rejects_in_flight_work_outside_scope() {
306
- let repo = TaskFixture::new(implementing_readme_task());
298
+ let repo = TaskFixture::new(implementing_readme_task_fixture());
307
299
  repo.init_git();
308
300
  repo.write("src/session.js", "export const session = null;\n");
309
301
 
@@ -417,27 +409,21 @@ fn progress_report(repo: &TaskFixture) -> TaskStateReport {
417
409
  .unwrap()
418
410
  }
419
411
 
420
- fn implementing_readme_task() -> serde_json::Value {
421
- json!({
422
- "schema": "naome.task-state.v1",
423
- "version": 1,
424
- "status": "implementing",
425
- "activeTask": active_task(json!({
426
- "allowedPaths": ["README.md"],
427
- "proofResults": []
428
- })),
429
- "blocker": null,
430
- "updatedAt": "2026-05-04T12:00:00.000Z"
431
- })
412
+ fn implementing_readme_task_fixture() -> serde_json::Value {
413
+ implementing_task_fixture(vec!["README.md"])
432
414
  }
433
415
 
434
416
  fn implementing_package_task() -> serde_json::Value {
417
+ implementing_task_fixture(vec!["Package.swift"])
418
+ }
419
+
420
+ fn implementing_task_fixture(allowed_paths: Vec<&str>) -> serde_json::Value {
435
421
  json!({
436
422
  "schema": "naome.task-state.v1",
437
423
  "version": 1,
438
424
  "status": "implementing",
439
425
  "activeTask": active_task(json!({
440
- "allowedPaths": ["Package.swift"],
426
+ "allowedPaths": allowed_paths,
441
427
  "proofResults": []
442
428
  })),
443
429
  "blocker": null,
@@ -11,7 +11,8 @@ use naome_core::{HarnessHealthOptions, MACHINE_OWNED_PATHS, PROJECT_OWNED_PATHS}
11
11
  use serde_json::{json, Value};
12
12
  use sha2::{Digest, Sha256};
13
13
  pub use states::{
14
- active_task, complete_task_state, idle_task_state, successful_admission, successful_proof,
14
+ active_task, complete_task_state, idle_task_state, ready_empty_verification_fixture,
15
+ successful_admission, successful_proof,
15
16
  };
16
17
 
17
18
  static FIXTURE_COUNTER: AtomicU64 = AtomicU64::new(0);
@@ -1,24 +1,25 @@
1
1
  use serde_json::{json, Value};
2
2
 
3
3
  pub fn idle_task_state() -> Value {
4
- json!({
5
- "schema": "naome.task-state.v1",
6
- "version": 1,
7
- "status": "idle",
8
- "activeTask": null,
9
- "blocker": null,
10
- "updatedAt": null
11
- })
4
+ task_state_record("idle", Value::Null, Value::Null)
12
5
  }
13
6
 
14
7
  pub fn complete_task_state(overrides: Value) -> Value {
8
+ task_state_record(
9
+ "complete",
10
+ active_task(overrides),
11
+ json!("2026-05-04T12:00:00.000Z"),
12
+ )
13
+ }
14
+
15
+ fn task_state_record(status: &str, active_task: Value, updated_at: Value) -> Value {
15
16
  json!({
16
17
  "schema": "naome.task-state.v1",
17
18
  "version": 1,
18
- "status": "complete",
19
- "activeTask": active_task(overrides),
19
+ "status": status,
20
+ "activeTask": active_task,
20
21
  "blocker": null,
21
- "updatedAt": "2026-05-04T12:00:00.000Z"
22
+ "updatedAt": updated_at
22
23
  })
23
24
  }
24
25
 
@@ -71,6 +72,22 @@ pub fn successful_proof(overrides: Value) -> Value {
71
72
  proof
72
73
  }
73
74
 
75
+ pub fn ready_empty_verification_fixture() -> Value {
76
+ serde_json::from_str(
77
+ r#"{
78
+ "schema": "naome.verification.v1",
79
+ "version": 1,
80
+ "status": "ready",
81
+ "lastUpdated": "2026-05-05",
82
+ "checks": [],
83
+ "changeTypes": [],
84
+ "releaseGates": [],
85
+ "phases": []
86
+ }"#,
87
+ )
88
+ .unwrap()
89
+ }
90
+
74
91
  fn merge_object(target: &mut Value, overrides: Value) {
75
92
  let Some(target_object) = target.as_object_mut() else {
76
93
  return;
@@ -2,30 +2,12 @@ use naome_core::seed_builtin_verification_checks;
2
2
 
3
3
  mod repo_support;
4
4
 
5
- use repo_support::{change_type, quality_check, verification_value, TestRepo};
5
+ use repo_support::{repo_docs_verification_fixture, TestRepo};
6
6
 
7
7
  #[test]
8
8
  fn seeds_builtin_checks_without_removing_repo_specific_checks() {
9
9
  let repo = TestRepo::new("verification-seed");
10
- repo.write_naome_json(
11
- "verification.json",
12
- verification_value(
13
- "ready",
14
- vec![quality_check(
15
- "repo-docs",
16
- "npm run docs:test",
17
- "Validate repository documentation.",
18
- "fast",
19
- vec!["package.json"],
20
- )],
21
- vec![change_type(
22
- "repo-docs",
23
- "Repository documentation changes.",
24
- vec!["docs/**"],
25
- vec!["repo-docs"],
26
- )],
27
- ),
28
- );
10
+ repo.write_naome_json("verification.json", repo_docs_verification_fixture());
29
11
 
30
12
  let changed = seed_builtin_verification_checks(repo.path()).unwrap();
31
13