test: remove Kimi tool-vocabulary hook tests
Some checks failed
Tests / PR mergeability (push) Successful in 17s
Tests / Base branch health (push) Successful in 9s
Tests / Detect test scope (push) Successful in 17s
Tests / lint-tests (push) Failing after 1m56s
Tests / plugin-validate (push) Successful in 1m2s
Tests / test (ubuntu-latest, 24, shard 1/3) (push) Failing after 21s
Tests / test (ubuntu-latest, 24, shard 2/3) (push) Failing after 18s
Tests / test (ubuntu-latest, 24, shard 3/3) (push) Failing after 20s
Tests / test (ubuntu-latest, 24) (push) Failing after 20s
Tests / test (inert CI) (push) Has been skipped
Tests / QA loop walk (smell ratchet) (push) Failing after 17s
Tests / Coverage gate (merged shards) (push) Has been skipped
Tests / Publish emitted-baseline artifact (push) Has been skipped
Dismiss Unauthorized PR Approvals / dismiss-unauthorized-approval (push) Successful in 7s
Tests / conformance test (macos-latest, 24) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 1/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 2/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 3/3) (push) Has been cancelled
Tests / Required tests (push) Has been cancelled
Some checks failed
Tests / PR mergeability (push) Successful in 17s
Tests / Base branch health (push) Successful in 9s
Tests / Detect test scope (push) Successful in 17s
Tests / lint-tests (push) Failing after 1m56s
Tests / plugin-validate (push) Successful in 1m2s
Tests / test (ubuntu-latest, 24, shard 1/3) (push) Failing after 21s
Tests / test (ubuntu-latest, 24, shard 2/3) (push) Failing after 18s
Tests / test (ubuntu-latest, 24, shard 3/3) (push) Failing after 20s
Tests / test (ubuntu-latest, 24) (push) Failing after 20s
Tests / test (inert CI) (push) Has been skipped
Tests / QA loop walk (smell ratchet) (push) Failing after 17s
Tests / Coverage gate (merged shards) (push) Has been skipped
Tests / Publish emitted-baseline artifact (push) Has been skipped
Dismiss Unauthorized PR Approvals / dismiss-unauthorized-approval (push) Successful in 7s
Tests / conformance test (macos-latest, 24) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 1/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 2/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 3/3) (push) Has been cancelled
Tests / Required tests (push) Has been cancelled
The Kimi payload normalization they exercised went away with the Kimi runtime. The Claude-vocabulary force-add block test from the same suite is kept.
This commit is contained in:
@@ -1,13 +1,5 @@
|
||||
/**
|
||||
* Tests for msd-workflow-guard.js PreToolUse hook.
|
||||
*
|
||||
* #2304 — Kimi tool vocabulary engages the guard: Kimi CLI registers this
|
||||
* guard with matcher 'Shell|WriteFile|StrReplaceFile' and forwards its own
|
||||
* tool vocabulary (tool_name 'Shell', possibly module-qualified). kimi-cli's
|
||||
* Shell.Params names its field `command` (src/kimi_cli/tools/shell/
|
||||
* __init__.py), same as Claude's Bash, so only the tool name needs
|
||||
* normalization. Pre-fix the guard's Bash branch never matched on Kimi and
|
||||
* the force-add block was silently dormant.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -44,7 +36,7 @@ function runHook(payload, timeoutMs = 5000) {
|
||||
};
|
||||
}
|
||||
|
||||
describe('#2304: Kimi tool vocabulary engages the workflow guard', () => {
|
||||
describe('workflow guard blocks force-add on a worktree-agent branch', () => {
|
||||
// A repo on a worktree-agent-* branch with the guard enabled: the one
|
||||
// state where the Bash branch produces an observable block, so a dormant
|
||||
// guard (silent exit 0) is distinguishable from a working one (exit 2).
|
||||
@@ -69,46 +61,7 @@ describe('#2304: Kimi tool vocabulary engages the workflow guard', () => {
|
||||
cleanup(repoDir);
|
||||
});
|
||||
|
||||
test('Shell force-add on a worktree-agent branch is blocked like Bash', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'Shell',
|
||||
tool_input: { command: 'git add -f secrets.env' },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 2, 'Kimi Shell should reach the Bash branch and block');
|
||||
const output = JSON.parse(r.stdout);
|
||||
assert.equal(
|
||||
output.code,
|
||||
'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN',
|
||||
'block payload should carry the force-add code'
|
||||
);
|
||||
assert.ok(
|
||||
r.stderr.includes('must not run git add -f'),
|
||||
'reason must reach stderr — that is what Kimi feeds back to the model on exit 2'
|
||||
);
|
||||
});
|
||||
|
||||
test('module-qualified kimi_cli.tools.shell:Shell is recognized', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'kimi_cli.tools.shell:Shell',
|
||||
tool_input: { command: 'git add --force secrets.env' },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 2);
|
||||
assert.equal(JSON.parse(r.stdout).code, 'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN');
|
||||
});
|
||||
|
||||
test('benign Shell command passes through', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'Shell',
|
||||
tool_input: { command: 'git status' },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 0);
|
||||
assert.equal(r.stdout, '');
|
||||
});
|
||||
|
||||
test('Bash (Claude vocabulary) still blocks — normalization is additive', () => {
|
||||
test('Bash force-add on a worktree-agent branch is blocked', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'Bash',
|
||||
tool_input: { command: 'git add -f secrets.env' },
|
||||
@@ -117,78 +70,6 @@ describe('#2304: Kimi tool vocabulary engages the workflow guard', () => {
|
||||
assert.equal(r.exitCode, 2);
|
||||
assert.equal(JSON.parse(r.stdout).code, 'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN');
|
||||
});
|
||||
|
||||
test('WriteFile outside .planning/ gets the workflow advisory like Write', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'WriteFile',
|
||||
tool_input: { path: path.join(repoDir, 'src', 'app.js'), content: 'x' },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 0);
|
||||
const output = JSON.parse(r.stdout);
|
||||
assert.equal(
|
||||
output.hookSpecificOutput?.code,
|
||||
'WORKFLOW_ADVISORY',
|
||||
'Kimi WriteFile should reach the write branch and emit the advisory'
|
||||
);
|
||||
});
|
||||
|
||||
test('StrReplaceFile editing .planning/ passes silently', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'StrReplaceFile',
|
||||
tool_input: { path: path.join(repoDir, '.planning', 'notes.md'), edit: { old: 'a', new: 'b' } },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 0);
|
||||
assert.equal(r.stdout, '');
|
||||
});
|
||||
|
||||
// #2547 — normalizeKimiPayload rebuilt old_string/new_string with
|
||||
// `String(e.old ?? '')`. `??` guards the value, not the dereference, so a
|
||||
// NULLISH entry threw a TypeError at the top of the handler, before the Bash
|
||||
// branch ran. The outer `catch { process.exit(0) }` swallowed it, so a Shell
|
||||
// payload carrying a spurious malformed `edit` field walked straight past the
|
||||
// force-add hard block. The `edit` field is never read on the Bash path — it
|
||||
// only has to be present to trigger the crash, which is what makes this
|
||||
// reachable from a command that has nothing to do with editing.
|
||||
//
|
||||
// The boundary is nullish specifically: `('x').old` is a legal property read
|
||||
// yielding undefined, so a string entry never threw. The `null entry` case is
|
||||
// the regression (exits 0 against pre-fix code); the rest are controls.
|
||||
describe('#2547: a spurious malformed edit field does not disarm the force-add block', () => {
|
||||
for (const [label, edit] of [
|
||||
['null entry (the #2547 bypass)', [null]],
|
||||
// `{"toString": null}` is valid JSON whose coercion throws "Cannot
|
||||
// convert object to primitive value" — the same crash-to-allow reached
|
||||
// through String() rather than through the property read.
|
||||
['non-coercible old (the #2547 String() bypass)', [{ old: { toString: null }, new: 'x' }]],
|
||||
['non-coercible new (the #2547 String() bypass)', [{ old: 'x', new: { toString: null } }]],
|
||||
['string entry (control — never threw)', ['nope']],
|
||||
['bare null, not a list (control — normalizes to no edits)', null],
|
||||
]) {
|
||||
test(`force-add still blocks with a spurious edit field (${label})`, () => {
|
||||
const r = runHook({
|
||||
tool_name: 'Shell',
|
||||
tool_input: { command: 'git add -f secrets.env', edit },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 2,
|
||||
`a spurious malformed edit field (${label}) must not downgrade the force-add ` +
|
||||
`block to a silent allow. Got exit ${r.exitCode}. stderr: ${r.stderr}`);
|
||||
assert.equal(JSON.parse(r.stdout).code, 'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN');
|
||||
});
|
||||
}
|
||||
|
||||
test('benign command with a malformed edit field still passes (no over-block)', () => {
|
||||
const r = runHook({
|
||||
tool_name: 'Shell',
|
||||
tool_input: { command: 'git status', edit: [null] },
|
||||
cwd: repoDir,
|
||||
});
|
||||
assert.equal(r.exitCode, 0, `benign command must stay allowed. stderr: ${r.stderr}`);
|
||||
assert.equal(r.stdout, '');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// #3504 (epic #1900 F22b) — the enabled force-add guard must fail CLOSED on
|
||||
@@ -238,7 +119,7 @@ describe('#3504: internal error fails closed for the enabled force-add guard', (
|
||||
assert.equal(output.code, 'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN');
|
||||
assert.equal(output.origin, 'fail-closed',
|
||||
'a block emitted by the catch must identify itself structurally, not claim a detected force-add');
|
||||
assert.ok(r.stderr.length > 0, 'block reason must reach stderr (Kimi exit-2 protocol)');
|
||||
assert.ok(r.stderr.length > 0, 'block reason must reach stderr (exit-2 protocol)');
|
||||
});
|
||||
|
||||
test('fault before force-add detection still blocks the force-add call', () => {
|
||||
@@ -247,13 +128,6 @@ describe('#3504: internal error fails closed for the enabled force-add guard', (
|
||||
assert.equal(r.exitCode, 2);
|
||||
assert.equal(JSON.parse(r.stdout).code, 'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN');
|
||||
});
|
||||
|
||||
test('fault on Kimi Shell vocabulary fails closed (normalization applies in the catch)', () => {
|
||||
const r = runFaultHook(
|
||||
{ tool_name: 'kimi_cli.tools.shell:Shell', tool_input: { command: 'git status' } }, agentRepo);
|
||||
assert.equal(r.exitCode, 2);
|
||||
assert.equal(JSON.parse(r.stdout).code, 'WORKTREE_AGENT_FORCE_ADD_FORBIDDEN');
|
||||
});
|
||||
});
|
||||
|
||||
describe('blocking context absent → exit 0 (advisory posture unchanged)', () => {
|
||||
|
||||
Reference in New Issue
Block a user