Files
nntrivi2001 57dc91585d feat: Claude Code Monitor — lanes, pipelines and a merged workspace
Internal SmartGift build of a Claude Code monitoring dashboard.

Lanes: a durable unit of parallel agent work, one per working directory,
tracked across session restarts. Managed lanes are git worktrees the
dashboard provisions and can reset or remove behind a three-check destroy
guard and a counted preflight; adopted lanes are directories you already
own and are never destroyable.

Pipelines: a lane moves through pipeline stages. A stage the agent declares
with evidence renders green; a stage inferred from the tool-event stream
renders dashed amber and never counts as done. Detection is forward-only
within a 30-minute window, and never writes the declared stage.

Workspace: one page at /run with a lane grid, the selected lane's pipeline,
and a full Claude console behind a disclosure.
2026-07-30 14:39:03 +07:00

86 lines
2.7 KiB
TypeScript

/**
* @file tool-guards.test.ts
* @description Unit tests for the tool guard functions, which are responsible for enforcing configuration policies related to mutating and destructive tools. The tests cover scenarios where mutations and destructive actions are enabled or disabled in the configuration, as well as validating the confirmation token for destructive actions. The tests use Node's built-in test runner and assert module for assertions.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { assertMutationsEnabled, assertDestructiveEnabled } from "../src/policy/tool-guards.js";
import type { AppConfig } from "../src/config/app-config.js";
function fakeConfig(overrides: Partial<AppConfig> = {}): AppConfig {
return {
serverName: "test",
serverVersion: "1.0.0",
dashboardBaseUrl: new URL("http://127.0.0.1:4820"),
requestTimeoutMs: 10_000,
retryCount: 2,
retryBackoffMs: 250,
allowMutations: false,
allowDestructive: false,
logLevel: "error",
transport: "stdio",
httpPort: 8819,
httpHost: "127.0.0.1",
...overrides,
};
}
describe("assertMutationsEnabled", () => {
it("throws when mutations disabled", () => {
assert.throws(
() => assertMutationsEnabled(fakeConfig({ allowMutations: false })),
/Mutating tools are disabled/
);
});
it("does not throw when mutations enabled", () => {
assert.doesNotThrow(() => assertMutationsEnabled(fakeConfig({ allowMutations: true })));
});
});
describe("assertDestructiveEnabled", () => {
it("throws when mutations disabled (even if destructive enabled)", () => {
assert.throws(
() =>
assertDestructiveEnabled(
fakeConfig({ allowMutations: false, allowDestructive: true }),
"CLEAR_ALL_DATA"
),
/Mutating tools are disabled/
);
});
it("throws when destructive disabled", () => {
assert.throws(
() =>
assertDestructiveEnabled(
fakeConfig({ allowMutations: true, allowDestructive: false }),
"CLEAR_ALL_DATA"
),
/Destructive tools are disabled/
);
});
it("throws on wrong confirmation token", () => {
assert.throws(
() =>
assertDestructiveEnabled(
fakeConfig({ allowMutations: true, allowDestructive: true }),
"WRONG_TOKEN"
),
/Invalid confirmation_token/
);
});
it("passes with correct config and token", () => {
assert.doesNotThrow(() =>
assertDestructiveEnabled(
fakeConfig({ allowMutations: true, allowDestructive: true }),
"CLEAR_ALL_DATA"
)
);
});
});