@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.
Files changed (77) hide show
  1. package/Cargo.lock +2 -2
  2. package/crates/naome-cli/Cargo.toml +1 -1
  3. package/crates/naome-cli/src/architecture_commands.rs +1 -1
  4. package/crates/naome-cli/src/quality_commands.rs +4 -4
  5. package/crates/naome-core/Cargo.toml +1 -1
  6. package/crates/naome-core/src/architecture/config/parser/sections.rs +1 -1
  7. package/crates/naome-core/src/architecture/config.rs +1 -1
  8. package/crates/naome-core/src/architecture/model.rs +19 -0
  9. package/crates/naome-core/src/architecture/output.rs +27 -24
  10. package/crates/naome-core/src/architecture/rules/budgets.rs +2 -1
  11. package/crates/naome-core/src/architecture/rules.rs +3 -1
  12. package/crates/naome-core/src/architecture/scan/cache.rs +145 -0
  13. package/crates/naome-core/src/architecture/scan/graph_builder.rs +31 -10
  14. package/crates/naome-core/src/architecture/scan.rs +232 -14
  15. package/crates/naome-core/src/architecture.rs +3 -3
  16. package/crates/naome-core/src/intent/legacy.rs +1 -1
  17. package/crates/naome-core/src/intent/model.rs +27 -0
  18. package/crates/naome-core/src/intent/resolver.rs +3 -28
  19. package/crates/naome-core/src/intent/resolver_baseline.rs +1 -2
  20. package/crates/naome-core/src/intent/resolver_policy.rs +1 -2
  21. package/crates/naome-core/src/intent.rs +2 -1
  22. package/crates/naome-core/src/quality/adapter_ios.rs +3 -1
  23. package/crates/naome-core/src/quality/adapter_support.rs +32 -0
  24. package/crates/naome-core/src/quality/adapters.rs +8 -25
  25. package/crates/naome-core/src/quality/analysis_model.rs +33 -0
  26. package/crates/naome-core/src/quality/cache.rs +1 -1
  27. package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +2 -1
  28. package/crates/naome-core/src/quality/checks/near_duplicates.rs +2 -1
  29. package/crates/naome-core/src/quality/mod.rs +1 -0
  30. package/crates/naome-core/src/quality/scanner/analysis.rs +1 -1
  31. package/crates/naome-core/src/quality/scanner.rs +1 -32
  32. package/crates/naome-core/src/quality/semantic/extract.rs +2 -1
  33. package/crates/naome-core/src/quality/structure/adapter_ios.rs +1 -1
  34. package/crates/naome-core/src/quality/structure/adapter_model.rs +23 -0
  35. package/crates/naome-core/src/quality/structure/adapters.rs +2 -23
  36. package/crates/naome-core/src/quality/structure/config.rs +2 -1
  37. package/crates/naome-core/src/quality/structure/defaults.rs +2 -2
  38. package/crates/naome-core/src/quality/structure/mod.rs +1 -0
  39. package/crates/naome-core/src/quality/structure/model.rs +6 -6
  40. package/crates/naome-core/src/repository_model.rs +6 -1
  41. package/crates/naome-core/src/route/builtin_checks.rs +1 -1
  42. package/crates/naome-core/src/route/builtin_require.rs +1 -1
  43. package/crates/naome-core/src/route/execution.rs +2 -34
  44. package/crates/naome-core/src/route/execution_baselines.rs +1 -1
  45. package/crates/naome-core/src/route/execution_model.rs +37 -0
  46. package/crates/naome-core/src/route/execution_support.rs +1 -1
  47. package/crates/naome-core/src/route/execution_tasks.rs +1 -1
  48. package/crates/naome-core/src/route/quality_gate.rs +0 -1
  49. package/crates/naome-core/src/route.rs +3 -1
  50. package/crates/naome-core/src/task_state/api.rs +5 -4
  51. package/crates/naome-core/src/task_state/commit_gate.rs +1 -1
  52. package/crates/naome-core/src/task_state/compact_proof.rs +2 -2
  53. package/crates/naome-core/src/task_state/completed_refresh.rs +0 -13
  54. package/crates/naome-core/src/task_state/completion.rs +13 -4
  55. package/crates/naome-core/src/task_state/mod.rs +1 -1
  56. package/crates/naome-core/src/task_state/progress.rs +1 -1
  57. package/crates/naome-core/src/task_state/proof.rs +1 -4
  58. package/crates/naome-core/src/task_state/proof_entry.rs +1 -1
  59. package/crates/naome-core/src/task_state/proof_model.rs +2 -18
  60. package/crates/naome-core/src/task_state/proof_sources.rs +2 -2
  61. package/crates/naome-core/src/task_state/proof_types.rs +17 -0
  62. package/crates/naome-core/src/task_state/shape.rs +1 -1
  63. package/crates/naome-core/src/task_state/task_diff_api.rs +1 -1
  64. package/crates/naome-core/src/verification_contract_policy.rs +2 -6
  65. package/crates/naome-core/src/workflow/agent/proof.rs +1 -1
  66. package/crates/naome-core/src/workflow/agent.rs +1 -1
  67. package/crates/naome-core/src/workflow/mod.rs +3 -1
  68. package/crates/naome-core/src/workflow/phase_inference.rs +1 -1
  69. package/crates/naome-core/src/workflow/phase_model.rs +22 -0
  70. package/crates/naome-core/src/workflow/phases.rs +1 -21
  71. package/crates/naome-core/tests/architecture_cache.rs +212 -0
  72. package/native/darwin-arm64/naome +0 -0
  73. package/native/linux-x64/naome +0 -0
  74. package/package.json +1 -1
  75. package/templates/naome-root/.naome/manifest.json +1 -1
  76. package/templates/naome-root/docs/naome/architecture-fitness.md +29 -8
  77. package/crates/naome-core/src/task_state/reconcile.rs +0 -7
