@consensus-tools/universal 0.9.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.
Files changed (69) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +451 -0
  3. package/dist/__tests__/defaults.test.d.ts +2 -0
  4. package/dist/__tests__/defaults.test.d.ts.map +1 -0
  5. package/dist/__tests__/defaults.test.js +55 -0
  6. package/dist/__tests__/defaults.test.js.map +1 -0
  7. package/dist/__tests__/fail-policy.test.d.ts +2 -0
  8. package/dist/__tests__/fail-policy.test.d.ts.map +1 -0
  9. package/dist/__tests__/fail-policy.test.js +80 -0
  10. package/dist/__tests__/fail-policy.test.js.map +1 -0
  11. package/dist/__tests__/frameworks.test.d.ts +2 -0
  12. package/dist/__tests__/frameworks.test.d.ts.map +1 -0
  13. package/dist/__tests__/frameworks.test.js +86 -0
  14. package/dist/__tests__/frameworks.test.js.map +1 -0
  15. package/dist/__tests__/logger.test.d.ts +2 -0
  16. package/dist/__tests__/logger.test.d.ts.map +1 -0
  17. package/dist/__tests__/logger.test.js +77 -0
  18. package/dist/__tests__/logger.test.js.map +1 -0
  19. package/dist/__tests__/resolve.test.d.ts +2 -0
  20. package/dist/__tests__/resolve.test.d.ts.map +1 -0
  21. package/dist/__tests__/resolve.test.js +71 -0
  22. package/dist/__tests__/resolve.test.js.map +1 -0
  23. package/dist/__tests__/wrap.test.d.ts +2 -0
  24. package/dist/__tests__/wrap.test.d.ts.map +1 -0
  25. package/dist/__tests__/wrap.test.js +90 -0
  26. package/dist/__tests__/wrap.test.js.map +1 -0
  27. package/dist/defaults.d.ts +20 -0
  28. package/dist/defaults.d.ts.map +1 -0
  29. package/dist/defaults.js +48 -0
  30. package/dist/defaults.js.map +1 -0
  31. package/dist/errors.d.ts +23 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +31 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/index.d.ts +38 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +239 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/logger.d.ts +12 -0
  40. package/dist/logger.d.ts.map +1 -0
  41. package/dist/logger.js +55 -0
  42. package/dist/logger.js.map +1 -0
  43. package/dist/resolve.d.ts +9 -0
  44. package/dist/resolve.d.ts.map +1 -0
  45. package/dist/resolve.js +25 -0
  46. package/dist/resolve.js.map +1 -0
  47. package/dist/types.d.ts +35 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +82 -0
  52. package/src/__tests__/defaults.test.ts +71 -0
  53. package/src/__tests__/fail-policy.test.ts +107 -0
  54. package/src/__tests__/frameworks.test.ts +106 -0
  55. package/src/__tests__/logger.test.ts +93 -0
  56. package/src/__tests__/resolve.test.ts +80 -0
  57. package/src/__tests__/wrap.test.ts +110 -0
  58. package/src/consensus-llm.test.ts +260 -0
  59. package/src/defaults.ts +124 -0
  60. package/src/errors.ts +35 -0
  61. package/src/index.ts +386 -0
  62. package/src/logger.ts +65 -0
  63. package/src/persona-reviewer-factory.ts +387 -0
  64. package/src/reputation-manager.test.ts +131 -0
  65. package/src/reputation-manager.ts +168 -0
  66. package/src/resolve.ts +30 -0
  67. package/src/risk-tiers.test.ts +36 -0
  68. package/src/risk-tiers.ts +49 -0
  69. package/src/types.ts +127 -0
