@lamentis/naome 1.3.7 → 1.3.9
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/crates/naome-cli/Cargo.toml +1 -1
- package/crates/naome-cli/src/install_bridge.rs +56 -8
- package/crates/naome-core/Cargo.toml +1 -1
- package/crates/naome-core/src/context/select.rs +58 -4
- 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/intent/classifier.rs +56 -81
- package/crates/naome-core/src/intent/envelope.rs +173 -19
- package/crates/naome-core/src/intent/legacy_response.rs +2 -0
- package/crates/naome-core/src/intent/model.rs +6 -0
- package/crates/naome-core/src/intent/resolver.rs +25 -0
- package/crates/naome-core/src/intent/risk.rs +11 -1
- package/crates/naome-core/src/intent.rs +1 -1
- 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/route/context.rs +8 -0
- package/crates/naome-core/src/workflow/integrity_support.rs +10 -3
- package/crates/naome-core/tests/context.rs +92 -0
- package/crates/naome-core/tests/harness_health.rs +149 -0
- package/crates/naome-core/tests/intent.rs +98 -18
- package/crates/naome-core/tests/intent_support/mod.rs +39 -1
- package/crates/naome-core/tests/intent_v2.rs +299 -10
- package/crates/naome-core/tests/quality_performance.rs +63 -2
- package/crates/naome-core/tests/repo_support/routes.rs +8 -2
- package/crates/naome-core/tests/route_baseline.rs +29 -0
- package/crates/naome-core/tests/route_completion.rs +26 -5
- package/crates/naome-core/tests/route_harness_refresh.rs +7 -1
- package/crates/naome-core/tests/route_user_diff.rs +1 -1
- package/crates/naome-core/tests/task_state_compact.rs +7 -1
- package/installer/filesystem.js +38 -0
- package/installer/flows.js +6 -1
- package/installer/harness-file-ops.js +36 -8
- 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 +25 -21
- package/templates/naome-root/.naome/bin/check-task-state.js +35 -42
- package/templates/naome-root/.naome/manifest.json +10 -10
- package/templates/naome-root/docs/naome/agent-workflow.md +14 -5
- package/templates/naome-root/docs/naome/architecture.md +9 -0
- package/crates/naome-core/src/intent/patterns.rs +0 -170
|
@@ -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
|
-
".
|
|
13
|
-
".naome/bin/check-task-state.js": "sha256:df54489a22b426180266e5e0fb5f9ec381477419f688435248afbf2b9b38ea81",
|
|
14
|
-
".naome/bin/naome.js": "sha256:a34c2e50a68d15ff2722a57590ccddc504e025d3c98ea62fd700d7ec1a789b9a",
|
|
13
|
+
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
15
14
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
15
|
+
".naome/bin/naome.js": "sha256:a34c2e50a68d15ff2722a57590ccddc504e025d3c98ea62fd700d7ec1a789b9a",
|
|
16
|
+
".naome/bin/check-task-state.js": "sha256:2612577b7e4ab45d9d39dd5ac54c8e7ed749d237d78f1a8d252f4dfa0b4eaaab",
|
|
17
|
+
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
16
18
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
|
-
"
|
|
18
|
-
"docs/naome/
|
|
19
|
+
"docs/naome/index.md": "sha256:07ef776f49130319a5280bdb3ae38af22141708253f38eb983a4336fbae1b25a",
|
|
20
|
+
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
21
|
+
"docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
|
|
19
22
|
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
23
|
+
"docs/naome/task-ledger.md": "sha256:6ca7222c80079b4662fb718d3c71d686770646f1fa52b83b0e90aed1c5a1101b",
|
|
20
24
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
21
|
-
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
22
|
-
"docs/naome/index.md": "sha256:07ef776f49130319a5280bdb3ae38af22141708253f38eb983a4336fbae1b25a",
|
|
23
|
-
"docs/naome/task-ledger.md": "sha256:ac637a31abdd13eee15a49086594e63f5c88fe12a5cf621b227310788ae7e583",
|
|
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
|
-
".
|
|
13
|
-
".naome/bin/check-task-state.js": "sha256:df54489a22b426180266e5e0fb5f9ec381477419f688435248afbf2b9b38ea81",
|
|
14
|
-
".naome/bin/naome.js": "sha256:a34c2e50a68d15ff2722a57590ccddc504e025d3c98ea62fd700d7ec1a789b9a",
|
|
13
|
+
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
15
14
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
15
|
+
".naome/bin/naome.js": "sha256:a34c2e50a68d15ff2722a57590ccddc504e025d3c98ea62fd700d7ec1a789b9a",
|
|
16
|
+
".naome/bin/check-task-state.js": "sha256:2612577b7e4ab45d9d39dd5ac54c8e7ed749d237d78f1a8d252f4dfa0b4eaaab",
|
|
17
|
+
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
16
18
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
17
|
-
"
|
|
18
|
-
"docs/naome/
|
|
19
|
+
"docs/naome/index.md": "sha256:07ef776f49130319a5280bdb3ae38af22141708253f38eb983a4336fbae1b25a",
|
|
20
|
+
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
21
|
+
"docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
|
|
19
22
|
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
23
|
+
"docs/naome/task-ledger.md": "sha256:6ca7222c80079b4662fb718d3c71d686770646f1fa52b83b0e90aed1c5a1101b",
|
|
20
24
|
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
21
|
-
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
22
|
-
"docs/naome/index.md": "sha256:07ef776f49130319a5280bdb3ae38af22141708253f38eb983a4336fbae1b25a",
|
|
23
|
-
"docs/naome/task-ledger.md": "sha256:ac637a31abdd13eee15a49086594e63f5c88fe12a5cf621b227310788ae7e583",
|
|
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
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
"harnessVersion": "1.
|
|
2
|
+
"harnessVersion": "1.3.9",
|
|
3
3
|
"installedAt": null,
|
|
4
4
|
"integrity": {
|
|
5
|
-
".
|
|
6
|
-
".naome/bin/check-task-state.js": "sha256:df54489a22b426180266e5e0fb5f9ec381477419f688435248afbf2b9b38ea81",
|
|
7
|
-
".naome/bin/naome.js": "sha256:a34c2e50a68d15ff2722a57590ccddc504e025d3c98ea62fd700d7ec1a789b9a",
|
|
5
|
+
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
8
6
|
".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
|
|
7
|
+
".naome/bin/naome.js": "sha256:a34c2e50a68d15ff2722a57590ccddc504e025d3c98ea62fd700d7ec1a789b9a",
|
|
8
|
+
".naome/bin/check-task-state.js": "sha256:2612577b7e4ab45d9d39dd5ac54c8e7ed749d237d78f1a8d252f4dfa0b4eaaab",
|
|
9
|
+
".naome/bin/check-harness-health.js": "sha256:802d7419774981a6af1826b3882270ff8f41259d516f98c52a02b4ddc184c467",
|
|
9
10
|
".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
|
|
10
|
-
"AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
|
|
11
|
-
"docs/naome/agent-workflow.md": "sha256:cbef6dee1543b4c74111f8dc23e81a5bf092a9585a342504678bfc9c9d0655ea",
|
|
12
|
-
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
13
|
-
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
14
|
-
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
15
11
|
"docs/naome/index.md": "sha256:07ef776f49130319a5280bdb3ae38af22141708253f38eb983a4336fbae1b25a",
|
|
12
|
+
"docs/naome/first-run.md": "sha256:1466ce8c65e19a1514885f917db14e8a772350e3f6d1c03a66326963365919e1",
|
|
13
|
+
"docs/naome/agent-workflow.md": "sha256:0be1c29adfbcd3fd73c4f904080ffc67237692fe413871a30243538c4db38ac7",
|
|
14
|
+
"docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
|
|
16
15
|
"docs/naome/task-ledger.md": "sha256:6ca7222c80079b4662fb718d3c71d686770646f1fa52b83b0e90aed1c5a1101b",
|
|
16
|
+
"docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
|
|
17
17
|
"docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
|
|
18
18
|
},
|
|
19
19
|
"machineOwned": [
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"docs/naome/first-run.md",
|
|
28
28
|
"docs/naome/agent-workflow.md",
|
|
29
29
|
"docs/naome/context-economy.md",
|
|
30
|
-
"docs/naome/execution.md",
|
|
31
30
|
"docs/naome/task-ledger.md",
|
|
31
|
+
"docs/naome/execution.md",
|
|
32
32
|
"docs/naome/upgrade.md"
|
|
33
33
|
],
|
|
34
34
|
"name": "naome",
|
|
@@ -11,11 +11,20 @@ Use this workflow after first-run intake is complete.
|
|
|
11
11
|
`canCreateTask` fields instead of inventing routing or final-response text.
|
|
12
12
|
If route returns a `taskRoot` different from the current directory, continue
|
|
13
13
|
the task from that path and leave the original worktree untouched.
|
|
14
|
-
When preparing the route prompt file,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
When preparing the route prompt file, first normalize the user's raw prompt
|
|
15
|
+
into a fenced `naome-prompt-envelope-v1` JSON envelope. The envelope is the
|
|
16
|
+
routing input; the raw user text below it is audit text. Use canonical NAOME
|
|
17
|
+
schema fields such as `requestKind`, `mutationIntent`,
|
|
18
|
+
`publicationIntent`, `requestedActions`, `referencedPaths`, `constraints`,
|
|
19
|
+
`uncertainties`, `workflowAction`, `taskIntent`, and `risk`. Do not derive
|
|
20
|
+
workflow actions from natural-language keywords, localized words, or the
|
|
21
|
+
prompt's prose language. If a prompt file has no envelope, route returns a
|
|
22
|
+
non-mutating `normalize_prompt_first` decision and the agent must add the
|
|
23
|
+
deterministic envelope before retrying. `naome-intent-v2` is not supported.
|
|
24
|
+
Unknown envelope values require normalization, and conflicting envelope
|
|
25
|
+
fields block as ambiguous instead of mutating. Put concrete files in
|
|
26
|
+
`referencedPaths`; prompt context selection treats those paths as the
|
|
27
|
+
primary source of path intent.
|
|
19
28
|
3. Use `node .naome/bin/naome.js explain --prompt-file <path> --json` only when
|
|
20
29
|
debugging why a policy won.
|
|
21
30
|
4. Run `node .naome/bin/naome.js status --json` when reporting state without
|
|
@@ -18,6 +18,15 @@ Status: Uninitialized
|
|
|
18
18
|
- Per-check proof files are local run evidence. Prefer compact proof batches in
|
|
19
19
|
the committed task-state projection when many release checks share the same
|
|
20
20
|
evidence paths.
|
|
21
|
+
- Prompt routing uses fenced `naome-prompt-envelope-v1` JSON envelopes as the
|
|
22
|
+
deterministic routing input. Raw natural-language prompts are audit text and
|
|
23
|
+
must not be treated as workflow authority until an agent normalizes them into
|
|
24
|
+
canonical fields such as `requestKind`, `mutationIntent`,
|
|
25
|
+
`publicationIntent`, `requestedActions`, `workflowAction`, `taskIntent`, and
|
|
26
|
+
`risk`. Legacy `naome-intent-v2` envelopes are not supported. Unknown
|
|
27
|
+
envelope values require prompt normalization, conflicting fields block as
|
|
28
|
+
ambiguous, and `referencedPaths` is the primary context-selection source for
|
|
29
|
+
prompt-mentioned files.
|
|
21
30
|
|
|
22
31
|
## Assumed Boundaries
|
|
23
32
|
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
use super::model::IntentKind;
|
|
2
|
-
|
|
3
|
-
pub(crate) fn normalized(text: &str) -> String {
|
|
4
|
-
text.to_lowercase()
|
|
5
|
-
.chars()
|
|
6
|
-
.map(|ch| if ch.is_alphanumeric() { ch } else { ' ' })
|
|
7
|
-
.collect::<String>()
|
|
8
|
-
.split_whitespace()
|
|
9
|
-
.collect::<Vec<_>>()
|
|
10
|
-
.join(" ")
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
pub(crate) fn lexical_tokens(text: &str) -> Vec<String> {
|
|
14
|
-
text.split_whitespace()
|
|
15
|
-
.map(|token| {
|
|
16
|
-
token
|
|
17
|
-
.trim_matches(|ch: char| !ch.is_alphanumeric() && ch != '_' && ch != '-')
|
|
18
|
-
.to_lowercase()
|
|
19
|
-
})
|
|
20
|
-
.filter(|token| !token.is_empty())
|
|
21
|
-
.collect()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
pub(crate) fn structured_workflow_intents(text: &str) -> Vec<IntentKind> {
|
|
25
|
-
let tokens = lexical_tokens(text);
|
|
26
|
-
let mut intents = Vec::new();
|
|
27
|
-
|
|
28
|
-
if let Some(intent) = structured_action(&tokens) {
|
|
29
|
-
intents.push(intent);
|
|
30
|
-
}
|
|
31
|
-
if let Some(intent) = legacy_v1_short_action_request(&tokens) {
|
|
32
|
-
intents.push(intent);
|
|
33
|
-
}
|
|
34
|
-
if legacy_v1_no_commit(&tokens) {
|
|
35
|
-
intents.push(IntentKind::NoCommitRequest);
|
|
36
|
-
}
|
|
37
|
-
if has_structured_token(&tokens, &["no_commit", "without_commit"]) {
|
|
38
|
-
intents.push(IntentKind::NoCommitRequest);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
intents.sort_by_key(|kind| kind.as_str());
|
|
42
|
-
intents.dedup();
|
|
43
|
-
intents
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
pub(crate) fn command_workflow_intents(text: &str) -> Vec<IntentKind> {
|
|
47
|
-
let tokens = lexical_tokens(text);
|
|
48
|
-
let mut intents = Vec::new();
|
|
49
|
-
if let Some(intent) = cli_action(&tokens) {
|
|
50
|
-
intents.push(intent);
|
|
51
|
-
}
|
|
52
|
-
intents
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
pub(crate) fn explicit_task_intent(text: &str) -> Option<IntentKind> {
|
|
56
|
-
let tokens = lexical_tokens(text);
|
|
57
|
-
if has_structured_token(&tokens, &["task_revision", "current_task", "active_task"]) {
|
|
58
|
-
return Some(IntentKind::TaskRevision);
|
|
59
|
-
}
|
|
60
|
-
if has_structured_token(&tokens, &["new_task", "create_new_task", "separate_task"]) {
|
|
61
|
-
return Some(IntentKind::NewTask);
|
|
62
|
-
}
|
|
63
|
-
None
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
pub(crate) fn is_generic_work_request(text: &str) -> bool {
|
|
67
|
-
!lexical_tokens(text).is_empty()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
fn structured_action(tokens: &[String]) -> Option<IntentKind> {
|
|
71
|
-
policy_action(tokens)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
fn policy_action(tokens: &[String]) -> Option<IntentKind> {
|
|
75
|
-
for token in tokens {
|
|
76
|
-
let intent = match token.as_str() {
|
|
77
|
-
"commit_task_baseline" | "commit_user_diff" | "commit_upgrade_baseline" => {
|
|
78
|
-
IntentKind::CommitRequest
|
|
79
|
-
}
|
|
80
|
-
"review_task_diff" | "review_current_task_diff" | "review_unowned_diff" => {
|
|
81
|
-
IntentKind::ReviewRequest
|
|
82
|
-
}
|
|
83
|
-
"repair_harness" | "repair_harness_only" => IntentKind::RepairRequest,
|
|
84
|
-
"cancel_task_changes" | "cancel_current_task" => IntentKind::CancelRequest,
|
|
85
|
-
"continue_current_task" | "task_complete" | "complete_task" => {
|
|
86
|
-
IntentKind::TaskCompletion
|
|
87
|
-
}
|
|
88
|
-
"answer_status_only" => IntentKind::StatusQuestion,
|
|
89
|
-
"clear_or_commit_unowned_diff" => IntentKind::Ambiguous,
|
|
90
|
-
_ => continue,
|
|
91
|
-
};
|
|
92
|
-
return Some(intent);
|
|
93
|
-
}
|
|
94
|
-
None
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
fn cli_action(tokens: &[String]) -> Option<IntentKind> {
|
|
98
|
-
match (
|
|
99
|
-
tokens.first().map(String::as_str),
|
|
100
|
-
tokens.get(1).map(String::as_str),
|
|
101
|
-
) {
|
|
102
|
-
(Some("naome"), Some("commit")) => Some(IntentKind::CommitRequest),
|
|
103
|
-
(Some("naome"), Some("status")) => Some(IntentKind::StatusQuestion),
|
|
104
|
-
(Some("naome"), Some("sync" | "update" | "install")) => Some(IntentKind::RepairRequest),
|
|
105
|
-
(Some("git"), Some("commit")) => Some(IntentKind::CommitRequest),
|
|
106
|
-
_ => None,
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Kept only so pre-v2 route callers keep their existing conservative behavior.
|
|
111
|
-
// A naome-intent-v2 envelope clears these candidates before policy resolution.
|
|
112
|
-
fn legacy_v1_short_action_request(tokens: &[String]) -> Option<IntentKind> {
|
|
113
|
-
let action_index = tokens
|
|
114
|
-
.iter()
|
|
115
|
-
.position(|token| legacy_v1_action_intent(token).is_some())?;
|
|
116
|
-
if action_index > 1 || tokens.len() > 6 {
|
|
117
|
-
return None;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
let intent = legacy_v1_action_intent(&tokens[action_index])?;
|
|
121
|
-
if intent == IntentKind::StatusQuestion || tokens.len() <= 3 {
|
|
122
|
-
return Some(intent);
|
|
123
|
-
}
|
|
124
|
-
if tokens.len() <= 2 || legacy_v1_has_action_scope(tokens) {
|
|
125
|
-
return Some(intent);
|
|
126
|
-
}
|
|
127
|
-
None
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
fn legacy_v1_no_commit(tokens: &[String]) -> bool {
|
|
131
|
-
tokens
|
|
132
|
-
.windows(3)
|
|
133
|
-
.any(|window| window[0] == "do" && window[1] == "not" && window[2] == "commit")
|
|
134
|
-
|| tokens
|
|
135
|
-
.windows(2)
|
|
136
|
-
.any(|window| matches!(window[0].as_str(), "no" | "without") && window[1] == "commit")
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
fn legacy_v1_action_intent(token: &str) -> Option<IntentKind> {
|
|
140
|
-
match token {
|
|
141
|
-
"commit" | "baseline" => Some(IntentKind::CommitRequest),
|
|
142
|
-
"review" => Some(IntentKind::ReviewRequest),
|
|
143
|
-
"repair" | "sync" => Some(IntentKind::RepairRequest),
|
|
144
|
-
"cancel" => Some(IntentKind::CancelRequest),
|
|
145
|
-
"complete" | "completion" => Some(IntentKind::TaskCompletion),
|
|
146
|
-
"status" => Some(IntentKind::StatusQuestion),
|
|
147
|
-
_ => None,
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
fn legacy_v1_has_action_scope(tokens: &[String]) -> bool {
|
|
152
|
-
has_structured_token(
|
|
153
|
-
tokens,
|
|
154
|
-
&[
|
|
155
|
-
"task",
|
|
156
|
-
"diff",
|
|
157
|
-
"harness",
|
|
158
|
-
"baseline",
|
|
159
|
-
"state",
|
|
160
|
-
"current_task",
|
|
161
|
-
"active_task",
|
|
162
|
-
],
|
|
163
|
-
)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
fn has_structured_token(tokens: &[String], accepted: &[&str]) -> bool {
|
|
167
|
-
tokens
|
|
168
|
-
.iter()
|
|
169
|
-
.any(|token| accepted.iter().any(|accepted| token == accepted))
|
|
170
|
-
}
|