@@ -8,13 +8,7 @@ use serde_json::Value;
8
8
  use crate::models::NaomeError;
9
9
 
10
10
  use super::phase_inference::infer_phases;
11
-
12
- #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13
- #[serde(rename_all = "camelCase")]
14
- pub struct CommandCheckResult {
15
- pub check_id: String,
16
- pub exit_code: i32,
17
- }
11
+ use super::phase_model::{CheckDefinition, CommandCheckResult, PhaseDefinition};
18
12
 
19
13
  #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20
14
  #[serde(rename_all = "camelCase")]
@@ -35,20 +29,6 @@ pub struct VerificationPhaseStatus {
35
29
  pub blocked_by: Vec<String>,
36
30
  }
37
31
 
38
- #[derive(Debug, Clone)]
39
- pub(super) struct CheckDefinition {
40
- pub(super) id: String,
41
- pub(super) command: String,
42
- pub(super) cost: String,
43
- }
44
-
45
- #[derive(Debug, Clone)]
46
- pub(super) struct PhaseDefinition {
47
- pub(super) id: String,
48
- pub(super) order: u32,
49
- pub(super) check_ids: Vec<String>,
50
- }
51
-
52
32
  pub fn verification_phase_plan(
53
33
  root: &Path,
54
34
  completed: &[CommandCheckResult],
@@ -0,0 +1,212 @@
1
+ use naome_core::{validate_architecture, ArchitectureScanOptions};
2
+ use std::path::Path;
3
+ use std::process::Command;
4
+
5
+ mod architecture_support;
6
+
7
+ use architecture_support::FixtureRepo;
8
+
9
+ #[test]
10
+ fn changed_only_uses_incremental_cache_after_initial_safe_full_scan() {
11
+ let repo = FixtureRepo::new();
12
+ repo.write(
13
+ "naome.arch.yaml",
14
+ forbidden_domain_to_infrastructure_config(),
15
+ );
16
+ repo.write("src/domain/event.ts", "export const event = 1;\n");
17
+ repo.write("src/infrastructure/db.ts", "export const db = 1;\n");
18
+ repo.init_git();
19
+
20
+ let initial = validate_architecture(repo.path(), changed_only()).unwrap();
21
+
22
+ assert!(initial.changed_only_requested);
23
+ assert!(initial.changed_only_degraded_to_full_scan);
24
+ assert_eq!(initial.changed_only_mode, "degraded_full_scan");
25
+ assert_eq!(
26
+ initial.changed_only_degradation_reason.as_deref(),
27
+ Some("cache_miss")
28
+ );
29
+
30
+ repo.write(
31
+ "src/domain/event.ts",
32
+ "import { db } from '../infrastructure/db';\nexport const event = db;\n",
33
+ );
34
+
35
+ let incremental = validate_architecture(repo.path(), changed_only()).unwrap();
36
+
37
+ assert!(incremental.changed_only_requested);
38
+ assert!(!incremental.changed_only_degraded_to_full_scan);
39
+ assert_eq!(incremental.changed_only_mode, "incremental_cache");
40
+ assert_eq!(incremental.changed_only_degradation_reason, None);
41
+ assert_eq!(incremental.files_scanned, 1);
42
+ assert_eq!(incremental.summary.errors, 1);
43
+ assert_eq!(
44
+ incremental.violations[0].path.as_deref(),
45
+ Some("src/domain/event.ts")
46
+ );
47
+ }
48
+
49
+ #[test]
50
+ fn changed_only_degrades_when_architecture_config_changes() {
51
+ let repo = FixtureRepo::new();
52
+ repo.write(
53
+ "naome.arch.yaml",
54
+ forbidden_domain_to_infrastructure_config(),
55
+ );
56
+ repo.write("src/domain/event.ts", "export const event = 1;\n");
57
+ repo.write("src/infrastructure/db.ts", "export const db = 1;\n");
58
+ repo.init_git();
59
+ validate_architecture(repo.path(), changed_only()).unwrap();
60
+
61
+ repo.write(
62
+ "naome.arch.yaml",
63
+ "layers:\n application:\n paths:\n - \"src/**\"\n",
64
+ );
65
+
66
+ let report = validate_architecture(repo.path(), changed_only()).unwrap();
67
+
68
+ assert!(report.changed_only_degraded_to_full_scan);
69
+ assert_eq!(report.changed_only_mode, "degraded_full_scan");
70
+ assert_eq!(
71
+ report.changed_only_degradation_reason.as_deref(),
72
+ Some("config_changed")
73
+ );
74
+ }
75
+
76
+ #[test]
77
+ fn changed_only_degrades_when_repository_file_set_changes() {
78
+ let repo = FixtureRepo::new();
79
+ repo.write(
80
+ "naome.arch.yaml",
81
+ forbidden_domain_to_infrastructure_config(),
82
+ );
83
+ repo.write("src/domain/event.ts", "export const event = 1;\n");
84
+ repo.write("src/infrastructure/db.ts", "export const db = 1;\n");
85
+ repo.init_git();
86
+ validate_architecture(repo.path(), changed_only()).unwrap();
87
+
88
+ repo.write("src/domain/new.ts", "export const fresh = 1;\n");
89
+
90
+ let report = validate_architecture(repo.path(), changed_only()).unwrap();
91
+
92
+ assert!(report.changed_only_degraded_to_full_scan);
93
+ assert_eq!(report.changed_only_mode, "degraded_full_scan");
94
+ assert_eq!(
95
+ report.changed_only_degradation_reason.as_deref(),
96
+ Some("file_set_changed")
97
+ );
98
+ }
99
+
100
+ #[test]
101
+ fn changed_only_degrades_when_cached_clean_file_content_changed() {
102
+ let repo = FixtureRepo::new();
103
+ repo.write(
104
+ "naome.arch.yaml",
105
+ forbidden_domain_to_infrastructure_config(),
106
+ );
107
+ repo.write("src/domain/event.ts", "export const event = 1;\n");
108
+ repo.write("src/infrastructure/db.ts", "export const db = 1;\n");
109
+ repo.init_git();
110
+ validate_architecture(repo.path(), changed_only()).unwrap();
111
+
112
+ repo.write(
113
+ "src/domain/event.ts",
114
+ "import { db } from '../infrastructure/db';\nexport const event = db;\n",
115
+ );
116
+ commit_all(repo.path(), "content change after cache");
117
+
118
+ let report = validate_architecture(repo.path(), changed_only()).unwrap();
119
+
120
+ assert!(report.changed_only_requested);
121
+ assert!(report.changed_only_degraded_to_full_scan);
122
+ assert_eq!(report.changed_only_mode, "degraded_full_scan");
123
+ assert_eq!(
124
+ report.changed_only_degradation_reason.as_deref(),
125
+ Some("content_changed")
126
+ );
127
+ assert_eq!(report.summary.errors, 1);
128
+ }
129
+
130
+ #[test]
131
+ fn changed_only_degrades_when_go_module_context_changes() {
132
+ let repo = FixtureRepo::new();
133
+ repo.write(
134
+ "naome.arch.yaml",
135
+ forbidden_domain_to_infrastructure_config(),
136
+ );
137
+ repo.write("go.mod", "module example.com/old\n\ngo 1.22\n");
138
+ repo.write(
139
+ "src/domain/event.go",
140
+ "package domain\n\nimport \"example.com/new/src/infrastructure/db\"\n\nvar Event = db.Value\n",
141
+ );
142
+ repo.write(
143
+ "src/infrastructure/db/db.go",
144
+ "package db\n\nvar Value = 1\n",
145
+ );
146
+ repo.init_git();
147
+ let initial = validate_architecture(repo.path(), changed_only()).unwrap();
148
+ assert_eq!(initial.summary.errors, 0);
149
+
150
+ repo.write("go.mod", "module example.com/new\n\ngo 1.22\n");
151
+
152
+ let report = validate_architecture(repo.path(), changed_only()).unwrap();
153
+
154
+ assert!(report.changed_only_requested);
155
+ assert!(report.changed_only_degraded_to_full_scan);
156
+ assert_eq!(report.changed_only_mode, "degraded_full_scan");
157
+ assert_eq!(
158
+ report.changed_only_degradation_reason.as_deref(),
159
+ Some("resolver_context_changed")
160
+ );
161
+ assert_eq!(report.summary.errors, 1);
162
+ assert_eq!(
163
+ report.violations[0].path.as_deref(),
164
+ Some("src/domain/event.go")
165
+ );
166
+ }
167
+
168
+ fn changed_only() -> ArchitectureScanOptions {
169
+ ArchitectureScanOptions {
170
+ changed_only: true,
171
+ ..ArchitectureScanOptions::default()
172
+ }
173
+ }
174
+
175
+ fn forbidden_domain_to_infrastructure_config() -> &'static str {
176
+ r#"layers:
177
+ domain:
178
+ paths:
179
+ - "src/domain/**"
180
+ infrastructure:
181
+ paths:
182
+ - "src/infrastructure/**"
183
+ allowed_dependencies:
184
+ domain:
185
+ infrastructure:
186
+ - domain
187
+ rules:
188
+ no_forbidden_layer_dependencies:
189
+ enabled: true
190
+ severity: error
191
+ "#
192
+ }
193
+
194
+ fn commit_all(root: &Path, message: &str) {
195
+ run_git(root, &["add", "."]);
196
+ run_git(root, &["commit", "-m", message]);
197
+ }
198
+
199
+ fn run_git(root: &Path, args: &[&str]) {
200
+ let output = Command::new("git")
201
+ .args(args)
202
+ .current_dir(root)
203
+ .output()
204
+ .unwrap();
205
+ assert!(
206
+ output.status.success(),
207
+ "git {:?} failed: {}{}",
208
+ args,
209
+ String::from_utf8_lossy(&output.stdout),
210
+ String::from_utf8_lossy(&output.stderr)
211
+ );
212
+ }
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lamentis/naome",
3
- "version": "1.3.13",
3
+ "version": "1.3.15",
4
4
  "description": "Native-first CLI for the NAOME agent harness.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  ".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
