@lamentis/naome 1.0.2 → 1.1.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.
- package/Cargo.lock +2 -2
- package/README.md +8 -1
- package/bin/naome-node.js +4 -1
- package/bin/naome.js +198 -3
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/main.rs +110 -13
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/decision.rs +82 -11
- package/crates/naome-core/src/git.rs +12 -1
- package/crates/naome-core/src/harness_health.rs +3 -1
- package/crates/naome-core/src/install_plan.rs +4 -2
- package/crates/naome-core/src/intent.rs +914 -0
- package/crates/naome-core/src/journal.rs +169 -0
- package/crates/naome-core/src/lib.rs +10 -1
- package/crates/naome-core/src/models.rs +63 -4
- package/crates/naome-core/src/route.rs +1063 -0
- package/crates/naome-core/src/task_state.rs +372 -21
- package/crates/naome-core/tests/decision.rs +8 -6
- package/crates/naome-core/tests/install_plan.rs +9 -1
- package/crates/naome-core/tests/intent.rs +826 -0
- package/crates/naome-core/tests/route.rs +1159 -0
- package/crates/naome-core/tests/task_state.rs +203 -4
- 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 +7 -6
- package/templates/naome-root/.naome/bin/check-task-state.js +7 -6
- package/templates/naome-root/.naome/bin/naome.js +143 -13
- package/templates/naome-root/.naome/manifest.json +8 -7
- package/templates/naome-root/.naome/upgrade-state.json +1 -1
- package/templates/naome-root/AGENTS.md +30 -5
- package/templates/naome-root/docs/naome/agent-workflow.md +45 -24
- package/templates/naome-root/docs/naome/execution.md +55 -51
- package/templates/naome-root/docs/naome/index.md +10 -3
|
@@ -106,10 +106,10 @@ fn accepts_complete_task_with_scoped_diff_and_notice() {
|
|
|
106
106
|
let report = validate_task_state(repo.path(), TaskStateOptions::default()).unwrap();
|
|
107
107
|
|
|
108
108
|
assert!(report.errors.is_empty(), "{:#?}", report.errors);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
let notices = report.notices.join("\n");
|
|
110
|
+
assert!(notices.contains("Task is complete and verified"));
|
|
111
|
+
assert!(notices.contains("NAOME intent can baseline it automatically"));
|
|
112
|
+
assert!(!notices.contains("commit_task_baseline"));
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
#[test]
|
|
@@ -187,6 +187,205 @@ fn commit_gate_allows_install_baseline_with_gitignore_and_project_owned_paths()
|
|
|
187
187
|
assert!(report.errors.is_empty(), "{:#?}", report.errors);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
#[test]
|
|
191
|
+
fn commit_gate_allows_staged_harness_refresh_split_from_completed_task() {
|
|
192
|
+
let repo = TaskFixture::new(complete_task_state(json!({
|
|
193
|
+
"allowedPaths": ["README.md"],
|
|
194
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))]
|
|
195
|
+
})));
|
|
196
|
+
repo.install_healthy_harness();
|
|
197
|
+
repo.init_git();
|
|
198
|
+
repo.write("README.md", "# Task result\n");
|
|
199
|
+
repo.write("AGENTS.md", "# Agent Instructions\n\nUpdated by sync.\n");
|
|
200
|
+
repo.write_json(
|
|
201
|
+
".naome/manifest.json",
|
|
202
|
+
json!({
|
|
203
|
+
"name": "naome",
|
|
204
|
+
"harnessVersion": "1.1.0",
|
|
205
|
+
"profile": "standard",
|
|
206
|
+
"machineOwned": MACHINE_OWNED_PATHS,
|
|
207
|
+
"projectOwned": PROJECT_OWNED_PATHS,
|
|
208
|
+
"integrity": {}
|
|
209
|
+
}),
|
|
210
|
+
);
|
|
211
|
+
repo.git(["add", "AGENTS.md", ".naome/manifest.json"]);
|
|
212
|
+
|
|
213
|
+
let report = validate_task_state(
|
|
214
|
+
repo.path(),
|
|
215
|
+
TaskStateOptions {
|
|
216
|
+
mode: TaskStateMode::CommitGate,
|
|
217
|
+
..TaskStateOptions::default()
|
|
218
|
+
},
|
|
219
|
+
)
|
|
220
|
+
.unwrap();
|
|
221
|
+
|
|
222
|
+
assert!(report.errors.is_empty(), "{:#?}", report.errors);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
#[test]
|
|
226
|
+
fn commit_gate_allows_staged_harness_refresh_after_completed_task_is_baselined() {
|
|
227
|
+
let repo = TaskFixture::new(complete_task_state(json!({
|
|
228
|
+
"allowedPaths": ["README.md"],
|
|
229
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))]
|
|
230
|
+
})));
|
|
231
|
+
repo.install_healthy_harness();
|
|
232
|
+
repo.write("README.md", "# Completed task result\n");
|
|
233
|
+
repo.init_git();
|
|
234
|
+
repo.write("AGENTS.md", "# Agent Instructions\n\nUpdated by sync.\n");
|
|
235
|
+
repo.write_json(
|
|
236
|
+
".naome/manifest.json",
|
|
237
|
+
json!({
|
|
238
|
+
"name": "naome",
|
|
239
|
+
"harnessVersion": "1.1.1",
|
|
240
|
+
"profile": "standard",
|
|
241
|
+
"machineOwned": MACHINE_OWNED_PATHS,
|
|
242
|
+
"projectOwned": PROJECT_OWNED_PATHS,
|
|
243
|
+
"integrity": {}
|
|
244
|
+
}),
|
|
245
|
+
);
|
|
246
|
+
repo.git(["add", "AGENTS.md", ".naome/manifest.json"]);
|
|
247
|
+
|
|
248
|
+
let report = validate_task_state(
|
|
249
|
+
repo.path(),
|
|
250
|
+
TaskStateOptions {
|
|
251
|
+
mode: TaskStateMode::CommitGate,
|
|
252
|
+
..TaskStateOptions::default()
|
|
253
|
+
},
|
|
254
|
+
)
|
|
255
|
+
.unwrap();
|
|
256
|
+
|
|
257
|
+
assert!(report.errors.is_empty(), "{:#?}", report.errors);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
#[test]
|
|
261
|
+
fn commit_gate_rejects_harness_refresh_when_completed_task_proof_is_missing() {
|
|
262
|
+
let repo = TaskFixture::new(complete_task_state(json!({
|
|
263
|
+
"allowedPaths": ["README.md"],
|
|
264
|
+
"proofResults": []
|
|
265
|
+
})));
|
|
266
|
+
repo.install_healthy_harness();
|
|
267
|
+
repo.write("README.md", "# Completed task result\n");
|
|
268
|
+
repo.init_git();
|
|
269
|
+
repo.write("AGENTS.md", "# Agent Instructions\n\nUpdated by sync.\n");
|
|
270
|
+
repo.git(["add", "AGENTS.md"]);
|
|
271
|
+
|
|
272
|
+
let report = validate_task_state(
|
|
273
|
+
repo.path(),
|
|
274
|
+
TaskStateOptions {
|
|
275
|
+
mode: TaskStateMode::CommitGate,
|
|
276
|
+
..TaskStateOptions::default()
|
|
277
|
+
},
|
|
278
|
+
)
|
|
279
|
+
.unwrap();
|
|
280
|
+
|
|
281
|
+
assert!(
|
|
282
|
+
report
|
|
283
|
+
.errors
|
|
284
|
+
.iter()
|
|
285
|
+
.any(|error| error.contains("activeTask.proofResults missing proof result: diff-check")),
|
|
286
|
+
"{:#?}",
|
|
287
|
+
report.errors
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#[test]
|
|
292
|
+
fn commit_gate_rejects_harness_refresh_with_pending_upgrade_state() {
|
|
293
|
+
let repo = TaskFixture::new(complete_task_state(json!({
|
|
294
|
+
"allowedPaths": ["README.md"],
|
|
295
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))]
|
|
296
|
+
})));
|
|
297
|
+
repo.install_healthy_harness();
|
|
298
|
+
repo.write("README.md", "# Completed task result\n");
|
|
299
|
+
repo.init_git();
|
|
300
|
+
repo.write("AGENTS.md", "# Agent Instructions\n\nUpdated by sync.\n");
|
|
301
|
+
repo.write_json(
|
|
302
|
+
".naome/upgrade-state.json",
|
|
303
|
+
json!({
|
|
304
|
+
"status": "needs_agent_upgrade",
|
|
305
|
+
"fromVersion": "1.1.0",
|
|
306
|
+
"toVersion": "1.1.1",
|
|
307
|
+
"pending": ["manual-step"],
|
|
308
|
+
"completed": []
|
|
309
|
+
}),
|
|
310
|
+
);
|
|
311
|
+
repo.git(["add", "AGENTS.md", ".naome/upgrade-state.json"]);
|
|
312
|
+
|
|
313
|
+
let report = validate_task_state(
|
|
314
|
+
repo.path(),
|
|
315
|
+
TaskStateOptions {
|
|
316
|
+
mode: TaskStateMode::CommitGate,
|
|
317
|
+
..TaskStateOptions::default()
|
|
318
|
+
},
|
|
319
|
+
)
|
|
320
|
+
.unwrap();
|
|
321
|
+
|
|
322
|
+
assert!(
|
|
323
|
+
report
|
|
324
|
+
.errors
|
|
325
|
+
.iter()
|
|
326
|
+
.any(|error| error.contains("NAOME upgrade is pending")),
|
|
327
|
+
"{:#?}",
|
|
328
|
+
report.errors
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
#[test]
|
|
333
|
+
fn commit_gate_rejects_support_only_harness_refresh_after_completed_task_is_baselined() {
|
|
334
|
+
let repo = TaskFixture::new(complete_task_state(json!({
|
|
335
|
+
"allowedPaths": ["README.md"],
|
|
336
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))]
|
|
337
|
+
})));
|
|
338
|
+
repo.install_healthy_harness();
|
|
339
|
+
repo.write("README.md", "# Completed task result\n");
|
|
340
|
+
repo.init_git();
|
|
341
|
+
repo.write_json(
|
|
342
|
+
".naome/upgrade-state.json",
|
|
343
|
+
json!({
|
|
344
|
+
"status": "complete",
|
|
345
|
+
"fromVersion": null,
|
|
346
|
+
"toVersion": "1.1.1",
|
|
347
|
+
"pending": [],
|
|
348
|
+
"completed": []
|
|
349
|
+
}),
|
|
350
|
+
);
|
|
351
|
+
repo.git(["add", ".naome/upgrade-state.json"]);
|
|
352
|
+
|
|
353
|
+
let report = validate_task_state(
|
|
354
|
+
repo.path(),
|
|
355
|
+
TaskStateOptions {
|
|
356
|
+
mode: TaskStateMode::CommitGate,
|
|
357
|
+
..TaskStateOptions::default()
|
|
358
|
+
},
|
|
359
|
+
)
|
|
360
|
+
.unwrap();
|
|
361
|
+
|
|
362
|
+
assert!(!report.errors.is_empty(), "{:#?}", report.errors);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
#[test]
|
|
366
|
+
fn commit_gate_ignores_unstaged_user_edits_outside_completed_task_scope() {
|
|
367
|
+
let repo = TaskFixture::new(complete_task_state(json!({
|
|
368
|
+
"allowedPaths": ["README.md"],
|
|
369
|
+
"proofResults": [successful_proof(json!({ "evidence": ["README.md"] }))]
|
|
370
|
+
})));
|
|
371
|
+
repo.write("USER.md", "user baseline\n");
|
|
372
|
+
repo.init_git();
|
|
373
|
+
repo.write("README.md", "# Task result\n");
|
|
374
|
+
repo.write("USER.md", "user local edit\n");
|
|
375
|
+
repo.git(["add", "README.md", ".naome/task-state.json"]);
|
|
376
|
+
|
|
377
|
+
let report = validate_task_state(
|
|
378
|
+
repo.path(),
|
|
379
|
+
TaskStateOptions {
|
|
380
|
+
mode: TaskStateMode::CommitGate,
|
|
381
|
+
..TaskStateOptions::default()
|
|
382
|
+
},
|
|
383
|
+
)
|
|
384
|
+
.unwrap();
|
|
385
|
+
|
|
386
|
+
assert!(report.errors.is_empty(), "{:#?}", report.errors);
|
|
387
|
+
}
|
|
388
|
+
|
|
190
389
|
#[test]
|
|
191
390
|
fn progress_accepts_implementing_task_with_scoped_diff_without_proof() {
|
|
192
391
|
let repo = TaskFixture::new(json!({
|
|
Binary file
|
package/native/linux-x64/naome
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -9,17 +9,18 @@ const nativeBinaryRelativePath = process.platform === "win32" ? ".naome/bin/naom
|
|
|
9
9
|
const nativeBinaryName = process.platform === "win32" ? "naome.exe" : "naome";
|
|
10
10
|
|
|
11
11
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
|
-
"AGENTS.md": "sha256:
|
|
12
|
+
"AGENTS.md": "sha256:84ce882fa6798a144c8c74673d4304fc6bf235b1cc417f7649eea9f7461775de",
|
|
13
13
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
14
|
-
".naome/bin/naome.js": "sha256:
|
|
14
|
+
".naome/bin/naome.js": "sha256:7894690ad47700a9a5e7ecb5a94ba42c1a12e2637d2c9f41f0023b1bd8bd22b6",
|
|
15
15
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
16
16
|
".naome/bin/check-harness-health.js": "sha256:dce2a380022dd63d86bd762869debafbc635ab3d7e8fae985e2d429d8ee437ad",
|
|
17
17
|
".naome/task-contract.schema.json": "sha256:c806416d4944eaed6dc48b3760fd0dd5b9b5a7c9ab895697fe36b54c41c1332f",
|
|
18
|
-
"docs/naome/index.md": "sha256:
|
|
18
|
+
"docs/naome/index.md": "sha256:d04691b25ed377c2a3aa2c56965d0db276539aeadcfdd2a2ec1be7ff7706dd6f",
|
|
19
19
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
20
|
-
"docs/naome/agent-workflow.md": "sha256:
|
|
21
|
-
"docs/naome/execution.md": "sha256:
|
|
22
|
-
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
20
|
+
"docs/naome/agent-workflow.md": "sha256:43ba8a6814068e1b932b12a392de70b39841dc82df0acdaac459d6714c501b9d",
|
|
21
|
+
"docs/naome/execution.md": "sha256:ad66611b2878d1ba8fe05ddc4cfe9de7fd41de172a0de8295c36227a2700631a",
|
|
22
|
+
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1",
|
|
23
|
+
".naome/bin/naome-rust": "sha256:cc754ae59477577dfc0130cc21c286beaf3f19e2852278bb8f1e8724277eb44b"
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
function main() {
|
|
@@ -9,17 +9,18 @@ const nativeBinaryRelativePath = process.platform === "win32" ? ".naome/bin/naom
|
|
|
9
9
|
const nativeBinaryName = process.platform === "win32" ? "naome.exe" : "naome";
|
|
10
10
|
|
|
11
11
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
|
-
"AGENTS.md": "sha256:
|
|
12
|
+
"AGENTS.md": "sha256:84ce882fa6798a144c8c74673d4304fc6bf235b1cc417f7649eea9f7461775de",
|
|
13
13
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
14
|
-
".naome/bin/naome.js": "sha256:
|
|
14
|
+
".naome/bin/naome.js": "sha256:7894690ad47700a9a5e7ecb5a94ba42c1a12e2637d2c9f41f0023b1bd8bd22b6",
|
|
15
15
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
16
16
|
".naome/bin/check-harness-health.js": "sha256:dce2a380022dd63d86bd762869debafbc635ab3d7e8fae985e2d429d8ee437ad",
|
|
17
17
|
".naome/task-contract.schema.json": "sha256:c806416d4944eaed6dc48b3760fd0dd5b9b5a7c9ab895697fe36b54c41c1332f",
|
|
18
|
-
"docs/naome/index.md": "sha256:
|
|
18
|
+
"docs/naome/index.md": "sha256:d04691b25ed377c2a3aa2c56965d0db276539aeadcfdd2a2ec1be7ff7706dd6f",
|
|
19
19
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
20
|
-
"docs/naome/agent-workflow.md": "sha256:
|
|
21
|
-
"docs/naome/execution.md": "sha256:
|
|
22
|
-
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
20
|
+
"docs/naome/agent-workflow.md": "sha256:43ba8a6814068e1b932b12a392de70b39841dc82df0acdaac459d6714c501b9d",
|
|
21
|
+
"docs/naome/execution.md": "sha256:ad66611b2878d1ba8fe05ddc4cfe9de7fd41de172a0de8295c36227a2700631a",
|
|
22
|
+
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1",
|
|
23
|
+
".naome/bin/naome-rust": "sha256:cc754ae59477577dfc0130cc21c286beaf3f19e2852278bb8f1e8724277eb44b"
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
function main(argv) {
|
|
@@ -27,7 +27,7 @@ function main(argv) {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
if (command === "status" || command === "next") {
|
|
30
|
+
if (command === "status" || command === "next" || command === "intent" || command === "route" || command === "explain") {
|
|
31
31
|
runNativeDecisionCommand(command, args);
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
@@ -145,25 +145,92 @@ function commit(args) {
|
|
|
145
145
|
fail("NAOME harness root not found. Run this inside a repository with .naome/task-state.json.");
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
const message = parseCommitMessage(args)
|
|
148
|
+
const message = parseCommitMessage(args);
|
|
149
149
|
const taskState = readTaskState(root);
|
|
150
150
|
|
|
151
151
|
if (taskState.status !== "complete") {
|
|
152
|
-
|
|
152
|
+
const decision = readDecision(root);
|
|
153
|
+
if (isSetupBaselineDecision(decision)) {
|
|
154
|
+
commitBaseline(root, message || defaultSetupCommitMessage(decision), { taskScoped: false });
|
|
155
|
+
console.log(`NAOME committed ${decision.state} baseline.`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fail(`naome commit requires task-state status complete or a setup baseline diff. Current status: ${taskState.status}.`);
|
|
153
160
|
}
|
|
154
161
|
|
|
155
|
-
|
|
162
|
+
const commitInfo = commitBaseline(root, message || defaultTaskCommitMessage(root), { taskScoped: true });
|
|
163
|
+
writeTaskJournal(root, "naome_commit_baseline", commitInfo);
|
|
164
|
+
|
|
165
|
+
console.log(`NAOME committed task ${taskState.activeTask?.id || "unknown"}.`);
|
|
166
|
+
}
|
|
156
167
|
|
|
157
|
-
|
|
168
|
+
function commitBaseline(root, message, options = {}) {
|
|
169
|
+
const changedPaths = options.taskScoped ? readTaskCommitPaths(root) : readChangedPaths(root);
|
|
158
170
|
if (changedPaths.length === 0) {
|
|
159
171
|
fail("Nothing to commit.");
|
|
160
172
|
}
|
|
161
173
|
|
|
162
|
-
|
|
174
|
+
const before = gitHead(root);
|
|
175
|
+
runGitOrExit(root, ["add", "-A", "--", ...changedPaths]);
|
|
163
176
|
runOrExit(root, [process.execPath, [join(root, ".naome", "bin", "check-task-state.js"), "--commit-gate"]]);
|
|
164
177
|
runGitOrExit(root, ["commit", "-m", message]);
|
|
178
|
+
return { before, after: gitHead(root) };
|
|
179
|
+
}
|
|
165
180
|
|
|
166
|
-
|
|
181
|
+
function readTaskCommitPaths(root) {
|
|
182
|
+
const nativeBinary = resolveNativeDecisionBinary(root);
|
|
183
|
+
verifyNativeBinary(nativeBinary);
|
|
184
|
+
const result = spawnSync(nativeBinary, ["commit-paths", "--json"], {
|
|
185
|
+
cwd: root,
|
|
186
|
+
encoding: "utf8",
|
|
187
|
+
env: {
|
|
188
|
+
...process.env,
|
|
189
|
+
NAOME_NODE_BIN: process.execPath
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
if (result.status !== 0) {
|
|
193
|
+
fail(`Cannot determine NAOME task commit paths: ${result.stderr.trim() || result.stdout.trim()}`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const paths = JSON.parse(result.stdout);
|
|
198
|
+
if (Array.isArray(paths) && paths.every((path) => typeof path === "string" && path.trim())) {
|
|
199
|
+
return paths;
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
// Fall through to a deterministic failure.
|
|
203
|
+
}
|
|
204
|
+
fail("Cannot determine NAOME task commit paths: native output was not a path array.");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function writeTaskJournal(root, outcome, commitInfo) {
|
|
208
|
+
const nativeBinary = resolveNativeDecisionBinary(root);
|
|
209
|
+
verifyNativeBinary(nativeBinary);
|
|
210
|
+
const args = [
|
|
211
|
+
"journal-task",
|
|
212
|
+
"--outcome",
|
|
213
|
+
outcome,
|
|
214
|
+
"--json"
|
|
215
|
+
];
|
|
216
|
+
if (commitInfo.before) {
|
|
217
|
+
args.push("--commit-before", commitInfo.before);
|
|
218
|
+
}
|
|
219
|
+
if (commitInfo.after) {
|
|
220
|
+
args.push("--commit-after", commitInfo.after);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const result = spawnSync(nativeBinary, args, {
|
|
224
|
+
cwd: root,
|
|
225
|
+
encoding: "utf8",
|
|
226
|
+
env: {
|
|
227
|
+
...process.env,
|
|
228
|
+
NAOME_NODE_BIN: process.execPath
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
if (result.status !== 0) {
|
|
232
|
+
fail(`Cannot write NAOME task journal: ${result.stderr.trim() || result.stdout.trim()}`);
|
|
233
|
+
}
|
|
167
234
|
}
|
|
168
235
|
|
|
169
236
|
function parseCommitMessage(args) {
|
|
@@ -181,12 +248,48 @@ function parseCommitMessage(args) {
|
|
|
181
248
|
return null;
|
|
182
249
|
}
|
|
183
250
|
|
|
184
|
-
function
|
|
251
|
+
function defaultTaskCommitMessage(root) {
|
|
185
252
|
const taskState = readTaskState(root);
|
|
186
253
|
const taskId = taskState.activeTask?.id || "task";
|
|
187
254
|
return `chore(naome): baseline ${taskId}`;
|
|
188
255
|
}
|
|
189
256
|
|
|
257
|
+
function defaultSetupCommitMessage(decision) {
|
|
258
|
+
return decision.state === "harness_repair_unbaselined"
|
|
259
|
+
? "chore(naome): baseline harness repair"
|
|
260
|
+
: "chore(naome): baseline setup";
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function readDecision(root) {
|
|
264
|
+
const nativeBinary = resolveNativeDecisionBinary(root);
|
|
265
|
+
verifyNativeBinary(nativeBinary);
|
|
266
|
+
const result = spawnSync(nativeBinary, ["status", "--json"], {
|
|
267
|
+
cwd: root,
|
|
268
|
+
encoding: "utf8",
|
|
269
|
+
env: {
|
|
270
|
+
...process.env,
|
|
271
|
+
NAOME_NODE_BIN: process.execPath
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (result.status !== 0) {
|
|
276
|
+
fail(`Cannot read NAOME status: ${result.stderr.trim() || result.stdout.trim()}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
return JSON.parse(result.stdout);
|
|
281
|
+
} catch (error) {
|
|
282
|
+
fail(`Cannot parse NAOME status: ${error.message}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function isSetupBaselineDecision(decision) {
|
|
287
|
+
return decision && (
|
|
288
|
+
decision.state === "install_or_upgrade_unbaselined" ||
|
|
289
|
+
decision.state === "harness_repair_unbaselined"
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
190
293
|
function readTaskState(root) {
|
|
191
294
|
const taskStatePath = join(root, ".naome", "task-state.json");
|
|
192
295
|
try {
|
|
@@ -197,12 +300,25 @@ function readTaskState(root) {
|
|
|
197
300
|
}
|
|
198
301
|
|
|
199
302
|
function readChangedPaths(root) {
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
303
|
+
const paths = new Set();
|
|
304
|
+
for (const args of [
|
|
305
|
+
["diff", "--name-only", "-z"],
|
|
306
|
+
["diff", "--name-only", "--cached", "-z"],
|
|
307
|
+
["ls-files", "--others", "--exclude-standard", "-z"]
|
|
308
|
+
]) {
|
|
309
|
+
const result = runGit(root, args);
|
|
310
|
+
if (result.status !== 0) {
|
|
311
|
+
fail(`git ${args.join(" ")} failed: ${result.stderr.trim() || result.stdout.trim()}`);
|
|
312
|
+
}
|
|
313
|
+
for (const path of result.stdout.split("\0")) {
|
|
314
|
+
const normalized = path.trim();
|
|
315
|
+
if (normalized) {
|
|
316
|
+
paths.add(normalized);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
203
319
|
}
|
|
204
320
|
|
|
205
|
-
return
|
|
321
|
+
return Array.from(paths).sort();
|
|
206
322
|
}
|
|
207
323
|
|
|
208
324
|
function runOrExit(root, command) {
|
|
@@ -233,6 +349,14 @@ function runGit(root, args, options = {}) {
|
|
|
233
349
|
});
|
|
234
350
|
}
|
|
235
351
|
|
|
352
|
+
function gitHead(root) {
|
|
353
|
+
const result = runGit(root, ["rev-parse", "HEAD"]);
|
|
354
|
+
if (result.status !== 0) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
return result.stdout.trim();
|
|
358
|
+
}
|
|
359
|
+
|
|
236
360
|
function findHarnessRoot(startPath) {
|
|
237
361
|
let current = resolve(startPath);
|
|
238
362
|
|
|
@@ -254,6 +378,12 @@ function printHelp() {
|
|
|
254
378
|
console.log("Usage:");
|
|
255
379
|
console.log(" naome status [--json]");
|
|
256
380
|
console.log(" naome next [--json]");
|
|
381
|
+
console.log(" naome intent --prompt-file <path> [--json]");
|
|
382
|
+
console.log(" naome intent --prompt <text> [--json]");
|
|
383
|
+
console.log(" naome route --prompt-file <path> [--execute] [--json]");
|
|
384
|
+
console.log(" naome route --prompt <text> [--execute] [--json]");
|
|
385
|
+
console.log(" naome explain --prompt-file <path> [--json]");
|
|
386
|
+
console.log(" naome explain --prompt <text> [--json]");
|
|
257
387
|
console.log(" naome install");
|
|
258
388
|
console.log(" naome sync");
|
|
259
389
|
console.log(" naome commit -m \"type(scope): message\"");
|
|
@@ -290,7 +420,7 @@ function installOrSync(command, args) {
|
|
|
290
420
|
process.exit(result.status === null ? 1 : result.status);
|
|
291
421
|
}
|
|
292
422
|
|
|
293
|
-
const result = spawnSync("npm", ["
|
|
423
|
+
const result = spawnSync("npm", ["exec", "--yes", "@lamentis/naome", "--", command, ...args], {
|
|
294
424
|
cwd: root,
|
|
295
425
|
encoding: "utf8",
|
|
296
426
|
stdio: "inherit"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naome",
|
|
3
|
-
"harnessVersion": "1.
|
|
3
|
+
"harnessVersion": "1.1.1",
|
|
4
4
|
"profile": "standard",
|
|
5
5
|
"installedAt": null,
|
|
6
6
|
"machineOwned": [
|
|
@@ -30,16 +30,17 @@
|
|
|
30
30
|
"docs/naome/testing.md"
|
|
31
31
|
],
|
|
32
32
|
"integrity": {
|
|
33
|
-
"AGENTS.md": "sha256:
|
|
33
|
+
"AGENTS.md": "sha256:84ce882fa6798a144c8c74673d4304fc6bf235b1cc417f7649eea9f7461775de",
|
|
34
34
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
35
|
-
".naome/bin/naome.js": "sha256:
|
|
35
|
+
".naome/bin/naome.js": "sha256:7894690ad47700a9a5e7ecb5a94ba42c1a12e2637d2c9f41f0023b1bd8bd22b6",
|
|
36
36
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
37
37
|
".naome/bin/check-harness-health.js": "sha256:dce2a380022dd63d86bd762869debafbc635ab3d7e8fae985e2d429d8ee437ad",
|
|
38
38
|
".naome/task-contract.schema.json": "sha256:c806416d4944eaed6dc48b3760fd0dd5b9b5a7c9ab895697fe36b54c41c1332f",
|
|
39
|
-
"docs/naome/index.md": "sha256:
|
|
39
|
+
"docs/naome/index.md": "sha256:d04691b25ed377c2a3aa2c56965d0db276539aeadcfdd2a2ec1be7ff7706dd6f",
|
|
40
40
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
41
|
-
"docs/naome/agent-workflow.md": "sha256:
|
|
42
|
-
"docs/naome/execution.md": "sha256:
|
|
43
|
-
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
41
|
+
"docs/naome/agent-workflow.md": "sha256:43ba8a6814068e1b932b12a392de70b39841dc82df0acdaac459d6714c501b9d",
|
|
42
|
+
"docs/naome/execution.md": "sha256:ad66611b2878d1ba8fe05ddc4cfe9de7fd41de172a0de8295c36227a2700631a",
|
|
43
|
+
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1",
|
|
44
|
+
".naome/bin/naome-rust": "sha256:cc754ae59477577dfc0130cc21c286beaf3f19e2852278bb8f1e8724277eb44b"
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -8,16 +8,16 @@ This repository uses NAOME as its coding-agent harness.
|
|
|
8
8
|
2. Do not read any file or directory matched by `.naomeignore`.
|
|
9
9
|
3. If `docs/naome/index.md` or `.naome/bin/check-harness-health.js` is missing,
|
|
10
10
|
do not begin feature work. Install the NAOME CLI with
|
|
11
|
-
`npm install -g @lamentis/naome`, then run `naome sync`
|
|
12
|
-
restart this list.
|
|
11
|
+
`npm install -g @lamentis/naome`, then run `naome sync --check-update`
|
|
12
|
+
from the repository root. Then restart this list.
|
|
13
13
|
4. Read `docs/naome/index.md`.
|
|
14
14
|
5. Read `.naome/init-state.json`.
|
|
15
15
|
6. Read `.naome/task-state.json`.
|
|
16
16
|
7. Read `.naome/upgrade-state.json`.
|
|
17
17
|
8. Run `node .naome/bin/check-harness-health.js`.
|
|
18
18
|
9. If harness health fails, do not begin feature work. Repair the machine-owned
|
|
19
|
-
harness files with `naome sync`, or ask the user
|
|
20
|
-
repair decisions.
|
|
19
|
+
harness files with `naome update` followed by `naome sync`, or ask the user
|
|
20
|
+
for one of the listed repair decisions.
|
|
21
21
|
10. If upgrade status is `needs_agent_upgrade`, do not begin feature work. Run
|
|
22
22
|
or continue `docs/naome/upgrade.md`.
|
|
23
23
|
11. If `initialized` is `false`, do not begin feature work. Run or continue the
|
|
@@ -30,15 +30,40 @@ This repository uses NAOME as its coding-agent harness.
|
|
|
30
30
|
## Core Rules
|
|
31
31
|
|
|
32
32
|
- Prefer discovered repository facts over assumptions.
|
|
33
|
+
- Do not look for generic root steering files such as `ARCHITECTURE.md` or
|
|
34
|
+
`docs/index.md` unless this repository's NAOME docs explicitly name them.
|
|
35
|
+
NAOME's default architecture and index files are
|
|
36
|
+
`docs/naome/architecture.md` and `docs/naome/index.md`.
|
|
33
37
|
- Record only facts from this target repository or from the user. Do not import
|
|
34
38
|
parent-workspace, outer-agent, chat, or unrelated repository instructions into
|
|
35
39
|
this repository's NAOME docs.
|
|
36
40
|
- Keep changes small and task-focused.
|
|
37
41
|
- Read only the NAOME docs relevant to the current task.
|
|
38
42
|
- Run Harness Health before Task Admission.
|
|
43
|
+
- For natural-language work requests, prefer
|
|
44
|
+
`naome route --prompt-file <path> --execute --json` and follow its
|
|
45
|
+
`userMessage`, `humanOptions`, `requiredContext`, `taskRoot`, `worktree`, and
|
|
46
|
+
`canCreateTask` fields. If `taskRoot` differs from the current directory,
|
|
47
|
+
continue the task in `taskRoot`; the original worktree contains unrelated user
|
|
48
|
+
edits that must remain untouched. Pure deterministic harness refresh diffs
|
|
49
|
+
are baselined in the current worktree before task creation; they must not
|
|
50
|
+
create repair-loop task worktrees. Use `naome explain --prompt-file <path>
|
|
51
|
+
--json` only for debugging policy.
|
|
52
|
+
- If route blocks or performs no mutation, do not fall back to raw `git commit`,
|
|
53
|
+
IDE commit, `git add`, or hook bypass commands. Only execute a commit when
|
|
54
|
+
NAOME route/commit performs it successfully or the user takes manual Git
|
|
55
|
+
ownership outside the agent task.
|
|
56
|
+
- If the user explicitly asks to commit their own unowned changes, use NAOME
|
|
57
|
+
route so the configured quality gate runs first. NAOME commits only the exact
|
|
58
|
+
paths it evaluated, requires committed verification coverage for every path,
|
|
59
|
+
and rechecks the final stabilized diff before creating the commit.
|
|
60
|
+
- Repair requests may baseline deterministic harness refresh files, but they
|
|
61
|
+
must leave unrelated user edits untouched unless the user explicitly takes
|
|
62
|
+
manual Git ownership.
|
|
39
63
|
- Machine-owned NAOME command shims, schemas, workflow docs, archives, and
|
|
40
64
|
native binaries may be local-only ignored files. Missing local-only files are
|
|
41
|
-
repaired with `naome sync`; they are not project
|
|
65
|
+
repaired with `naome update` followed by `naome sync`; they are not project
|
|
66
|
+
context.
|
|
42
67
|
- Enforce Task Admission before accepting new feature work.
|
|
43
68
|
- Do not start feature work while the git diff contains setup, upgrade,
|
|
44
69
|
previous-task, or other unowned changes.
|