@lamentis/naome 1.3.17 → 1.4.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 (55) 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 +16 -3
  4. package/crates/naome-cli/src/main.rs +10 -1
  5. package/crates/naome-cli/src/task_commands/common.rs +32 -0
  6. package/crates/naome-cli/src/task_commands/readiness.rs +40 -0
  7. package/crates/naome-cli/src/task_commands/record.rs +134 -0
  8. package/crates/naome-cli/src/task_commands/repair.rs +30 -0
  9. package/crates/naome-cli/src/task_commands/scope_request.rs +24 -0
  10. package/crates/naome-cli/src/task_commands/timeline.rs +71 -0
  11. package/crates/naome-cli/src/task_commands.rs +69 -1
  12. package/crates/naome-cli/tests/task_cli.rs +58 -0
  13. package/crates/naome-cli/tests/task_cli_agent_controls.rs +217 -0
  14. package/crates/naome-cli/tests/task_cli_control.rs +126 -0
  15. package/crates/naome-cli/tests/task_cli_support/mod.rs +150 -0
  16. package/crates/naome-core/Cargo.toml +1 -1
  17. package/crates/naome-core/src/architecture/output.rs +196 -0
  18. package/crates/naome-core/src/architecture/scan/cache.rs +1 -1
  19. package/crates/naome-core/src/architecture.rs +1 -0
  20. package/crates/naome-core/src/lib.rs +15 -9
  21. package/crates/naome-core/src/task_state/mod.rs +10 -0
  22. package/crates/naome-core/src/task_state/status/agent_model.rs +76 -0
  23. package/crates/naome-core/src/task_state/status/control/action.rs +87 -0
  24. package/crates/naome-core/src/task_state/status/control/exit_code.rs +32 -0
  25. package/crates/naome-core/src/task_state/status/control/loop_state.rs +70 -0
  26. package/crates/naome-core/src/task_state/status/control/policy.rs +31 -0
  27. package/crates/naome-core/src/task_state/status/control/proof_recording.rs +25 -0
  28. package/crates/naome-core/src/task_state/status/control/recovery.rs +19 -0
  29. package/crates/naome-core/src/task_state/status/control/repair.rs +125 -0
  30. package/crates/naome-core/src/task_state/status/control/shared.rs +25 -0
  31. package/crates/naome-core/src/task_state/status/control.rs +16 -0
  32. package/crates/naome-core/src/task_state/status/git.rs +133 -0
  33. package/crates/naome-core/src/task_state/status/model.rs +150 -0
  34. package/crates/naome-core/src/task_state/status/proof.rs +167 -0
  35. package/crates/naome-core/src/task_state/status/proof_read.rs +150 -0
  36. package/crates/naome-core/src/task_state/status/report.rs +148 -0
  37. package/crates/naome-core/src/task_state/status/report_context.rs +126 -0
  38. package/crates/naome-core/src/task_state/status/report_support.rs +117 -0
  39. package/crates/naome-core/src/task_state/status/scope.rs +111 -0
  40. package/crates/naome-core/src/task_state/status/transition.rs +73 -0
  41. package/crates/naome-core/src/task_state/status.rs +23 -0
  42. package/crates/naome-core/src/task_state/status_output.rs +103 -0
  43. package/crates/naome-core/tests/architecture_cache.rs +1 -1
  44. package/crates/naome-core/tests/architecture_config.rs +68 -1
  45. package/crates/naome-core/tests/task_state_support/mod.rs +15 -1
  46. package/crates/naome-core/tests/task_state_support/states.rs +4 -0
  47. package/crates/naome-core/tests/task_status.rs +301 -0
  48. package/crates/naome-core/tests/task_status_git.rs +141 -0
  49. package/native/darwin-arm64/naome +0 -0
  50. package/native/linux-x64/naome +0 -0
  51. package/package.json +1 -1
  52. package/templates/naome-root/.naome/bin/check-harness-health.js +1 -1
  53. package/templates/naome-root/.naome/bin/check-task-state.js +1 -1
  54. package/templates/naome-root/.naome/manifest.json +2 -2
  55. package/templates/naome-root/docs/naome/architecture-fitness.md +23 -23
