@lamentis/naome 1.1.2 → 1.2.1

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 (204) hide show
  1. package/Cargo.lock +2 -2
  2. package/Cargo.toml +1 -1
  3. package/LICENSE +180 -21
  4. package/README.md +49 -6
  5. package/bin/naome-node.js +2 -1579
  6. package/bin/naome.js +68 -16
  7. package/crates/naome-cli/Cargo.toml +1 -1
  8. package/crates/naome-cli/src/check_commands.rs +135 -0
  9. package/crates/naome-cli/src/cli_args.rs +5 -0
  10. package/crates/naome-cli/src/dispatcher.rs +37 -0
  11. package/crates/naome-cli/src/install_bridge.rs +83 -0
  12. package/crates/naome-cli/src/main.rs +60 -341
  13. package/crates/naome-cli/src/prompt_commands.rs +68 -0
  14. package/crates/naome-cli/src/quality_commands.rs +229 -0
  15. package/crates/naome-cli/src/simple_commands.rs +53 -0
  16. package/crates/naome-cli/src/workflow_commands.rs +153 -0
  17. package/crates/naome-core/Cargo.toml +1 -1
  18. package/crates/naome-core/src/decision/checks.rs +64 -0
  19. package/crates/naome-core/src/decision/idle.rs +67 -0
  20. package/crates/naome-core/src/decision/json.rs +36 -0
  21. package/crates/naome-core/src/decision/states.rs +165 -0
  22. package/crates/naome-core/src/decision.rs +131 -353
  23. package/crates/naome-core/src/harness_health/integrity.rs +96 -0
  24. package/crates/naome-core/src/harness_health.rs +14 -126
  25. package/crates/naome-core/src/install_plan.rs +5 -0
  26. package/crates/naome-core/src/intent/classifier.rs +171 -0
  27. package/crates/naome-core/src/intent/envelope.rs +108 -0
  28. package/crates/naome-core/src/intent/legacy.rs +138 -0
  29. package/crates/naome-core/src/intent/legacy_response.rs +76 -0
  30. package/crates/naome-core/src/intent/model.rs +71 -0
  31. package/crates/naome-core/src/intent/patterns.rs +170 -0
  32. package/crates/naome-core/src/intent/resolver.rs +162 -0
  33. package/crates/naome-core/src/intent/resolver_active.rs +17 -0
  34. package/crates/naome-core/src/intent/resolver_baseline.rs +55 -0
  35. package/crates/naome-core/src/intent/resolver_catalog.rs +167 -0
  36. package/crates/naome-core/src/intent/resolver_policy.rs +72 -0
  37. package/crates/naome-core/src/intent/resolver_shared.rs +55 -0
  38. package/crates/naome-core/src/intent/risk.rs +40 -0
  39. package/crates/naome-core/src/intent/segment.rs +170 -0
  40. package/crates/naome-core/src/intent.rs +64 -879
  41. package/crates/naome-core/src/journal.rs +9 -20
  42. package/crates/naome-core/src/lib.rs +15 -0
  43. package/crates/naome-core/src/paths.rs +3 -1
  44. package/crates/naome-core/src/quality/adapter_support.rs +89 -0
  45. package/crates/naome-core/src/quality/adapters.rs +131 -0
  46. package/crates/naome-core/src/quality/baseline.rs +75 -0
  47. package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +175 -0
  48. package/crates/naome-core/src/quality/checks/near_duplicates.rs +130 -0
  49. package/crates/naome-core/src/quality/checks.rs +228 -0
  50. package/crates/naome-core/src/quality/cleanup.rs +84 -0
  51. package/crates/naome-core/src/quality/config.rs +102 -0
  52. package/crates/naome-core/src/quality/config_support.rs +24 -0
  53. package/crates/naome-core/src/quality/mod.rs +108 -0
  54. package/crates/naome-core/src/quality/scanner/repo_paths.rs +103 -0
  55. package/crates/naome-core/src/quality/scanner.rs +379 -0
  56. package/crates/naome-core/src/quality/structure/adapters.rs +84 -0
  57. package/crates/naome-core/src/quality/structure/checks/basic.rs +153 -0
  58. package/crates/naome-core/src/quality/structure/checks/directory.rs +144 -0
  59. package/crates/naome-core/src/quality/structure/checks/pairing.rs +63 -0
  60. package/crates/naome-core/src/quality/structure/checks.rs +124 -0
  61. package/crates/naome-core/src/quality/structure/classify/roles.rs +188 -0
  62. package/crates/naome-core/src/quality/structure/classify.rs +94 -0
  63. package/crates/naome-core/src/quality/structure/config.rs +89 -0
  64. package/crates/naome-core/src/quality/structure/defaults.rs +107 -0
  65. package/crates/naome-core/src/quality/structure/mod.rs +77 -0
  66. package/crates/naome-core/src/quality/structure/model.rs +124 -0
  67. package/crates/naome-core/src/quality/types.rs +292 -0
  68. package/crates/naome-core/src/route/builtin_checks.rs +155 -0
  69. package/crates/naome-core/src/route/builtin_context.rs +73 -0
  70. package/crates/naome-core/src/route/builtin_integrity.rs +49 -0
  71. package/crates/naome-core/src/route/builtin_require.rs +40 -0
  72. package/crates/naome-core/src/route/context.rs +180 -0
  73. package/crates/naome-core/src/route/execution.rs +96 -0
  74. package/crates/naome-core/src/route/execution_baselines.rs +146 -0
  75. package/crates/naome-core/src/route/execution_support.rs +57 -0
  76. package/crates/naome-core/src/route/execution_tasks.rs +71 -0
  77. package/crates/naome-core/src/route/git_ops.rs +72 -0
  78. package/crates/naome-core/src/route/quality_gate.rs +73 -0
  79. package/crates/naome-core/src/route/quality_gate_config.rs +126 -0
  80. package/crates/naome-core/src/route/quality_gate_snapshot.rs +69 -0
  81. package/crates/naome-core/src/route/worktree.rs +75 -0
  82. package/crates/naome-core/src/route/worktree_files.rs +32 -0
  83. package/crates/naome-core/src/route/worktree_plan.rs +131 -0
  84. package/crates/naome-core/src/route.rs +44 -1155
  85. package/crates/naome-core/src/task_state/admission.rs +63 -0
  86. package/crates/naome-core/src/task_state/admission_proof.rs +72 -0
  87. package/crates/naome-core/src/task_state/api.rs +130 -0
  88. package/crates/naome-core/src/task_state/commit_gate.rs +138 -0
  89. package/crates/naome-core/src/task_state/compact_proof.rs +160 -0
  90. package/crates/naome-core/src/task_state/completed_refresh.rs +89 -0
  91. package/crates/naome-core/src/task_state/completion.rs +72 -0
  92. package/crates/naome-core/src/task_state/deleted_paths.rs +47 -0
  93. package/crates/naome-core/src/task_state/diff.rs +95 -0
  94. package/crates/naome-core/src/task_state/evidence.rs +154 -0
  95. package/crates/naome-core/src/task_state/git_io.rs +86 -0
  96. package/crates/naome-core/src/task_state/git_parse.rs +86 -0
  97. package/crates/naome-core/src/task_state/git_refs.rs +37 -0
  98. package/crates/naome-core/src/task_state/human_review_state.rs +31 -0
  99. package/crates/naome-core/src/task_state/mod.rs +38 -0
  100. package/crates/naome-core/src/task_state/process_guard.rs +40 -0
  101. package/crates/naome-core/src/task_state/progress.rs +123 -0
  102. package/crates/naome-core/src/task_state/proof.rs +139 -0
  103. package/crates/naome-core/src/task_state/proof_entry.rs +66 -0
  104. package/crates/naome-core/src/task_state/proof_model.rs +70 -0
  105. package/crates/naome-core/src/task_state/proof_sources.rs +76 -0
  106. package/crates/naome-core/src/task_state/push_gate.rs +49 -0
  107. package/crates/naome-core/src/task_state/reconcile.rs +7 -0
  108. package/crates/naome-core/src/task_state/repair.rs +168 -0
  109. package/crates/naome-core/src/task_state/shape.rs +117 -0
  110. package/crates/naome-core/src/task_state/task_diff_api.rs +170 -0
  111. package/crates/naome-core/src/task_state/task_records.rs +131 -0
  112. package/crates/naome-core/src/task_state/task_references.rs +126 -0
  113. package/crates/naome-core/src/task_state/types.rs +87 -0
  114. package/crates/naome-core/src/task_state/util.rs +137 -0
  115. package/crates/naome-core/src/verification/render.rs +122 -0
  116. package/crates/naome-core/src/verification.rs +177 -58
  117. package/crates/naome-core/src/verification_contract.rs +49 -21
  118. package/crates/naome-core/src/workflow/integrity.rs +123 -0
  119. package/crates/naome-core/src/workflow/integrity_normalize.rs +7 -0
  120. package/crates/naome-core/src/workflow/integrity_support.rs +110 -0
  121. package/crates/naome-core/src/workflow/mod.rs +18 -0
  122. package/crates/naome-core/src/workflow/mutation.rs +68 -0
  123. package/crates/naome-core/src/workflow/output.rs +111 -0
  124. package/crates/naome-core/src/workflow/phase_inference.rs +73 -0
  125. package/crates/naome-core/src/workflow/phases.rs +169 -0
  126. package/crates/naome-core/src/workflow/policy.rs +156 -0
  127. package/crates/naome-core/src/workflow/processes.rs +91 -0
  128. package/crates/naome-core/src/workflow/types.rs +42 -0
  129. package/crates/naome-core/tests/decision.rs +24 -118
  130. package/crates/naome-core/tests/harness_health.rs +5 -0
  131. package/crates/naome-core/tests/intent.rs +97 -792
  132. package/crates/naome-core/tests/intent_support/mod.rs +133 -0
  133. package/crates/naome-core/tests/intent_v2.rs +90 -0
  134. package/crates/naome-core/tests/quality.rs +319 -0
  135. package/crates/naome-core/tests/quality_structure.rs +116 -0
  136. package/crates/naome-core/tests/quality_structure_adapters.rs +98 -0
  137. package/crates/naome-core/tests/quality_structure_policy.rs +125 -0
  138. package/crates/naome-core/tests/quality_structure_support/mod.rs +249 -0
  139. package/crates/naome-core/tests/repo_support/mod.rs +16 -0
  140. package/crates/naome-core/tests/repo_support/repo.rs +113 -0
  141. package/crates/naome-core/tests/repo_support/repo_factories.rs +99 -0
  142. package/crates/naome-core/tests/repo_support/repo_helpers.rs +123 -0
  143. package/crates/naome-core/tests/repo_support/routes.rs +81 -0
  144. package/crates/naome-core/tests/repo_support/verification.rs +168 -0
  145. package/crates/naome-core/tests/repo_support/verification_values.rs +135 -0
  146. package/crates/naome-core/tests/route.rs +1 -1476
  147. package/crates/naome-core/tests/route_baseline.rs +86 -0
  148. package/crates/naome-core/tests/route_completion.rs +141 -0
  149. package/crates/naome-core/tests/route_harness_refresh.rs +135 -0
  150. package/crates/naome-core/tests/route_user_diff.rs +198 -0
  151. package/crates/naome-core/tests/route_worktree.rs +54 -0
  152. package/crates/naome-core/tests/task_state.rs +60 -429
  153. package/crates/naome-core/tests/task_state_compact.rs +110 -0
  154. package/crates/naome-core/tests/task_state_compact_support/mod.rs +5 -0
  155. package/crates/naome-core/tests/task_state_compact_support/repo.rs +130 -0
  156. package/crates/naome-core/tests/task_state_compact_support/states.rs +151 -0
  157. package/crates/naome-core/tests/task_state_support/mod.rs +163 -0
  158. package/crates/naome-core/tests/task_state_support/states.rs +84 -0
  159. package/crates/naome-core/tests/verification.rs +4 -45
  160. package/crates/naome-core/tests/verification_contract.rs +22 -78
  161. package/crates/naome-core/tests/workflow_integrity.rs +85 -0
  162. package/crates/naome-core/tests/workflow_policy.rs +139 -0
  163. package/crates/naome-core/tests/workflow_support/mod.rs +194 -0
  164. package/installer/agents.js +90 -0
  165. package/installer/context.js +67 -0
  166. package/installer/filesystem.js +166 -0
  167. package/installer/flows.js +84 -0
  168. package/installer/git-boundary.js +170 -0
  169. package/installer/git-hook-content.js +36 -0
  170. package/installer/git-hooks.js +134 -0
  171. package/installer/git-local.js +2 -0
  172. package/installer/git-shared.js +35 -0
  173. package/installer/harness-file-ops.js +140 -0
  174. package/installer/harness-files.js +56 -0
  175. package/installer/harness-verification.js +123 -0
  176. package/installer/install-plan.js +66 -0
  177. package/installer/main.js +25 -0
  178. package/installer/manifest-state.js +167 -0
  179. package/installer/native-build.js +24 -0
  180. package/installer/native-format.js +6 -0
  181. package/installer/native.js +162 -0
  182. package/installer/output.js +131 -0
  183. package/installer/version.js +32 -0
  184. package/native/darwin-arm64/naome +0 -0
  185. package/native/linux-x64/naome +0 -0
  186. package/package.json +3 -2
  187. package/templates/naome-root/.naome/bin/check-harness-health.js +66 -85
  188. package/templates/naome-root/.naome/bin/check-task-state.js +9 -10
  189. package/templates/naome-root/.naome/bin/naome.js +51 -76
  190. package/templates/naome-root/.naome/manifest.json +22 -18
  191. package/templates/naome-root/.naome/repository-quality-baseline.json +5 -0
  192. package/templates/naome-root/.naome/repository-quality.json +24 -0
  193. package/templates/naome-root/.naome/repository-structure.json +90 -0
  194. package/templates/naome-root/.naome/task-contract.schema.json +93 -11
  195. package/templates/naome-root/.naome/upgrade-state.json +1 -1
  196. package/templates/naome-root/.naome/verification.json +38 -0
  197. package/templates/naome-root/AGENTS.md +3 -0
  198. package/templates/naome-root/docs/naome/agent-workflow.md +25 -12
  199. package/templates/naome-root/docs/naome/execution.md +25 -21
  200. package/templates/naome-root/docs/naome/index.md +5 -3
  201. package/templates/naome-root/docs/naome/repository-quality.md +46 -0
  202. package/templates/naome-root/docs/naome/repository-structure.md +51 -0
  203. package/templates/naome-root/docs/naome/testing.md +13 -0
  204. package/crates/naome-core/src/task_state.rs +0 -2210
