@lamentis/naome 1.3.11 → 1.3.12

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 (30) 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 +2 -6
  4. package/crates/naome-cli/tests/architecture_cli.rs +60 -0
  5. package/crates/naome-core/Cargo.toml +1 -1
  6. package/crates/naome-core/src/architecture/config/parser/sections.rs +44 -1
  7. package/crates/naome-core/src/architecture/config/parser.rs +1 -0
  8. package/crates/naome-core/src/architecture/config.rs +35 -0
  9. package/crates/naome-core/src/architecture/output.rs +15 -1
  10. package/crates/naome-core/src/architecture/rules/budgets.rs +179 -0
  11. package/crates/naome-core/src/architecture/rules/context.rs +138 -0
  12. package/crates/naome-core/src/architecture/rules/cycles.rs +39 -0
  13. package/crates/naome-core/src/architecture/rules/external.rs +185 -0
  14. package/crates/naome-core/src/architecture/rules/graph.rs +177 -0
  15. package/crates/naome-core/src/architecture/rules/transitive.rs +89 -0
  16. package/crates/naome-core/src/architecture/rules.rs +13 -39
  17. package/crates/naome-core/src/architecture/scan/imports/extractors.rs +4 -7
  18. package/crates/naome-core/src/architecture/scan/imports/resolver.rs +3 -21
  19. package/crates/naome-core/src/architecture/scan/imports.rs +16 -0
  20. package/crates/naome-core/src/architecture.rs +1 -1
  21. package/crates/naome-core/src/lib.rs +1 -0
  22. package/crates/naome-core/tests/architecture.rs +53 -85
  23. package/crates/naome-core/tests/architecture_rules.rs +498 -0
  24. package/crates/naome-core/tests/architecture_support/mod.rs +78 -0
  25. package/installer/harness-files.js +3 -3
  26. package/native/darwin-arm64/naome +0 -0
  27. package/native/linux-x64/naome +0 -0
  28. package/package.json +1 -1
  29. package/templates/naome-root/.naome/manifest.json +1 -1
  30. package/templates/naome-root/docs/naome/architecture-fitness.md +49 -6