@@ -0,0 +1,141 @@
1
+ #![allow(dead_code, unused_imports)]
2
+
3
+ use std::fs;
4
+
5
+ use naome_core::{task_status_exit_code, task_status_report};
6
+ use serde_json::json;
7
+
8
+ mod task_state_support;
9
+
10
+ use task_state_support::{active_task, task_state_with_status, TaskFixture};
11
+
12
+ #[test]
13
+ fn task_status_reports_git_recovery_findings() {
14
+ let repo = TaskFixture::new(task_state_with_status(
15
+ "implementing",
16
+ active_task(json!({
17
+ "allowedPaths": ["**"],
18
+ "requiredCheckIds": [],
19
+ "proofResults": []
20
+ })),
21
+ ));
22
+ repo.init_git();
23
+ repo.set_admission_head("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
24
+
25
+ let status = task_status_report(repo.path()).unwrap();
26
+
27
+ assert_eq!(status.git.admission_head_reachable, false);
28
+ assert!(status
29
+ .findings
30
+ .iter()
31
+ .any(|finding| finding.id == "task.git.admission_head_missing"));
32
+ }
33
+
34
+ #[test]
35
+ fn task_status_reports_unreachable_existing_admission_head() {
36
+ let repo = TaskFixture::new(task_state_with_status(
37
+ "implementing",
38
+ active_task(json!({})),
39
+ ));
40
+ repo.init_git();
41
+ let admission_head = repo.git(["rev-parse", "HEAD"]).trim().to_string();
42
+ repo.git(["checkout", "--orphan", "other"]);
43
+ repo.write("OTHER.md", "other\n");
44
+ repo.git(["add", "."]);
45
+ repo.git(["commit", "-m", "other"]);
46
+ repo.set_admission_head(&admission_head);
47
+
48
+ let status = task_status_report(repo.path()).unwrap();
49
+
50
+ assert!(status.findings.iter().any(|finding| {
51
+ finding.id == "task.git.admission_head_not_reachable"
52
+ && finding.suggested_fix.contains("Rebase")
53
+ }));
54
+ }
55
+
56
+ #[test]
57
+ fn task_status_reports_operation_in_progress_and_conflict_markers() {
58
+ let repo = TaskFixture::new(task_state_with_status(
59
+ "implementing",
60
+ active_task(json!({})),
61
+ ));
62
+ repo.init_git();
63
+ let merge_head = repo.git(["rev-parse", "--git-path", "MERGE_HEAD"]);
64
+ fs::write(repo.path().join(merge_head.trim()), "deadbeef\n").unwrap();
65
+
66
+ let status = task_status_report(repo.path()).unwrap();
67
+ assert!(status
68
+ .findings
69
+ .iter()
70
+ .any(|finding| finding.id == "task.git.operation_in_progress"));
71
+
72
+ fs::write(
73
+ repo.path().join(".naome/task-state.json"),
74
+ "<<<<<<< HEAD\n{}\n=======\n{}\n>>>>>>> branch\n",
75
+ )
76
+ .unwrap();
77
+ let status = task_status_report(repo.path()).unwrap();
78
+ assert!(status
79
+ .findings
80
+ .iter()
81
+ .any(|finding| finding.id == "task.state.conflict_markers"));
82
+ }
83
+
84
+ #[test]
85
+ fn task_status_reports_branch_divergence_when_upstream_split() {
86
+ let repo = TaskFixture::new(task_state_with_status(
87
+ "implementing",
88
+ active_task(json!({
89
+ "allowedPaths": ["**"],
90
+ "requiredCheckIds": [],
91
+ "proofResults": []
92
+ })),
93
+ ));
94
+ repo.init_git();
95
+ let remote = repo.path().join("remote.git");
96
+ let branch = repo.git(["rev-parse", "--abbrev-ref", "HEAD"]);
97
+ let branch = branch.trim();
98
+ repo.git(["init", "--bare", remote.to_str().unwrap()]);
99
+ repo.git(["remote", "add", "origin", remote.to_str().unwrap()]);
100
+ repo.git(["push", "-u", "origin", branch]);
101
+
102
+ repo.write("LOCAL.md", "local\n");
103
+ repo.git(["add", "."]);
104
+ repo.git(["commit", "-m", "local"]);
105
+
106
+ let clone = std::env::temp_dir().join(format!(
107
+ "naome-task-status-remote-work-{}",
108
+ std::process::id()
109
+ ));
110
+ let _ = fs::remove_dir_all(&clone);
111
+ repo.git(["clone", remote.to_str().unwrap(), clone.to_str().unwrap()]);
112
+ git_in(&clone, ["config", "user.email", "naome@example.com"]);
113
+ git_in(&clone, ["config", "user.name", "NAOME Test"]);
114
+ fs::write(clone.join("REMOTE.md"), "remote\n").unwrap();
115
+ git_in(&clone, ["add", "."]);
116
+ git_in(&clone, ["commit", "-m", "remote"]);
117
+ git_in(&clone, ["push"]);
118
+ repo.git(["fetch", "origin"]);
119
+
120
+ let status = task_status_report(repo.path()).unwrap();
121
+ assert_eq!(status.git.ahead, 1);
122
+ assert_eq!(status.git.behind, 1);
123
+ assert!(status
124
+ .findings
125
+ .iter()
126
+ .any(|finding| finding.id == "task.git.branch_diverged"));
127
+ assert_eq!(task_status_exit_code(&status.findings, &status.proof), 0);
128
+ }
129
+
130
+ fn git_in<const N: usize>(root: &std::path::Path, args: [&str; N]) {
131
+ let output = std::process::Command::new("git")
132
+ .args(args)
133
+ .current_dir(root)
134
+ .output()
135
+ .unwrap();
136
+ assert!(
137
+ output.status.success(),
138
+ "{}",
139
+ String::from_utf8_lossy(&output.stderr)
140
+ );
141
+ }
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lamentis/naome",
3
- "version": "1.3.17",
3
+ "version": "1.4.1",
4
4
  "description": "Native-first CLI for the NAOME agent harness.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -17,7 +17,7 @@ const expectedMachineOwnedIntegrity = Object.freeze({
17
17
  ".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
18
18
  "AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
19
19
  "docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
20
- "docs/naome/architecture-fitness.md": "sha256:5067f57787f0cac0be4b0d49079f03b595fdab6e4fba4b8bdde4bc3cfc0d1de1",
20
+ "docs/naome/architecture-fitness.md": "sha256:be38e0c6dea8b1ebeee3bfd4a2e4e17008829360b1b4649ef45f2ce61e7287bd",
21
21
  "docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
22
22
  "docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
23
23
  "docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
@@ -17,7 +17,7 @@ const expectedMachineOwnedIntegrity = Object.freeze({
17
17
  ".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
18
18
  "AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
19
19
  "docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
20
- "docs/naome/architecture-fitness.md": "sha256:5067f57787f0cac0be4b0d49079f03b595fdab6e4fba4b8bdde4bc3cfc0d1de1",
20
+ "docs/naome/architecture-fitness.md": "sha256:be38e0c6dea8b1ebeee3bfd4a2e4e17008829360b1b4649ef45f2ce61e7287bd",
21
21
  "docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
22
22
  "docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
23
23
  "docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
@@ -1,5 +1,5 @@
1
1
  {
2
- "harnessVersion": "1.3.13",
2
+ "harnessVersion": "1.4.0",
3
3
  "installedAt": null,
4
4
  "integrity": {
5
5
  ".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
@@ -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:5067f57787f0cac0be4b0d49079f03b595fdab6e4fba4b8bdde4bc3cfc0d1de1",
12
+ "docs/naome/architecture-fitness.md": "sha256:be38e0c6dea8b1ebeee3bfd4a2e4e17008829360b1b4649ef45f2ce61e7287bd",
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,6 +14,8 @@ 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 --sarif [--output architecture.sarif]` emits SARIF 2.1.0
18
+ for CI code-scanning while preserving failing exit codes.
17
19
  - `naome arch validate --changed-only` uses changed paths with the persistent
18
20
  architecture cache when available and safely degrades to a full scan when the
19
21
  cache cannot prove graph-level soundness.
@@ -110,15 +112,14 @@ edges as clean architecture.
110
112
 
111
113
  ## Configuration Findings
112
114
 
113
- Validation can pass while still reporting configuration findings. These are
114
- non-blocking warnings about weak architecture policy, such as:
115
+ Validation can pass while still reporting non-blocking configuration findings
116
+ about weak architecture policy, such as:
115
117
 
116
118
  - broad catch-all layers or contexts overlapping narrower boundaries;
117
119
  - layers or contexts whose path patterns match no files;
118
120
  - unresolved imports that could hide real dependency edges.
119
121
 
120
- Use `naome arch explain --json` or `naome arch validate --json` to inspect
121
- `configFindings` deterministically in CI or agent loops.
122
+ Use JSON output to inspect `configFindings` deterministically in CI or agents.
122
123
 
123
124
  ## Incremental Cache
124
125
 
@@ -148,7 +149,11 @@ The command is deterministic in both cache-backed and fallback modes; CI can
148
149
  inspect the JSON fields above when it needs to distinguish performance from
149
150
  soundness fallbacks.
150
151
 
151
- For v1.4 readiness, architecture fitness is a release gate whenever source,
152
+ Use `node .naome/bin/naome.js arch validate --sarif --output architecture.sarif`
153
+ when CI can upload SARIF. It contains blocking violations, configuration
154
+ findings, unresolved imports, and `agentInstruction` properties for repair loops.
155
+
156
+ For v1.4.0, architecture fitness is a release gate whenever source,
152
157
  manifest, alias, config, or structure changes can alter dependency edges. Treat
153
158
  error-level violations as blocking. Warning-level config findings are advisory
154
159
  unless the repository chooses stricter policy, but unresolved imports should be
@@ -156,29 +161,24 @@ triaged before claiming a clean architecture result.
156
161
 
157
162
  ## Language Support
158
163
 
159
- The v1.3.17 foundation classifies TypeScript, JavaScript, Rust, Python, Go,
160
- Java, Kotlin, and Swift files by path extension. It extracts import facts for
161
- TypeScript, JavaScript, Rust, Python, Go, and Swift. It resolves relative
162
- imports, repository-absolute aliases, TypeScript/JavaScript `paths` aliases
163
- from nearby `tsconfig.json` or `jsconfig.json`, Python package imports with
164
- local `__init__.py` roots, Go module imports, SwiftPM target imports, and Rust
165
- crate/self/super module paths where possible.
166
- Unresolved imports are represented explicitly as graph nodes instead of
167
- dropping them. Swift and iOS app repositories get Apple framework imports, SwiftPM
168
- manifests, and Xcode Swift package references represented in the normalized
169
- graph; Apple SDK frameworks are treated as platform APIs for external policy.
170
- It also extracts package and dependency facts from `package.json`,
171
- `Cargo.toml`, `pyproject.toml`, `go.mod`, lightweight `pom.xml` / Gradle
172
- manifests, `Package.swift`, and `.xcodeproj/project.pbxproj`, then emits
173
- manifest-identity package nodes and manifest-owned `DependsOn` edges to
174
- external dependencies.
164
+ The v1.4.0 foundation classifies TypeScript, JavaScript, Rust, Python, Go, Java,
165
+ Kotlin, and Swift files by path extension. It extracts imports for TypeScript,
166
+ JavaScript, Rust, Python, Go, and Swift, resolving relative paths,
167
+ repository-absolute aliases, TS/JS `paths`, Python package roots, Go modules,
168
+ SwiftPM targets, and Rust crate/self/super module paths where possible.
169
+ Unresolved imports become explicit graph nodes. Swift/iOS repositories get Apple
170
+ framework imports, SwiftPM manifests, and Xcode Swift package references in the
171
+ normalized graph; Apple SDK frameworks are treated as platform APIs. Manifest
172
+ facts from `package.json`, `Cargo.toml`, `pyproject.toml`, `go.mod`, lightweight
173
+ `pom.xml` / Gradle manifests, `Package.swift`, and `.xcodeproj/project.pbxproj`
174
+ emit manifest-identity package nodes and manifest-owned dependency edges.
175
175
  Architecture rules now cover layers, bounded contexts, public APIs, cycles,
176
176
  transitive layer reach, import/fan-out budgets, and external dependency
177
177
  policies.
178
178
 
179
179
  ## Acceptance Coverage
180
180
 
181
- v1.4 readiness is covered with deterministic fixture repositories for
181
+ v1.4.0 readiness is covered with deterministic fixture repositories for
182
182
  TypeScript/JavaScript aliases, Rust crate paths, Python package roots, Go
183
183
  modules, Swift/iOS targets, and mixed monorepos. These fixtures assert both
184
184
  positive local-edge resolution and negative forbidden-dependency findings.
@@ -187,7 +187,7 @@ positive local-edge resolution and negative forbidden-dependency findings.
187
187
 
188
188
  This release intentionally keeps validation file-graph based. Manifest
189
189
  extractors are dependency-owner oriented and do not yet parse every build-tool
190
- feature. Deep symbol-level call analysis and SARIF output remain follow-up work.
190
+ feature. Deep symbol-level call analysis remains follow-up work.
191
191
 
192
192
  ## v1.4 Migration Checklist
193
193