@@ -0,0 +1,55 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { DEFAULTS, DEFAULT_GUARD, DEFAULT_POLICY, DEFAULT_PERSONA_COUNT, DEFAULT_PERSONA_TRIO, policyToStrategy, } from "../defaults.js";
3
+ import { ConfigError } from "../errors.js";
4
+ describe("DEFAULTS", () => {
5
+ it("provides full defaults matching expected values", () => {
6
+ expect(DEFAULTS.policy).toBe("majority");
7
+ expect(DEFAULTS.guards).toEqual(["agent_action"]);
8
+ expect(DEFAULTS.failPolicy).toBe("closed");
9
+ expect(DEFAULTS.storage).toBe("memory");
10
+ expect(DEFAULTS.logger).toBe(true);
11
+ });
12
+ it("exports expected guard and policy constants", () => {
13
+ expect(DEFAULT_GUARD).toBe("agent_action");
14
+ expect(DEFAULT_POLICY).toBe("majority");
15
+ expect(DEFAULT_PERSONA_COUNT).toBe(3);
16
+ expect(DEFAULT_PERSONA_TRIO).toEqual(["security", "compliance", "user-impact"]);
17
+ });
18
+ it("merges partial config with defaults", () => {
19
+ const partial = { policy: "unanimous", failPolicy: "open" };
20
+ const merged = { ...DEFAULTS, ...partial };
21
+ expect(merged.policy).toBe("unanimous");
22
+ expect(merged.failPolicy).toBe("open");
23
+ // Untouched defaults remain
24
+ expect(merged.guards).toEqual(["agent_action"]);
25
+ expect(merged.storage).toBe("memory");
26
+ expect(merged.logger).toBe(true);
27
+ });
28
+ });
29
+ describe("policyToStrategy", () => {
30
+ it("maps 'majority' to { strategy: 'majority' }", () => {
31
+ expect(policyToStrategy("majority")).toEqual({ strategy: "majority" });
32
+ });
33
+ it("maps 'supermajority' to { strategy: 'threshold', threshold: 0.67 }", () => {
34
+ expect(policyToStrategy("supermajority")).toEqual({ strategy: "threshold", threshold: 0.67 });
35
+ });
36
+ it("maps 'unanimous' to { strategy: 'unanimous' }", () => {
37
+ expect(policyToStrategy("unanimous")).toEqual({ strategy: "unanimous" });
38
+ });
39
+ it("maps 'threshold:0.8' to { strategy: 'threshold', threshold: 0.8 }", () => {
40
+ expect(policyToStrategy("threshold:0.8")).toEqual({ strategy: "threshold", threshold: 0.8 });
41
+ });
42
+ it("throws ConfigError for unknown policy name", () => {
43
+ expect(() => policyToStrategy("bogus")).toThrow(ConfigError);
44
+ expect(() => policyToStrategy("bogus")).toThrow('Unknown policy "bogus"');
45
+ });
46
+ it("throws ConfigError for invalid threshold value", () => {
47
+ expect(() => policyToStrategy("threshold:abc")).toThrow(ConfigError);
48
+ expect(() => policyToStrategy("threshold:abc")).toThrow("Invalid threshold value");
49
+ });
50
+ it("throws ConfigError for threshold out of range", () => {
51
+ expect(() => policyToStrategy("threshold:1.5")).toThrow(ConfigError);
52
+ expect(() => policyToStrategy("threshold:-0.1")).toThrow(ConfigError);
53
+ });
54
+ });
55
+ //# sourceMappingURL=defaults.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.test.js","sourceRoot":"","sources":["../../src/__tests__/defaults.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fail-policy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fail-policy.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/fail-policy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { ConsensusBlockedError } from "../errors.js";
3
+ // Mock the wrapper's consensus function and guards' createGuardTemplate
4
+ const mockWrapped = vi.fn();
5
+ vi.mock("@consensus-tools/wrapper", () => ({
6
+ consensus: vi.fn(() => mockWrapped),
7
+ }));
8
+ vi.mock("@consensus-tools/guards", () => ({
9
+ createGuardTemplate: vi.fn((_name, _config) => ({
10
+ asReviewer: () => vi.fn(),
11
+ })),
12
+ GUARD_CONFIGS: {
13
+ security: { description: "Security reviewer", rules: () => [] },
14
+ compliance: { description: "Compliance reviewer", rules: () => [] },
15
+ "user-impact": { description: "User-impact reviewer", rules: () => [] },
16
+ },
17
+ DEFAULT_PERSONA_TRIO: ["security", "compliance", "user-impact"],
18
+ }));
19
+ const { consensus } = await import("../index.js");
20
+ describe("failPolicy behavior", () => {
21
+ let originalNodeEnv;
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ originalNodeEnv = process.env["NODE_ENV"];
25
+ });
26
+ afterEach(() => {
27
+ if (originalNodeEnv === undefined) {
28
+ delete process.env["NODE_ENV"];
29
+ }
30
+ else {
31
+ process.env["NODE_ENV"] = originalNodeEnv;
32
+ }
33
+ });
34
+ it("failPolicy: 'closed' + error -> ConsensusBlockedError thrown", async () => {
35
+ const fn = vi.fn(async () => "result");
36
+ mockWrapped.mockRejectedValueOnce(new Error("deliberation crashed"));
37
+ const wrapped = consensus.wrap(fn, { failPolicy: "closed" });
38
+ await expect(wrapped("myTool", {})).rejects.toThrow(ConsensusBlockedError);
39
+ // Second call: verify message
40
+ mockWrapped.mockRejectedValueOnce(new Error("deliberation crashed again"));
41
+ const wrapped2 = consensus.wrap(fn, { failPolicy: "closed" });
42
+ await expect(wrapped2("myTool", {})).rejects.toThrow("Consensus deliberation failed");
43
+ });
44
+ it("failPolicy: 'open' + error -> fn result returned", async () => {
45
+ const fn = vi.fn(async (_name, _args) => "fallback-result");
46
+ // First call: mockWrapped rejects (deliberation error)
47
+ mockWrapped.mockRejectedValueOnce(new Error("deliberation crashed"));
48
+ const wrapped = consensus.wrap(fn, { failPolicy: "open" });
49
+ const result = await wrapped("myTool", { key: "val" });
50
+ // failPolicy 'open' should call fn directly and return its result
51
+ expect(result).toBe("fallback-result");
52
+ expect(fn).toHaveBeenCalledWith("myTool", { key: "val" });
53
+ });
54
+ it("NODE_ENV=production + failPolicy:'open' -> console.warn emitted", () => {
55
+ process.env["NODE_ENV"] = "production";
56
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
57
+ const fn = vi.fn(async () => "result");
58
+ consensus.wrap(fn, { failPolicy: "open" });
59
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("failPolicy 'open' in production"));
60
+ warnSpy.mockRestore();
61
+ });
62
+ it("NODE_ENV=production + storage:'memory' -> console.warn emitted", () => {
63
+ process.env["NODE_ENV"] = "production";
64
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
65
+ const fn = vi.fn(async () => "result");
66
+ // storage defaults to 'memory', so no explicit override needed
67
+ consensus.wrap(fn, { storage: "memory" });
68
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("storage 'memory' in production"));
69
+ warnSpy.mockRestore();
70
+ });
71
+ it("NODE_ENV=development -> no warnings emitted", () => {
72
+ process.env["NODE_ENV"] = "development";
73
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
74
+ const fn = vi.fn(async () => "result");
75
+ consensus.wrap(fn, { failPolicy: "open", storage: "memory" });
76
+ expect(warnSpy).not.toHaveBeenCalled();
77
+ warnSpy.mockRestore();
78
+ });
79
+ });
80
+ //# sourceMappingURL=fail-policy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fail-policy.test.js","sourceRoot":"","sources":["../../src/__tests__/fail-policy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=frameworks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/frameworks.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { MissingDependencyError } from "../errors.js";
3
+ // Mock the wrapper and guards (needed for module load)
4
+ vi.mock("@consensus-tools/wrapper", () => ({
5
+ consensus: vi.fn(() => vi.fn()),
6
+ }));
7
+ vi.mock("@consensus-tools/guards", () => ({
8
+ createGuardTemplate: vi.fn((_name, _config) => ({
9
+ asReviewer: () => vi.fn(),
10
+ })),
11
+ }));
12
+ // Mock the optional adapter packages to simulate them not being installed
13
+ vi.mock("@consensus-tools/langchain", () => {
14
+ throw new Error("Cannot find module '@consensus-tools/langchain'");
15
+ });
16
+ vi.mock("@consensus-tools/ai-sdk", () => {
17
+ throw new Error("Cannot find module '@consensus-tools/ai-sdk'");
18
+ });
19
+ vi.mock("@consensus-tools/mcp", () => {
20
+ throw new Error("Cannot find module '@consensus-tools/mcp'");
21
+ });
22
+ const { consensus } = await import("../index.js");
23
+ describe("framework shortcuts", () => {
24
+ it("consensus.langchain() throws MissingDependencyError when adapter not installed", async () => {
25
+ await expect(consensus.langchain({})).rejects.toThrow(MissingDependencyError);
26
+ await expect(consensus.langchain({})).rejects.toThrow("@consensus-tools/langchain");
27
+ });
28
+ it("consensus.aiSdk() throws MissingDependencyError when adapter not installed", async () => {
29
+ await expect(consensus.aiSdk(() => { })).rejects.toThrow(MissingDependencyError);
30
+ await expect(consensus.aiSdk(() => { })).rejects.toThrow("@consensus-tools/ai-sdk");
31
+ });
32
+ it("consensus.mcp() throws MissingDependencyError when adapter not installed", async () => {
33
+ await expect(consensus.mcp()).rejects.toThrow(MissingDependencyError);
34
+ await expect(consensus.mcp()).rejects.toThrow("@consensus-tools/mcp");
35
+ });
36
+ });
37
+ describe("consensus.langchain() with adapter installed", () => {
38
+ it("returns a handler instance when adapter is available", async () => {
39
+ // Create a mock handler class
40
+ class MockGuardHandler {
41
+ name = "consensus-guard";
42
+ config;
43
+ constructor(config) {
44
+ this.config = config;
45
+ }
46
+ }
47
+ // Temporarily override the langchain mock to return a working module
48
+ const mockMod = {
49
+ ConsensusGuardCallbackHandler: MockGuardHandler,
50
+ };
51
+ // We need to test with a fresh import; use vi.doMock to override for a scoped import
52
+ vi.doMock("@consensus-tools/langchain", () => mockMod);
53
+ // Re-import to pick up the new mock
54
+ const { consensus: freshConsensus } = await import("../index.js");
55
+ const handler = await freshConsensus.langchain(null, { policy: "supermajority", guards: ["security"] });
56
+ expect(handler).toBeInstanceOf(MockGuardHandler);
57
+ expect(handler.config).toEqual({
58
+ policy: "supermajority",
59
+ guards: ["security"],
60
+ onDecision: undefined,
61
+ });
62
+ // Restore the original mock (not installed)
63
+ vi.doMock("@consensus-tools/langchain", () => {
64
+ throw new Error("Cannot find module '@consensus-tools/langchain'");
65
+ });
66
+ });
67
+ it("uses default policy 'majority' when no config provided", async () => {
68
+ class MockGuardHandler {
69
+ name = "consensus-guard";
70
+ config;
71
+ constructor(config) {
72
+ this.config = config;
73
+ }
74
+ }
75
+ vi.doMock("@consensus-tools/langchain", () => ({
76
+ ConsensusGuardCallbackHandler: MockGuardHandler,
77
+ }));
78
+ const { consensus: freshConsensus } = await import("../index.js");
79
+ const handler = await freshConsensus.langchain(null);
80
+ expect(handler.config.policy).toBe("majority");
81
+ vi.doMock("@consensus-tools/langchain", () => {
82
+ throw new Error("Cannot find module '@consensus-tools/langchain'");
83
+ });
84
+ });
85
+ });
86
+ //# sourceMappingURL=frameworks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks.test.js","sourceRoot":"","sources":["../../src/__tests__/frameworks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logger.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/logger.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { createLogger } from "../logger.js";
3
+ describe("createLogger", () => {
4
+ it("emits deliberation.start event via beforeSubmit hook", () => {
5
+ const logFn = vi.fn();
6
+ const hooks = createLogger({ logger: logFn });
7
+ hooks.beforeSubmit(["arg1", "arg2"]);
8
+ expect(logFn).toHaveBeenCalledOnce();
9
+ const event = logFn.mock.calls[0][0];
10
+ expect(event.event).toBe("deliberation.start");
11
+ expect(event.data).toEqual({ args: ["arg1", "arg2"] });
12
+ expect(typeof event.timestamp).toBe("number");
13
+ });
14
+ it("emits deliberation.result event via afterResolve hook", () => {
15
+ const logFn = vi.fn();
16
+ const hooks = createLogger({ logger: logFn });
17
+ const mockResult = {
18
+ action: "allow",
19
+ output: "ok",
20
+ scores: [{ score: 0.9, rationale: "safe" }],
21
+ aggregateScore: 0.9,
22
+ attempt: 1,
23
+ };
24
+ hooks.afterResolve(mockResult);
25
+ expect(logFn).toHaveBeenCalledOnce();
26
+ const event = logFn.mock.calls[0][0];
27
+ expect(event.event).toBe("deliberation.result");
28
+ expect(event.data).toEqual({
29
+ action: "allow",
30
+ aggregateScore: 0.9,
31
+ attempt: 1,
32
+ scoresCount: 1,
33
+ });
34
+ });
35
+ it("emits deliberation.error-level event via onBlock hook", () => {
36
+ const logFn = vi.fn();
37
+ const hooks = createLogger({ logger: logFn });
38
+ const mockResult = {
39
+ action: "block",
40
+ output: null,
41
+ scores: [{ score: 0, rationale: "blocked" }],
42
+ aggregateScore: 0,
43
+ attempt: 1,
44
+ };
45
+ hooks.onBlock(mockResult);
46
+ expect(logFn).toHaveBeenCalledOnce();
47
+ const event = logFn.mock.calls[0][0];
48
+ expect(event.event).toBe("deliberation.result");
49
+ expect(event.data.action).toBe("block");
50
+ });
51
+ it("returns empty hooks when logger is false (suppresses all events)", () => {
52
+ const hooks = createLogger({ logger: false });
53
+ expect(hooks.beforeSubmit).toBeUndefined();
54
+ expect(hooks.afterResolve).toBeUndefined();
55
+ expect(hooks.onBlock).toBeUndefined();
56
+ expect(hooks.onEscalate).toBeUndefined();
57
+ });
58
+ it("uses custom logger function to receive events", () => {
59
+ const events = [];
60
+ const customLogger = (event) => {
61
+ events.push(event);
62
+ };
63
+ const hooks = createLogger({ logger: customLogger });
64
+ hooks.beforeSubmit(["hello"]);
65
+ hooks.afterResolve({
66
+ action: "allow",
67
+ output: "world",
68
+ scores: [],
69
+ aggregateScore: 1.0,
70
+ attempt: 1,
71
+ });
72
+ expect(events).toHaveLength(2);
73
+ expect(events[0].event).toBe("deliberation.start");
74
+ expect(events[1].event).toBe("deliberation.result");
75
+ });
76
+ });
77
+ //# sourceMappingURL=logger.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../../src/__tests__/logger.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=resolve.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/resolve.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { resolveWrappable } from "../resolve.js";
3
+ describe("resolveWrappable", () => {
4
+ it("returns the function directly when input is a function", () => {
5
+ const fn = async (name, args) => ({ name, args });
6
+ const result = resolveWrappable(fn);
7
+ expect(result).toBe(fn);
8
+ });
9
+ it("returns .execute when input has .execute", async () => {
10
+ const obj = {
11
+ state: "bound",
12
+ execute: async function (name, args) {
13
+ return { name, args, state: this.state };
14
+ },
15
+ };
16
+ const resolved = resolveWrappable(obj);
17
+ const output = await resolved("test", { a: 1 });
18
+ expect(output).toEqual({ name: "test", args: { a: 1 }, state: "bound" });
19
+ });
20
+ it("returns .invoke when input has .invoke", async () => {
21
+ const obj = {
22
+ state: "invoked",
23
+ invoke: async function (name, args) {
24
+ return { name, args, state: this.state };
25
+ },
26
+ };
27
+ const resolved = resolveWrappable(obj);
28
+ const output = await resolved("test", { b: 2 });
29
+ expect(output).toEqual({ name: "test", args: { b: 2 }, state: "invoked" });
30
+ });
31
+ it("returns .call when input has .call", async () => {
32
+ const obj = {
33
+ state: "called",
34
+ call: async function (name, args) {
35
+ return { name, args, state: this.state };
36
+ },
37
+ };
38
+ const resolved = resolveWrappable(obj);
39
+ const output = await resolved("test", { c: 3 });
40
+ expect(output).toEqual({ name: "test", args: { c: 3 }, state: "called" });
41
+ });
42
+ it("prefers .execute over .invoke when both exist (resolution order)", async () => {
43
+ const obj = {
44
+ execute: async (_name, _args) => "execute-wins",
45
+ invoke: async (_name, _args) => "invoke-loses",
46
+ };
47
+ const resolved = resolveWrappable(obj);
48
+ const output = await resolved("test", {});
49
+ expect(output).toBe("execute-wins");
50
+ });
51
+ it("throws TypeError for null", () => {
52
+ expect(() => resolveWrappable(null)).toThrow(TypeError);
53
+ expect(() => resolveWrappable(null)).toThrow("Expected a Wrappable");
54
+ });
55
+ it("throws TypeError for undefined", () => {
56
+ expect(() => resolveWrappable(undefined)).toThrow(TypeError);
57
+ expect(() => resolveWrappable(undefined)).toThrow("Expected a Wrappable");
58
+ });
59
+ it("throws TypeError for object with no matching methods", () => {
60
+ const obj = { foo: () => "bar" };
61
+ expect(() => resolveWrappable(obj)).toThrow(TypeError);
62
+ expect(() => resolveWrappable(obj)).toThrow("Expected a Wrappable");
63
+ });
64
+ it("throws TypeError for string primitive", () => {
65
+ expect(() => resolveWrappable("hello")).toThrow(TypeError);
66
+ });
67
+ it("throws TypeError for number primitive", () => {
68
+ expect(() => resolveWrappable(42)).toThrow(TypeError);
69
+ });
70
+ });
71
+ //# sourceMappingURL=resolve.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.test.js","sourceRoot":"","sources":["../../src/__tests__/resolve.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=wrap.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrap.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/wrap.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { ConsensusBlockedError } from "../errors.js";
3
+ // Mock the wrapper's consensus function and guards' createGuardTemplate
4
+ const mockWrapped = vi.fn();
5
+ vi.mock("@consensus-tools/wrapper", () => ({
6
+ consensus: vi.fn(() => mockWrapped),
7
+ }));
8
+ vi.mock("@consensus-tools/guards", () => ({
9
+ createGuardTemplate: vi.fn((_name, _config) => ({
10
+ asReviewer: () => vi.fn(),
11
+ })),
12
+ GUARD_CONFIGS: {
13
+ security: { description: "Security reviewer", rules: () => [] },
14
+ compliance: { description: "Compliance reviewer", rules: () => [] },
15
+ "user-impact": { description: "User-impact reviewer", rules: () => [] },
16
+ },
17
+ DEFAULT_PERSONA_TRIO: ["security", "compliance", "user-impact"],
18
+ }));
19
+ // Import after mocks are set up
20
+ const { consensus } = await import("../index.js");
21
+ describe("consensus.wrap()", () => {
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ });
25
+ it("happy path: wrap function, reviewers run, decision returned", async () => {
26
+ const fn = vi.fn(async (_name, _args) => "tool-result");
27
+ mockWrapped.mockResolvedValueOnce({
28
+ action: "allow",
29
+ output: "tool-result",
30
+ scores: [{ score: 0.9, rationale: "approved" }],
31
+ aggregateScore: 0.9,
32
+ attempt: 1,
33
+ });
34
+ const wrapped = consensus.wrap(fn);
35
+ const result = await wrapped("myTool", { input: "data" });
36
+ expect(result).toBe("tool-result");
37
+ expect(mockWrapped).toHaveBeenCalledWith("myTool", { input: "data" });
38
+ });
39
+ it("wrapped fn returns undefined -> reviewers evaluate undefined", async () => {
40
+ const fn = vi.fn(async () => undefined);
41
+ mockWrapped.mockResolvedValueOnce({
42
+ action: "allow",
43
+ output: undefined,
44
+ scores: [{ score: 0.8 }],
45
+ aggregateScore: 0.8,
46
+ attempt: 1,
47
+ });
48
+ const wrapped = consensus.wrap(fn);
49
+ const result = await wrapped("myTool", {});
50
+ expect(result).toBeUndefined();
51
+ });
52
+ it("wrapped fn throws synchronously -> failPolicy 'closed' throws ConsensusBlockedError", async () => {
53
+ const fn = vi.fn(() => {
54
+ throw new Error("sync explosion");
55
+ });
56
+ mockWrapped.mockRejectedValueOnce(new Error("sync explosion"));
57
+ const wrapped = consensus.wrap(fn, { failPolicy: "closed" });
58
+ await expect(wrapped("myTool", {})).rejects.toThrow(ConsensusBlockedError);
59
+ });
60
+ it("all reviewers return score=0 -> unanimous block with failPolicy closed", async () => {
61
+ const fn = vi.fn(async () => "result");
62
+ mockWrapped.mockResolvedValueOnce({
63
+ action: "block",
64
+ output: null,
65
+ scores: [
66
+ { score: 0, rationale: "blocked-1" },
67
+ { score: 0, rationale: "blocked-2" },
68
+ { score: 0, rationale: "blocked-3" },
69
+ ],
70
+ aggregateScore: 0,
71
+ attempt: 1,
72
+ });
73
+ const wrapped = consensus.wrap(fn, { failPolicy: "closed" });
74
+ await expect(wrapped("dangerousTool", {})).rejects.toThrow(ConsensusBlockedError);
75
+ // Second call to verify message content
76
+ mockWrapped.mockResolvedValueOnce({
77
+ action: "block",
78
+ output: null,
79
+ scores: [
80
+ { score: 0, rationale: "blocked-1" },
81
+ { score: 0, rationale: "blocked-2" },
82
+ { score: 0, rationale: "blocked-3" },
83
+ ],
84
+ aggregateScore: 0,
85
+ attempt: 1,
86
+ });
87
+ await expect(wrapped("dangerousTool", {})).rejects.toThrow(/Consensus block/);
88
+ });
89
+ });
90
+ //# sourceMappingURL=wrap.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrap.test.js","sourceRoot":"","sources":["../../src/__tests__/wrap.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { StrategyConfig } from "@consensus-tools/wrapper";
2
+ import type { UniversalConfig } from "./types.js";
3
+ export { DEFAULT_PERSONA_TRIO } from "@consensus-tools/guards";
4
+ export declare const DEFAULT_GUARD = "agent_action";
5
+ export declare const DEFAULT_POLICY = "majority";
6
+ export declare const DEFAULT_PERSONA_COUNT = 3;
7
+ export declare const DEFAULTS: Required<Pick<UniversalConfig, "policy" | "guards" | "failPolicy" | "storage" | "logger">>;
8
+ /**
9
+ * Maps a user-facing policy name to a wrapper StrategyConfig.
10
+ *
11
+ * Supported names:
12
+ * 'majority' -> { strategy: 'majority' }
13
+ * 'supermajority' -> { strategy: 'threshold', threshold: 0.67 }
14
+ * 'unanimous' -> { strategy: 'unanimous' }
15
+ * 'threshold:X' -> { strategy: 'threshold', threshold: X }
16
+ *
17
+ * @throws ConfigError for unrecognized policy names.
18
+ */
19
+ export declare function policyToStrategy(policy: string): StrategyConfig;
20
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAI/D,eAAO,MAAM,aAAa,iBAAiB,CAAC;AAC5C,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAC7B,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC,CAOjF,CAAC;AAIF;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CA0B/D"}
@@ -0,0 +1,48 @@
1
+ import { ConfigError } from "./errors.js";
2
+ export { DEFAULT_PERSONA_TRIO } from "@consensus-tools/guards";
3
+ // ── Default Configuration ────────────────────────────────────────────
4
+ export const DEFAULT_GUARD = "agent_action";
5
+ export const DEFAULT_POLICY = "majority";
6
+ export const DEFAULT_PERSONA_COUNT = 3;
7
+ export const DEFAULTS = {
8
+ policy: DEFAULT_POLICY,
9
+ guards: [DEFAULT_GUARD],
10
+ failPolicy: "closed",
11
+ storage: "memory",
12
+ logger: true,
13
+ };
14
+ // ── Policy-to-Strategy Mapping ───────────────────────────────────────
15
+ /**
16
+ * Maps a user-facing policy name to a wrapper StrategyConfig.
17
+ *
18
+ * Supported names:
19
+ * 'majority' -> { strategy: 'majority' }
20
+ * 'supermajority' -> { strategy: 'threshold', threshold: 0.67 }
21
+ * 'unanimous' -> { strategy: 'unanimous' }
22
+ * 'threshold:X' -> { strategy: 'threshold', threshold: X }
23
+ *
24
+ * @throws ConfigError for unrecognized policy names.
25
+ */
26
+ export function policyToStrategy(policy) {
27
+ switch (policy) {
28
+ case "majority":
29
+ return { strategy: "majority" };
30
+ case "supermajority":
31
+ return { strategy: "threshold", threshold: 0.67 };
32
+ case "unanimous":
33
+ return { strategy: "unanimous" };
34
+ default: {
35
+ // Handle 'threshold:X' pattern
36
+ if (policy.startsWith("threshold:")) {
37
+ const value = Number(policy.slice("threshold:".length));
38
+ if (Number.isNaN(value) || value < 0 || value > 1) {
39
+ throw new ConfigError(`Invalid threshold value in policy "${policy}". Expected a number between 0 and 1.`);
40
+ }
41
+ return { strategy: "threshold", threshold: value };
42
+ }
43
+ throw new ConfigError(`Unknown policy "${policy}". ` +
44
+ `Supported: 'majority', 'supermajority', 'unanimous', 'threshold:X' (where X is 0-1).`);
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=defaults.js.map