10
10
  "AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
11
11
  "docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
12
- "docs/naome/architecture-fitness.md": "sha256:26f04884c3ada083380bee5c3cb1aa3f39d8c8a1cc31ccc84c4ae795c594de5b",
12
+ "docs/naome/architecture-fitness.md": "sha256:88aa979f61f82c2802c416af2c374ba041c94157189d59048d6889b07034d394",
13
13
  "docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
14
14
  "docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
15
15
  "docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
@@ -14,8 +14,9 @@ facts instead of prompt text.
14
14
  - `naome arch validate` runs architecture rules with human output.
15
15
  - `naome arch validate --json` emits stable machine-readable output.
16
16
  - `naome arch validate --agent-feedback` emits compact repair instructions.
17
- - `naome arch validate --changed-only` uses changed paths when available and
18
- safely degrades to a full scan for graph-level soundness.
17
+ - `naome arch validate --changed-only` uses changed paths with the persistent
18
+ architecture cache when available and safely degrades to a full scan when the
19
+ cache cannot prove graph-level soundness.
19
20
 
20
21
  ## Graph Model
21
22
 
@@ -127,17 +128,37 @@ ignore:
127
128
  Agents should run `naome arch validate --changed-only --json` after changing
128
129
  source or template files. JSON output includes status, severity counts,
