unbound-cli 1.3.2 → 1.4.0
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/PLAN-web-4887.md +477 -0
- package/PLAN.md +117 -0
- package/README.md +8 -2
- package/package.json +1 -1
- package/src/commands/policy.js +183 -10
- package/src/commands/setup.js +4 -2
- package/src/lib/policy-ai-assist.js +503 -0
- package/test/eval/README.md +45 -0
- package/test/eval/policy-prompts.json +122 -0
- package/test/eval/run-eval.js +57 -0
- package/test/policy-ai-assist-mcp.test.js +606 -0
- package/test/policy-ai-assist-preflight.test.js +66 -0
- package/test/policy-ai-assist.test.js +884 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const { test } = require('node:test');
|
|
2
|
+
const assert = require('node:assert/strict');
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
validatePromptPreflight,
|
|
6
|
+
OUT_OF_SCOPE_KEYWORDS,
|
|
7
|
+
MAX_PROMPT_LEN,
|
|
8
|
+
} = require('../src/lib/policy-ai-assist');
|
|
9
|
+
|
|
10
|
+
// Spec §6.2 step 3 / §6.9: trim then check length; 1800 chars passes, 1801 rejects
|
|
11
|
+
// with backend-equivalent wording.
|
|
12
|
+
|
|
13
|
+
test('preflight: prompt of 1799 chars passes', () => {
|
|
14
|
+
const r = validatePromptPreflight({ prompt: 'a'.repeat(1799) });
|
|
15
|
+
assert.equal(r.warnings.length, 0);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('preflight: prompt of 1800 chars passes (boundary)', () => {
|
|
19
|
+
const r = validatePromptPreflight({ prompt: 'a'.repeat(MAX_PROMPT_LEN) });
|
|
20
|
+
assert.equal(r.warnings.length, 0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('preflight: prompt of 1801 chars rejects with verbatim wording', () => {
|
|
24
|
+
assert.throws(
|
|
25
|
+
() => validatePromptPreflight({ prompt: 'a'.repeat(1801) }),
|
|
26
|
+
new RegExp(`^Error: Input is too long \\(max ${MAX_PROMPT_LEN} characters\\)\\.$`)
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// §6.2 step 4: parametrized over the keyword list — every token surfaces a warning.
|
|
31
|
+
for (const token of OUT_OF_SCOPE_KEYWORDS) {
|
|
32
|
+
test(`preflight: out-of-scope keyword "${token}" produces a warning`, () => {
|
|
33
|
+
const r = validatePromptPreflight({ prompt: `block X in ${token} mode` });
|
|
34
|
+
assert.ok(r.warnings.includes(token), `expected warning for ${token}, got ${JSON.stringify(r.warnings)}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// §6.2 step 5: collapse runs of >=2 newlines to a single newline.
|
|
39
|
+
test('preflight: collapses three consecutive newlines to one', () => {
|
|
40
|
+
const r = validatePromptPreflight({ prompt: 'line1\n\n\nline2' });
|
|
41
|
+
assert.equal(r.sanitizedPrompt, 'line1\nline2');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('preflight: collapses two consecutive newlines to one', () => {
|
|
45
|
+
const r = validatePromptPreflight({ prompt: 'a\n\nb' });
|
|
46
|
+
assert.equal(r.sanitizedPrompt, 'a\nb');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('preflight: a single newline is left alone', () => {
|
|
50
|
+
const r = validatePromptPreflight({ prompt: 'a\nb' });
|
|
51
|
+
assert.equal(r.sanitizedPrompt, 'a\nb');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// §6.2: warning is informational only; under --yes the caller logs it and
|
|
55
|
+
// continues. The helper itself never throws for warnings — it just reports.
|
|
56
|
+
test('preflight: warnings do not throw', () => {
|
|
57
|
+
// Use a keyword that is NOT a substring of "production" (the keyword set
|
|
58
|
+
// contains "prod" which would also match): pick a non-overlapping one.
|
|
59
|
+
const r = validatePromptPreflight({ prompt: 'block weekend pushes' });
|
|
60
|
+
assert.ok(r.warnings.includes('weekend'));
|
|
61
|
+
// No throw — the function returned and we got here.
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('preflight: missing prompt throws', () => {
|
|
65
|
+
assert.throws(() => validatePromptPreflight({}), /--prompt is required/);
|
|
66
|
+
});
|