@lamentis/naome 1.3.8 → 1.3.10
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 +5 -0
- package/bin/naome.js +1 -1
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/architecture_commands.rs +123 -0
- package/crates/naome-cli/src/cli_args.rs +4 -0
- package/crates/naome-cli/src/dispatcher.rs +2 -0
- package/crates/naome-cli/src/install_bridge.rs +56 -8
- package/crates/naome-cli/src/main.rs +6 -0
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/architecture/config/parser/scalar.rs +26 -0
- package/crates/naome-core/src/architecture/config/parser/sections.rs +137 -0
- package/crates/naome-core/src/architecture/config/parser.rs +96 -0
- package/crates/naome-core/src/architecture/config.rs +114 -0
- package/crates/naome-core/src/architecture/model.rs +80 -0
- package/crates/naome-core/src/architecture/output.rs +178 -0
- package/crates/naome-core/src/architecture/rules.rs +140 -0
- package/crates/naome-core/src/architecture/scan/graph_builder/emit.rs +56 -0
- package/crates/naome-core/src/architecture/scan/graph_builder/facts.rs +88 -0
- package/crates/naome-core/src/architecture/scan/graph_builder.rs +134 -0
- package/crates/naome-core/src/architecture/scan/path_scan.rs +92 -0
- package/crates/naome-core/src/architecture/scan.rs +75 -0
- package/crates/naome-core/src/architecture.rs +31 -0
- package/crates/naome-core/src/harness_health/integrity.rs +41 -23
- package/crates/naome-core/src/harness_health/manifest.rs +97 -0
- package/crates/naome-core/src/harness_health.rs +58 -106
- package/crates/naome-core/src/install_plan.rs +2 -0
- package/crates/naome-core/src/lib.rs +16 -8
- package/crates/naome-core/src/quality/cache.rs +122 -19
- package/crates/naome-core/src/quality/scanner/analysis.rs +4 -2
- package/crates/naome-core/src/quality/scanner/repo_paths.rs +27 -3
- package/crates/naome-core/src/quality/scanner.rs +5 -2
- package/crates/naome-core/src/workflow/integrity_support.rs +10 -3
- package/crates/naome-core/tests/architecture.rs +209 -0
- package/crates/naome-core/tests/harness_health.rs +150 -0
- package/crates/naome-core/tests/quality_performance.rs +63 -2
- package/installer/filesystem.js +38 -0
- package/installer/flows.js +6 -1
- package/installer/harness-file-ops.js +36 -8
- package/installer/harness-files.js +3 -0
- package/installer/manifest-state.js +2 -2
- package/installer/native.js +63 -18
- 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 +23 -19
- package/templates/naome-root/.naome/bin/check-task-state.js +33 -40
- package/templates/naome-root/.naome/bin/naome.js +2 -2
- package/templates/naome-root/.naome/manifest.json +8 -6
- package/templates/naome-root/.naome/verification.json +15 -1
- package/templates/naome-root/docs/naome/architecture-fitness.md +97 -0
- package/templates/naome-root/docs/naome/index.md +4 -3
- package/templates/naome-root/docs/naome/testing.md +6 -3
package/installer/native.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
lstatSync,
|
|
7
7
|
mkdirSync,
|
|
8
8
|
readFileSync,
|
|
9
|
+
unlinkSync,
|
|
9
10
|
writeFileSync,
|
|
10
11
|
} from "node:fs";
|
|
11
12
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -32,8 +33,8 @@ export function installNativeDecisionBinary(ctx) {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
if (usesSourceNativeFallback(ctx)) {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
removeInstalledNativeDecisionBinary(ctx);
|
|
37
|
+
patchInstalledNativeIntegrity(ctx, "sha256:generated");
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -52,7 +53,7 @@ export function installNativeDecisionBinary(ctx) {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
chmodSync(targetPath, 0o755);
|
|
55
|
-
|
|
56
|
+
patchInstalledNativeIntegrity(ctx, `sha256:${sourceHash}`);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export function findNativeDecisionBinary(ctx) {
|
|
@@ -75,7 +76,7 @@ export function findNativeDecisionBinary(ctx) {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
export function patchInstalledMachineOwnedIntegrity(ctx) {
|
|
78
|
-
const integrityBlock = formatExpectedIntegrityBlock(
|
|
79
|
+
const integrityBlock = formatExpectedIntegrityBlock(installedMachineOwnedIntegrity(ctx));
|
|
79
80
|
|
|
80
81
|
for (const relativePath of [ctx.healthCheckerRelativePath, ctx.taskStateCheckerRelativePath]) {
|
|
81
82
|
const targetPath = join(ctx.targetRoot, relativePath);
|
|
@@ -110,6 +111,23 @@ export function installedNativeBinaryHash(ctx) {
|
|
|
110
111
|
return sha256(readFileSync(targetPath));
|
|
111
112
|
}
|
|
112
113
|
|
|
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
|
+
|
|
113
131
|
export function templateIntegrity(ctx) {
|
|
114
132
|
const integrity = {};
|
|
115
133
|
|
|
@@ -121,6 +139,17 @@ export function templateIntegrity(ctx) {
|
|
|
121
139
|
return integrity;
|
|
122
140
|
}
|
|
123
141
|
|
|
142
|
+
export function installedMachineOwnedIntegrity(ctx) {
|
|
143
|
+
const integrity = templateIntegrity(ctx);
|
|
144
|
+
const nativeHash = installedNativeBinaryHash(ctx);
|
|
145
|
+
|
|
146
|
+
if (!usesSourceNativeFallback(ctx) && nativeHash) {
|
|
147
|
+
integrity[ctx.nativeBinaryRelativePath] = `sha256:${nativeHash}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return integrity;
|
|
151
|
+
}
|
|
152
|
+
|
|
124
153
|
export function sha256(content) {
|
|
125
154
|
return createHash("sha256").update(content).digest("hex");
|
|
126
155
|
}
|
|
@@ -132,7 +161,7 @@ export function machineFileHash(ctx, relativePath, content) {
|
|
|
132
161
|
normalized = normalized.toString("utf8").replace(ctx.integrityBlockPattern, ctx.normalizedIntegrityBlock);
|
|
133
162
|
}
|
|
134
163
|
|
|
135
|
-
if (relativePath
|
|
164
|
+
if (hasGeneratedNativeIntegrity(ctx, relativePath)) {
|
|
136
165
|
normalized = normalized.toString("utf8").replace(ctx.nativeIntegrityPattern, ctx.normalizedNativeIntegrity);
|
|
137
166
|
}
|
|
138
167
|
|
|
@@ -143,20 +172,36 @@ export function hasGeneratedIntegrity(ctx, relativePath) {
|
|
|
143
172
|
return relativePath === ctx.healthCheckerRelativePath || relativePath === ctx.taskStateCheckerRelativePath;
|
|
144
173
|
}
|
|
145
174
|
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
175
|
+
export function hasGeneratedNativeIntegrity(ctx, relativePath) {
|
|
176
|
+
return [
|
|
177
|
+
ctx.healthCheckerRelativePath,
|
|
178
|
+
ctx.taskStateCheckerRelativePath,
|
|
179
|
+
ctx.naomeCommandRelativePath,
|
|
180
|
+
].includes(relativePath);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function patchInstalledNativeIntegrity(ctx, expectedIntegrity) {
|
|
184
|
+
const nativeIntegrityPaths = [
|
|
185
|
+
ctx.healthCheckerRelativePath,
|
|
186
|
+
ctx.taskStateCheckerRelativePath,
|
|
187
|
+
ctx.naomeCommandRelativePath,
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
for (const relativePath of nativeIntegrityPaths) {
|
|
191
|
+
const targetPath = join(ctx.targetRoot, relativePath);
|
|
192
|
+
if (!existsSync(targetPath) || hasSymlinkInTargetPath(ctx, relativePath)) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
151
195
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
196
|
+
const content = readFileSync(targetPath, "utf8");
|
|
197
|
+
const nextContent = content.replace(
|
|
198
|
+
ctx.nativeIntegrityPattern,
|
|
199
|
+
`const expectedNativeBinaryIntegrity = "${expectedIntegrity}";\n`,
|
|
200
|
+
);
|
|
157
201
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
202
|
+
if (nextContent !== content) {
|
|
203
|
+
writeFileSync(targetPath, nextContent);
|
|
204
|
+
ctx.updated.push(relativePath);
|
|
205
|
+
}
|
|
161
206
|
}
|
|
162
207
|
}
|
|
Binary file
|
package/native/linux-x64/naome
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -7,20 +7,21 @@ const path = require("node:path");
|
|
|
7
7
|
|
|
8
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
|
+
const expectedNativeBinaryIntegrity = "sha256:generated";
|
|
10
11
|
|
|
11
12
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
|
-
".naome/bin/check-harness-health.js": "sha256:
|
|
13
|
-
".naome/bin/check-task-state.js": "sha256:
|
|
14
|
-
".naome/bin/naome.js": "sha256:
|
|
13
|
+
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
14
|
+
".naome/bin/check-task-state.js": "sha256:2612577b7e4ab45d9d39dd5ac54c8e7ed749d237d78f1a8d252f4dfa0b4eaaab",
|
|
15
|
+
".naome/bin/naome.js": "sha256:f129c580fb70b3a1d92d0ab0de9fa6c131b2fc51a8dcdebe9d6f5a812a3be61b",
|
|
15
16
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
16
17
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
18
|
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
18
|
-
"docs/naome/agent-workflow.md": "sha256:
|
|
19
|
+
"docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
|
|
19
20
|
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
20
21
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
21
22
|
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
22
|
-
"docs/naome/index.md": "sha256:
|
|
23
|
-
"docs/naome/task-ledger.md": "sha256:
|
|
23
|
+
"docs/naome/index.md": "sha256:cac748ed375d86d288460456fc5d606b29bd99d91148522c303d5400a083dbc5",
|
|
24
|
+
"docs/naome/task-ledger.md": "sha256:6ca7222c80079b4662fb718d3c71d686770646f1fa52b83b0e90aed1c5a1101b",
|
|
24
25
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -39,7 +40,7 @@ const result = childProcess.spawnSync(binary, ["check-harness-health", "--root",
|
|
|
39
40
|
process.exit(result.status === null ? 1 : result.status);
|
|
40
41
|
|
|
41
42
|
function selectBinary(rootDir) {
|
|
42
|
-
const wantedHash =
|
|
43
|
+
const wantedHash = expectedNativeHash();
|
|
43
44
|
const candidates = [
|
|
44
45
|
process.env.NAOME_NATIVE_BIN,
|
|
45
46
|
path.join(rootDir, nativeBinaryPath),
|
|
@@ -47,13 +48,13 @@ function selectBinary(rootDir) {
|
|
|
47
48
|
path.join(rootDir, "packages", "naome", "target", "debug", nativeBinaryName)
|
|
48
49
|
].filter(Boolean);
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if (wantedHash) {
|
|
52
|
+
for (const candidate of candidates) {
|
|
53
|
+
if (canRun(candidate, rootDir, wantedHash)) {
|
|
54
|
+
return candidate;
|
|
55
|
+
}
|
|
53
56
|
}
|
|
54
|
-
}
|
|
55
57
|
|
|
56
|
-
if (wantedHash) {
|
|
57
58
|
stop(`No runnable NAOME native harness health binary matched ${wantedHash}. Run naome sync again.`);
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -62,20 +63,19 @@ function selectBinary(rootDir) {
|
|
|
62
63
|
return built;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
stop("NAOME native harness health binary
|
|
66
|
+
stop("NAOME native harness health binary has no trusted packaged integrity. Run naome sync again.");
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
function
|
|
69
|
+
function expectedNativeHash() {
|
|
69
70
|
if (isSha(process.env.NAOME_EXPECTED_NATIVE_INTEGRITY)) {
|
|
70
71
|
return process.env.NAOME_EXPECTED_NATIVE_INTEGRITY;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return isSha(manifest.integrity?.[nativeBinaryPath]) ? manifest.integrity[nativeBinaryPath] : null;
|
|
76
|
-
} catch {
|
|
77
|
-
return null;
|
|
74
|
+
if (isSha(expectedNativeBinaryIntegrity)) {
|
|
75
|
+
return expectedNativeBinaryIntegrity;
|
|
78
76
|
}
|
|
77
|
+
|
|
78
|
+
return null;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
function canRun(candidate, rootDir, wantedHash) {
|
|
@@ -96,6 +96,10 @@ function canRun(candidate, rootDir, wantedHash) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function buildFromSource(rootDir) {
|
|
99
|
+
if (expectedNativeBinaryIntegrity !== "sha256:generated") {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
99
103
|
const manifest = path.join(rootDir, "packages", "naome", "Cargo.toml");
|
|
100
104
|
if (!fs.existsSync(manifest)) {
|
|
101
105
|
return null;
|
|
@@ -7,20 +7,21 @@ const { spawnSync } = require("node:child_process");
|
|
|
7
7
|
|
|
8
8
|
const nativeBinaryRelativePath = process.platform === "win32" ? ".naome/bin/naome-rust.exe" : ".naome/bin/naome-rust";
|
|
9
9
|
const nativeBinaryName = process.platform === "win32" ? "naome.exe" : "naome";
|
|
10
|
+
const expectedNativeBinaryIntegrity = "sha256:generated";
|
|
10
11
|
|
|
11
12
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
|
-
".naome/bin/check-harness-health.js": "sha256:
|
|
13
|
-
".naome/bin/check-task-state.js": "sha256:
|
|
14
|
-
".naome/bin/naome.js": "sha256:
|
|
13
|
+
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
14
|
+
".naome/bin/check-task-state.js": "sha256:2612577b7e4ab45d9d39dd5ac54c8e7ed749d237d78f1a8d252f4dfa0b4eaaab",
|
|
15
|
+
".naome/bin/naome.js": "sha256:f129c580fb70b3a1d92d0ab0de9fa6c131b2fc51a8dcdebe9d6f5a812a3be61b",
|
|
15
16
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
16
17
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
18
|
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
18
|
-
"docs/naome/agent-workflow.md": "sha256:
|
|
19
|
+
"docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
|
|
19
20
|
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
20
21
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
21
22
|
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
22
|
-
"docs/naome/index.md": "sha256:
|
|
23
|
-
"docs/naome/task-ledger.md": "sha256:
|
|
23
|
+
"docs/naome/index.md": "sha256:cac748ed375d86d288460456fc5d606b29bd99d91148522c303d5400a083dbc5",
|
|
24
|
+
"docs/naome/task-ledger.md": "sha256:6ca7222c80079b4662fb718d3c71d686770646f1fa52b83b0e90aed1c5a1101b",
|
|
24
25
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -62,7 +63,7 @@ function modeArgs(argv) {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
function resolveNativeDecisionBinary(root) {
|
|
65
|
-
const expectedIntegrity = expectedNativeIntegrity(
|
|
66
|
+
const expectedIntegrity = expectedNativeIntegrity();
|
|
66
67
|
const candidates = [
|
|
67
68
|
process.env.NAOME_NATIVE_BIN,
|
|
68
69
|
join(root, nativeBinaryRelativePath),
|
|
@@ -70,13 +71,13 @@ function resolveNativeDecisionBinary(root) {
|
|
|
70
71
|
join(root, "packages", "naome", "target", "debug", nativeBinaryName)
|
|
71
72
|
].filter(Boolean);
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
if (expectedIntegrity) {
|
|
75
|
+
for (const candidate of candidates) {
|
|
76
|
+
if (isUsableNativeBinary(candidate, root, expectedIntegrity)) {
|
|
77
|
+
return candidate;
|
|
78
|
+
}
|
|
76
79
|
}
|
|
77
|
-
}
|
|
78
80
|
|
|
79
|
-
if (expectedIntegrity) {
|
|
80
81
|
fail(`No runnable NAOME native task-state binary matched ${expectedIntegrity}. Run naome sync again.`);
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -88,29 +89,16 @@ function resolveNativeDecisionBinary(root) {
|
|
|
88
89
|
fail("NAOME native task-state binary is missing or incompatible. Run naome sync again.");
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
function expectedNativeIntegrity(
|
|
92
|
+
function expectedNativeIntegrity() {
|
|
92
93
|
if (isIntegrityHash(process.env.NAOME_EXPECTED_NATIVE_INTEGRITY)) {
|
|
93
94
|
return process.env.NAOME_EXPECTED_NATIVE_INTEGRITY;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
if (!existsSync(manifestPath)) {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
let manifest;
|
|
102
|
-
try {
|
|
103
|
-
manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
104
|
-
} catch {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const expected = manifest.integrity?.[nativeBinaryRelativePath];
|
|
109
|
-
if (!isIntegrityHash(expected)) {
|
|
97
|
+
if (expectedNativeBinaryIntegrity === "sha256:generated") {
|
|
110
98
|
return null;
|
|
111
99
|
}
|
|
112
100
|
|
|
113
|
-
return
|
|
101
|
+
return expectedNativeBinaryIntegrity;
|
|
114
102
|
}
|
|
115
103
|
|
|
116
104
|
function isUsableNativeBinary(candidate, root, expectedIntegrity) {
|
|
@@ -125,30 +113,35 @@ function isUsableNativeBinary(candidate, root, expectedIntegrity) {
|
|
|
125
113
|
}
|
|
126
114
|
}
|
|
127
115
|
|
|
128
|
-
const probe = spawnSync(candidate, [], {
|
|
129
|
-
cwd: root,
|
|
130
|
-
encoding: "utf8",
|
|
131
|
-
stdio: "ignore"
|
|
132
|
-
});
|
|
116
|
+
const probe = spawnSync(candidate, [], { cwd: root, stdio: ["ignore", "ignore", "ignore"] });
|
|
133
117
|
return !probe.error && probe.status !== null;
|
|
134
118
|
}
|
|
135
119
|
|
|
136
120
|
function buildSourceNativeBinary(root) {
|
|
137
|
-
|
|
121
|
+
if (expectedNativeBinaryIntegrity !== "sha256:generated") {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const packageRoot = join(root, "packages", "naome");
|
|
126
|
+
const manifestPath = join(packageRoot, "Cargo.toml");
|
|
138
127
|
if (!existsSync(manifestPath)) {
|
|
139
128
|
return null;
|
|
140
129
|
}
|
|
141
130
|
|
|
142
|
-
const result = spawnSync(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
131
|
+
const result = spawnSync(
|
|
132
|
+
"cargo",
|
|
133
|
+
["build", "--release", "--manifest-path", manifestPath, "-p", "naome-cli"],
|
|
134
|
+
{
|
|
135
|
+
cwd: root,
|
|
136
|
+
encoding: "utf8",
|
|
137
|
+
stdio: "ignore"
|
|
138
|
+
}
|
|
139
|
+
);
|
|
147
140
|
if (result.status !== 0) {
|
|
148
141
|
return null;
|
|
149
142
|
}
|
|
150
143
|
|
|
151
|
-
const builtPath = join(
|
|
144
|
+
const builtPath = join(packageRoot, "target", "release", nativeBinaryName);
|
|
152
145
|
return existsSync(builtPath) ? builtPath : null;
|
|
153
146
|
}
|
|
154
147
|
|
|
@@ -27,7 +27,7 @@ function main(argv) {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
if (["status", "next", "intent", "route", "explain", "context", "doctor", "task", "quality", "semantic", "repo", "structure", "cleanup", "refresh-integrity", "workflow"].includes(command)) {
|
|
30
|
+
if (["status", "next", "intent", "route", "explain", "context", "doctor", "task", "quality", "semantic", "arch", "repo", "structure", "cleanup", "refresh-integrity", "workflow"].includes(command)) {
|
|
31
31
|
runNativeDecisionCommand(command, args);
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
@@ -367,7 +367,7 @@ function findAncestorWithAnyMarker(startPath, markers) {
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
function printHelp() {
|
|
370
|
-
const commands = "naome status [--json]|naome next [--json]|naome intent --prompt-file <path> [--json]|naome intent --prompt <text> [--json]|naome route --prompt-file <path> [--execute] [--json]|naome route --prompt <text> [--execute] [--json]|naome explain --prompt-file <path> [--json]|naome explain --prompt <text> [--json]|naome context select --changed [--json]|naome context select --prompt-file <path> [--json]|naome context select --prompt <text> [--json]|naome doctor [--json]|naome task render-state [--write] [--json]|naome task migrate-ledger [--write] [--json]|naome quality init [--baseline|--deep-baseline] [--json]|naome quality check --changed [--include-scanned-paths] [--json]|naome quality check --path <path> [--path <path>...] [--include-scanned-paths] [--json]|naome quality report [--deep] [--include-scanned-paths] [--json]|naome quality cache status [--json]|naome quality cache clear|naome semantic report [--deep] [--json]|naome semantic check --changed [--json]|naome semantic check --path <path> [--path <path>...] [--json]|naome semantic route --finding <id> [--json]|naome semantic loop [--json]|naome repo model [--write] [--json]|naome repo check [--json]|naome repo explain --path <path> [--json]|naome structure report [--json]|naome structure explain --path <path> [--json]|naome cleanup plan [--json]|naome cleanup route --path <path> [--json]|naome refresh-integrity [--json]|naome workflow agent-plan|context-delta|proof-plan|capabilities|edit-watchdog|decision-gate|digest [--json]|naome workflow search-profile|check-search|phases|processes|mutations [--json]|naome install|naome sync|naome commit -m \"type(scope): message\"|node .naome/bin/naome.js commit -m \"type(scope): message\"".split("|");
|
|
370
|
+
const commands = "naome status [--json]|naome next [--json]|naome intent --prompt-file <path> [--json]|naome intent --prompt <text> [--json]|naome route --prompt-file <path> [--execute] [--json]|naome route --prompt <text> [--execute] [--json]|naome explain --prompt-file <path> [--json]|naome explain --prompt <text> [--json]|naome context select --changed [--json]|naome context select --prompt-file <path> [--json]|naome context select --prompt <text> [--json]|naome doctor [--json]|naome task render-state [--write] [--json]|naome task migrate-ledger [--write] [--json]|naome quality init [--baseline|--deep-baseline] [--json]|naome quality check --changed [--include-scanned-paths] [--json]|naome quality check --path <path> [--path <path>...] [--include-scanned-paths] [--json]|naome quality report [--deep] [--include-scanned-paths] [--json]|naome quality cache status [--json]|naome quality cache clear|naome semantic report [--deep] [--json]|naome semantic check --changed [--json]|naome semantic check --path <path> [--path <path>...] [--json]|naome semantic route --finding <id> [--json]|naome semantic loop [--json]|naome arch init [--config <path>] [--json]|naome arch explain [--config <path>] [--json]|naome arch scan [--config <path>] [--changed-only] [--write] [--output <path>] [--json]|naome arch validate [--config <path>] [--changed-only] [--json|--agent-feedback]|naome repo model [--write] [--json]|naome repo check [--json]|naome repo explain --path <path> [--json]|naome structure report [--json]|naome structure explain --path <path> [--json]|naome cleanup plan [--json]|naome cleanup route --path <path> [--json]|naome refresh-integrity [--json]|naome workflow agent-plan|context-delta|proof-plan|capabilities|edit-watchdog|decision-gate|digest [--json]|naome workflow search-profile|check-search|phases|processes|mutations [--json]|naome install|naome sync|naome commit -m \"type(scope): message\"|node .naome/bin/naome.js commit -m \"type(scope): message\"".split("|");
|
|
371
371
|
console.log(["Usage:", ...commands.map((command) => ` ${command}`)].join("\n"));
|
|
372
372
|
}
|
|
373
373
|
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
"harnessVersion": "1.3.
|
|
2
|
+
"harnessVersion": "1.3.10",
|
|
3
3
|
"installedAt": null,
|
|
4
4
|
"integrity": {
|
|
5
|
-
".naome/bin/check-harness-health.js": "sha256:
|
|
6
|
-
".naome/bin/check-task-state.js": "sha256:
|
|
7
|
-
".naome/bin/naome.js": "sha256:
|
|
5
|
+
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
6
|
+
".naome/bin/check-task-state.js": "sha256:2612577b7e4ab45d9d39dd5ac54c8e7ed749d237d78f1a8d252f4dfa0b4eaaab",
|
|
7
|
+
".naome/bin/naome.js": "sha256:f129c580fb70b3a1d92d0ab0de9fa6c131b2fc51a8dcdebe9d6f5a812a3be61b",
|
|
8
8
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
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:ec2cff9f2090d9b6bfeb2464a650cff97790c4d3e626fd40a42374d5f79c7c38",
|
|
12
13
|
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
13
14
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
14
15
|
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
15
|
-
"docs/naome/index.md": "sha256:
|
|
16
|
+
"docs/naome/index.md": "sha256:cac748ed375d86d288460456fc5d606b29bd99d91148522c303d5400a083dbc5",
|
|
16
17
|
"docs/naome/task-ledger.md": "sha256:6ca7222c80079b4662fb718d3c71d686770646f1fa52b83b0e90aed1c5a1101b",
|
|
17
18
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
18
19
|
},
|
|
@@ -27,8 +28,9 @@
|
|
|
27
28
|
"docs/naome/first-run.md",
|
|
28
29
|
"docs/naome/agent-workflow.md",
|
|
29
30
|
"docs/naome/context-economy.md",
|
|
30
|
-
"docs/naome/execution.md",
|
|
31
31
|
"docs/naome/task-ledger.md",
|
|
32
|
+
"docs/naome/architecture-fitness.md",
|
|
33
|
+
"docs/naome/execution.md",
|
|
32
34
|
"docs/naome/upgrade.md"
|
|
33
35
|
],
|
|
34
36
|
"name": "naome",
|
|
@@ -65,6 +65,19 @@
|
|
|
65
65
|
".naome/repository-quality-baseline.json"
|
|
66
66
|
],
|
|
67
67
|
"lastVerified": null
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "architecture-fitness-check",
|
|
71
|
+
"command": "node .naome/bin/naome.js arch validate --changed-only",
|
|
72
|
+
"cwd": ".",
|
|
73
|
+
"purpose": "Validate changed files against deterministic NAOME architecture fitness rules.",
|
|
74
|
+
"cost": "fast",
|
|
75
|
+
"source": "NAOME built-in",
|
|
76
|
+
"evidence": [
|
|
77
|
+
"naome.arch.yaml",
|
|
78
|
+
"docs/naome/architecture-fitness.md"
|
|
79
|
+
],
|
|
80
|
+
"lastVerified": null
|
|
68
81
|
}
|
|
69
82
|
],
|
|
70
83
|
"phases": [
|
|
@@ -81,7 +94,8 @@
|
|
|
81
94
|
"order": 20,
|
|
82
95
|
"checkIds": [
|
|
83
96
|
"repository-quality-check",
|
|
84
|
-
"repository-semantic-check"
|
|
97
|
+
"repository-semantic-check",
|
|
98
|
+
"architecture-fitness-check"
|
|
85
99
|
]
|
|
86
100
|
},
|
|
87
101
|
{
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Architecture Fitness
|
|
2
|
+
|
|
3
|
+
NAOME architecture fitness validates repository structure with deterministic
|
|
4
|
+
rules before agent changes are accepted. The rule layer is language-agnostic:
|
|
5
|
+
language-specific extractors feed a normalized graph, and rules evaluate graph
|
|
6
|
+
facts instead of prompt text.
|
|
7
|
+
|
|
8
|
+
## Commands
|
|
9
|
+
|
|
10
|
+
- `naome arch init` writes a starter `naome.arch.yaml`.
|
|
11
|
+
- `naome arch explain` prints inferred layers, contexts, rules, and extractors.
|
|
12
|
+
- `naome arch scan --json` emits the normalized graph.
|
|
13
|
+
- `naome arch scan --write` writes `.naome/architecture-graph.json`.
|
|
14
|
+
- `naome arch validate` runs architecture rules with human output.
|
|
15
|
+
- `naome arch validate --json` emits stable machine-readable output.
|
|
16
|
+
- `naome arch validate --agent-feedback` emits compact repair instructions.
|
|
17
|
+
- `naome arch validate --changed-only` uses changed paths when available and
|
|
18
|
+
safely degrades to a full scan for graph-level soundness.
|
|
19
|
+
|
|
20
|
+
## Graph Model
|
|
21
|
+
|
|
22
|
+
The foundation graph uses stable IDs and normalized node and edge kinds. Nodes
|
|
23
|
+
cover repositories, directories, files, layers, bounded contexts, modules,
|
|
24
|
+
symbols, packages, and external dependencies. Edges cover containment and the
|
|
25
|
+
dependency edge kinds required by later extractor slices.
|
|
26
|
+
|
|
27
|
+
Each node and edge carries path, language, source range when known, confidence,
|
|
28
|
+
extractor name, raw origin data, stable ID, and a human-readable label.
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
`naome.arch.yaml` defines layers, bounded contexts, rules, and ignored paths.
|
|
33
|
+
Ignored paths require a reason so agents cannot silently suppress architecture
|
|
34
|
+
ownership.
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
layers:
|
|
38
|
+
domain:
|
|
39
|
+
paths:
|
|
40
|
+
- "src/domain/**"
|
|
41
|
+
infrastructure:
|
|
42
|
+
paths:
|
|
43
|
+
- "src/infrastructure/**"
|
|
44
|
+
|
|
45
|
+
contexts:
|
|
46
|
+
billing:
|
|
47
|
+
paths:
|
|
48
|
+
- "src/billing/**"
|
|
49
|
+
public_api:
|
|
50
|
+
- "src/billing/index.ts"
|
|
51
|
+
|
|
52
|
+
rules:
|
|
53
|
+
max_file_lines:
|
|
54
|
+
enabled: true
|
|
55
|
+
value: 400
|
|
56
|
+
severity: warning
|
|
57
|
+
generated_manual_boundary:
|
|
58
|
+
enabled: true
|
|
59
|
+
severity: error
|
|
60
|
+
|
|
61
|
+
ignore:
|
|
62
|
+
- path: "generated/**"
|
|
63
|
+
reason: "Generated code is not architecture-owned."
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Current Rules
|
|
67
|
+
|
|
68
|
+
- `arch.max_file_lines` enforces the configured file line budget.
|
|
69
|
+
- `arch.generated_manual_boundary` prevents changed files under explicitly
|
|
70
|
+
ignored generated paths from being accepted without regeneration or a config
|
|
71
|
+
change.
|
|
72
|
+
|
|
73
|
+
## Agent Integration
|
|
74
|
+
|
|
75
|
+
Agents should run `naome arch validate --changed-only --json` after changing
|
|
76
|
+
source or template files. JSON output includes status, severity counts,
|
|
77
|
+
violations, concrete suggestions, and `agentFeedback` entries optimized for
|
|
78
|
+
repair loops.
|
|
79
|
+
|
|
80
|
+
## CI Integration
|
|
81
|
+
|
|
82
|
+
Use `node .naome/bin/naome.js arch validate --changed-only` as a fast gate.
|
|
83
|
+
The first foundation release reports warnings for existing file-size debt and
|
|
84
|
+
fails only on configured error rules.
|
|
85
|
+
|
|
86
|
+
## Language Support
|
|
87
|
+
|
|
88
|
+
The v1.3.10 foundation classifies TypeScript, JavaScript, Rust, Python, Go,
|
|
89
|
+
Java, Kotlin, and Swift files by path extension. Import extractors, resolver
|
|
90
|
+
rules, cycle detection, layer dependency rules, and manifest extraction are
|
|
91
|
+
planned follow-up slices before v1.4.0.
|
|
92
|
+
|
|
93
|
+
## Limitations
|
|
94
|
+
|
|
95
|
+
This release intentionally starts with path extraction, graph construction,
|
|
96
|
+
file budgets, generated/manual boundaries, JSON output, human output, and CLI
|
|
97
|
+
integration. It does not yet resolve imports or validate cross-layer imports.
|
|
@@ -22,9 +22,10 @@ for the current step.
|
|
|
22
22
|
15. `testing.md`
|
|
23
23
|
16. `repository-quality.md`, when repository-quality checks or cleanup are relevant
|
|
24
24
|
17. `repository-structure.md`, when path roles or structure cleanup are relevant
|
|
25
|
-
18. `
|
|
26
|
-
19. `
|
|
27
|
-
20. `
|
|
25
|
+
18. `architecture-fitness.md`, when architecture graph or rule feedback matters
|
|
26
|
+
19. `security.md`
|
|
27
|
+
20. `agent-workflow.md`
|
|
28
|
+
21. `decisions.md`, when changing durable project policy
|
|
28
29
|
|
|
29
30
|
## Source Types
|
|
30
31
|
|
|
@@ -26,6 +26,7 @@ and stale-policy issues before the task grows. It does not replace the final
|
|
|
26
26
|
| naome-task-state | `node .naome/bin/check-task-state.js` | `.` | fast | null |
|
|
27
27
|
| repository-quality-check | `node .naome/bin/naome.js quality check --changed` | `.` | fast | null |
|
|
28
28
|
| repository-semantic-check | `node .naome/bin/naome.js semantic check --changed` | `.` | fast | null |
|
|
29
|
+
| architecture-fitness-check | `node .naome/bin/naome.js arch validate --changed-only` | `.` | fast | null |
|
|
29
30
|
|
|
30
31
|
## Verification Phases
|
|
31
32
|
|
|
@@ -52,6 +53,7 @@ phase is failing or missing.
|
|
|
52
53
|
- `.naome/bin/check-harness-health.js`
|
|
53
54
|
- `.naome/bin/check-task-state.js`
|
|
54
55
|
- `.naome/task-contract.schema.json`
|
|
56
|
+
- `docs/naome/architecture-fitness.md`
|
|
55
57
|
|
|
56
58
|
## Rules
|
|
57
59
|
|
|
@@ -66,8 +68,9 @@ phase is failing or missing.
|
|
|
66
68
|
and 12 release gates.
|
|
67
69
|
- Store long command output as a compact summary that preserves command, cwd,
|
|
68
70
|
exit code, relevant lines, affected paths, and artifacts.
|
|
69
|
-
- When intake defines change types, include `repository-quality-check
|
|
70
|
-
`repository-semantic-check` as required
|
|
71
|
-
documentation, harness, template, and CI
|
|
71
|
+
- When intake defines change types, include `repository-quality-check`,
|
|
72
|
+
`repository-semantic-check`, and `architecture-fitness-check` as required
|
|
73
|
+
checks for source, structure, documentation, harness, template, and CI
|
|
74
|
+
changes.
|
|
72
75
|
- Before completion, select proof from the Verification Map when possible.
|
|
73
76
|
- Report exact commands and results. Do not claim proof that did not run.
|