@lamentis/naome 1.4.1 → 1.4.2
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.
- package/Cargo.lock +2 -2
- package/README.md +17 -122
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/main.rs +9 -5
- package/crates/naome-cli/src/task_commands/can_edit.rs +116 -0
- package/crates/naome-cli/src/task_commands/check_run/output.rs +34 -0
- package/crates/naome-cli/src/task_commands/check_run/receipts.rs +155 -0
- package/crates/naome-cli/src/task_commands/check_run/verification.rs +165 -0
- package/crates/naome-cli/src/task_commands/check_run.rs +192 -0
- package/crates/naome-cli/src/task_commands/common.rs +39 -1
- package/crates/naome-cli/src/task_commands/complete.rs +43 -0
- package/crates/naome-cli/src/task_commands/loop_control.rs +55 -0
- package/crates/naome-cli/src/task_commands/readiness.rs +14 -10
- package/crates/naome-cli/src/task_commands/record.rs +139 -37
- package/crates/naome-cli/src/task_commands/repair.rs +58 -11
- package/crates/naome-cli/src/task_commands.rs +14 -3
- package/crates/naome-cli/tests/task_cli_agent_controls.rs +9 -16
- package/crates/naome-cli/tests/task_cli_loop.rs +383 -0
- package/crates/naome-cli/tests/task_cli_loop_edit.rs +144 -0
- package/crates/naome-cli/tests/task_cli_support/mod.rs +28 -0
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/lib.rs +7 -7
- package/crates/naome-core/src/task_state/evidence_fingerprint.rs +47 -0
- package/crates/naome-core/src/task_state/mod.rs +2 -0
- package/crates/naome-core/src/task_state/status/control/repair.rs +2 -2
- package/crates/naome-core/src/task_state/status/model.rs +2 -0
- package/crates/naome-core/src/task_state/status/proof.rs +59 -9
- package/crates/naome-core/src/task_state/status/proof_read.rs +14 -0
- package/crates/naome-core/src/task_state/status/report_context.rs +23 -1
- package/crates/naome-core/src/task_state/status/transition.rs +29 -1
- package/crates/naome-core/tests/task_status.rs +122 -0
- package/installer/context.js +1 -1
- package/installer/harness-verification.js +2 -6
- package/installer/manifest-state.js +2 -2
- package/installer/native.js +3 -31
- package/native/darwin-arm64/naome +0 -0
- package/native/linux-x64/naome +0 -0
- package/package.json +1 -1
- package/templates/naome-root/.naome/bin/check-harness-health.js +2 -2
- package/templates/naome-root/.naome/bin/check-task-state.js +4 -39
- package/templates/naome-root/.naome/bin/naome.js +2 -30
- package/templates/naome-root/.naome/manifest.json +2 -2
|
@@ -134,6 +134,45 @@ fn proof_plan_reports_missing_and_stale_required_checks() {
|
|
|
134
134
|
}));
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
#[test]
|
|
138
|
+
fn proof_plan_marks_mutable_npm_scripts_not_safe_to_execute() {
|
|
139
|
+
let repo = TaskFixture::new(task_state_with_status(
|
|
140
|
+
"implementing",
|
|
141
|
+
active_task(json!({
|
|
142
|
+
"allowedPaths": ["package.json"],
|
|
143
|
+
"requiredCheckIds": ["package-dry-run"],
|
|
144
|
+
"proofResults": []
|
|
145
|
+
})),
|
|
146
|
+
));
|
|
147
|
+
repo.write_json(
|
|
148
|
+
".naome/verification.json",
|
|
149
|
+
json!({
|
|
150
|
+
"checks": [{
|
|
151
|
+
"id": "package-dry-run",
|
|
152
|
+
"command": "npm run pack:dry-run",
|
|
153
|
+
"cwd": ".",
|
|
154
|
+
"purpose": "Validate package output.",
|
|
155
|
+
"cost": "medium",
|
|
156
|
+
"source": "npm",
|
|
157
|
+
"evidence": ["package.json"]
|
|
158
|
+
}]
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
repo.init_git();
|
|
162
|
+
repo.write_json(
|
|
163
|
+
"package.json",
|
|
164
|
+
json!({ "scripts": { "pack:dry-run": "echo changed" } }),
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
let plan = task_proof_plan(repo.path()).unwrap();
|
|
168
|
+
|
|
169
|
+
assert!(plan.recommended_commands.iter().any(|command| {
|
|
170
|
+
command.check_id == "package-dry-run"
|
|
171
|
+
&& command.command == "npm run pack:dry-run"
|
|
172
|
+
&& !command.safe_to_execute
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
|
|
137
176
|
#[test]
|
|
138
177
|
fn proof_plan_next_action_reports_missing_proof_without_command_metadata() {
|
|
139
178
|
let repo = TaskFixture::new(task_state_with_status(
|
|
@@ -200,6 +239,89 @@ fn transition_readiness_blocks_missing_proof_and_allows_fresh_proof() {
|
|
|
200
239
|
assert_eq!(allowed.agent_loop.state, "ready_to_commit");
|
|
201
240
|
}
|
|
202
241
|
|
|
242
|
+
#[test]
|
|
243
|
+
fn transition_readiness_treats_mismatched_proof_fingerprint_as_stale() {
|
|
244
|
+
let repo = TaskFixture::new(task_state_with_status(
|
|
245
|
+
"implementing",
|
|
246
|
+
active_task(json!({
|
|
247
|
+
"allowedPaths": ["README.md"],
|
|
248
|
+
"requiredCheckIds": ["diff-check"],
|
|
249
|
+
"proofPathSets": {
|
|
250
|
+
"current": ["README.md"]
|
|
251
|
+
},
|
|
252
|
+
"proofBatches": [{
|
|
253
|
+
"id": "old-proof",
|
|
254
|
+
"checkedAt": "2026-05-04T12:00:00.000Z",
|
|
255
|
+
"evidencePathSet": "current",
|
|
256
|
+
"proofs": [{
|
|
257
|
+
"checkId": "diff-check",
|
|
258
|
+
"exitCode": 0,
|
|
259
|
+
"evidenceFingerprint": "fnv64:0000000000000000"
|
|
260
|
+
}]
|
|
261
|
+
}]
|
|
262
|
+
})),
|
|
263
|
+
));
|
|
264
|
+
repo.init_git();
|
|
265
|
+
repo.write("README.md", "changed after proof\n");
|
|
266
|
+
|
|
267
|
+
let transition = task_transition_readiness(repo.path(), "complete").unwrap();
|
|
268
|
+
|
|
269
|
+
assert!(!transition.allowed);
|
|
270
|
+
assert!(transition
|
|
271
|
+
.blocking_findings
|
|
272
|
+
.iter()
|
|
273
|
+
.any(|finding| finding.id == "task.transition.stale_proof"));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
#[test]
|
|
277
|
+
fn transition_readiness_blocks_pending_human_review_and_stale_blockers() {
|
|
278
|
+
let human_review = TaskFixture::new(task_state_with_status(
|
|
279
|
+
"implementing",
|
|
280
|
+
active_task(json!({
|
|
281
|
+
"requiredCheckIds": ["diff-check"],
|
|
282
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))],
|
|
283
|
+
"humanReview": {
|
|
284
|
+
"required": true,
|
|
285
|
+
"approved": false,
|
|
286
|
+
"reason": "Security-sensitive change."
|
|
287
|
+
}
|
|
288
|
+
})),
|
|
289
|
+
));
|
|
290
|
+
human_review.init_git();
|
|
291
|
+
|
|
292
|
+
let transition = task_transition_readiness(human_review.path(), "complete").unwrap();
|
|
293
|
+
|
|
294
|
+
assert!(!transition.allowed);
|
|
295
|
+
assert!(transition
|
|
296
|
+
.blocking_findings
|
|
297
|
+
.iter()
|
|
298
|
+
.any(|finding| finding.id == "task.transition.human_review_required"));
|
|
299
|
+
|
|
300
|
+
let mut blocked_state = task_state_with_status(
|
|
301
|
+
"implementing",
|
|
302
|
+
active_task(json!({
|
|
303
|
+
"requiredCheckIds": ["diff-check"],
|
|
304
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))]
|
|
305
|
+
})),
|
|
306
|
+
);
|
|
307
|
+
blocked_state["blocker"] = json!({
|
|
308
|
+
"type": "scope_drift",
|
|
309
|
+
"message": "Resolve stale blocker before completion.",
|
|
310
|
+
"paths": ["README.md"],
|
|
311
|
+
"humanOptions": ["review_task_state"]
|
|
312
|
+
});
|
|
313
|
+
let blocker = TaskFixture::new(blocked_state);
|
|
314
|
+
blocker.init_git();
|
|
315
|
+
|
|
316
|
+
let transition = task_transition_readiness(blocker.path(), "complete").unwrap();
|
|
317
|
+
|
|
318
|
+
assert!(!transition.allowed);
|
|
319
|
+
assert!(transition
|
|
320
|
+
.blocking_findings
|
|
321
|
+
.iter()
|
|
322
|
+
.any(|finding| finding.id == "task.transition.blocker_present"));
|
|
323
|
+
}
|
|
324
|
+
|
|
203
325
|
#[test]
|
|
204
326
|
fn legacy_proof_results_remain_readable_when_fresh() {
|
|
205
327
|
let repo = TaskFixture::new(task_state_with_status(
|
package/installer/context.js
CHANGED
|
@@ -49,7 +49,7 @@ export function createInstallerContext() {
|
|
|
49
49
|
normalizedIntegrityBlock:
|
|
50
50
|
"const expectedMachineOwnedIntegrity = Object.freeze({\n __generated__: \"sha256:generated\"\n});\n",
|
|
51
51
|
nativeIntegrityPattern:
|
|
52
|
-
/^const expectedNativeBinaryIntegrity = "
|
|
52
|
+
/^const expectedNativeBinaryIntegrity = "sha256:[a-f0-9]{64}";\n/m,
|
|
53
53
|
normalizedNativeIntegrity: 'const expectedNativeBinaryIntegrity = "sha256:generated";\n',
|
|
54
54
|
executableMachineOwnedPaths: new Set([
|
|
55
55
|
".naome/bin/naome.js",
|
|
@@ -3,7 +3,6 @@ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, writeFile
|
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
|
|
5
5
|
import { hasSymlinkInTargetPath, removeSkipped } from "./filesystem.js";
|
|
6
|
-
import { findNativeDecisionBinary, usesSourceNativeFallback } from "./native.js";
|
|
7
6
|
import { printCommandFailure, printError } from "./output.js";
|
|
8
7
|
|
|
9
8
|
export function ensureBuiltInVerificationChecks(ctx) {
|
|
@@ -71,13 +70,10 @@ function ensureVerificationFileExists(ctx, relativePath, targetPath) {
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
function verificationSeederBinary(ctx) {
|
|
74
|
-
const nativePath =
|
|
75
|
-
? findNativeDecisionBinary(ctx)
|
|
76
|
-
: join(ctx.targetRoot, ctx.nativeBinaryRelativePath);
|
|
73
|
+
const nativePath = join(ctx.targetRoot, ctx.nativeBinaryRelativePath);
|
|
77
74
|
if (
|
|
78
|
-
!nativePath ||
|
|
79
75
|
!existsSync(nativePath) ||
|
|
80
|
-
|
|
76
|
+
hasSymlinkInTargetPath(ctx, ctx.nativeBinaryRelativePath) ||
|
|
81
77
|
!lstatSync(nativePath).isFile()
|
|
82
78
|
) {
|
|
83
79
|
printError(ctx, "NAOME native decision binary is unavailable for verification seeding.");
|
|
@@ -2,7 +2,7 @@ import { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from "n
|
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
|
|
4
4
|
import { hasSymlinkInTargetPath } from "./filesystem.js";
|
|
5
|
-
import { installedMachineOwnedIntegrity, installedNativeBinaryHash
|
|
5
|
+
import { installedMachineOwnedIntegrity, installedNativeBinaryHash } from "./native.js";
|
|
6
6
|
import { printError } from "./output.js";
|
|
7
7
|
import { isVersion } from "./version.js";
|
|
8
8
|
|
|
@@ -121,7 +121,7 @@ function applyManifestHealthMetadata(ctx, manifest) {
|
|
|
121
121
|
manifest.integrity = installedMachineOwnedIntegrity(ctx);
|
|
122
122
|
|
|
123
123
|
const nativeHash = installedNativeBinaryHash(ctx);
|
|
124
|
-
if (
|
|
124
|
+
if (nativeHash) {
|
|
125
125
|
if (!manifest.machineOwned.includes(ctx.nativeBinaryRelativePath)) {
|
|
126
126
|
manifest.machineOwned.push(ctx.nativeBinaryRelativePath);
|
|
127
127
|
}
|
package/installer/native.js
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
lstatSync,
|
|
7
7
|
mkdirSync,
|
|
8
8
|
readFileSync,
|
|
9
|
-
unlinkSync,
|
|
10
9
|
writeFileSync,
|
|
11
10
|
} from "node:fs";
|
|
12
11
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -32,12 +31,6 @@ export function installNativeDecisionBinary(ctx) {
|
|
|
32
31
|
process.exit(1);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
if (usesSourceNativeFallback(ctx)) {
|
|
36
|
-
removeInstalledNativeDecisionBinary(ctx);
|
|
37
|
-
patchInstalledNativeIntegrity(ctx, "sha256:generated");
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
34
|
mkdirSync(dirname(targetPath), { recursive: true });
|
|
42
35
|
const sourceHash = sha256(readFileSync(sourcePath));
|
|
43
36
|
const targetHash =
|
|
@@ -93,11 +86,6 @@ export function patchInstalledMachineOwnedIntegrity(ctx) {
|
|
|
93
86
|
}
|
|
94
87
|
}
|
|
95
88
|
|
|
96
|
-
export function usesSourceNativeFallback(ctx) {
|
|
97
|
-
return existsSync(join(ctx.targetRoot, "packages", "naome", "Cargo.toml"))
|
|
98
|
-
&& existsSync(join(ctx.targetRoot, "packages", "naome", "crates", "naome-cli", "src", "main.rs"));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
89
|
export function installedNativeBinaryHash(ctx) {
|
|
102
90
|
const targetPath = join(ctx.targetRoot, ctx.nativeBinaryRelativePath);
|
|
103
91
|
if (
|
|
@@ -111,23 +99,6 @@ export function installedNativeBinaryHash(ctx) {
|
|
|
111
99
|
return sha256(readFileSync(targetPath));
|
|
112
100
|
}
|
|
113
101
|
|
|
114
|
-
function removeInstalledNativeDecisionBinary(ctx) {
|
|
115
|
-
const targetPath = join(ctx.targetRoot, ctx.nativeBinaryRelativePath);
|
|
116
|
-
if (!existsSync(targetPath)) {
|
|
117
|
-
ctx.skipped.push(ctx.nativeBinaryRelativePath);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (hasSymlinkInTargetPath(ctx, ctx.nativeBinaryRelativePath) || !lstatSync(targetPath).isFile()) {
|
|
122
|
-
ctx.skipped.push(ctx.nativeBinaryRelativePath);
|
|
123
|
-
ctx.unsafeSkipped.push(ctx.nativeBinaryRelativePath);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
unlinkSync(targetPath);
|
|
128
|
-
ctx.updated.push(ctx.nativeBinaryRelativePath);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
102
|
export function templateIntegrity(ctx) {
|
|
132
103
|
const integrity = {};
|
|
133
104
|
|
|
@@ -143,7 +114,7 @@ export function installedMachineOwnedIntegrity(ctx) {
|
|
|
143
114
|
const integrity = templateIntegrity(ctx);
|
|
144
115
|
const nativeHash = installedNativeBinaryHash(ctx);
|
|
145
116
|
|
|
146
|
-
if (
|
|
117
|
+
if (nativeHash) {
|
|
147
118
|
integrity[ctx.nativeBinaryRelativePath] = `sha256:${nativeHash}`;
|
|
148
119
|
}
|
|
149
120
|
|
|
@@ -181,6 +152,7 @@ export function hasGeneratedNativeIntegrity(ctx, relativePath) {
|
|
|
181
152
|
}
|
|
182
153
|
|
|
183
154
|
function patchInstalledNativeIntegrity(ctx, expectedIntegrity) {
|
|
155
|
+
const nativeIntegrityPatchPattern = /^const expectedNativeBinaryIntegrity = "(?:sha256:[a-f0-9]{64}|sha256:generated)";\n/m;
|
|
184
156
|
const nativeIntegrityPaths = [
|
|
185
157
|
ctx.healthCheckerRelativePath,
|
|
186
158
|
ctx.taskStateCheckerRelativePath,
|
|
@@ -195,7 +167,7 @@ function patchInstalledNativeIntegrity(ctx, expectedIntegrity) {
|
|
|
195
167
|
|
|
196
168
|
const content = readFileSync(targetPath, "utf8");
|
|
197
169
|
const nextContent = content.replace(
|
|
198
|
-
|
|
170
|
+
nativeIntegrityPatchPattern,
|
|
199
171
|
`const expectedNativeBinaryIntegrity = "${expectedIntegrity}";\n`,
|
|
200
172
|
);
|
|
201
173
|
|
|
Binary file
|
package/native/linux-x64/naome
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -11,8 +11,8 @@ const expectedNativeBinaryIntegrity = "sha256:generated";
|
|
|
11
11
|
|
|
12
12
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
13
13
|
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
14
|
-
".naome/bin/check-task-state.js": "sha256:
|
|
15
|
-
".naome/bin/naome.js": "sha256:
|
|
14
|
+
".naome/bin/check-task-state.js": "sha256:d1c12ba6d8a0ffc3fd28c6900b675c4bbc9c54b6bd287d219f6e9104bfb9621e",
|
|
15
|
+
".naome/bin/naome.js": "sha256:8a9d9ed783981ef9750021fa30e92460283775bb4a0eacdea60b63041a9c6a05",
|
|
16
16
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
17
17
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
18
18
|
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
@@ -11,8 +11,8 @@ const expectedNativeBinaryIntegrity = "sha256:generated";
|
|
|
11
11
|
|
|
12
12
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
13
13
|
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
14
|
-
".naome/bin/check-task-state.js": "sha256:
|
|
15
|
-
".naome/bin/naome.js": "sha256:
|
|
14
|
+
".naome/bin/check-task-state.js": "sha256:d1c12ba6d8a0ffc3fd28c6900b675c4bbc9c54b6bd287d219f6e9104bfb9621e",
|
|
15
|
+
".naome/bin/naome.js": "sha256:8a9d9ed783981ef9750021fa30e92460283775bb4a0eacdea60b63041a9c6a05",
|
|
16
16
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
17
17
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
18
18
|
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
@@ -67,9 +67,7 @@ function resolveNativeDecisionBinary(root) {
|
|
|
67
67
|
const expectedIntegrity = expectedNativeIntegrity();
|
|
68
68
|
const candidates = [
|
|
69
69
|
process.env.NAOME_NATIVE_BIN,
|
|
70
|
-
join(root, nativeBinaryRelativePath)
|
|
71
|
-
join(root, "packages", "naome", "target", "release", nativeBinaryName),
|
|
72
|
-
join(root, "packages", "naome", "target", "debug", nativeBinaryName)
|
|
70
|
+
expectedIntegrity && join(root, nativeBinaryRelativePath)
|
|
73
71
|
].filter(Boolean);
|
|
74
72
|
|
|
75
73
|
if (expectedIntegrity) {
|
|
@@ -82,12 +80,7 @@ function resolveNativeDecisionBinary(root) {
|
|
|
82
80
|
fail(`No runnable NAOME native task-state binary matched ${expectedIntegrity}. Run naome sync again.`);
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
if (built && isUsableNativeBinary(built, root, null)) {
|
|
87
|
-
return built;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
fail("NAOME native task-state binary is missing or incompatible. Run naome sync again.");
|
|
83
|
+
fail("NAOME native task-state binary is missing trusted integrity. Run naome sync again.");
|
|
91
84
|
}
|
|
92
85
|
|
|
93
86
|
function expectedNativeIntegrity() {
|
|
@@ -118,34 +111,6 @@ function isUsableNativeBinary(candidate, root, expectedIntegrity) {
|
|
|
118
111
|
return !probe.error && probe.status !== null;
|
|
119
112
|
}
|
|
120
113
|
|
|
121
|
-
function buildSourceNativeBinary(root) {
|
|
122
|
-
if (expectedNativeBinaryIntegrity !== "sha256:generated") {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const packageRoot = join(root, "packages", "naome");
|
|
127
|
-
const manifestPath = join(packageRoot, "Cargo.toml");
|
|
128
|
-
if (!existsSync(manifestPath)) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const result = spawnSync(
|
|
133
|
-
"cargo",
|
|
134
|
-
["build", "--release", "--manifest-path", manifestPath, "-p", "naome-cli"],
|
|
135
|
-
{
|
|
136
|
-
cwd: root,
|
|
137
|
-
encoding: "utf8",
|
|
138
|
-
stdio: "ignore"
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
if (result.status !== 0) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const builtPath = join(packageRoot, "target", "release", nativeBinaryName);
|
|
146
|
-
return existsSync(builtPath) ? builtPath : null;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
114
|
function findHarnessRoot(startPath) {
|
|
150
115
|
let current = resolve(startPath);
|
|
151
116
|
|
|
@@ -66,9 +66,7 @@ function spawnNative(root, args, options = {}) {
|
|
|
66
66
|
function resolveNativeDecisionBinary(root) {
|
|
67
67
|
const candidates = [
|
|
68
68
|
process.env.NAOME_NATIVE_BIN,
|
|
69
|
-
join(root, nativeBinaryRelativePath)
|
|
70
|
-
join(root, "packages", "naome", "target", "release", nativeBinaryName),
|
|
71
|
-
join(root, "packages", "naome", "target", "debug", nativeBinaryName)
|
|
69
|
+
expectedNativeBinaryIntegrity !== "sha256:generated" && join(root, nativeBinaryRelativePath)
|
|
72
70
|
].filter(Boolean);
|
|
73
71
|
|
|
74
72
|
for (const candidate of candidates) {
|
|
@@ -77,11 +75,6 @@ function resolveNativeDecisionBinary(root) {
|
|
|
77
75
|
}
|
|
78
76
|
}
|
|
79
77
|
|
|
80
|
-
const built = buildSourceNativeBinary(root);
|
|
81
|
-
if (built && isUsableNativeBinary(built, root)) {
|
|
82
|
-
return built;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
78
|
fail("NAOME native decision binary is missing or incompatible. Run naome sync again, or set NAOME_NATIVE_BIN to a built naome binary.");
|
|
86
79
|
}
|
|
87
80
|
|
|
@@ -91,7 +84,7 @@ function isUsableNativeBinary(candidate, root) {
|
|
|
91
84
|
}
|
|
92
85
|
|
|
93
86
|
if (expectedNativeBinaryIntegrity === "sha256:generated") {
|
|
94
|
-
return isRunnableNativeBinary(candidate, root);
|
|
87
|
+
return candidate === process.env.NAOME_NATIVE_BIN && isRunnableNativeBinary(candidate, root);
|
|
95
88
|
}
|
|
96
89
|
|
|
97
90
|
const actual = `sha256:${createHash("sha256").update(readFileSync(candidate)).digest("hex")}`;
|
|
@@ -111,27 +104,6 @@ function isRunnableNativeBinary(candidate, root) {
|
|
|
111
104
|
return !probe.error && probe.status !== null;
|
|
112
105
|
}
|
|
113
106
|
|
|
114
|
-
function buildSourceNativeBinary(root) {
|
|
115
|
-
if (expectedNativeBinaryIntegrity !== "sha256:generated") {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const sourcePath = (...parts) => join(root, "packages", "naome", ...parts);
|
|
120
|
-
const manifestPath = sourcePath("Cargo.toml");
|
|
121
|
-
if (!existsSync(manifestPath)) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const buildArgs = ["build", "--release", "--manifest-path", manifestPath, "-p", "naome-cli"];
|
|
126
|
-
const result = spawnSync("cargo", buildArgs, { cwd: root, encoding: "utf8", stdio: "ignore" });
|
|
127
|
-
if (result.status !== 0) {
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const builtPath = sourcePath("target", "release", nativeBinaryName);
|
|
132
|
-
return existsSync(builtPath) ? builtPath : null;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
107
|
function commit(args) {
|
|
136
108
|
const root = findHarnessRoot(process.cwd());
|
|
137
109
|
if (!root) {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"installedAt": null,
|
|
4
4
|
"integrity": {
|
|
5
5
|
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
6
|
-
".naome/bin/check-task-state.js": "sha256:
|
|
7
|
-
".naome/bin/naome.js": "sha256:
|
|
6
|
+
".naome/bin/check-task-state.js": "sha256:d1c12ba6d8a0ffc3fd28c6900b675c4bbc9c54b6bd287d219f6e9104bfb9621e",
|
|
7
|
+
".naome/bin/naome.js": "sha256:8a9d9ed783981ef9750021fa30e92460283775bb4a0eacdea60b63041a9c6a05",
|
|
8
8
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
9
9
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
10
10
|
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|