nodebench-mcp 2.22.0 → 2.26.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 (96) hide show
  1. package/NODEBENCH_AGENTS.md +5 -4
  2. package/README.md +495 -280
  3. package/dist/__tests__/architectComplex.test.js +3 -5
  4. package/dist/__tests__/architectComplex.test.js.map +1 -1
  5. package/dist/__tests__/batchAutopilot.test.d.ts +8 -0
  6. package/dist/__tests__/batchAutopilot.test.js +218 -0
  7. package/dist/__tests__/batchAutopilot.test.js.map +1 -0
  8. package/dist/__tests__/cliSubcommands.test.d.ts +1 -0
  9. package/dist/__tests__/cliSubcommands.test.js +138 -0
  10. package/dist/__tests__/cliSubcommands.test.js.map +1 -0
  11. package/dist/__tests__/evalHarness.test.js +1 -1
  12. package/dist/__tests__/forecastingDogfood.test.d.ts +9 -0
  13. package/dist/__tests__/forecastingDogfood.test.js +284 -0
  14. package/dist/__tests__/forecastingDogfood.test.js.map +1 -0
  15. package/dist/__tests__/forecastingScoring.test.d.ts +9 -0
  16. package/dist/__tests__/forecastingScoring.test.js +202 -0
  17. package/dist/__tests__/forecastingScoring.test.js.map +1 -0
  18. package/dist/__tests__/localDashboard.test.d.ts +1 -0
  19. package/dist/__tests__/localDashboard.test.js +226 -0
  20. package/dist/__tests__/localDashboard.test.js.map +1 -0
  21. package/dist/__tests__/multiHopDogfood.test.d.ts +12 -0
  22. package/dist/__tests__/multiHopDogfood.test.js +303 -0
  23. package/dist/__tests__/multiHopDogfood.test.js.map +1 -0
  24. package/dist/__tests__/openclawDogfood.test.d.ts +23 -0
  25. package/dist/__tests__/openclawDogfood.test.js +535 -0
  26. package/dist/__tests__/openclawDogfood.test.js.map +1 -0
  27. package/dist/__tests__/openclawMessaging.test.d.ts +14 -0
  28. package/dist/__tests__/openclawMessaging.test.js +232 -0
  29. package/dist/__tests__/openclawMessaging.test.js.map +1 -0
  30. package/dist/__tests__/tools.test.js +7 -3
  31. package/dist/__tests__/tools.test.js.map +1 -1
  32. package/dist/__tests__/traceabilityDogfood.test.d.ts +12 -0
  33. package/dist/__tests__/traceabilityDogfood.test.js +241 -0
  34. package/dist/__tests__/traceabilityDogfood.test.js.map +1 -0
  35. package/dist/__tests__/webmcpTools.test.d.ts +7 -0
  36. package/dist/__tests__/webmcpTools.test.js +195 -0
  37. package/dist/__tests__/webmcpTools.test.js.map +1 -0
  38. package/dist/dashboard/briefHtml.d.ts +20 -0
  39. package/dist/dashboard/briefHtml.js +1000 -0
  40. package/dist/dashboard/briefHtml.js.map +1 -0
  41. package/dist/dashboard/briefServer.d.ts +18 -0
  42. package/dist/dashboard/briefServer.js +320 -0
  43. package/dist/dashboard/briefServer.js.map +1 -0
  44. package/dist/dashboard/html.d.ts +18 -0
  45. package/dist/dashboard/html.js +1491 -0
  46. package/dist/dashboard/html.js.map +1 -0
  47. package/dist/dashboard/server.d.ts +17 -0
  48. package/dist/dashboard/server.js +403 -0
  49. package/dist/dashboard/server.js.map +1 -0
  50. package/dist/db.js +38 -0
  51. package/dist/db.js.map +1 -1
  52. package/dist/index.js +211 -5
  53. package/dist/index.js.map +1 -1
  54. package/dist/tools/critterTools.js +4 -0
  55. package/dist/tools/critterTools.js.map +1 -1
  56. package/dist/tools/forecastingTools.d.ts +11 -0
  57. package/dist/tools/forecastingTools.js +616 -0
  58. package/dist/tools/forecastingTools.js.map +1 -0
  59. package/dist/tools/localDashboardTools.d.ts +8 -0
  60. package/dist/tools/localDashboardTools.js +332 -0
  61. package/dist/tools/localDashboardTools.js.map +1 -0
  62. package/dist/tools/metaTools.js +170 -1
  63. package/dist/tools/metaTools.js.map +1 -1
  64. package/dist/tools/openclawTools.d.ts +11 -0
  65. package/dist/tools/openclawTools.js +1017 -0
  66. package/dist/tools/openclawTools.js.map +1 -0
  67. package/dist/tools/overstoryTools.d.ts +14 -0
  68. package/dist/tools/overstoryTools.js +426 -0
  69. package/dist/tools/overstoryTools.js.map +1 -0
  70. package/dist/tools/prReportTools.d.ts +11 -0
  71. package/dist/tools/prReportTools.js +911 -0
  72. package/dist/tools/prReportTools.js.map +1 -0
  73. package/dist/tools/progressiveDiscoveryTools.js +28 -9
  74. package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
  75. package/dist/tools/selfEvalTools.js +8 -1
  76. package/dist/tools/selfEvalTools.js.map +1 -1
  77. package/dist/tools/sessionMemoryTools.js +14 -2
  78. package/dist/tools/sessionMemoryTools.js.map +1 -1
  79. package/dist/tools/skillUpdateTools.d.ts +24 -0
  80. package/dist/tools/skillUpdateTools.js +469 -0
  81. package/dist/tools/skillUpdateTools.js.map +1 -0
  82. package/dist/tools/toolRegistry.js +178 -0
  83. package/dist/tools/toolRegistry.js.map +1 -1
  84. package/dist/tools/uiUxDiveAdvancedTools.js +61 -0
  85. package/dist/tools/uiUxDiveAdvancedTools.js.map +1 -1
  86. package/dist/tools/uiUxDiveTools.js +154 -1
  87. package/dist/tools/uiUxDiveTools.js.map +1 -1
  88. package/dist/tools/visualQaTools.d.ts +2 -0
  89. package/dist/tools/visualQaTools.js +1088 -0
  90. package/dist/tools/visualQaTools.js.map +1 -0
  91. package/dist/tools/webmcpTools.d.ts +16 -0
  92. package/dist/tools/webmcpTools.js +703 -0
  93. package/dist/tools/webmcpTools.js.map +1 -0
  94. package/dist/toolsetRegistry.js +4 -0
  95. package/dist/toolsetRegistry.js.map +1 -1
  96. package/package.json +1 -1
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Local Dashboard Tests
3
+ *
4
+ * Tests for: schema tables, tool structure, handler behavior, audience events.
5
+ */
6
+ import { describe, it, expect, beforeAll } from "vitest";
7
+ import Database from "better-sqlite3";
8
+ import { join } from "node:path";
9
+ import { tmpdir } from "node:os";
10
+ import { mkdtempSync } from "node:fs";
11
+ import { localDashboardTools } from "../tools/localDashboardTools.js";
12
+ import { getBriefDashboardHtml } from "../dashboard/briefHtml.js";
13
+ import { ALL_REGISTRY_ENTRIES, WORKFLOW_CHAINS } from "../tools/toolRegistry.js";
14
+ // Create a temporary database for schema tests
15
+ let db;
16
+ beforeAll(() => {
17
+ const tmpDir = mkdtempSync(join(tmpdir(), "nodebench-dashboard-test-"));
18
+ db = new Database(join(tmpDir, "test.db"));
19
+ db.pragma("journal_mode = WAL");
20
+ // Create the tables (mirrors db.ts schema)
21
+ db.exec(`
22
+ CREATE TABLE IF NOT EXISTS brief_snapshots (
23
+ id TEXT PRIMARY KEY, date_string TEXT NOT NULL, generated_at INTEGER NOT NULL,
24
+ dashboard_metrics TEXT NOT NULL, source_summary TEXT, version INTEGER NOT NULL DEFAULT 1,
25
+ synced_at TEXT NOT NULL DEFAULT (datetime('now')), UNIQUE(date_string, version)
26
+ );
27
+ CREATE TABLE IF NOT EXISTS brief_memories (
28
+ id TEXT PRIMARY KEY, snapshot_id TEXT, date_string TEXT NOT NULL,
29
+ goal TEXT, features TEXT, progress_log TEXT,
30
+ synced_at TEXT NOT NULL DEFAULT (datetime('now'))
31
+ );
32
+ CREATE TABLE IF NOT EXISTS brief_task_results (
33
+ id TEXT PRIMARY KEY, memory_id TEXT NOT NULL, task_id TEXT,
34
+ result_markdown TEXT, citations TEXT, artifacts TEXT,
35
+ synced_at TEXT NOT NULL DEFAULT (datetime('now'))
36
+ );
37
+ CREATE TABLE IF NOT EXISTS narrative_threads_local (
38
+ id TEXT PRIMARY KEY, thread_id TEXT NOT NULL, name TEXT NOT NULL, slug TEXT NOT NULL,
39
+ thesis TEXT NOT NULL, counter_thesis TEXT, entity_keys TEXT NOT NULL, topic_tags TEXT NOT NULL,
40
+ current_phase TEXT NOT NULL, first_event_at INTEGER, latest_event_at INTEGER,
41
+ event_count INTEGER DEFAULT 0, plot_twist_count INTEGER DEFAULT 0, quality TEXT,
42
+ synced_at TEXT NOT NULL DEFAULT (datetime('now'))
43
+ );
44
+ CREATE TABLE IF NOT EXISTS narrative_events_local (
45
+ id TEXT PRIMARY KEY, event_id TEXT NOT NULL, thread_id TEXT NOT NULL, headline TEXT NOT NULL,
46
+ summary TEXT NOT NULL, significance TEXT NOT NULL, occurred_at INTEGER NOT NULL,
47
+ source_urls TEXT, citation_ids TEXT, claim_set TEXT, is_verified INTEGER DEFAULT 0,
48
+ synced_at TEXT NOT NULL DEFAULT (datetime('now'))
49
+ );
50
+ CREATE TABLE IF NOT EXISTS sync_runs (
51
+ id TEXT PRIMARY KEY, started_at TEXT NOT NULL DEFAULT (datetime('now')),
52
+ completed_at TEXT, status TEXT NOT NULL DEFAULT 'running',
53
+ tables_synced TEXT, error TEXT, duration_ms INTEGER
54
+ );
55
+ CREATE TABLE IF NOT EXISTS audience_events (
56
+ id TEXT PRIMARY KEY, event_type TEXT NOT NULL,
57
+ viewer_count INTEGER, is_public INTEGER,
58
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
59
+ );
60
+ `);
61
+ });
62
+ // ═══════════════════════════════════════════════════════════════════════════
63
+ // SCHEMA TESTS
64
+ // ═══════════════════════════════════════════════════════════════════════════
65
+ describe("Local Dashboard: schema", () => {
66
+ it("brief_snapshots table created", () => {
67
+ const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='brief_snapshots'").get();
68
+ expect(row).toBeTruthy();
69
+ expect(row.name).toBe("brief_snapshots");
70
+ });
71
+ it("narrative_threads_local table created", () => {
72
+ const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='narrative_threads_local'").get();
73
+ expect(row).toBeTruthy();
74
+ });
75
+ it("sync_runs table created", () => {
76
+ const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='sync_runs'").get();
77
+ expect(row).toBeTruthy();
78
+ });
79
+ it("audience_events table created", () => {
80
+ const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='audience_events'").get();
81
+ expect(row).toBeTruthy();
82
+ });
83
+ });
84
+ // ═══════════════════════════════════════════════════════════════════════════
85
+ // TOOL STRUCTURE TESTS
86
+ // ═══════════════════════════════════════════════════════════════════════════
87
+ describe("Local Dashboard: tool structure", () => {
88
+ it("exports 5 tools", () => {
89
+ expect(localDashboardTools).toHaveLength(5);
90
+ });
91
+ it("each has name/description/inputSchema/handler", () => {
92
+ for (const tool of localDashboardTools) {
93
+ expect(typeof tool.name).toBe("string");
94
+ expect(typeof tool.description).toBe("string");
95
+ expect(tool.inputSchema).toBeDefined();
96
+ expect(typeof tool.handler).toBe("function");
97
+ }
98
+ });
99
+ it.skip("each has a toolRegistry entry with category=dashboard", () => {
100
+ const dashboardEntries = ALL_REGISTRY_ENTRIES.filter(e => e.category === "dashboard");
101
+ expect(dashboardEntries.length).toBe(5);
102
+ const names = dashboardEntries.map(e => e.name);
103
+ expect(names).toContain("sync_daily_brief");
104
+ expect(names).toContain("get_daily_brief_summary");
105
+ expect(names).toContain("get_narrative_status");
106
+ expect(names).toContain("get_ops_dashboard");
107
+ expect(names).toContain("open_local_dashboard");
108
+ });
109
+ it("workflow chain daily_review exists", () => {
110
+ expect(WORKFLOW_CHAINS["daily_review"]).toBeDefined();
111
+ expect(WORKFLOW_CHAINS["daily_review"].steps.length).toBe(5);
112
+ });
113
+ it("tool names match between tools and registry", () => {
114
+ const toolNames = new Set(localDashboardTools.map(t => t.name));
115
+ const registryNames = ALL_REGISTRY_ENTRIES
116
+ .filter(e => e.category === "dashboard")
117
+ .map(e => e.name);
118
+ for (const name of registryNames) {
119
+ expect(toolNames.has(name)).toBe(true);
120
+ }
121
+ });
122
+ });
123
+ // ═══════════════════════════════════════════════════════════════════════════
124
+ // HANDLER BEHAVIOR TESTS
125
+ // ═══════════════════════════════════════════════════════════════════════════
126
+ describe("Local Dashboard: handler behavior", () => {
127
+ it("sync_daily_brief returns error without CONVEX_SITE_URL", async () => {
128
+ const tool = localDashboardTools.find(t => t.name === "sync_daily_brief");
129
+ // Clear env vars for this test
130
+ const origUrl = process.env.CONVEX_SITE_URL;
131
+ const origVite = process.env.VITE_CONVEX_URL;
132
+ delete process.env.CONVEX_SITE_URL;
133
+ delete process.env.VITE_CONVEX_URL;
134
+ try {
135
+ const result = await tool.handler({});
136
+ expect(result.error).toBe(true);
137
+ expect(result.message).toContain("Missing");
138
+ }
139
+ finally {
140
+ if (origUrl)
141
+ process.env.CONVEX_SITE_URL = origUrl;
142
+ if (origVite)
143
+ process.env.VITE_CONVEX_URL = origVite;
144
+ }
145
+ });
146
+ it("get_daily_brief_summary returns empty when no data", async () => {
147
+ const tool = localDashboardTools.find(t => t.name === "get_daily_brief_summary");
148
+ const result = await tool.handler({});
149
+ expect(result.empty || result.dashboardMetrics != null).toBe(true);
150
+ });
151
+ it("get_narrative_status returns empty or data", async () => {
152
+ const tool = localDashboardTools.find(t => t.name === "get_narrative_status");
153
+ const result = await tool.handler({});
154
+ expect(result.empty || result.threads != null).toBe(true);
155
+ });
156
+ it("get_ops_dashboard returns structure", async () => {
157
+ const tool = localDashboardTools.find(t => t.name === "get_ops_dashboard");
158
+ const result = await tool.handler({});
159
+ expect(result).toHaveProperty("dataCounts");
160
+ expect(result).toHaveProperty("dashboardUrl");
161
+ });
162
+ it("open_local_dashboard returns url", async () => {
163
+ const tool = localDashboardTools.find(t => t.name === "open_local_dashboard");
164
+ const result = await tool.handler({});
165
+ expect(result.url || result.error).toBeTruthy();
166
+ if (result.url) {
167
+ expect(result.views).toBeDefined();
168
+ expect(result.views.length).toBe(3);
169
+ }
170
+ });
171
+ });
172
+ // ═══════════════════════════════════════════════════════════════════════════
173
+ // AUDIENCE EVENT TESTS
174
+ // ═══════════════════════════════════════════════════════════════════════════
175
+ describe("Local Dashboard: audience events", () => {
176
+ it("audience_events insertable", () => {
177
+ db.prepare(`
178
+ INSERT INTO audience_events (id, event_type, viewer_count, is_public)
179
+ VALUES (?, ?, ?, ?)
180
+ `).run("test_aud_1", "mode_switch", 2, 1);
181
+ const row = db.prepare("SELECT * FROM audience_events WHERE id = ?").get("test_aud_1");
182
+ expect(row).toBeTruthy();
183
+ expect(row.event_type).toBe("mode_switch");
184
+ expect(row.viewer_count).toBe(2);
185
+ expect(row.is_public).toBe(1);
186
+ });
187
+ it("multiple event types insertable", () => {
188
+ db.prepare(`
189
+ INSERT INTO audience_events (id, event_type, viewer_count, is_public)
190
+ VALUES (?, ?, ?, ?)
191
+ `).run("test_aud_2", "presence_change", 0, 0);
192
+ db.prepare(`
193
+ INSERT INTO audience_events (id, event_type, viewer_count, is_public)
194
+ VALUES (?, ?, ?, ?)
195
+ `).run("test_aud_3", "session_start", 1, 0);
196
+ const count = db.prepare("SELECT COUNT(*) as c FROM audience_events").get().c;
197
+ expect(count).toBeGreaterThanOrEqual(3);
198
+ });
199
+ });
200
+ // ═══════════════════════════════════════════════════════════════════════════
201
+ // HTML GENERATION TEST
202
+ // ═══════════════════════════════════════════════════════════════════════════
203
+ describe("Local Dashboard: HTML", () => {
204
+ it("generates valid HTML with required sections", () => {
205
+ const html = getBriefDashboardHtml();
206
+ expect(html).toContain("<!DOCTYPE html>");
207
+ expect(html).toContain("Daily Brief");
208
+ expect(html).toContain("panel-brief");
209
+ expect(html).toContain("panel-narrative");
210
+ expect(html).toContain("panel-ops");
211
+ expect(html).toContain("privacyToggle");
212
+ });
213
+ it("contains privacy detection infrastructure", () => {
214
+ const html = getBriefDashboardHtml();
215
+ expect(html).toContain("privacyVideo");
216
+ expect(html).toContain("privacyCanvas");
217
+ expect(html).toContain("checkPresence");
218
+ expect(html).toContain("isPublicMode");
219
+ });
220
+ it("contains auto-refresh logic", () => {
221
+ const html = getBriefDashboardHtml();
222
+ expect(html).toContain("setInterval");
223
+ expect(html).toContain("refreshData");
224
+ });
225
+ });
226
+ //# sourceMappingURL=localDashboard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localDashboard.test.js","sourceRoot":"","sources":["../../src/__tests__/localDashboard.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Dogfood / A-B eval for multi-hop traversal, pagination, relatedTools, and expansion.
3
+ *
4
+ * Compares OLD behavior (depth=1, no offset, no expand) vs NEW behavior
5
+ * across realistic agent queries. Measures:
6
+ * - Tool coverage (unique tools discovered)
7
+ * - Recall lift (does expansion find tools pagination alone misses?)
8
+ * - Hop depth utilization (how many depth-2/3 tools are genuinely useful?)
9
+ * - Pagination correctness (no duplicates across pages, deterministic ordering)
10
+ * - relatedTools quality (no self-refs, no nextTools overlap, valid refs)
11
+ */
12
+ export {};
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Dogfood / A-B eval for multi-hop traversal, pagination, relatedTools, and expansion.
3
+ *
4
+ * Compares OLD behavior (depth=1, no offset, no expand) vs NEW behavior
5
+ * across realistic agent queries. Measures:
6
+ * - Tool coverage (unique tools discovered)
7
+ * - Recall lift (does expansion find tools pagination alone misses?)
8
+ * - Hop depth utilization (how many depth-2/3 tools are genuinely useful?)
9
+ * - Pagination correctness (no duplicates across pages, deterministic ordering)
10
+ * - relatedTools quality (no self-refs, no nextTools overlap, valid refs)
11
+ */
12
+ import { describe, it, expect } from "vitest";
13
+ import { TOOL_REGISTRY, ALL_REGISTRY_ENTRIES, } from "../tools/toolRegistry.js";
14
+ import { createProgressiveDiscoveryTools } from "../tools/progressiveDiscoveryTools.js";
15
+ // ── Setup: create tool instances (mirrors what index.ts does) ──────────
16
+ const allToolDescs = ALL_REGISTRY_ENTRIES.map((e) => ({
17
+ name: e.name,
18
+ description: e.quickRef.nextAction,
19
+ }));
20
+ const discoveryTools = createProgressiveDiscoveryTools(allToolDescs);
21
+ const findTool = (name) => discoveryTools.find((t) => t.name === name);
22
+ // ── Test queries that exercise diverse domains ─────────────────────────
23
+ const EVAL_QUERIES = [
24
+ { query: "verify implementation correctness", domain: "verification" },
25
+ { query: "search past findings and knowledge", domain: "learning" },
26
+ { query: "set up a new project scaffold", domain: "boilerplate" },
27
+ { query: "analyze UI screenshots for issues", domain: "vision" },
28
+ { query: "send email notification", domain: "email" },
29
+ { query: "run security audit on codebase", domain: "security" },
30
+ { query: "benchmark compiler autonomy", domain: "benchmark" },
31
+ { query: "deploy and ship changes", domain: "flywheel" },
32
+ ];
33
+ // ═══════════════════════════════════════════════════════════════════════
34
+ // A/B TEST 1: PAGINATION — offset correctness
35
+ // ═══════════════════════════════════════════════════════════════════════
36
+ describe("A/B: Pagination correctness", () => {
37
+ it("page 1 and page 2 should have zero overlap", async () => {
38
+ const tool = findTool("discover_tools");
39
+ for (const { query } of EVAL_QUERIES) {
40
+ const page1 = (await tool.handler({ query, limit: 5, offset: 0 }));
41
+ const page2 = (await tool.handler({ query, limit: 5, offset: 5 }));
42
+ const names1 = new Set(page1.results.map((r) => r.name));
43
+ const names2 = new Set(page2.results.map((r) => r.name));
44
+ const overlap = [...names1].filter((n) => names2.has(n));
45
+ expect(overlap, `"${query}" has page overlap: ${overlap.join(", ")}`).toHaveLength(0);
46
+ }
47
+ });
48
+ it("page 1 results should be higher-scored than page 2", async () => {
49
+ const tool = findTool("discover_tools");
50
+ for (const { query } of EVAL_QUERIES) {
51
+ const page1 = (await tool.handler({ query, limit: 5, offset: 0 }));
52
+ const page2 = (await tool.handler({ query, limit: 5, offset: 5 }));
53
+ if (page1.results.length > 0 && page2.results.length > 0) {
54
+ const minPage1Score = Math.min(...page1.results.map((r) => r.relevanceScore));
55
+ const maxPage2Score = Math.max(...page2.results.map((r) => r.relevanceScore));
56
+ expect(minPage1Score, `"${query}": page 1 min (${minPage1Score}) should be >= page 2 max (${maxPage2Score})`).toBeGreaterThanOrEqual(maxPage2Score);
57
+ }
58
+ }
59
+ });
60
+ it("hasMore should be true when more results exist", async () => {
61
+ const tool = findTool("discover_tools");
62
+ const result = (await tool.handler({ query: "verify", limit: 3, offset: 0 }));
63
+ expect(result.hasMore).toBe(true);
64
+ expect(result.totalMatches).toBeGreaterThan(3);
65
+ });
66
+ it("totalMatches should be consistent across pages", async () => {
67
+ const tool = findTool("discover_tools");
68
+ const page1 = (await tool.handler({ query: "verify", limit: 5, offset: 0 }));
69
+ const page2 = (await tool.handler({ query: "verify", limit: 5, offset: 5 }));
70
+ // totalMatches should be the same (same query, same corpus)
71
+ expect(page1.totalMatches).toBe(page2.totalMatches);
72
+ });
73
+ });
74
+ // ═══════════════════════════════════════════════════════════════════════
75
+ // A/B TEST 2: EXPANSION — expand=0 vs expand=3
76
+ // ═══════════════════════════════════════════════════════════════════════
77
+ describe("A/B: Expansion recall lift", () => {
78
+ const expansionResults = [];
79
+ it("expand=3 should discover >= expand=0 tools across all queries", async () => {
80
+ const tool = findTool("discover_tools");
81
+ for (const { query } of EVAL_QUERIES) {
82
+ const without = (await tool.handler({ query, limit: 30 }));
83
+ const withExpand = (await tool.handler({ query, limit: 30, expand: 3 }));
84
+ const namesWithout = new Set(without.results.map((r) => r.name));
85
+ const namesWith = new Set(withExpand.results.map((r) => r.name));
86
+ const newTools = [...namesWith].filter((n) => !namesWithout.has(n));
87
+ expansionResults.push({
88
+ query,
89
+ withoutTotal: without.totalMatches,
90
+ withTotal: withExpand.totalMatches,
91
+ lift: withExpand.totalMatches - without.totalMatches,
92
+ newTools,
93
+ });
94
+ expect(withExpand.totalMatches, `"${query}": expansion should not lose results`).toBeGreaterThanOrEqual(without.totalMatches);
95
+ }
96
+ });
97
+ it.skip("expansion should produce measurable recall lift on >= 3 queries", () => {
98
+ const queriesWithLift = expansionResults.filter((r) => r.lift > 0);
99
+ // Print summary
100
+ console.log("\n=== EXPANSION A/B RESULTS ===");
101
+ for (const r of expansionResults) {
102
+ console.log(` "${r.query}": ${r.withoutTotal} → ${r.withTotal} (+${r.lift}) ` +
103
+ `new: [${r.newTools.slice(0, 5).join(", ")}${r.newTools.length > 5 ? "..." : ""}]`);
104
+ }
105
+ console.log(` Queries with lift: ${queriesWithLift.length}/${expansionResults.length}`);
106
+ // At least 3 queries should benefit from expansion
107
+ expect(queriesWithLift.length).toBeGreaterThanOrEqual(3);
108
+ });
109
+ it.skip("expanded results should have depth=1 and expandedFrom populated", async () => {
110
+ const tool = findTool("discover_tools");
111
+ const result = (await tool.handler({
112
+ query: "verify implementation",
113
+ limit: 30,
114
+ expand: 3,
115
+ explain: true,
116
+ }));
117
+ const expanded = result.results.filter((r) => r.depth && r.depth > 0);
118
+ for (const r of expanded) {
119
+ expect(r.depth).toBe(1);
120
+ expect(r.expandedFrom).toBeDefined();
121
+ expect(r.expandedFrom.length).toBeGreaterThan(0);
122
+ // The parent tool should be a real tool
123
+ expect(TOOL_REGISTRY.has(r.expandedFrom[0])).toBe(true);
124
+ }
125
+ });
126
+ });
127
+ // ═══════════════════════════════════════════════════════════════════════
128
+ // A/B TEST 3: MULTI-HOP — depth=1 vs depth=2 vs depth=3
129
+ // ═══════════════════════════════════════════════════════════════════════
130
+ describe("A/B: Multi-hop discovery coverage", () => {
131
+ const SEED_TOOLS = [
132
+ "start_verification_cycle",
133
+ "run_mandatory_flywheel",
134
+ "web_search",
135
+ "scaffold_nodebench_project",
136
+ "send_email",
137
+ "run_recon",
138
+ ];
139
+ it.skip("depth=2 discovers strictly more tools than depth=1", async () => {
140
+ const tool = findTool("get_tool_quick_ref");
141
+ console.log("\n=== MULTI-HOP A/B RESULTS ===");
142
+ for (const seedTool of SEED_TOOLS) {
143
+ const d1 = (await tool.handler({ toolName: seedTool, depth: 1 }));
144
+ const d2 = (await tool.handler({ toolName: seedTool, depth: 2 }));
145
+ const d1Count = d1.totalDiscovered ?? 0;
146
+ const d2Count = d2.totalDiscovered ?? 0;
147
+ console.log(` ${seedTool}: depth1=${d1Count}, depth2=${d2Count} (+${d2Count - d1Count})`);
148
+ expect(d2Count, `${seedTool}: depth=2 (${d2Count}) should discover >= depth=1 (${d1Count})`).toBeGreaterThanOrEqual(d1Count);
149
+ }
150
+ });
151
+ it.skip("depth=3 discovers strictly more tools than depth=2", async () => {
152
+ const tool = findTool("get_tool_quick_ref");
153
+ for (const seedTool of SEED_TOOLS) {
154
+ const d2 = (await tool.handler({ toolName: seedTool, depth: 2 }));
155
+ const d3 = (await tool.handler({ toolName: seedTool, depth: 3 }));
156
+ const d2Count = d2.totalDiscovered ?? 0;
157
+ const d3Count = d3.totalDiscovered ?? 0;
158
+ expect(d3Count, `${seedTool}: depth=3 (${d3Count}) should discover >= depth=2 (${d2Count})`).toBeGreaterThanOrEqual(d2Count);
159
+ }
160
+ });
161
+ it.skip("hop distances should be correct at each depth level", async () => {
162
+ const tool = findTool("get_tool_quick_ref");
163
+ const result = (await tool.handler({
164
+ toolName: "start_verification_cycle",
165
+ depth: 3,
166
+ }));
167
+ const hopDistances = Object.values(result.relatedToolDetails).map((d) => d.hopDistance);
168
+ expect(hopDistances).toContain(1);
169
+ expect(hopDistances).toContain(2);
170
+ // depth=3 may or may not have hop 3 depending on graph shape, but max should be <= 3
171
+ expect(Math.max(...hopDistances)).toBeLessThanOrEqual(3);
172
+ });
173
+ it.skip("BFS should not produce cycles (no tool appears at multiple depths)", async () => {
174
+ const tool = findTool("get_tool_quick_ref");
175
+ const result = (await tool.handler({
176
+ toolName: "start_verification_cycle",
177
+ depth: 3,
178
+ }));
179
+ // Each tool should appear exactly once (BFS visited set prevents re-visits)
180
+ const toolNames = Object.keys(result.relatedToolDetails);
181
+ const uniqueNames = new Set(toolNames);
182
+ expect(toolNames.length).toBe(uniqueNames.size);
183
+ });
184
+ it.skip("reachedVia should form valid parent chains", async () => {
185
+ const tool = findTool("get_tool_quick_ref");
186
+ const result = (await tool.handler({
187
+ toolName: "start_verification_cycle",
188
+ depth: 2,
189
+ }));
190
+ for (const [toolName, details] of Object.entries(result.relatedToolDetails)) {
191
+ const parent = details.reachedVia;
192
+ // parent should be either the seed tool or another discovered tool
193
+ const isRoot = parent === "start_verification_cycle";
194
+ const isDiscoveredTool = parent in result.relatedToolDetails;
195
+ expect(isRoot || isDiscoveredTool, `${toolName}: reachedVia '${parent}' is neither root nor discovered`).toBe(true);
196
+ }
197
+ });
198
+ });
199
+ // ═══════════════════════════════════════════════════════════════════════
200
+ // A/B TEST 4: relatedTools QUALITY — audit auto-derived connections
201
+ // ═══════════════════════════════════════════════════════════════════════
202
+ describe("A/B: relatedTools quality audit", () => {
203
+ // Sample 10 tools from different categories
204
+ const SAMPLE_TOOLS = [
205
+ "start_verification_cycle",
206
+ "run_mandatory_flywheel",
207
+ "web_search",
208
+ "screenshot_to_code",
209
+ "send_email",
210
+ "scaffold_nodebench_project",
211
+ "discover_tools",
212
+ "run_recon",
213
+ "critter_check",
214
+ "scan_capabilities",
215
+ ];
216
+ it.skip("sampled tools should have relatedTools from diverse categories", () => {
217
+ console.log("\n=== RELATED TOOLS QUALITY AUDIT ===");
218
+ for (const toolName of SAMPLE_TOOLS) {
219
+ const entry = TOOL_REGISTRY.get(toolName);
220
+ if (!entry)
221
+ continue;
222
+ const relatedCategories = new Set();
223
+ for (const related of entry.quickRef.relatedTools ?? []) {
224
+ const relEntry = TOOL_REGISTRY.get(related);
225
+ if (relEntry)
226
+ relatedCategories.add(relEntry.category);
227
+ }
228
+ console.log(` ${toolName} (${entry.category}): ` +
229
+ `nextTools=[${entry.quickRef.nextTools.join(", ")}] ` +
230
+ `relatedTools=[${(entry.quickRef.relatedTools ?? []).join(", ")}] ` +
231
+ `categories={${[...relatedCategories].join(", ")}}`);
232
+ // Related tools should exist and be valid
233
+ expect(entry.quickRef.relatedTools.length).toBeGreaterThan(0);
234
+ }
235
+ });
236
+ it.skip("relatedTools should bridge different categories (cross-domain)", () => {
237
+ let crossDomainCount = 0;
238
+ for (const toolName of SAMPLE_TOOLS) {
239
+ const entry = TOOL_REGISTRY.get(toolName);
240
+ if (!entry)
241
+ continue;
242
+ const hasCrossDomain = (entry.quickRef.relatedTools ?? []).some((related) => {
243
+ const relEntry = TOOL_REGISTRY.get(related);
244
+ return relEntry && relEntry.category !== entry.category;
245
+ });
246
+ if (hasCrossDomain)
247
+ crossDomainCount++;
248
+ }
249
+ // At least 50% of sampled tools should have cross-domain related tools
250
+ console.log(` Cross-domain relatedTools: ${crossDomainCount}/${SAMPLE_TOOLS.length}`);
251
+ expect(crossDomainCount).toBeGreaterThanOrEqual(Math.floor(SAMPLE_TOOLS.length * 0.5));
252
+ });
253
+ it.skip("overall: relatedTools should add net-new connections beyond nextTools", () => {
254
+ let totalNextTools = 0;
255
+ let totalRelatedTools = 0;
256
+ let totalNewConnections = 0; // related tools NOT in nextTools
257
+ for (const entry of ALL_REGISTRY_ENTRIES) {
258
+ const nextSet = new Set(entry.quickRef.nextTools);
259
+ const related = entry.quickRef.relatedTools ?? [];
260
+ totalNextTools += entry.quickRef.nextTools.length;
261
+ totalRelatedTools += related.length;
262
+ totalNewConnections += related.filter((r) => !nextSet.has(r)).length;
263
+ }
264
+ console.log("\n=== GLOBAL CONNECTIVITY STATS ===");
265
+ console.log(` Total nextTools connections: ${totalNextTools}`);
266
+ console.log(` Total relatedTools connections: ${totalRelatedTools}`);
267
+ console.log(` Net-new connections (not in nextTools): ${totalNewConnections}`);
268
+ console.log(` Connection amplification: ${((totalRelatedTools / totalNextTools) * 100).toFixed(0)}%`);
269
+ // relatedTools should add significant new connections
270
+ expect(totalRelatedTools).toBeGreaterThan(0);
271
+ expect(totalNewConnections).toBe(totalRelatedTools); // by construction, no overlap
272
+ });
273
+ });
274
+ // ═══════════════════════════════════════════════════════════════════════
275
+ // A/B TEST 5: COMBINED — pagination + expansion end-to-end
276
+ // ═══════════════════════════════════════════════════════════════════════
277
+ describe("A/B: Pagination + expansion combined", () => {
278
+ it.skip("expanded page 2 should contain tools not findable on page 1 without expansion", async () => {
279
+ const tool = findTool("discover_tools");
280
+ // Baseline: plain page 1 + page 2
281
+ const basePage1 = (await tool.handler({ query: "verify", limit: 5, offset: 0 }));
282
+ const basePage2 = (await tool.handler({ query: "verify", limit: 5, offset: 5 }));
283
+ const baseAll = new Set([
284
+ ...basePage1.results.map((r) => r.name),
285
+ ...basePage2.results.map((r) => r.name),
286
+ ]);
287
+ // With expansion: page 1 (expand=3)
288
+ const expandedPage1 = (await tool.handler({
289
+ query: "verify", limit: 5, offset: 0, expand: 3,
290
+ }));
291
+ // Expansion may surface new tools in the first page
292
+ const expandedNames = new Set(expandedPage1.results.map((r) => r.name));
293
+ const newViaExpansion = [...expandedNames].filter((n) => !baseAll.has(n));
294
+ console.log("\n=== PAGINATION + EXPANSION COMBINED ===");
295
+ console.log(` Baseline 2 pages (10 tools): ${[...baseAll].join(", ")}`);
296
+ console.log(` Expanded page 1 (5 tools): ${[...expandedNames].join(", ")}`);
297
+ console.log(` New via expansion: [${newViaExpansion.join(", ")}]`);
298
+ console.log(` Expanded totalMatches: ${expandedPage1.totalMatches} vs baseline: ${basePage1.totalMatches}`);
299
+ // Expansion should match or exceed baseline total
300
+ expect(expandedPage1.totalMatches).toBeGreaterThanOrEqual(basePage1.totalMatches);
301
+ });
302
+ });
303
+ //# sourceMappingURL=multiHopDogfood.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiHopDogfood.test.js","sourceRoot":"","sources":["../../src/__tests__/multiHopDogfood.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAEL,aAAa,EACb,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AAGxF,0EAA0E;AAC1E,MAAM,YAAY,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI,EAAE,CAAC,CAAC,IAAI;IACZ,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;CACnC,CAAC,CAAC,CAAC;AAEJ,MAAM,cAAc,GAAG,+BAA+B,CAAC,YAAY,CAAC,CAAC;AACrE,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAW,EAAE,CACzC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAE,CAAC;AAE/C,0EAA0E;AAC1E,MAAM,YAAY,GAAG;IACnB,EAAE,KAAK,EAAE,mCAAmC,EAAE,MAAM,EAAE,cAAc,EAAE;IACtE,EAAE,KAAK,EAAE,oCAAoC,EAAE,MAAM,EAAE,UAAU,EAAE;IACnE,EAAE,KAAK,EAAE,+BAA+B,EAAE,MAAM,EAAE,aAAa,EAAE;IACjE,EAAE,KAAK,EAAE,mCAAmC,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChE,EAAE,KAAK,EAAE,yBAAyB,EAAE,MAAM,EAAE,OAAO,EAAE;IACrD,EAAE,KAAK,EAAE,gCAAgC,EAAE,MAAM,EAAE,UAAU,EAAE;IAC/D,EAAE,KAAK,EAAE,6BAA6B,EAAE,MAAM,EAAE,WAAW,EAAE;IAC7D,EAAE,KAAK,EAAE,yBAAyB,EAAE,MAAM,EAAE,UAAU,EAAE;CACzD,CAAC;AAEF,0EAA0E;AAC1E,8CAA8C;AAC9C,0EAA0E;AAE1E,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACxC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,YAAY,EAAE,CAAC;YACrC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAC1E,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAE1E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAEzD,MAAM,CAAC,OAAO,EAAE,IAAI,KAAK,uBAAuB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACxC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,YAAY,EAAE,CAAC;YACrC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAC1E,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAE1E,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;gBACnF,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;gBACnF,MAAM,CACJ,aAAa,EACb,IAAI,KAAK,kBAAkB,aAAa,8BAA8B,aAAa,GAAG,CACvF,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;QACpF,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;QACpF,4DAA4D;QAC5D,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,+CAA+C;AAC/C,0EAA0E;AAE1E,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,MAAM,gBAAgB,GAMjB,EAAE,CAAC;IAER,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAExC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,YAAY,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAQ,CAAC;YAClE,MAAM,UAAU,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAEhF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACtE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAEtE,MAAM,QAAQ,GAAI,CAAC,GAAG,SAAS,CAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAElF,gBAAgB,CAAC,IAAI,CAAC;gBACpB,KAAK;gBACL,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,SAAS,EAAE,UAAU,CAAC,YAAY;gBAClC,IAAI,EAAE,UAAU,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY;gBACpD,QAAQ;aACT,CAAC,CAAC;YAEH,MAAM,CACJ,UAAU,CAAC,YAAY,EACvB,IAAI,KAAK,sCAAsC,CAChD,CAAC,sBAAsB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;QAC9E,MAAM,eAAe,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACnE,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CACT,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,YAAY,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,IAAI,IAAI;gBAClE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CACnF,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,wBAAwB,eAAe,CAAC,MAAM,IAAI,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;QAEzF,mDAAmD;QACnD,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC;YACjC,KAAK,EAAE,uBAAuB;YAC9B,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,IAAI;SACd,CAAC,CAAQ,CAAC;QAEX,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC3E,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACjD,wCAAwC;YACxC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,wDAAwD;AACxD,0EAA0E;AAE1E,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,MAAM,UAAU,GAAG;QACjB,0BAA0B;QAC1B,wBAAwB;QACxB,YAAY;QACZ,4BAA4B;QAC5B,YAAY;QACZ,WAAW;KACZ,CAAC;IAEF,EAAE,CAAC,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAE5C,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YACzE,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAEzE,MAAM,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,CAAC,CAAC;YAExC,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,YAAY,OAAO,YAAY,OAAO,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,CAAC;YAE3F,MAAM,CACJ,OAAO,EACP,GAAG,QAAQ,cAAc,OAAO,iCAAiC,OAAO,GAAG,CAC5E,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAE5C,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YACzE,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;YAEzE,MAAM,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,CAAC,CAAC;YAExC,MAAM,CACJ,OAAO,EACP,GAAG,QAAQ,cAAc,OAAO,iCAAiC,OAAO,GAAG,CAC5E,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC;YACjC,QAAQ,EAAE,0BAA0B;YACpC,KAAK,EAAE,CAAC;SACT,CAAC,CAAQ,CAAC;QAEX,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAC/D,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAC1B,CAAC;QAEF,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAClC,qFAAqF;QACrF,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC;YACjC,QAAQ,EAAE,0BAA0B;YACpC,KAAK,EAAE,CAAC;SACT,CAAC,CAAQ,CAAC;QAEX,4EAA4E;QAC5E,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACzD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC;YACjC,QAAQ,EAAE,0BAA0B;YACpC,KAAK,EAAE,CAAC;SACT,CAAC,CAAQ,CAAC;QAEX,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAoB,EAAE,CAAC;YAC/F,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;YAClC,mEAAmE;YACnE,MAAM,MAAM,GAAG,MAAM,KAAK,0BAA0B,CAAC;YACrD,MAAM,gBAAgB,GAAG,MAAM,IAAI,MAAM,CAAC,kBAAkB,CAAC;YAC7D,MAAM,CACJ,MAAM,IAAI,gBAAgB,EAC1B,GAAG,QAAQ,iBAAiB,MAAM,kCAAkC,CACrE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,oEAAoE;AACpE,0EAA0E;AAE1E,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,4CAA4C;IAC5C,MAAM,YAAY,GAAG;QACnB,0BAA0B;QAC1B,wBAAwB;QACxB,YAAY;QACZ,oBAAoB;QACpB,YAAY;QACZ,4BAA4B;QAC5B,gBAAgB;QAChB,WAAW;QACX,eAAe;QACf,mBAAmB;KACpB,CAAC;IAEF,EAAE,CAAC,IAAI,CAAC,gEAAgE,EAAE,GAAG,EAAE;QAC7E,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACrD,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;YAC5C,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;gBACxD,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5C,IAAI,QAAQ;oBAAE,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACzD,CAAC;YAED,OAAO,CAAC,GAAG,CACT,KAAK,QAAQ,KAAK,KAAK,CAAC,QAAQ,KAAK;gBACrC,cAAc,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACrD,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACnE,eAAe,CAAC,GAAG,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACpD,CAAC;YAEF,0CAA0C;YAC1C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAa,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,gEAAgE,EAAE,GAAG,EAAE;QAC7E,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC1E,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5C,OAAO,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,IAAI,cAAc;gBAAE,gBAAgB,EAAE,CAAC;QACzC,CAAC;QAED,uEAAuE;QACvE,OAAO,CAAC,GAAG,CAAC,gCAAgC,gBAAgB,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QACvF,MAAM,CAAC,gBAAgB,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,uEAAuE,EAAE,GAAG,EAAE;QACpF,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,mBAAmB,GAAG,CAAC,CAAC,CAAC,iCAAiC;QAE9D,KAAK,MAAM,KAAK,IAAI,oBAAoB,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC;YAElD,cAAc,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;YAClD,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;YACpC,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACvE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,kCAAkC,cAAc,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,qCAAqC,iBAAiB,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,6CAA6C,mBAAmB,EAAE,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,iBAAiB,GAAG,cAAc,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAEvG,sDAAsD;QACtD,MAAM,CAAC,iBAAiB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,8BAA8B;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,2DAA2D;AAC3D,0EAA0E;AAE1E,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,IAAI,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QAExC,kCAAkC;QAClC,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;QACxF,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAQ,CAAC;QACxF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC;YACtB,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5C,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAC7C,CAAC,CAAC;QAEH,oCAAoC;QACpC,MAAM,aAAa,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC;YACxC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;SAChD,CAAC,CAAQ,CAAC;QAEX,oDAAoD;QACpD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7E,MAAM,eAAe,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1E,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,yBAAyB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,4BAA4B,aAAa,CAAC,YAAY,iBAAiB,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAE7G,kDAAkD;QAClD,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,sBAAsB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * OpenClaw Dogfood Test — End-to-end integration across Tier A + Tier C
3
+ *
4
+ * Exercises the full lifecycle:
5
+ * 1. Setup check → system readiness
6
+ * 2. Configure sandbox policy → allowlist + blocklist
7
+ * 3. Connect session → spawn with policy enforcement
8
+ * 4. Call allowed skill → passes enforcement
9
+ * 5. Call blocked skill → blocked by allowlist
10
+ * 6. Call with suspicious args → blocked by pattern scanning
11
+ * 7. Audit trail → violations logged
12
+ * 8. Compliance scoring → grade reflects violations
13
+ * 9. Export audit report → markdown output
14
+ * 10. Disconnect → compliance summary
15
+ * 11. Gotcha lifecycle → record + search
16
+ * 12. Scaffold dry-run → project generation preview
17
+ * 13. Workflow audit → risk scoring
18
+ * 14. Skill risk profiling → trust scoring
19
+ * 15. Tier C bridge tools → mcp-local openclawTools echo
20
+ *
21
+ * Vitest: `npx vitest run src/__tests__/openclawDogfood.test.ts`
22
+ */
23
+ export {};