129
130
  violations, concrete suggestions, and `agentFeedback` entries optimized for
130
- repair loops.
131
+ repair loops. It also reports `changedOnlyMode` and
132
+ `changedOnlyDegradationReason`, so agents can distinguish an incremental cache
133
+ run from a deliberate full-scan fallback.
134
+
135
+ ## Incremental Cache
136
+
137
+ NAOME stores architecture file facts in `.naome/cache/architecture/cache.json`.
138
+ Cache entries are keyed by file path and content hash, and the cache is tied to
139
+ the effective architecture config hash plus the repository file-list hash.
140
+
141
+ Changed-only validation is sound by construction:
142
+
143
+ - the first run without a compatible cache performs a full scan and records
144
+ `changedOnlyMode: "degraded_full_scan"` with reason `cache_miss`;
145
+ - config changes perform a full scan with reason `config_changed`;
146
+ - added or deleted repository files perform a full scan with reason
147
+ `file_set_changed`;
148
+ - when config and file set are unchanged, NAOME reuses cached facts for
149
+ untouched files, rescans changed files, rebuilds the full graph, and runs all
150
+ graph-level rules against that graph.
131
151
 
132
152
  ## CI Integration
133
153
 
134
154
  Use `node .naome/bin/naome.js arch validate --changed-only` as a fast gate.
