@lamentis/naome 1.2.0 → 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 (113) hide show
  1. package/Cargo.lock +2 -2
  2. package/bin/naome-node.js +2 -1579
  3. package/bin/naome.js +19 -5
  4. package/crates/naome-cli/Cargo.toml +1 -1
  5. package/crates/naome-cli/src/dispatcher.rs +2 -1
  6. package/crates/naome-cli/src/main.rs +3 -0
  7. package/crates/naome-cli/src/quality_commands.rs +90 -2
  8. package/crates/naome-core/Cargo.toml +1 -1
  9. package/crates/naome-core/src/decision/checks.rs +64 -0
  10. package/crates/naome-core/src/decision/idle.rs +67 -0
  11. package/crates/naome-core/src/decision/json.rs +36 -0
  12. package/crates/naome-core/src/decision/states.rs +165 -0
  13. package/crates/naome-core/src/decision.rs +131 -353
  14. package/crates/naome-core/src/install_plan.rs +2 -0
  15. package/crates/naome-core/src/lib.rs +5 -3
  16. package/crates/naome-core/src/paths.rs +3 -1
  17. package/crates/naome-core/src/quality/adapter_support.rs +89 -0
  18. package/crates/naome-core/src/quality/adapters.rs +20 -67
  19. package/crates/naome-core/src/quality/cleanup.rs +13 -1
  20. package/crates/naome-core/src/quality/config.rs +8 -15
  21. package/crates/naome-core/src/quality/config_support.rs +24 -0
  22. package/crates/naome-core/src/quality/mod.rs +18 -0
  23. package/crates/naome-core/src/quality/scanner.rs +20 -8
  24. package/crates/naome-core/src/quality/structure/adapters.rs +84 -0
  25. package/crates/naome-core/src/quality/structure/checks/basic.rs +153 -0
  26. package/crates/naome-core/src/quality/structure/checks/directory.rs +144 -0
  27. package/crates/naome-core/src/quality/structure/checks/pairing.rs +63 -0
  28. package/crates/naome-core/src/quality/structure/checks.rs +124 -0
  29. package/crates/naome-core/src/quality/structure/classify/roles.rs +188 -0
  30. package/crates/naome-core/src/quality/structure/classify.rs +94 -0
  31. package/crates/naome-core/src/quality/structure/config.rs +89 -0
  32. package/crates/naome-core/src/quality/structure/defaults.rs +107 -0
  33. package/crates/naome-core/src/quality/structure/mod.rs +77 -0
  34. package/crates/naome-core/src/quality/structure/model.rs +124 -0
  35. package/crates/naome-core/src/quality/types.rs +3 -0
  36. package/crates/naome-core/src/route/builtin_checks.rs +155 -0
  37. package/crates/naome-core/src/route/builtin_context.rs +73 -0
  38. package/crates/naome-core/src/route/builtin_integrity.rs +49 -0
  39. package/crates/naome-core/src/route/builtin_require.rs +40 -0
  40. package/crates/naome-core/src/route/context.rs +180 -0
  41. package/crates/naome-core/src/route/execution.rs +96 -0
  42. package/crates/naome-core/src/route/execution_baselines.rs +146 -0
  43. package/crates/naome-core/src/route/execution_support.rs +57 -0
  44. package/crates/naome-core/src/route/execution_tasks.rs +71 -0
  45. package/crates/naome-core/src/route/git_ops.rs +72 -0
  46. package/crates/naome-core/src/route/quality_gate.rs +73 -0
  47. package/crates/naome-core/src/route/quality_gate_config.rs +126 -0
  48. package/crates/naome-core/src/route/quality_gate_snapshot.rs +69 -0
  49. package/crates/naome-core/src/route/worktree.rs +75 -0
  50. package/crates/naome-core/src/route/worktree_files.rs +32 -0
  51. package/crates/naome-core/src/route/worktree_plan.rs +131 -0
  52. package/crates/naome-core/src/route.rs +44 -1217
  53. package/crates/naome-core/src/verification.rs +1 -0
  54. package/crates/naome-core/tests/decision.rs +24 -118
  55. package/crates/naome-core/tests/harness_health.rs +2 -0
  56. package/crates/naome-core/tests/quality.rs +12 -118
  57. package/crates/naome-core/tests/quality_structure.rs +116 -0
  58. package/crates/naome-core/tests/quality_structure_adapters.rs +98 -0
  59. package/crates/naome-core/tests/quality_structure_policy.rs +125 -0
  60. package/crates/naome-core/tests/quality_structure_support/mod.rs +249 -0
  61. package/crates/naome-core/tests/repo_support/mod.rs +16 -0
  62. package/crates/naome-core/tests/repo_support/repo.rs +113 -0
  63. package/crates/naome-core/tests/repo_support/repo_factories.rs +99 -0
  64. package/crates/naome-core/tests/repo_support/repo_helpers.rs +123 -0
  65. package/crates/naome-core/tests/repo_support/routes.rs +81 -0
  66. package/crates/naome-core/tests/repo_support/verification.rs +168 -0
  67. package/crates/naome-core/tests/repo_support/verification_values.rs +135 -0
  68. package/crates/naome-core/tests/route.rs +1 -1376
  69. package/crates/naome-core/tests/route_baseline.rs +86 -0
  70. package/crates/naome-core/tests/route_completion.rs +141 -0
  71. package/crates/naome-core/tests/route_harness_refresh.rs +135 -0
  72. package/crates/naome-core/tests/route_user_diff.rs +198 -0
  73. package/crates/naome-core/tests/route_worktree.rs +54 -0
  74. package/crates/naome-core/tests/task_state.rs +60 -432
  75. package/crates/naome-core/tests/task_state_compact_support/repo.rs +1 -1
  76. package/crates/naome-core/tests/task_state_support/mod.rs +163 -0
  77. package/crates/naome-core/tests/task_state_support/states.rs +84 -0
  78. package/crates/naome-core/tests/verification.rs +4 -45
  79. package/crates/naome-core/tests/verification_contract.rs +22 -78
  80. package/crates/naome-core/tests/workflow_support/mod.rs +1 -1
  81. package/installer/agents.js +90 -0
  82. package/installer/context.js +67 -0
  83. package/installer/filesystem.js +166 -0
  84. package/installer/flows.js +84 -0
  85. package/installer/git-boundary.js +170 -0
  86. package/installer/git-hook-content.js +36 -0
  87. package/installer/git-hooks.js +134 -0
  88. package/installer/git-local.js +2 -0
  89. package/installer/git-shared.js +35 -0
  90. package/installer/harness-file-ops.js +140 -0
  91. package/installer/harness-files.js +56 -0
  92. package/installer/harness-verification.js +123 -0
  93. package/installer/install-plan.js +66 -0
  94. package/installer/main.js +25 -0
  95. package/installer/manifest-state.js +167 -0
  96. package/installer/native-build.js +24 -0
  97. package/installer/native-format.js +6 -0
  98. package/installer/native.js +162 -0
  99. package/installer/output.js +131 -0
  100. package/installer/version.js +32 -0
  101. package/native/darwin-arm64/naome +0 -0
  102. package/native/linux-x64/naome +0 -0
  103. package/package.json +2 -1
  104. package/templates/naome-root/.naome/bin/check-harness-health.js +2 -2
  105. package/templates/naome-root/.naome/bin/check-task-state.js +2 -2
  106. package/templates/naome-root/.naome/bin/naome.js +25 -21
  107. package/templates/naome-root/.naome/manifest.json +4 -2
  108. package/templates/naome-root/.naome/repository-structure.json +90 -0
  109. package/templates/naome-root/.naome/verification.json +1 -0
  110. package/templates/naome-root/docs/naome/index.md +4 -3
  111. package/templates/naome-root/docs/naome/repository-quality.md +3 -0
  112. package/templates/naome-root/docs/naome/repository-structure.md +51 -0
  113. package/templates/naome-root/docs/naome/testing.md +2 -1
@@ -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
+ }