@lamentis/naome 1.2.0 → 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/bin/naome-node.js +2 -1579
- package/bin/naome.js +19 -5
- package/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/dispatcher.rs +2 -1
- package/crates/naome-cli/src/main.rs +3 -0
- package/crates/naome-cli/src/quality_commands.rs +90 -2
- 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/install_plan.rs +2 -0
- package/crates/naome-core/src/lib.rs +5 -3
- 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 +20 -67
- package/crates/naome-core/src/quality/cleanup.rs +13 -1
- package/crates/naome-core/src/quality/config.rs +8 -15
- package/crates/naome-core/src/quality/config_support.rs +24 -0
- package/crates/naome-core/src/quality/mod.rs +18 -0
- package/crates/naome-core/src/quality/scanner.rs +20 -8
- 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 +3 -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 -1217
- package/crates/naome-core/src/verification.rs +1 -0
- package/crates/naome-core/tests/decision.rs +24 -118
- package/crates/naome-core/tests/harness_health.rs +2 -0
- package/crates/naome-core/tests/quality.rs +12 -118
- 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 -1376
- 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 -432
- package/crates/naome-core/tests/task_state_compact_support/repo.rs +1 -1
- 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_support/mod.rs +1 -1
- 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 +2 -1
- package/templates/naome-root/.naome/bin/check-harness-health.js +2 -2
- package/templates/naome-root/.naome/bin/check-task-state.js +2 -2
- package/templates/naome-root/.naome/bin/naome.js +25 -21
- package/templates/naome-root/.naome/manifest.json +4 -2
- package/templates/naome-root/.naome/repository-structure.json +90 -0
- package/templates/naome-root/.naome/verification.json +1 -0
- package/templates/naome-root/docs/naome/index.md +4 -3
- package/templates/naome-root/docs/naome/repository-quality.md +3 -0
- package/templates/naome-root/docs/naome/repository-structure.md +51 -0
- package/templates/naome-root/docs/naome/testing.md +2 -1
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lamentis/naome",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Native-first CLI for the NAOME agent harness.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -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"
|
|
@@ -11,14 +11,14 @@ const nativeBinaryName = process.platform === "win32" ? "naome.exe" : "naome";
|
|
|
11
11
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
12
|
".naome/bin/check-harness-health.js": "sha256:dc4de52b79c69600b9ba47b924e2c2b8de61a2cbfab6d1ccc0f1924d963db657",
|
|
13
13
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
14
|
-
".naome/bin/naome.js": "sha256:
|
|
14
|
+
".naome/bin/naome.js": "sha256:87eabd690bf55f0b0195446db46fa7c19bfa17395d31c2f34a9ef9339d2229e2",
|
|
15
15
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
16
16
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
17
|
"AGENTS.md": "sha256:9192ea81f90bb19f8043513c49b5da9e9598ee694da8356f345e7ccbca0e28df",
|
|
18
18
|
"docs/naome/agent-workflow.md": "sha256:802eb34cf268fc9c5e7aefc28192efef4bf60302d30b3f78e5a61b876ce8a098",
|
|
19
19
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
20
20
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
21
|
-
"docs/naome/index.md": "sha256:
|
|
21
|
+
"docs/naome/index.md": "sha256:a674102cc801702dc77102afb59be0f5ab189dc638caf0bef358b9d6087d0742",
|
|
22
22
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
23
23
|
});
|
|
24
24
|
|
|
@@ -11,14 +11,14 @@ const nativeBinaryName = process.platform === "win32" ? "naome.exe" : "naome";
|
|
|
11
11
|
const expectedMachineOwnedIntegrity = Object.freeze({
|
|
12
12
|
".naome/bin/check-harness-health.js": "sha256:dc4de52b79c69600b9ba47b924e2c2b8de61a2cbfab6d1ccc0f1924d963db657",
|
|
13
13
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
14
|
-
".naome/bin/naome.js": "sha256:
|
|
14
|
+
".naome/bin/naome.js": "sha256:87eabd690bf55f0b0195446db46fa7c19bfa17395d31c2f34a9ef9339d2229e2",
|
|
15
15
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
16
16
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
17
|
"AGENTS.md": "sha256:9192ea81f90bb19f8043513c49b5da9e9598ee694da8356f345e7ccbca0e28df",
|
|
18
18
|
"docs/naome/agent-workflow.md": "sha256:802eb34cf268fc9c5e7aefc28192efef4bf60302d30b3f78e5a61b876ce8a098",
|
|
19
19
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
20
20
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
21
|
-
"docs/naome/index.md": "sha256:
|
|
21
|
+
"docs/naome/index.md": "sha256:a674102cc801702dc77102afb59be0f5ab189dc638caf0bef358b9d6087d0742",
|
|
22
22
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
23
23
|
});
|
|
24
24
|
|
|
@@ -27,7 +27,7 @@ function main(argv) {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
if (["status", "next", "intent", "route", "explain", "quality", "cleanup", "refresh-integrity", "workflow"].includes(command)) {
|
|
30
|
+
if (["status", "next", "intent", "route", "explain", "quality", "structure", "cleanup", "refresh-integrity", "workflow"].includes(command)) {
|
|
31
31
|
runNativeDecisionCommand(command, args);
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
@@ -349,26 +349,30 @@ function findAncestorWithMarker(startPath, markerParts) {
|
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
function printHelp() {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
352
|
+
const commands = [
|
|
353
|
+
"naome status [--json]",
|
|
354
|
+
"naome next [--json]",
|
|
355
|
+
"naome intent --prompt-file <path> [--json]",
|
|
356
|
+
"naome intent --prompt <text> [--json]",
|
|
357
|
+
"naome route --prompt-file <path> [--execute] [--json]",
|
|
358
|
+
"naome route --prompt <text> [--execute] [--json]",
|
|
359
|
+
"naome explain --prompt-file <path> [--json]",
|
|
360
|
+
"naome explain --prompt <text> [--json]",
|
|
361
|
+
"naome quality init [--json]",
|
|
362
|
+
"naome quality check --changed [--json]",
|
|
363
|
+
"naome quality report [--json]",
|
|
364
|
+
"naome structure report [--json]",
|
|
365
|
+
"naome structure explain --path <path> [--json]",
|
|
366
|
+
"naome cleanup plan [--json]",
|
|
367
|
+
"naome cleanup route --path <path> [--json]",
|
|
368
|
+
"naome refresh-integrity [--json]",
|
|
369
|
+
"naome workflow search-profile|check-search|phases|processes|mutations [--json]",
|
|
370
|
+
"naome install",
|
|
371
|
+
"naome sync",
|
|
372
|
+
"naome commit -m \"type(scope): message\"",
|
|
373
|
+
"node .naome/bin/naome.js commit -m \"type(scope): message\""
|
|
374
|
+
];
|
|
375
|
+
console.log(["Usage:", ...commands.map((command) => ` ${command}`)].join("\n"));
|
|
372
376
|
}
|
|
373
377
|
|
|
374
378
|
function fail(message) {
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"integrity": {
|
|
5
5
|
".naome/bin/check-harness-health.js": "sha256:dc4de52b79c69600b9ba47b924e2c2b8de61a2cbfab6d1ccc0f1924d963db657",
|
|
6
6
|
".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
|
|
7
|
-
".naome/bin/naome.js": "sha256:
|
|
7
|
+
".naome/bin/naome.js": "sha256:87eabd690bf55f0b0195446db46fa7c19bfa17395d31c2f34a9ef9339d2229e2",
|
|
8
8
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
9
9
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
10
10
|
"AGENTS.md": "sha256:9192ea81f90bb19f8043513c49b5da9e9598ee694da8356f345e7ccbca0e28df",
|
|
11
11
|
"docs/naome/agent-workflow.md": "sha256:802eb34cf268fc9c5e7aefc28192efef4bf60302d30b3f78e5a61b876ce8a098",
|
|
12
12
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
13
13
|
"docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
|
|
14
|
-
"docs/naome/index.md": "sha256:
|
|
14
|
+
"docs/naome/index.md": "sha256:a674102cc801702dc77102afb59be0f5ab189dc638caf0bef358b9d6087d0742",
|
|
15
15
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
16
16
|
},
|
|
17
17
|
"machineOwned": [
|
|
@@ -37,11 +37,13 @@
|
|
|
37
37
|
".naome/upgrade-state.json",
|
|
38
38
|
".naome/verification.json",
|
|
39
39
|
".naome/repository-quality.json",
|
|
40
|
+
".naome/repository-structure.json",
|
|
40
41
|
".naome/repository-quality-baseline.json",
|
|
41
42
|
"docs/naome/architecture.md",
|
|
42
43
|
"docs/naome/decisions.md",
|
|
43
44
|
"docs/naome/repo-profile.md",
|
|
44
45
|
"docs/naome/repository-quality.md",
|
|
46
|
+
"docs/naome/repository-structure.md",
|
|
45
47
|
"docs/naome/security.md",
|
|
46
48
|
"docs/naome/testing.md"
|
|
47
49
|
]
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "naome.repository-structure.v1",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"status": "ready",
|
|
5
|
+
"enabledAdapters": [],
|
|
6
|
+
"sourceRoots": [
|
|
7
|
+
"src/**",
|
|
8
|
+
"app/**",
|
|
9
|
+
"apps/*/src/**",
|
|
10
|
+
"packages/*/src/**",
|
|
11
|
+
"crates/*/src/**",
|
|
12
|
+
"**/src/**",
|
|
13
|
+
"lib/**"
|
|
14
|
+
],
|
|
15
|
+
"testRoots": [
|
|
16
|
+
"test/**",
|
|
17
|
+
"tests/**",
|
|
18
|
+
"__tests__/**",
|
|
19
|
+
"packages/*/test/**",
|
|
20
|
+
"packages/*/tests/**",
|
|
21
|
+
"crates/*/tests/**",
|
|
22
|
+
"**/tests/**",
|
|
23
|
+
"scripts/*.test.js"
|
|
24
|
+
],
|
|
25
|
+
"docsRoots": [
|
|
26
|
+
"docs/**",
|
|
27
|
+
"doc/**"
|
|
28
|
+
],
|
|
29
|
+
"generatedRoots": [
|
|
30
|
+
"**/generated/**",
|
|
31
|
+
"**/__generated__/**",
|
|
32
|
+
"**/codegen/**",
|
|
33
|
+
"**/*.generated.*"
|
|
34
|
+
],
|
|
35
|
+
"artifactRoots": [
|
|
36
|
+
"dist/**",
|
|
37
|
+
"build/**",
|
|
38
|
+
"coverage/**",
|
|
39
|
+
".next/**",
|
|
40
|
+
"target/**",
|
|
41
|
+
"**/dist/**",
|
|
42
|
+
"**/build/**"
|
|
43
|
+
],
|
|
44
|
+
"moduleRoots": [
|
|
45
|
+
"src/**",
|
|
46
|
+
"app/**",
|
|
47
|
+
"packages/*/src/**",
|
|
48
|
+
"crates/*/src/**",
|
|
49
|
+
"**/src/**"
|
|
50
|
+
],
|
|
51
|
+
"allowedRootFiles": [
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE",
|
|
54
|
+
"NOTICE",
|
|
55
|
+
"CHANGELOG.md",
|
|
56
|
+
"CONTRIBUTING.md",
|
|
57
|
+
"SECURITY.md",
|
|
58
|
+
"AGENTS.md",
|
|
59
|
+
"package.json",
|
|
60
|
+
"Cargo.toml",
|
|
61
|
+
"pyproject.toml",
|
|
62
|
+
"go.mod",
|
|
63
|
+
"go.sum",
|
|
64
|
+
"Makefile",
|
|
65
|
+
".gitignore",
|
|
66
|
+
".naomeignore"
|
|
67
|
+
],
|
|
68
|
+
"directoryRoleRules": [],
|
|
69
|
+
"layerRules": [],
|
|
70
|
+
"ignoredPaths": [
|
|
71
|
+
".git/**",
|
|
72
|
+
"node_modules/**",
|
|
73
|
+
"vendor/**",
|
|
74
|
+
"target/**",
|
|
75
|
+
"**/target/**",
|
|
76
|
+
"dist/**",
|
|
77
|
+
"build/**",
|
|
78
|
+
"coverage/**",
|
|
79
|
+
".next/**"
|
|
80
|
+
],
|
|
81
|
+
"disabledChecks": [],
|
|
82
|
+
"changedCodePolicy": "block",
|
|
83
|
+
"debtPolicy": "report",
|
|
84
|
+
"limits": {
|
|
85
|
+
"maxDirectoryFiles": 40,
|
|
86
|
+
"maxPathDepth": 10,
|
|
87
|
+
"maxDirectoryRoles": 2,
|
|
88
|
+
"maxDumpingGroundFiles": 12
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -18,9 +18,10 @@ for the current step.
|
|
|
18
18
|
11. `testing.md`
|
|
19
19
|
12. `.naome/verification.json`
|
|
20
20
|
13. `repository-quality.md`, when repository-quality checks or cleanup are relevant
|
|
21
|
-
14. `
|
|
22
|
-
15. `
|
|
23
|
-
16. `
|
|
21
|
+
14. `repository-structure.md`, when path roles or structure cleanup are relevant
|
|
22
|
+
15. `security.md`
|
|
23
|
+
16. `agent-workflow.md`
|
|
24
|
+
17. `decisions.md`, when changing durable project policy
|
|
24
25
|
|
|
25
26
|
## Source Types
|
|
26
27
|
|
|
@@ -33,6 +33,9 @@ to avoid overlapping window spam and include repeated regions inside the same
|
|
|
33
33
|
file. Near-duplicate function checks compare functions/components, not
|
|
34
34
|
container symbols against their own children.
|
|
35
35
|
|
|
36
|
+
Structure checks run through the same gate. See `repository-structure.md` for
|
|
37
|
+
path roles, module/layer policy, adapters, and cleanup routing.
|
|
38
|
+
|
|
36
39
|
Agents may propose stricter repo-specific rules after inspecting the language
|
|
37
40
|
and stack.
|
|
38
41
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Repository Structure
|
|
2
|
+
|
|
3
|
+
NAOME checks whether new and changed files land in a maintainable directory
|
|
4
|
+
structure. Existing structure debt stays visible in reports and cleanup routes,
|
|
5
|
+
but normal feature work is blocked only by relevant changed paths.
|
|
6
|
+
|
|
7
|
+
## Model
|
|
8
|
+
|
|
9
|
+
The structure model classifies each path as:
|
|
10
|
+
|
|
11
|
+
`path -> role -> module -> layer -> language -> generated/debt/changed`
|
|
12
|
+
|
|
13
|
+
Generic roles are `source`, `test`, `docs`, `config`, `script`, `generated`,
|
|
14
|
+
`artifact`, `dependency/vendor`, and `unknown`.
|
|
15
|
+
|
|
16
|
+
## Gates
|
|
17
|
+
|
|
18
|
+
- `naome quality check --changed` includes structure checks.
|
|
19
|
+
- `naome quality report` shows structure debt with other quality findings.
|
|
20
|
+
- `naome structure report --json` returns only structure findings.
|
|
21
|
+
- `naome structure explain --path <path> --json` explains one path's role,
|
|
22
|
+
module, layer, language, generated flag, debt flag, and changed flag.
|
|
23
|
+
- `naome cleanup plan` and `naome cleanup route --path <path>` include
|
|
24
|
+
structure findings when a cleanup task should move or split files.
|
|
25
|
+
|
|
26
|
+
## Checks
|
|
27
|
+
|
|
28
|
+
Structure checks include directory role mixing, misplaced file roles,
|
|
29
|
+
root-level file sprawl, dumping-ground directories, directory size, path depth,
|
|
30
|
+
case-insensitive path collisions, and source/test pairing hints.
|
|
31
|
+
|
|
32
|
+
Dumping-ground names such as `utils`, `helpers`, `common`, `shared`, `misc`,
|
|
33
|
+
and `lib` are not banned. New feature logic there is reported when a named
|
|
34
|
+
module location is more appropriate.
|
|
35
|
+
|
|
36
|
+
## Adapters
|
|
37
|
+
|
|
38
|
+
The core is language-independent. Adapters add deterministic signals for stack
|
|
39
|
+
conventions. Built-in adapters currently include `rust` and
|
|
40
|
+
`javascript-typescript`; future adapters can add source roots, test roots,
|
|
41
|
+
module roots, and allowed root files without changing gate behavior.
|
|
42
|
+
|
|
43
|
+
## Local Policy
|
|
44
|
+
|
|
45
|
+
Rules live in `.naome/repository-structure.json`. Product defaults contain no
|
|
46
|
+
repository-specific paths. Local policy may add source roots, test roots,
|
|
47
|
+
generated roots, allowed root files, directory role rules, and layer rules.
|
|
48
|
+
|
|
49
|
+
Use local policy to document real repository conventions, not to grant special
|
|
50
|
+
rights to one product or hide cleanup work. Loosening a structure rule to pass a
|
|
51
|
+
feature diff requires human review.
|
|
@@ -58,6 +58,7 @@ phase is failing or missing.
|
|
|
58
58
|
- Store long command output as a compact summary that preserves command, cwd,
|
|
59
59
|
exit code, relevant lines, affected paths, and artifacts.
|
|
60
60
|
- When intake defines change types, include `repository-quality-check` as a
|
|
61
|
-
required check for source, documentation, harness, template, and
|
|
61
|
+
required check for source, structure, documentation, harness, template, and
|
|
62
|
+
CI changes.
|
|
62
63
|
- Before completion, select proof from the Verification Map when possible.
|
|
63
64
|
- Report exact commands and results. Do not claim proof that did not run.
|