135
- The first foundation release reports warnings for existing file-size debt and
136
- fails only on configured error rules.
155
+ The command is deterministic in both cache-backed and fallback modes; CI can
156
+ inspect the JSON fields above when it needs to distinguish performance from
157
+ soundness fallbacks.
137
158
 
138
159
  ## Language Support
139
160
 
140
- The v1.3.13 foundation classifies TypeScript, JavaScript, Rust, Python, Go,
161
+ The v1.3.14 foundation classifies TypeScript, JavaScript, Rust, Python, Go,
141
162
  Java, Kotlin, and Swift files by path extension. It extracts import facts for
142
163
  TypeScript, JavaScript, Rust, Python, Go, and Swift, resolves relative imports
143
164
  and simple repository-absolute aliases where the language supports them, and
@@ -158,5 +179,5 @@ policies.
158
179
 
159
180
  This release intentionally keeps validation file-graph based. Manifest
160
181
  extractors are dependency-owner oriented and do not yet parse every build-tool
161
- feature. SARIF output, persistent scan caching, and deeper symbol-level call
162
- analysis remain planned follow-up slices before v1.4.0.
182
+ feature. SARIF output and deeper symbol-level call analysis remain planned
183
+ follow-up slices before v1.4.0.
@@ -1,7 +0,0 @@
1
- pub(super) use super::completed_refresh::add_completed_task_diff_notice;
2
- pub(super) use super::push_gate::{format_dirty_diff_admission_blocker, validate_push_gate};
3
- pub(super) use super::repair::{
4
- is_deterministic_harness_refresh_diff, is_harness_repair_diff,
5
- is_install_or_upgrade_baseline_diff, is_packaged_machine_owned_path, is_repair_archive_path,
6
- is_safe_harness_refresh_path,
7
- };