@@ -0,0 +1,99 @@
1
+ use serde_json::{json, Value};
2
+
3
+ use super::repo::TestRepo;
4
+ use super::verification_values::completed_task_state;
5
+
6
+ impl TestRepo {
7
+ pub fn completed_task_with_diff(name: &str) -> Self {
8
+ let repo = Self::new(name);
9
+ repo.init_git();
10
+ repo.write_file("README.md", "# Baseline\n");
11
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
12
+ repo.git(&["add", "."]);
13
+ repo.git(&["commit", "-m", "baseline"]);
14
+ let admission_head = repo.git_stdout(&["rev-parse", "HEAD"]);
15
+ repo.write_base_naome_state(completed_task_state(&admission_head));
16
+ repo.git(&["add", ".naome/task-state.json"]);
17
+ repo.git(&["commit", "-m", "task state"]);
18
+ repo.write_file("README.md", "# Changed\n");
19
+ repo
20
+ }
21
+
22
+ pub fn completed_task_with_unrelated_user_edit(name: &str) -> Self {
23
+ let repo = Self::new(name);
24
+ repo.init_git();
25
+ repo.write_file("README.md", "# Baseline\n");
26
+ repo.write_file("USER.md", "user baseline\n");
27
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
28
+ repo.git(&["add", "."]);
29
+ repo.git(&["commit", "-m", "baseline"]);
30
+ let admission_head = repo.git_stdout(&["rev-parse", "HEAD"]);
31
+ repo.write_base_naome_state(completed_task_state(&admission_head));
32
+ repo.git(&["add", ".naome/task-state.json"]);
33
+ repo.git(&["commit", "-m", "task state"]);
34
+ repo.write_file("README.md", "# Changed\n");
35
+ repo.write_file("USER.md", "user local edit\n");
36
+ repo
37
+ }
38
+
39
+ pub fn completed_task_with_harness_refresh_diff(name: &str) -> Self {
40
+ let repo = Self::completed_task_with_diff(name);
41
+ repo.write_current_harness_refresh();
42
+ repo
43
+ }
44
+
45
+ pub fn completed_task_with_harness_refresh_only(name: &str) -> Self {
46
+ let repo = Self::new(name);
47
+ repo.init_git();
48
+ repo.write_file("README.md", "# Baseline\n");
49
+ repo.write_file("AGENTS.md", "# Agent Instructions\n\nOld harness.\n");
50
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
51
+ repo.write_harness_manifest("old");
52
+ repo.commit_all("baseline");
53
+ let admission_head = repo.git_stdout(&["rev-parse", "HEAD"]);
54
+ repo.write_base_naome_state(completed_task_state(&admission_head));
55
+ repo.git(&["add", ".naome/task-state.json"]);
56
+ repo.git(&["commit", "-m", "task state"]);
57
+ repo.write_current_harness_refresh();
58
+ repo
59
+ }
60
+
61
+ pub fn dirty_harness_refresh_repo(name: &str, with_user_edit: bool) -> Self {
62
+ let repo = Self::new(name);
63
+ repo.init_git();
64
+ repo.write_file("README.md", "# Baseline\n");
65
+ repo.write_file("USER.md", "user baseline\n");
66
+ repo.write_file("AGENTS.md", "# Agent Instructions\n\nOld harness.\n");
67
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
68
+ repo.write_harness_manifest("old");
69
+ repo.commit_all("baseline");
70
+ repo.write_current_harness_refresh();
71
+ if with_user_edit {
72
+ repo.write_file("USER.md", "user local edit\n");
73
+ }
74
+ repo
75
+ }
76
+
77
+ pub fn idle_readme(name: &str) -> Self {
78
+ let repo = Self::new(name);
79
+ repo.init_git();
80
+ repo.write_file("README.md", "# Baseline\n");
81
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
82
+ repo.commit_all("baseline");
83
+ repo
84
+ }
85
+
86
+ pub fn readme_quality_repo(
87
+ name: &str,
88
+ extra_checks: Vec<Value>,
89
+ required_checks: Vec<&str>,
90
+ ) -> Self {
91
+ let repo = Self::new(name);
92
+ repo.init_git();
93
+ repo.write_file("README.md", "# Baseline\n");
94
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
95
+ repo.write_readme_quality_verification(extra_checks, required_checks);
96
+ repo.commit_all("baseline");
97
+ repo
98
+ }
99
+ }
@@ -0,0 +1,123 @@
1
+ use std::fs;
2
+
3
+ use serde_json::json;
4
+
5
+ use super::repo::TestRepo;
6
+
7
+ impl TestRepo {
8
+ pub fn product_quality_repo(name: &str) -> Self {
9
+ let repo = Self::new(name);
10
+ repo.init_git();
11
+ repo.write_file(
12
+ "packages/naome/crates/naome-core/src/route.rs",
13
+ "pub fn baseline() {}\n",
14
+ );
15
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
16
+ repo.write_product_quality_verification();
17
+ repo.commit_all("baseline");
18
+ repo
19
+ }
20
+
21
+ pub fn repository_quality_failure_repo(name: &str) -> Self {
22
+ let repo = Self::new(name);
23
+ repo.init_git();
24
+ repo.write_file(".naome/repository-quality.json", quality_limits_fixture());
25
+ repo.write_file(
26
+ "src/large.js",
27
+ "export function legacy() {\n one();\n two();\n three();\n four();\n}\n",
28
+ );
29
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
30
+ repo.write_source_quality_verification();
31
+ repo.commit_all("baseline");
32
+ repo
33
+ }
34
+
35
+ pub fn readme_unsafe_diff_check_repo(name: &str) -> Self {
36
+ let repo = Self::new(name);
37
+ repo.init_git();
38
+ repo.write_file("README.md", "# Baseline\n");
39
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
40
+ repo.write_unsafe_readme_diff_verification();
41
+ repo.commit_all("baseline");
42
+ repo
43
+ }
44
+
45
+ pub fn dirty_user_edit_repo(name: &str) -> Self {
46
+ let repo = Self::new(name);
47
+ repo.init_git();
48
+ repo.write_file("README.md", "# Baseline\n");
49
+ repo.write_file("USER.md", "user baseline\n");
50
+ repo.write_base_naome_state(json!({ "status": "idle", "activeTask": null }));
51
+ repo.commit_all("baseline");
52
+ repo.write_file("USER.md", "user local edit\n");
53
+ repo
54
+ }
55
+
56
+ pub fn create_stale_task_worktrees(&self, count: usize) {
57
+ let common_dir = self.git_stdout(&["rev-parse", "--git-common-dir"]);
58
+ let worktree_root = self.path().join(common_dir).join("naome").join("worktrees");
59
+ fs::create_dir_all(&worktree_root).unwrap();
60
+ for index in 0..count {
61
+ fs::create_dir_all(worktree_root.join(format!("stale-{index}"))).unwrap();
62
+ }
63
+ }
64
+
65
+ pub fn head_commit_paths(&self) -> String {
66
+ self.git_stdout(&["show", "--name-only", "--format=", "HEAD"])
67
+ }
68
+
69
+ pub fn write_implementing_task_state(&self, allowed_path: &str, check_id: &str) {
70
+ self.write_naome_json(
71
+ "task-state.json",
72
+ json!({
73
+ "status": "implementing",
74
+ "activeTask": {
75
+ "id": "rust-task",
76
+ "allowedPaths": [allowed_path],
77
+ "requiredCheckIds": [check_id],
78
+ "proofResults": []
79
+ }
80
+ }),
81
+ );
82
+ }
83
+
84
+ pub fn write_current_harness_refresh(&self) {
85
+ self.write_file("AGENTS.md", "# Agent Instructions\n\nUpdated by sync.\n");
86
+ self.write_harness_manifest("standard");
87
+ }
88
+
89
+ pub fn write_harness_manifest(&self, profile: &str) {
90
+ self.write_naome_json(
91
+ "manifest.json",
92
+ json!({
93
+ "name": "naome",
94
+ "harnessVersion": "1.1.0",
95
+ "profile": profile,
96
+ "machineOwned": ["AGENTS.md"],
97
+ "projectOwned": [".naome/manifest.json", ".naome/task-state.json"],
98
+ "integrity": {}
99
+ }),
100
+ );
101
+ }
102
+ }
103
+
104
+ fn quality_limits_fixture() -> &'static str {
105
+ r#"{
106
+ "schema": "naome.repository-quality.v1",
107
+ "version": 1,
108
+ "status": "ready",
109
+ "limits": {
110
+ "maxFileLines": 5,
111
+ "maxNewFileLines": 5,
112
+ "maxDiffAddedLines": 200,
113
+ "maxFunctionLines": 40,
114
+ "maxTopLevelSymbols": 30,
115
+ "duplicateBlockLines": 4,
116
+ "nearDuplicateSimilarity": 0.9
117
+ },
118
+ "disabledChecks": [],
119
+ "ignoredPaths": [],
120
+ "generatedPaths": []
121
+ }
122
+ "#
123
+ }
@@ -0,0 +1,81 @@
1
+ use std::path::Path;
2
+
3
+ use naome_core::{evaluate_route, EvaluationOptions, NaomeError, RouteDecision, RouteOptions};
4
+
5
+ use super::TestRepo;
6
+
7
+ const NEW_README_TASK_PROMPT: &str = "Add another line to README as a new task.";
8
+
9
+ pub fn route_commit_request(repo: &TestRepo) -> RouteDecision {
10
+ evaluate_route(
11
+ repo.path(),
12
+ "commit my changes",
13
+ RouteOptions {
14
+ execute: true,
15
+ evaluation: EvaluationOptions::offline(),
16
+ },
17
+ )
18
+ .unwrap()
19
+ }
20
+
21
+ pub fn route_new_task(repo: &TestRepo, prompt: &str, execute: bool) -> RouteDecision {
22
+ try_route_new_task(repo, prompt, execute).unwrap()
23
+ }
24
+
25
+ pub fn try_route_new_task(
26
+ repo: &TestRepo,
27
+ prompt: &str,
28
+ execute: bool,
29
+ ) -> Result<RouteDecision, NaomeError> {
30
+ evaluate_route(
31
+ repo.path(),
32
+ prompt,
33
+ RouteOptions {
34
+ execute,
35
+ evaluation: EvaluationOptions::offline(),
36
+ },
37
+ )
38
+ }
39
+
40
+ pub fn route_readme_task(repo: &TestRepo, execute: bool) -> RouteDecision {
41
+ route_new_task(repo, NEW_README_TASK_PROMPT, execute)
42
+ }
43
+
44
+ pub fn try_route_readme_task(repo: &TestRepo, execute: bool) -> Result<RouteDecision, NaomeError> {
45
+ try_route_new_task(repo, NEW_README_TASK_PROMPT, execute)
46
+ }
47
+
48
+ pub fn assert_isolated_worktree_ready(route: &RouteDecision, repo: &TestRepo, status: &str) {
49
+ assert!(route.can_create_task);
50
+ assert_eq!(route.next_decision.state, "ready_for_task");
51
+ assert!(route.worktree.is_some());
52
+ assert_eq!(repo.git_status_short(), status);
53
+ assert_eq!(
54
+ TestRepo::git_status_short_at(Path::new(&route.task_root)),
55
+ ""
56
+ );
57
+ }
58
+
59
+ pub fn assert_commit_paths(repo: &TestRepo, present: &[&str], absent: &[&str]) {
60
+ let committed_paths = repo.head_commit_paths();
61
+ for path in present {
62
+ assert!(committed_paths.contains(path));
63
+ }
64
+ for path in absent {
65
+ assert!(!committed_paths.contains(path));
66
+ }
67
+ }
68
+
69
+ pub fn assert_user_diff_committed(route: &RouteDecision, repo: &TestRepo) {
70
+ assert_eq!(route.policy_action, "commit_user_diff_with_quality_gate");
71
+ assert!(route.allowed);
72
+ assert!(route.mutation_performed);
73
+ assert_eq!(
74
+ route.executed_actions,
75
+ vec![
76
+ "run_user_diff_quality_gate".to_string(),
77
+ "commit_user_diff".to_string()
78
+ ]
79
+ );
80
+ assert_eq!(repo.git_status_short(), "");
81
+ }
@@ -0,0 +1,168 @@
1
+ use serde_json::{json, Value};
2
+
3
+ use super::repo::TestRepo;
4
+ use super::verification_values::{
5
+ change_type, diff_check, mutating_diff_check, repository_quality_check, verification_value,
6
+ };
7
+
8
+ impl TestRepo {
9
+ pub fn write_base_naome_state(&self, task_state: serde_json::Value) {
10
+ self.write_naome_json(
11
+ "init-state.json",
12
+ json!({ "initialized": true, "intakeStatus": "complete" }),
13
+ );
14
+ self.write_naome_json("upgrade-state.json", json!({ "status": "complete" }));
15
+ self.write_naome_json(
16
+ "verification.json",
17
+ json!({
18
+ "schema": "naome.verification.v1",
19
+ "version": 1,
20
+ "status": "ready",
21
+ "checks": [diff_check(vec!["README.md"])],
22
+ "changeTypes": [],
23
+ "releaseGates": []
24
+ }),
25
+ );
26
+ self.write_naome_json("task-state.json", task_state);
27
+ }
28
+
29
+ pub fn write_readme_quality_verification(
30
+ &self,
31
+ extra_checks: Vec<Value>,
32
+ required_checks: Vec<&str>,
33
+ ) {
34
+ let mut checks = vec![diff_check(vec!["README.md"])];
35
+ checks.extend(extra_checks);
36
+
37
+ self.write_naome_json(
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
+ }),
56
+ );
57
+ }
58
+
59
+ pub fn write_product_quality_verification(&self) {
60
+ self.write_naome_json(
61
+ "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
+ }),
84
+ );
85
+ }
86
+
87
+ pub fn write_source_quality_verification(&self) {
88
+ self.write_naome_json(
89
+ "verification.json",
90
+ verification_value(
91
+ "ready",
92
+ vec![repository_quality_check()],
93
+ vec![change_type(
94
+ "source",
95
+ "Source changes.",
96
+ vec!["src/**"],
97
+ vec!["repository-quality-check"],
98
+ )],
99
+ ),
100
+ );
101
+ }
102
+
103
+ pub fn write_readme_rename_verification(&self) {
104
+ self.write_naome_json(
105
+ "verification.json",
106
+ verification_value(
107
+ "ready",
108
+ vec![diff_check(vec!["README.md", "INTRO.md"])],
109
+ vec![change_type(
110
+ "docs",
111
+ "Repository docs.",
112
+ vec!["README.md", "INTRO.md"],
113
+ vec!["diff-check"],
114
+ )],
115
+ ),
116
+ );
117
+ }
118
+
119
+ pub fn write_unsafe_readme_diff_verification(&self) {
120
+ self.write_naome_json(
121
+ "verification.json",
122
+ verification_value(
123
+ "ready",
124
+ vec![mutating_diff_check()],
125
+ vec![change_type(
126
+ "readme",
127
+ "README changes.",
128
+ vec!["README.md"],
129
+ vec!["diff-check"],
130
+ )],
131
+ ),
132
+ );
133
+ }
134
+ }
135
+
136
+ fn product_quality_checks() -> Vec<serde_json::Value> {
137
+ vec![
138
+ super::verification_values::quality_check(
139
+ "installer-tests",
140
+ "npm run test:naome-installer",
141
+ "Validate installer behavior.",
142
+ "medium",
143
+ vec!["scripts/naome-installer.test.js"],
144
+ ),
145
+ super::verification_values::quality_check(
146
+ "rust-build",
147
+ "npm run build:rust",
148
+ "Build native CLI.",
149
+ "medium",
150
+ vec!["packages/naome/Cargo.toml"],
151
+ ),
152
+ super::verification_values::quality_check(
153
+ "decision-engine-tests",
154
+ "npm run test:decision-engine",
155
+ "Validate route decisions.",
156
+ "fast",
157
+ vec!["packages/naome/crates/naome-core/tests/route.rs"],
158
+ ),
159
+ super::verification_values::quality_check(
160
+ "package-dry-run",
161
+ "npm run pack:dry-run",
162
+ "Validate package metadata.",
163
+ "medium",
164
+ vec!["packages/naome/package.json"],
165
+ ),
166
+ diff_check(vec!["packages/naome/crates/naome-core/src/route.rs"]),
167
+ ]
168
+ }
@@ -0,0 +1,135 @@
1
+ use serde_json::json;
2
+
3
+ pub fn completed_task_state(admission_head: &str) -> serde_json::Value {
4
+ json!({
5
+ "schema": "naome.task-state.v1",
6
+ "version": 1,
7
+ "status": "complete",
8
+ "activeTask": {
9
+ "id": "readme-task",
10
+ "request": "Change README.",
11
+ "userPrompt": {
12
+ "receivedAt": "2026-05-06T00:00:00.000Z",
13
+ "text": "Change README."
14
+ },
15
+ "admission": {
16
+ "command": "node .naome/bin/check-task-state.js --admission",
17
+ "cwd": ".",
18
+ "exitCode": 0,
19
+ "checkedAt": "2026-05-06T00:00:00.000Z",
20
+ "gitHead": admission_head,
21
+ "changedPaths": []
22
+ },
23
+ "allowedPaths": ["README.md"],
24
+ "declaredChangeTypes": ["product-docs"],
25
+ "requiredCheckIds": ["diff-check"],
26
+ "proofResults": [
27
+ {
28
+ "checkId": "diff-check",
29
+ "command": "git diff --check",
30
+ "cwd": ".",
31
+ "exitCode": 0,
32
+ "checkedAt": "2026-05-06T00:00:00.000Z",
33
+ "evidence": ["README.md"]
34
+ }
35
+ ],
36
+ "revisions": [],
37
+ "humanReview": {
38
+ "required": false,
39
+ "approved": false,
40
+ "reason": null
41
+ }
42
+ },
43
+ "blocker": null,
44
+ "updatedAt": "2026-05-06T00:00:00.000Z"
45
+ })
46
+ }
47
+
48
+ pub fn diff_check(evidence: Vec<&str>) -> serde_json::Value {
49
+ json!({
50
+ "id": "diff-check",
51
+ "command": "git diff --check",
52
+ "cwd": ".",
53
+ "purpose": "Reject whitespace errors.",
54
+ "cost": "fast",
55
+ "source": "test",
56
+ "evidence": evidence,
57
+ "lastVerified": null
58
+ })
59
+ }
60
+
61
+ pub fn verification_value(
62
+ status: &str,
63
+ checks: Vec<serde_json::Value>,
64
+ change_types: Vec<serde_json::Value>,
65
+ ) -> serde_json::Value {
66
+ json!({
67
+ "schema": "naome.verification.v1",
68
+ "version": 1,
69
+ "status": status,
70
+ "checks": checks,
71
+ "changeTypes": change_types,
72
+ "releaseGates": []
73
+ })
74
+ }
75
+
76
+ pub fn change_type(
77
+ id: &str,
78
+ description: &str,
79
+ paths: Vec<&str>,
80
+ required_checks: Vec<&str>,
81
+ ) -> serde_json::Value {
82
+ json!({
83
+ "id": id,
84
+ "description": description,
85
+ "paths": paths,
86
+ "requiredChecks": required_checks,
87
+ "recommendedChecks": [],
88
+ "humanReview": false
89
+ })
90
+ }
91
+
92
+ pub fn quality_check(
93
+ id: &str,
94
+ command: &str,
95
+ purpose: &str,
96
+ cost: &str,
97
+ evidence: Vec<&str>,
98
+ ) -> serde_json::Value {
99
+ json!({
100
+ "id": id,
101
+ "command": command,
102
+ "cwd": ".",
103
+ "purpose": purpose,
104
+ "cost": cost,
105
+ "source": "test",
106
+ "evidence": evidence,
107
+ "lastVerified": null
108
+ })
109
+ }
110
+
111
+ pub fn repository_quality_check() -> serde_json::Value {
112
+ json!({
113
+ "id": "repository-quality-check",
114
+ "command": "naome quality check --changed",
115
+ "cwd": ".",
116
+ "purpose": "Validate changed files against repository quality rules.",
117
+ "cost": "fast",
118
+ "source": "NAOME built-in",
119
+ "evidence": ["src/**"],
120
+ "lastVerified": null
121
+ })
122
+ }
123
+
124
+ pub fn mutating_diff_check() -> serde_json::Value {
125
+ json!({
126
+ "id": "diff-check",
127
+ "command": "node -e \"const fs = require('fs'); const marker = '.git/naome-diff-check-marker'; if (fs.existsSync(marker)) { fs.writeFileSync('NEW.md', '# unexpected\\\\n'); } else { fs.writeFileSync(marker, 'x'); }\"",
128
+ "cwd": ".",
129
+ "purpose": "Simulate a mutating diff check.",
130
+ "cost": "fast",
131
+ "source": "test",
132
+ "evidence": ["README.md"],
133
+ "lastVerified": null
134
+ })
135
+ }