@@ -0,0 +1,78 @@
1
+ use std::fs;
2
+ use std::path::{Path, PathBuf};
3
+ use std::process::Command;
4
+ use std::sync::atomic::{AtomicU64, Ordering};
5
+ use std::time::{SystemTime, UNIX_EPOCH};
6
+
7
+ use naome_core::{ArchitectureEdgeKind, ArchitectureScanReport};
8
+
9
+ static FIXTURE_COUNTER: AtomicU64 = AtomicU64::new(0);
10
+
11
+ pub struct FixtureRepo {
12
+ root: PathBuf,
13
+ }
14
+
15
+ impl FixtureRepo {
16
+ pub fn new() -> Self {
17
+ let nonce = SystemTime::now()
18
+ .duration_since(UNIX_EPOCH)
19
+ .unwrap()
20
+ .as_nanos();
21
+ let counter = FIXTURE_COUNTER.fetch_add(1, Ordering::Relaxed);
22
+ let root = std::env::temp_dir().join(format!(
23
+ "naome-arch-fixture-{}-{nonce}-{counter}",
24
+ std::process::id()
25
+ ));
26
+ fs::create_dir_all(&root).unwrap();
27
+ fs::write(
28
+ root.join(".naomeignore"),
29
+ ".naome/archive/\n.naome/tasks/\n",
30
+ )
31
+ .unwrap();
32
+ Self { root }
33
+ }
34
+
35
+ pub fn path(&self) -> &Path {
36
+ &self.root
37
+ }
38
+
39
+ pub fn write(&self, relative_path: &str, content: &str) {
40
+ let fixture_path = self.root.join(relative_path);
41
+ if let Some(parent) = fixture_path.parent() {
42
+ if !parent.exists() {
43
+ fs::create_dir_all(parent).unwrap();
44
+ }
45
+ }
46
+ fs::write(&fixture_path, content.as_bytes()).unwrap();
47
+ }
48
+
49
+ pub fn init_git(&self) {
50
+ run_git(&self.root, &["init"]);
51
+ run_git(&self.root, &["config", "user.email", "naome@example.com"]);
52
+ run_git(&self.root, &["config", "user.name", "NAOME Test"]);
53
+ self.write("README.md", "# Fixture\n");
54
+ run_git(&self.root, &["add", "."]);
55
+ run_git(&self.root, &["commit", "-m", "baseline"]);
56
+ }
57
+ }
58
+
59
+ pub fn has_import_edge(scan: &ArchitectureScanReport, from: &str, to: &str) -> bool {
60
+ scan.graph.edges.iter().any(|edge| {
61
+ edge.kind == ArchitectureEdgeKind::Imports && edge.from == from && edge.to == to
62
+ })
63
+ }
64
+
65
+ fn run_git(root: &Path, args: &[&str]) {
66
+ let result = Command::new("git")
67
+ .args(args)
68
+ .current_dir(root)
69
+ .output()
70
+ .unwrap();
71
+ assert!(
72
+ result.status.success(),
73
+ "git {:?} failed: {}{}",
74
+ args,
75
+ String::from_utf8_lossy(&result.stdout),
76
+ String::from_utf8_lossy(&result.stderr)
77
+ );
78
+ }
@@ -22,7 +22,7 @@ export function ensureCoreHarnessFiles(ctx, archiveDirName) {
22
22
  replaceHarnessFile(ctx, "docs/naome/task-ledger.md", archiveDirName);
23
23
  ensureTemplateFile(ctx, "docs/naome/repository-model.md");
24
24
  ensureTemplateFile(ctx, "docs/naome/security.md");
25
- ensureTemplateFile(ctx, "docs/naome/architecture-fitness.md");
25
+ replaceHarnessFile(ctx, "docs/naome/architecture-fitness.md", archiveDirName);
26
26
  replaceHarnessFile(ctx, "docs/naome/upgrade.md", archiveDirName);
27
27
  }
28
28
 
@@ -40,7 +40,7 @@ export function ensureTaskControlHarnessFiles(ctx, archiveDirName) {
40
40
  replaceHarnessFile(ctx, "docs/naome/agent-workflow.md", archiveDirName);
41
41
  replaceHarnessFile(ctx, "docs/naome/context-economy.md", archiveDirName);
42
42
  replaceHarnessFile(ctx, "docs/naome/execution.md", archiveDirName);
43
- ensureTemplateFile(ctx, "docs/naome/architecture-fitness.md");
43
+ replaceHarnessFile(ctx, "docs/naome/architecture-fitness.md", archiveDirName);
44
44
  replaceHarnessFile(ctx, "docs/naome/upgrade.md", archiveDirName);
45
45
  }
46
46
 
@@ -59,7 +59,7 @@ export function ensureHarnessHealthFiles(ctx, archiveDirName) {
59
59
  replaceHarnessFile(ctx, "docs/naome/context-economy.md", archiveDirName);
60
60
  replaceHarnessFile(ctx, "docs/naome/execution.md", archiveDirName);
61
61
  ensureTemplateFile(ctx, "docs/naome/security.md");
62
- ensureTemplateFile(ctx, "docs/naome/architecture-fitness.md");
62
+ replaceHarnessFile(ctx, "docs/naome/architecture-fitness.md", archiveDirName);
63
63
  replaceHarnessFile(ctx, "docs/naome/upgrade.md", archiveDirName);
64
64
  ensureNaomeIgnore(ctx);
65
65
  }
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lamentis/naome",
3
- "version": "1.3.11",
3
+ "version": "1.3.12",
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:a1f08dc02eff4e4c37934cf48e3d7ed2453e34d55dac475bc24ab913e03f263d",
12
+ "docs/naome/architecture-fitness.md": "sha256:3963d9a92d6481d4e72815a4dd749549320f23c45100b4821e75b7e6f3ffd00b",
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",
@@ -53,6 +53,29 @@ rules:
53
53
  no_forbidden_layer_dependencies:
54
54
  enabled: true
55
55
  severity: error
56
+ no_cross_context_internal_imports:
57
+ enabled: true
58
+ severity: error
59
+ public_api_boundary:
60
+ enabled: true
61
+ severity: error
62
+ no_cycles:
63
+ enabled: true
64
+ severity: error
65
+ no_transitive_forbidden_layer_dependencies:
66
+ enabled: true
67
+ severity: error
68
+ max_imports_per_file:
69
+ enabled: true
70
+ value: 20
71
+ severity: warning
72
+ max_fan_out:
73
+ enabled: true
74
+ value: 20
75
+ severity: warning
76
+ external_dependency_policy:
77
+ enabled: true
78
+ severity: error
56
79
  max_file_lines:
57
80
  enabled: true
58
81
  value: 400
@@ -66,6 +89,14 @@ allowed_dependencies:
66
89
  infrastructure:
67
90
  - domain
68
91
 
92
+ external_dependencies:
93
+ domain:
94
+ allow: []
95
+ infrastructure:
96
+ allow:
97
+ - "stripe"
98
+ - "@supabase/*"
99
+
69
100
  ignore:
70
101
  - path: "generated/**"
71
102
  reason: "Generated code is not architecture-owned."
@@ -79,6 +110,17 @@ ignore:
79
110
  change.
80
111
  - `arch.no_forbidden_layer_dependencies` rejects import edges whose source
81
112
  layer is not allowed to depend on the imported file's layer.
113
+ - `arch.no_cross_context_internal_imports` rejects imports into another bounded
114
+ context's internal files.
115
+ - `arch.public_api_boundary` requires cross-context imports to target declared
116
+ `public_api` paths.
117
+ - `arch.no_cycles` detects file-level import cycles.
118
+ - `arch.no_transitive_forbidden_layer_dependencies` catches indirect reachability
119
+ from a layer to a forbidden layer.
120
+ - `arch.max_imports_per_file` and `arch.max_fan_out` enforce local dependency
121
+ budgets.
122
+ - `arch.external_dependency_policy` enforces allowed external packages per layer
123
+ or context.
82
124
 
83
125
  ## Agent Integration
84
126
 
@@ -95,15 +137,16 @@ fails only on configured error rules.
95
137
 
96
138
  ## Language Support
97
139
 
98
- The v1.3.11 foundation classifies TypeScript, JavaScript, Rust, Python, Go,
140
+ The v1.3.12 foundation classifies TypeScript, JavaScript, Rust, Python, Go,
99
141
  Java, Kotlin, and Swift files by path extension. It extracts import facts for
100
142
  TypeScript, JavaScript, Rust, Python, and Go, resolves relative imports and
101
143
  simple repository-absolute aliases, and represents unresolved imports
102
- explicitly as graph nodes instead of dropping them.
144
+ explicitly as graph nodes instead of dropping them. Architecture rules now
145
+ cover layers, bounded contexts, public APIs, cycles, transitive layer reach,
146
+ import/fan-out budgets, and external dependency policies.
103
147
 
104
148
  ## Limitations
105
149
 
106
- This release intentionally validates direct file-level import edges. Manifest
107
- extractors, cross-context public API boundaries, cycle detection, transitive
108
- forbidden dependencies, SARIF output, and persistent scan caching remain planned
109
- follow-up slices before v1.4.0.
150
+ This release intentionally keeps validation file-graph based. Manifest
151
+ extractors, SARIF output, persistent scan caching, and deeper symbol-level call
152
+ analysis remain planned follow-up slices before v1.4.0.