@lamentis/naome 1.1.2 → 1.2.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/Cargo.toml +1 -1
- package/LICENSE +180 -21
- package/README.md +49 -6
- package/bin/naome-node.js +2 -1579
- package/bin/naome.js +68 -16
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/check_commands.rs +135 -0
- package/crates/naome-cli/src/cli_args.rs +5 -0
- package/crates/naome-cli/src/dispatcher.rs +37 -0
- package/crates/naome-cli/src/install_bridge.rs +83 -0
- package/crates/naome-cli/src/main.rs +60 -341
- package/crates/naome-cli/src/prompt_commands.rs +68 -0
- package/crates/naome-cli/src/quality_commands.rs +229 -0
- package/crates/naome-cli/src/simple_commands.rs +53 -0
- package/crates/naome-cli/src/workflow_commands.rs +153 -0
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/decision/checks.rs +64 -0
- package/crates/naome-core/src/decision/idle.rs +67 -0
- package/crates/naome-core/src/decision/json.rs +36 -0
- package/crates/naome-core/src/decision/states.rs +165 -0
- package/crates/naome-core/src/decision.rs +131 -353
- package/crates/naome-core/src/harness_health/integrity.rs +96 -0
- package/crates/naome-core/src/harness_health.rs +14 -126
- package/crates/naome-core/src/install_plan.rs +5 -0
- package/crates/naome-core/src/intent/classifier.rs +171 -0
- package/crates/naome-core/src/intent/envelope.rs +108 -0
- package/crates/naome-core/src/intent/legacy.rs +138 -0
- package/crates/naome-core/src/intent/legacy_response.rs +76 -0
- package/crates/naome-core/src/intent/model.rs +71 -0
- package/crates/naome-core/src/intent/patterns.rs +170 -0
- package/crates/naome-core/src/intent/resolver.rs +162 -0
- package/crates/naome-core/src/intent/resolver_active.rs +17 -0
- package/crates/naome-core/src/intent/resolver_baseline.rs +55 -0
- package/crates/naome-core/src/intent/resolver_catalog.rs +167 -0
- package/crates/naome-core/src/intent/resolver_policy.rs +72 -0
- package/crates/naome-core/src/intent/resolver_shared.rs +55 -0
- package/crates/naome-core/src/intent/risk.rs +40 -0
- package/crates/naome-core/src/intent/segment.rs +170 -0
- package/crates/naome-core/src/intent.rs +64 -879
- package/crates/naome-core/src/journal.rs +9 -20
- package/crates/naome-core/src/lib.rs +15 -0
- package/crates/naome-core/src/paths.rs +3 -1
- package/crates/naome-core/src/quality/adapter_support.rs +89 -0
- package/crates/naome-core/src/quality/adapters.rs +131 -0
- package/crates/naome-core/src/quality/baseline.rs +75 -0
- package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +175 -0
- package/crates/naome-core/src/quality/checks/near_duplicates.rs +130 -0
- package/crates/naome-core/src/quality/checks.rs +228 -0
- package/crates/naome-core/src/quality/cleanup.rs +84 -0
- package/crates/naome-core/src/quality/config.rs +102 -0
- package/crates/naome-core/src/quality/config_support.rs +24 -0
- package/crates/naome-core/src/quality/mod.rs +108 -0
- package/crates/naome-core/src/quality/scanner/repo_paths.rs +103 -0
- package/crates/naome-core/src/quality/scanner.rs +379 -0
- package/crates/naome-core/src/quality/structure/adapters.rs +84 -0
- package/crates/naome-core/src/quality/structure/checks/basic.rs +153 -0
- package/crates/naome-core/src/quality/structure/checks/directory.rs +144 -0
- package/crates/naome-core/src/quality/structure/checks/pairing.rs +63 -0
- package/crates/naome-core/src/quality/structure/checks.rs +124 -0
- package/crates/naome-core/src/quality/structure/classify/roles.rs +188 -0
- package/crates/naome-core/src/quality/structure/classify.rs +94 -0
- package/crates/naome-core/src/quality/structure/config.rs +89 -0
- package/crates/naome-core/src/quality/structure/defaults.rs +107 -0
- package/crates/naome-core/src/quality/structure/mod.rs +77 -0
- package/crates/naome-core/src/quality/structure/model.rs +124 -0
- package/crates/naome-core/src/quality/types.rs +292 -0
- package/crates/naome-core/src/route/builtin_checks.rs +155 -0
- package/crates/naome-core/src/route/builtin_context.rs +73 -0
- package/crates/naome-core/src/route/builtin_integrity.rs +49 -0
- package/crates/naome-core/src/route/builtin_require.rs +40 -0
- package/crates/naome-core/src/route/context.rs +180 -0
- package/crates/naome-core/src/route/execution.rs +96 -0
- package/crates/naome-core/src/route/execution_baselines.rs +146 -0
- package/crates/naome-core/src/route/execution_support.rs +57 -0
- package/crates/naome-core/src/route/execution_tasks.rs +71 -0
- package/crates/naome-core/src/route/git_ops.rs +72 -0
- package/crates/naome-core/src/route/quality_gate.rs +73 -0
- package/crates/naome-core/src/route/quality_gate_config.rs +126 -0
- package/crates/naome-core/src/route/quality_gate_snapshot.rs +69 -0
- package/crates/naome-core/src/route/worktree.rs +75 -0
- package/crates/naome-core/src/route/worktree_files.rs +32 -0
- package/crates/naome-core/src/route/worktree_plan.rs +131 -0
- package/crates/naome-core/src/route.rs +44 -1155
- package/crates/naome-core/src/task_state/admission.rs +63 -0
- package/crates/naome-core/src/task_state/admission_proof.rs +72 -0
- package/crates/naome-core/src/task_state/api.rs +130 -0
- package/crates/naome-core/src/task_state/commit_gate.rs +138 -0
- package/crates/naome-core/src/task_state/compact_proof.rs +160 -0
- package/crates/naome-core/src/task_state/completed_refresh.rs +89 -0
- package/crates/naome-core/src/task_state/completion.rs +72 -0
- package/crates/naome-core/src/task_state/deleted_paths.rs +47 -0
- package/crates/naome-core/src/task_state/diff.rs +95 -0
- package/crates/naome-core/src/task_state/evidence.rs +154 -0
- package/crates/naome-core/src/task_state/git_io.rs +86 -0
- package/crates/naome-core/src/task_state/git_parse.rs +86 -0
- package/crates/naome-core/src/task_state/git_refs.rs +37 -0
- package/crates/naome-core/src/task_state/human_review_state.rs +31 -0
- package/crates/naome-core/src/task_state/mod.rs +38 -0
- package/crates/naome-core/src/task_state/process_guard.rs +40 -0
- package/crates/naome-core/src/task_state/progress.rs +123 -0
- package/crates/naome-core/src/task_state/proof.rs +139 -0
- package/crates/naome-core/src/task_state/proof_entry.rs +66 -0
- package/crates/naome-core/src/task_state/proof_model.rs +70 -0
- package/crates/naome-core/src/task_state/proof_sources.rs +76 -0
- package/crates/naome-core/src/task_state/push_gate.rs +49 -0
- package/crates/naome-core/src/task_state/reconcile.rs +7 -0
- package/crates/naome-core/src/task_state/repair.rs +168 -0
- package/crates/naome-core/src/task_state/shape.rs +117 -0
- package/crates/naome-core/src/task_state/task_diff_api.rs +170 -0
- package/crates/naome-core/src/task_state/task_records.rs +131 -0
- package/crates/naome-core/src/task_state/task_references.rs +126 -0
- package/crates/naome-core/src/task_state/types.rs +87 -0
- package/crates/naome-core/src/task_state/util.rs +137 -0
- package/crates/naome-core/src/verification/render.rs +122 -0
- package/crates/naome-core/src/verification.rs +177 -58
- package/crates/naome-core/src/verification_contract.rs +49 -21
- package/crates/naome-core/src/workflow/integrity.rs +123 -0
- package/crates/naome-core/src/workflow/integrity_normalize.rs +7 -0
- package/crates/naome-core/src/workflow/integrity_support.rs +110 -0
- package/crates/naome-core/src/workflow/mod.rs +18 -0
- package/crates/naome-core/src/workflow/mutation.rs +68 -0
- package/crates/naome-core/src/workflow/output.rs +111 -0
- package/crates/naome-core/src/workflow/phase_inference.rs +73 -0
- package/crates/naome-core/src/workflow/phases.rs +169 -0
- package/crates/naome-core/src/workflow/policy.rs +156 -0
- package/crates/naome-core/src/workflow/processes.rs +91 -0
- package/crates/naome-core/src/workflow/types.rs +42 -0
- package/crates/naome-core/tests/decision.rs +24 -118
- package/crates/naome-core/tests/harness_health.rs +5 -0
- package/crates/naome-core/tests/intent.rs +97 -792
- package/crates/naome-core/tests/intent_support/mod.rs +133 -0
- package/crates/naome-core/tests/intent_v2.rs +90 -0
- package/crates/naome-core/tests/quality.rs +319 -0
- package/crates/naome-core/tests/quality_structure.rs +116 -0
- package/crates/naome-core/tests/quality_structure_adapters.rs +98 -0
- package/crates/naome-core/tests/quality_structure_policy.rs +125 -0
- package/crates/naome-core/tests/quality_structure_support/mod.rs +249 -0
- package/crates/naome-core/tests/repo_support/mod.rs +16 -0
- package/crates/naome-core/tests/repo_support/repo.rs +113 -0
- package/crates/naome-core/tests/repo_support/repo_factories.rs +99 -0
- package/crates/naome-core/tests/repo_support/repo_helpers.rs +123 -0
- package/crates/naome-core/tests/repo_support/routes.rs +81 -0
- package/crates/naome-core/tests/repo_support/verification.rs +168 -0
- package/crates/naome-core/tests/repo_support/verification_values.rs +135 -0
- package/crates/naome-core/tests/route.rs +1 -1476
- package/crates/naome-core/tests/route_baseline.rs +86 -0
- package/crates/naome-core/tests/route_completion.rs +141 -0
- package/crates/naome-core/tests/route_harness_refresh.rs +135 -0
- package/crates/naome-core/tests/route_user_diff.rs +198 -0
- package/crates/naome-core/tests/route_worktree.rs +54 -0
- package/crates/naome-core/tests/task_state.rs +60 -429
- package/crates/naome-core/tests/task_state_compact.rs +110 -0
- package/crates/naome-core/tests/task_state_compact_support/mod.rs +5 -0
- package/crates/naome-core/tests/task_state_compact_support/repo.rs +130 -0
- package/crates/naome-core/tests/task_state_compact_support/states.rs +151 -0
- package/crates/naome-core/tests/task_state_support/mod.rs +163 -0
- package/crates/naome-core/tests/task_state_support/states.rs +84 -0
- package/crates/naome-core/tests/verification.rs +4 -45
- package/crates/naome-core/tests/verification_contract.rs +22 -78
- package/crates/naome-core/tests/workflow_integrity.rs +85 -0
- package/crates/naome-core/tests/workflow_policy.rs +139 -0
- package/crates/naome-core/tests/workflow_support/mod.rs +194 -0
- package/installer/agents.js +90 -0
- package/installer/context.js +67 -0
- package/installer/filesystem.js +166 -0
- package/installer/flows.js +84 -0
- package/installer/git-boundary.js +170 -0
- package/installer/git-hook-content.js +36 -0
- package/installer/git-hooks.js +134 -0
- package/installer/git-local.js +2 -0
- package/installer/git-shared.js +35 -0
- package/installer/harness-file-ops.js +140 -0
- package/installer/harness-files.js +56 -0
- package/installer/harness-verification.js +123 -0
- package/installer/install-plan.js +66 -0
- package/installer/main.js +25 -0
- package/installer/manifest-state.js +167 -0
- package/installer/native-build.js +24 -0
- package/installer/native-format.js +6 -0
- package/installer/native.js +162 -0
- package/installer/output.js +131 -0
- package/installer/version.js +32 -0
- package/native/darwin-arm64/naome +0 -0
- package/native/linux-x64/naome +0 -0
- package/package.json +3 -2
- package/templates/naome-root/.naome/bin/check-harness-health.js +66 -85
- package/templates/naome-root/.naome/bin/check-task-state.js +9 -10
- package/templates/naome-root/.naome/bin/naome.js +51 -76
- package/templates/naome-root/.naome/manifest.json +22 -18
- package/templates/naome-root/.naome/repository-quality-baseline.json +5 -0
- package/templates/naome-root/.naome/repository-quality.json +24 -0
- package/templates/naome-root/.naome/repository-structure.json +90 -0
- package/templates/naome-root/.naome/task-contract.schema.json +93 -11
- package/templates/naome-root/.naome/upgrade-state.json +1 -1
- package/templates/naome-root/.naome/verification.json +38 -0
- package/templates/naome-root/AGENTS.md +3 -0
- package/templates/naome-root/docs/naome/agent-workflow.md +25 -12
- package/templates/naome-root/docs/naome/execution.md +25 -21
- package/templates/naome-root/docs/naome/index.md +5 -3
- package/templates/naome-root/docs/naome/repository-quality.md +46 -0
- package/templates/naome-root/docs/naome/repository-structure.md +51 -0
- package/templates/naome-root/docs/naome/testing.md +13 -0
- package/crates/naome-core/src/task_state.rs +0 -2210
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import {
|
|
3
|
+
chmodSync,
|
|
4
|
+
copyFileSync,
|
|
5
|
+
existsSync,
|
|
6
|
+
lstatSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
} from "node:fs";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
|
|
13
|
+
import { hasSymlinkInTargetPath } from "./filesystem.js";
|
|
14
|
+
import { buildNativeDecisionBinary } from "./native-build.js";
|
|
15
|
+
import { formatExpectedIntegrityBlock } from "./native-format.js";
|
|
16
|
+
import { printError } from "./output.js";
|
|
17
|
+
|
|
18
|
+
export function installNativeDecisionBinary(ctx) {
|
|
19
|
+
const targetPath = join(ctx.targetRoot, ctx.nativeBinaryRelativePath);
|
|
20
|
+
|
|
21
|
+
if (hasSymlinkInTargetPath(ctx, ctx.nativeBinaryRelativePath)) {
|
|
22
|
+
ctx.skipped.push(ctx.nativeBinaryRelativePath);
|
|
23
|
+
ctx.unsafeSkipped.push(ctx.nativeBinaryRelativePath);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const sourcePath = findNativeDecisionBinary(ctx);
|
|
28
|
+
if (!sourcePath) {
|
|
29
|
+
printError(ctx, "NAOME native decision binary is unavailable.");
|
|
30
|
+
console.error("Install Cargo or provide NAOME_NATIVE_BIN with a built naome binary, then rerun naome sync.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (usesSourceNativeFallback(ctx)) {
|
|
35
|
+
patchNaomeCommandNativeIntegrity(ctx, "sha256:generated");
|
|
36
|
+
ctx.skipped.push(ctx.nativeBinaryRelativePath);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
mkdirSync(dirname(targetPath), { recursive: true });
|
|
41
|
+
const sourceHash = sha256(readFileSync(sourcePath));
|
|
42
|
+
const targetHash =
|
|
43
|
+
existsSync(targetPath) && lstatSync(targetPath).isFile()
|
|
44
|
+
? sha256(readFileSync(targetPath))
|
|
45
|
+
: null;
|
|
46
|
+
|
|
47
|
+
if (sourceHash !== targetHash) {
|
|
48
|
+
copyFileSync(sourcePath, targetPath);
|
|
49
|
+
ctx.updated.push(ctx.nativeBinaryRelativePath);
|
|
50
|
+
} else {
|
|
51
|
+
ctx.skipped.push(ctx.nativeBinaryRelativePath);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
chmodSync(targetPath, 0o755);
|
|
55
|
+
patchNaomeCommandNativeIntegrity(ctx, `sha256:${sourceHash}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function findNativeDecisionBinary(ctx) {
|
|
59
|
+
const candidates = [];
|
|
60
|
+
|
|
61
|
+
if (process.env.NAOME_NATIVE_BIN) {
|
|
62
|
+
candidates.push(resolve(ctx.targetRoot, process.env.NAOME_NATIVE_BIN));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
candidates.push(join(ctx.packageRoot, "native", `${process.platform}-${process.arch}`, ctx.nativeBinaryName));
|
|
66
|
+
candidates.push(join(ctx.packageRoot, "target", "release", ctx.nativeBinaryName));
|
|
67
|
+
|
|
68
|
+
for (const candidate of candidates) {
|
|
69
|
+
if (existsSync(candidate) && lstatSync(candidate).isFile()) {
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return buildNativeDecisionBinary(ctx);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function patchInstalledMachineOwnedIntegrity(ctx) {
|
|
78
|
+
const integrityBlock = formatExpectedIntegrityBlock(templateIntegrity(ctx));
|
|
79
|
+
|
|
80
|
+
for (const relativePath of [ctx.healthCheckerRelativePath, ctx.taskStateCheckerRelativePath]) {
|
|
81
|
+
const targetPath = join(ctx.targetRoot, relativePath);
|
|
82
|
+
if (!existsSync(targetPath) || hasSymlinkInTargetPath(ctx, relativePath)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const content = readFileSync(targetPath, "utf8");
|
|
87
|
+
const nextContent = content.replace(ctx.integrityBlockPattern, integrityBlock);
|
|
88
|
+
if (nextContent !== content) {
|
|
89
|
+
writeFileSync(targetPath, nextContent);
|
|
90
|
+
ctx.updated.push(relativePath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function usesSourceNativeFallback(ctx) {
|
|
96
|
+
return existsSync(join(ctx.targetRoot, "packages", "naome", "Cargo.toml"))
|
|
97
|
+
&& existsSync(join(ctx.targetRoot, "packages", "naome", "crates", "naome-cli", "src", "main.rs"));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function installedNativeBinaryHash(ctx) {
|
|
101
|
+
const targetPath = join(ctx.targetRoot, ctx.nativeBinaryRelativePath);
|
|
102
|
+
if (
|
|
103
|
+
!existsSync(targetPath) ||
|
|
104
|
+
hasSymlinkInTargetPath(ctx, ctx.nativeBinaryRelativePath) ||
|
|
105
|
+
!lstatSync(targetPath).isFile()
|
|
106
|
+
) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return sha256(readFileSync(targetPath));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function templateIntegrity(ctx) {
|
|
114
|
+
const integrity = {};
|
|
115
|
+
|
|
116
|
+
for (const relativePath of ctx.machineOwnedPaths) {
|
|
117
|
+
const sourcePath = join(ctx.templateRoot, relativePath);
|
|
118
|
+
integrity[relativePath] = `sha256:${machineFileHash(ctx, relativePath, readFileSync(sourcePath))}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return integrity;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function sha256(content) {
|
|
125
|
+
return createHash("sha256").update(content).digest("hex");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function machineFileHash(ctx, relativePath, content) {
|
|
129
|
+
let normalized = content;
|
|
130
|
+
|
|
131
|
+
if (hasGeneratedIntegrity(ctx, relativePath)) {
|
|
132
|
+
normalized = normalized.toString("utf8").replace(ctx.integrityBlockPattern, ctx.normalizedIntegrityBlock);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (relativePath === ctx.naomeCommandRelativePath) {
|
|
136
|
+
normalized = normalized.toString("utf8").replace(ctx.nativeIntegrityPattern, ctx.normalizedNativeIntegrity);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return sha256(normalized);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function hasGeneratedIntegrity(ctx, relativePath) {
|
|
143
|
+
return relativePath === ctx.healthCheckerRelativePath || relativePath === ctx.taskStateCheckerRelativePath;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function patchNaomeCommandNativeIntegrity(ctx, expectedIntegrity) {
|
|
147
|
+
const commandPath = join(ctx.targetRoot, ctx.naomeCommandRelativePath);
|
|
148
|
+
if (!existsSync(commandPath) || hasSymlinkInTargetPath(ctx, ctx.naomeCommandRelativePath)) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const content = readFileSync(commandPath, "utf8");
|
|
153
|
+
const nextContent = content.replace(
|
|
154
|
+
ctx.nativeIntegrityPattern,
|
|
155
|
+
`const expectedNativeBinaryIntegrity = "${expectedIntegrity}";\n`,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
if (nextContent !== content) {
|
|
159
|
+
writeFileSync(commandPath, nextContent);
|
|
160
|
+
ctx.updated.push(ctx.naomeCommandRelativePath);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
export function printHeader(ctx) {
|
|
5
|
+
console.log("");
|
|
6
|
+
console.log(`${ctx.color.bold("NAOME")} ${ctx.color.dim(`v${ctx.packageVersion}`)}`);
|
|
7
|
+
console.log(ctx.color.dim("AI coding-agent harness installer"));
|
|
8
|
+
console.log("");
|
|
9
|
+
console.log(`${ctx.color.dim("target ")} ${ctx.targetRoot}`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function printSection(ctx, title) {
|
|
13
|
+
console.log("");
|
|
14
|
+
console.log(ctx.color.bold(title));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function printList(ctx, items, marker) {
|
|
18
|
+
for (const item of uniqueStrings(items)) {
|
|
19
|
+
console.log(`${ctx.color.dim(marker)} ${item}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function uniqueStrings(items) {
|
|
24
|
+
return Array.from(new Set(items));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function printError(ctx, message) {
|
|
28
|
+
console.error("");
|
|
29
|
+
console.error(`${ctx.color.red("x")} ${message}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function printCancelled(ctx, message) {
|
|
33
|
+
console.log("");
|
|
34
|
+
console.log(`${ctx.color.yellow("-")} ${message}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function printCommandFailure(ctx, message, result) {
|
|
38
|
+
printError(ctx, message);
|
|
39
|
+
if (result.stdout.trim()) {
|
|
40
|
+
console.error(result.stdout.trim());
|
|
41
|
+
}
|
|
42
|
+
if (result.stderr.trim()) {
|
|
43
|
+
console.error(result.stderr.trim());
|
|
44
|
+
}
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function printSummary(ctx, existingInstall) {
|
|
49
|
+
console.log("");
|
|
50
|
+
console.log(`${ctx.color.green("+")} ${ctx.summaryTitle}`);
|
|
51
|
+
|
|
52
|
+
const detailedOutput = shouldPrintDetailedSummary(ctx, existingInstall);
|
|
53
|
+
if (!detailedOutput) {
|
|
54
|
+
printCompactSummary(ctx);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
printDetailedSummary(ctx, detailedOutput);
|
|
58
|
+
if (ctx.unsafeSkipped.length > 0) {
|
|
59
|
+
printSection(ctx, "Skipped unsafe symlinked paths");
|
|
60
|
+
printList(ctx, ctx.unsafeSkipped, "!");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (isRepositoryInitialized(ctx)) {
|
|
64
|
+
console.log("");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
printSection(ctx, "Next step");
|
|
69
|
+
console.log("Copy this into your coding agent:");
|
|
70
|
+
console.log("");
|
|
71
|
+
console.log(ctx.color.dim("```"));
|
|
72
|
+
console.log(ctx.nextStepPrompt);
|
|
73
|
+
console.log(ctx.color.dim("```"));
|
|
74
|
+
console.log("");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function printDetailedSummary(ctx, detailedOutput) {
|
|
78
|
+
if (detailedOutput && ctx.installed.length > 0) {
|
|
79
|
+
const items = uniqueStrings(ctx.installed);
|
|
80
|
+
printSection(ctx, `Installed ${items.length} ${items.length === 1 ? "item" : "items"}`);
|
|
81
|
+
printList(ctx, ctx.installed, "+");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (detailedOutput && ctx.updated.length > 0) {
|
|
85
|
+
const items = uniqueStrings(ctx.updated);
|
|
86
|
+
printSection(ctx, `Updated ${items.length} ${items.length === 1 ? "item" : "items"}`);
|
|
87
|
+
printList(ctx, ctx.updated, "~");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (detailedOutput && ctx.archived.length > 0) {
|
|
91
|
+
printSection(ctx, "Archived");
|
|
92
|
+
for (const entry of ctx.archived) {
|
|
93
|
+
console.log(`${ctx.color.dim(">")} ${entry.from} -> ${entry.to}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (detailedOutput && ctx.skipped.length > 0) {
|
|
98
|
+
const items = uniqueStrings(ctx.skipped);
|
|
99
|
+
printSection(ctx, `Skipped ${items.length} existing ${items.length === 1 ? "path" : "paths"}`);
|
|
100
|
+
printList(ctx, ctx.skipped, "-");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function shouldPrintDetailedSummary(ctx, existingInstall) {
|
|
105
|
+
return ctx.verboseOutput || !existingInstall;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function printCompactSummary(ctx) {
|
|
109
|
+
const installedCount = uniqueStrings(ctx.installed).length;
|
|
110
|
+
const updatedCount = uniqueStrings(ctx.updated).length;
|
|
111
|
+
const archivedCount = ctx.archived.length;
|
|
112
|
+
|
|
113
|
+
if (installedCount > 0) {
|
|
114
|
+
console.log(`${ctx.color.dim("installed")} ${installedCount}`);
|
|
115
|
+
}
|
|
116
|
+
if (updatedCount > 0) {
|
|
117
|
+
console.log(`${ctx.color.dim("updated")} ${updatedCount}`);
|
|
118
|
+
}
|
|
119
|
+
if (archivedCount > 0) {
|
|
120
|
+
console.log(`${ctx.color.dim("archived")} ${archivedCount}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isRepositoryInitialized(ctx) {
|
|
125
|
+
try {
|
|
126
|
+
const initState = JSON.parse(readFileSync(join(ctx.targetRoot, ".naome", "init-state.json"), "utf8"));
|
|
127
|
+
return initState.initialized === true;
|
|
128
|
+
} catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { printError } from "./output.js";
|
|
2
|
+
|
|
3
|
+
export function compareVersions(ctx, left, right) {
|
|
4
|
+
const leftParts = parseVersion(ctx, left);
|
|
5
|
+
const rightParts = parseVersion(ctx, right);
|
|
6
|
+
|
|
7
|
+
for (let index = 0; index < 3; index += 1) {
|
|
8
|
+
if (leftParts[index] > rightParts[index]) {
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (leftParts[index] < rightParts[index]) {
|
|
13
|
+
return -1;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function isVersion(version) {
|
|
21
|
+
return typeof version === "string" && /^\d+\.\d+\.\d+$/.test(version);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseVersion(ctx, version) {
|
|
25
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
|
26
|
+
if (!match) {
|
|
27
|
+
printError(ctx, `Invalid NAOME version: ${version}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return match.slice(1).map((part) => Number.parseInt(part, 10));
|
|
32
|
+
}
|
|
Binary file
|
package/native/linux-x64/naome
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lamentis/naome",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Native-first CLI for the NAOME agent harness.",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"agent",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"Cargo.lock",
|
|
32
32
|
"Cargo.toml",
|
|
33
33
|
"crates",
|
|
34
|
+
"installer",
|
|
34
35
|
"native",
|
|
35
36
|
"templates",
|
|
36
37
|
"README.md"
|
|
@@ -1,158 +1,141 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const crypto = require("node:crypto");
|
|
5
|
+
const childProcess = require("node:child_process");
|
|
6
|
+
const path = require("node:path");
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const nativeBinaryPath = process.platform === "win32" ? ".naome/bin/naome-rust.exe" : ".naome/bin/naome-rust";
|
|
9
9
|
const nativeBinaryName = process.platform === "win32" ? "naome.exe" : "naome";
|
|
10
10
|
|
|
11
11
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
|
-
"
|
|
13
|
-
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
14
|
-
".naome/bin/naome.js": "sha256:7894690ad47700a9a5e7ecb5a94ba42c1a12e2637d2c9f41f0023b1bd8bd22b6",
|
|
12
|
+
".naome/bin/check-harness-health.js": "sha256:dc4de52b79c69600b9ba47b924e2c2b8de61a2cbfab6d1ccc0f1924d963db657",
|
|
15
13
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
16
|
-
".naome/bin/
|
|
17
|
-
".naome/
|
|
18
|
-
"
|
|
14
|
+
".naome/bin/naome.js": "sha256:87eabd690bf55f0b0195446db46fa7c19bfa17395d31c2f34a9ef9339d2229e2",
|
|
15
|
+
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
16
|
+
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
|
+
"AGENTS.md": "sha256:9192ea81f90bb19f8043513c49b5da9e9598ee694da8356f345e7ccbca0e28df",
|
|
18
|
+
"docs/naome/agent-workflow.md": "sha256:802eb34cf268fc9c5e7aefc28192efef4bf60302d30b3f78e5a61b876ce8a098",
|
|
19
|
+
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
19
20
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
20
|
-
"docs/naome/
|
|
21
|
-
"docs/naome/
|
|
22
|
-
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1",
|
|
23
|
-
".naome/bin/naome-rust": "sha256:cc754ae59477577dfc0130cc21c286beaf3f19e2852278bb8f1e8724277eb44b"
|
|
21
|
+
"docs/naome/index.md": "sha256:a674102cc801702dc77102afb59be0f5ab189dc638caf0bef358b9d6087d0742",
|
|
22
|
+
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
24
23
|
});
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
const root = findRoot(process.cwd()) || path.resolve(__dirname, "..", "..");
|
|
26
|
+
const binary = selectBinary(root);
|
|
27
|
+
const result = childProcess.spawnSync(binary, ["check-harness-health", "--root", root], {
|
|
28
|
+
cwd: root,
|
|
29
|
+
encoding: "utf8",
|
|
30
|
+
env: {
|
|
31
|
+
...process.env,
|
|
32
|
+
NAOME_EXPECTED_INTEGRITY_JSON: JSON.stringify(expectedMachineOwnedIntegrity)
|
|
33
|
+
},
|
|
34
|
+
stdio: "inherit"
|
|
35
|
+
});
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
cwd: root,
|
|
32
|
-
encoding: "utf8",
|
|
33
|
-
env: {
|
|
34
|
-
...process.env,
|
|
35
|
-
NAOME_EXPECTED_INTEGRITY_JSON: JSON.stringify(expectedMachineOwnedIntegrity)
|
|
36
|
-
},
|
|
37
|
-
stdio: "inherit"
|
|
38
|
-
});
|
|
37
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
function resolveNativeDecisionBinary(root) {
|
|
44
|
-
const expectedIntegrity = expectedNativeIntegrity(root);
|
|
39
|
+
function selectBinary(rootDir) {
|
|
40
|
+
const wantedHash = manifestNativeHash(rootDir);
|
|
45
41
|
const candidates = [
|
|
46
42
|
process.env.NAOME_NATIVE_BIN,
|
|
47
|
-
join(
|
|
48
|
-
join(
|
|
49
|
-
join(
|
|
43
|
+
path.join(rootDir, nativeBinaryPath),
|
|
44
|
+
path.join(rootDir, "packages", "naome", "target", "release", nativeBinaryName),
|
|
45
|
+
path.join(rootDir, "packages", "naome", "target", "debug", nativeBinaryName)
|
|
50
46
|
].filter(Boolean);
|
|
51
47
|
|
|
52
48
|
for (const candidate of candidates) {
|
|
53
|
-
if (
|
|
49
|
+
if (canRun(candidate, rootDir, wantedHash)) {
|
|
54
50
|
return candidate;
|
|
55
51
|
}
|
|
56
52
|
}
|
|
57
53
|
|
|
58
|
-
if (
|
|
59
|
-
|
|
54
|
+
if (wantedHash) {
|
|
55
|
+
stop(`No runnable NAOME native harness health binary matched ${wantedHash}. Run naome sync again.`);
|
|
60
56
|
}
|
|
61
57
|
|
|
62
|
-
const built =
|
|
63
|
-
if (built &&
|
|
58
|
+
const built = buildFromSource(rootDir);
|
|
59
|
+
if (built && canRun(built, rootDir, null)) {
|
|
64
60
|
return built;
|
|
65
61
|
}
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
stop("NAOME native harness health binary is missing or incompatible. Run naome sync again.");
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
function
|
|
71
|
-
if (
|
|
66
|
+
function manifestNativeHash(rootDir) {
|
|
67
|
+
if (isSha(process.env.NAOME_EXPECTED_NATIVE_INTEGRITY)) {
|
|
72
68
|
return process.env.NAOME_EXPECTED_NATIVE_INTEGRITY;
|
|
73
69
|
}
|
|
74
70
|
|
|
75
|
-
const manifestPath = join(root, ".naome", "manifest.json");
|
|
76
|
-
if (!existsSync(manifestPath)) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let manifest;
|
|
81
71
|
try {
|
|
82
|
-
manifest = JSON.parse(readFileSync(
|
|
72
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(rootDir, ".naome", "manifest.json"), "utf8"));
|
|
73
|
+
return isSha(manifest.integrity?.[nativeBinaryPath]) ? manifest.integrity[nativeBinaryPath] : null;
|
|
83
74
|
} catch {
|
|
84
75
|
return null;
|
|
85
76
|
}
|
|
86
|
-
|
|
87
|
-
const expected = manifest.integrity?.[nativeBinaryRelativePath];
|
|
88
|
-
if (!isIntegrityHash(expected)) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return expected;
|
|
93
77
|
}
|
|
94
78
|
|
|
95
|
-
function
|
|
96
|
-
if (!candidate || !existsSync(candidate)) {
|
|
79
|
+
function canRun(candidate, rootDir, wantedHash) {
|
|
80
|
+
if (!candidate || !fs.existsSync(candidate)) {
|
|
97
81
|
return false;
|
|
98
82
|
}
|
|
99
83
|
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
if (actual !== expectedIntegrity) {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
84
|
+
if (wantedHash && fileSha(candidate) !== wantedHash) {
|
|
85
|
+
return false;
|
|
105
86
|
}
|
|
106
87
|
|
|
107
|
-
const probe = spawnSync(candidate, [], {
|
|
108
|
-
cwd:
|
|
88
|
+
const probe = childProcess.spawnSync(candidate, [], {
|
|
89
|
+
cwd: rootDir,
|
|
109
90
|
encoding: "utf8",
|
|
110
91
|
stdio: "ignore"
|
|
111
92
|
});
|
|
112
93
|
return !probe.error && probe.status !== null;
|
|
113
94
|
}
|
|
114
95
|
|
|
115
|
-
function
|
|
116
|
-
const
|
|
117
|
-
if (!existsSync(
|
|
96
|
+
function buildFromSource(rootDir) {
|
|
97
|
+
const manifest = path.join(rootDir, "packages", "naome", "Cargo.toml");
|
|
98
|
+
if (!fs.existsSync(manifest)) {
|
|
118
99
|
return null;
|
|
119
100
|
}
|
|
120
101
|
|
|
121
|
-
const
|
|
122
|
-
cwd:
|
|
102
|
+
const build = childProcess.spawnSync("cargo", ["build", "--release", "--manifest-path", manifest, "-p", "naome-cli"], {
|
|
103
|
+
cwd: rootDir,
|
|
123
104
|
encoding: "utf8",
|
|
124
105
|
stdio: "ignore"
|
|
125
106
|
});
|
|
126
|
-
if (
|
|
107
|
+
if (build.status !== 0) {
|
|
127
108
|
return null;
|
|
128
109
|
}
|
|
129
110
|
|
|
130
|
-
const
|
|
131
|
-
return existsSync(
|
|
111
|
+
const binaryPath = path.join(rootDir, "packages", "naome", "target", "release", nativeBinaryName);
|
|
112
|
+
return fs.existsSync(binaryPath) ? binaryPath : null;
|
|
132
113
|
}
|
|
133
114
|
|
|
134
|
-
function
|
|
135
|
-
let current = resolve(
|
|
136
|
-
|
|
137
|
-
while (true) {
|
|
138
|
-
if (existsSync(join(current, ".naome", "manifest.json"))) {
|
|
115
|
+
function findRoot(startDir) {
|
|
116
|
+
for (let current = path.resolve(startDir); ;) {
|
|
117
|
+
if (fs.existsSync(path.join(current, ".naome", "manifest.json"))) {
|
|
139
118
|
return current;
|
|
140
119
|
}
|
|
141
120
|
|
|
142
|
-
const parent = dirname(current);
|
|
121
|
+
const parent = path.dirname(current);
|
|
143
122
|
if (parent === current) {
|
|
144
123
|
return null;
|
|
145
124
|
}
|
|
146
|
-
|
|
147
125
|
current = parent;
|
|
148
126
|
}
|
|
149
127
|
}
|
|
150
128
|
|
|
151
|
-
function
|
|
129
|
+
function isSha(value) {
|
|
152
130
|
return typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value);
|
|
153
131
|
}
|
|
154
132
|
|
|
155
|
-
function
|
|
133
|
+
function fileSha(filePath) {
|
|
134
|
+
const digest = crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
|
|
135
|
+
return `sha256:${digest}`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function stop(message) {
|
|
156
139
|
console.error("NAOME harness health check failed.");
|
|
157
140
|
console.error(`- ${message}`);
|
|
158
141
|
console.error("");
|
|
@@ -160,5 +143,3 @@ function fail(message) {
|
|
|
160
143
|
console.error("Run naome sync to repair machine-owned files after review.");
|
|
161
144
|
process.exit(1);
|
|
162
145
|
}
|
|
163
|
-
|
|
164
|
-
main();
|
|
@@ -9,18 +9,17 @@ 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
|
-
"
|
|
13
|
-
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
14
|
-
".naome/bin/naome.js": "sha256:7894690ad47700a9a5e7ecb5a94ba42c1a12e2637d2c9f41f0023b1bd8bd22b6",
|
|
12
|
+
".naome/bin/check-harness-health.js": "sha256:dc4de52b79c69600b9ba47b924e2c2b8de61a2cbfab6d1ccc0f1924d963db657",
|
|
15
13
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
16
|
-
".naome/bin/
|
|
17
|
-
".naome/
|
|
18
|
-
"
|
|
14
|
+
".naome/bin/naome.js": "sha256:87eabd690bf55f0b0195446db46fa7c19bfa17395d31c2f34a9ef9339d2229e2",
|
|
15
|
+
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
16
|
+
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
|
+
"AGENTS.md": "sha256:9192ea81f90bb19f8043513c49b5da9e9598ee694da8356f345e7ccbca0e28df",
|
|
18
|
+
"docs/naome/agent-workflow.md": "sha256:802eb34cf268fc9c5e7aefc28192efef4bf60302d30b3f78e5a61b876ce8a098",
|
|
19
|
+
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
19
20
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
20
|
-
"docs/naome/
|
|
21
|
-
"docs/naome/
|
|
22
|
-
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1",
|
|
23
|
-
".naome/bin/naome-rust": "sha256:cc754ae59477577dfc0130cc21c286beaf3f19e2852278bb8f1e8724277eb44b"
|
|
21
|
+
"docs/naome/index.md": "sha256:a674102cc801702dc77102afb59be0f5ab189dc638caf0bef358b9d6087d0742",
|
|
22
|
+
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
24
23
|
});
|
|
25
24
|
|
|
26
25
|
function main(argv) {
|