cipher-security 2.0.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 (76) hide show
  1. package/bin/cipher.js +566 -0
  2. package/lib/api/billing.js +321 -0
  3. package/lib/api/compliance.js +693 -0
  4. package/lib/api/controls.js +1401 -0
  5. package/lib/api/index.js +49 -0
  6. package/lib/api/marketplace.js +467 -0
  7. package/lib/api/openai-proxy.js +383 -0
  8. package/lib/api/server.js +685 -0
  9. package/lib/autonomous/feedback-loop.js +554 -0
  10. package/lib/autonomous/framework.js +512 -0
  11. package/lib/autonomous/index.js +97 -0
  12. package/lib/autonomous/leaderboard.js +594 -0
  13. package/lib/autonomous/modes/architect.js +412 -0
  14. package/lib/autonomous/modes/blue.js +386 -0
  15. package/lib/autonomous/modes/incident.js +684 -0
  16. package/lib/autonomous/modes/privacy.js +369 -0
  17. package/lib/autonomous/modes/purple.js +294 -0
  18. package/lib/autonomous/modes/recon.js +250 -0
  19. package/lib/autonomous/parallel.js +587 -0
  20. package/lib/autonomous/researcher.js +583 -0
  21. package/lib/autonomous/runner.js +955 -0
  22. package/lib/autonomous/scheduler.js +615 -0
  23. package/lib/autonomous/task-parser.js +127 -0
  24. package/lib/autonomous/validators/forensic.js +266 -0
  25. package/lib/autonomous/validators/osint.js +216 -0
  26. package/lib/autonomous/validators/privacy.js +296 -0
  27. package/lib/autonomous/validators/purple.js +298 -0
  28. package/lib/autonomous/validators/sigma.js +248 -0
  29. package/lib/autonomous/validators/threat-model.js +363 -0
  30. package/lib/benchmark/agent.js +119 -0
  31. package/lib/benchmark/baselines.js +43 -0
  32. package/lib/benchmark/builder.js +143 -0
  33. package/lib/benchmark/config.js +35 -0
  34. package/lib/benchmark/coordinator.js +91 -0
  35. package/lib/benchmark/index.js +20 -0
  36. package/lib/benchmark/llm.js +58 -0
  37. package/lib/benchmark/models.js +137 -0
  38. package/lib/benchmark/reporter.js +103 -0
  39. package/lib/benchmark/runner.js +103 -0
  40. package/lib/benchmark/sandbox.js +96 -0
  41. package/lib/benchmark/scorer.js +32 -0
  42. package/lib/benchmark/solver.js +166 -0
  43. package/lib/benchmark/tools.js +62 -0
  44. package/lib/bot/bot.js +238 -0
  45. package/lib/brand.js +105 -0
  46. package/lib/commands.js +100 -0
  47. package/lib/complexity.js +377 -0
  48. package/lib/config.js +213 -0
  49. package/lib/gateway/client.js +309 -0
  50. package/lib/gateway/commands.js +991 -0
  51. package/lib/gateway/config-validate.js +109 -0
  52. package/lib/gateway/gateway.js +367 -0
  53. package/lib/gateway/index.js +62 -0
  54. package/lib/gateway/mode.js +309 -0
  55. package/lib/gateway/plugins.js +222 -0
  56. package/lib/gateway/prompt.js +214 -0
  57. package/lib/mcp/server.js +262 -0
  58. package/lib/memory/compressor.js +425 -0
  59. package/lib/memory/engine.js +763 -0
  60. package/lib/memory/evolution.js +668 -0
  61. package/lib/memory/index.js +58 -0
  62. package/lib/memory/orchestrator.js +506 -0
  63. package/lib/memory/retriever.js +515 -0
  64. package/lib/memory/synthesizer.js +333 -0
  65. package/lib/pipeline/async-scanner.js +510 -0
  66. package/lib/pipeline/binary-analysis.js +1043 -0
  67. package/lib/pipeline/dom-xss-scanner.js +435 -0
  68. package/lib/pipeline/github-actions.js +792 -0
  69. package/lib/pipeline/index.js +124 -0
  70. package/lib/pipeline/osint.js +498 -0
  71. package/lib/pipeline/sarif.js +373 -0
  72. package/lib/pipeline/scanner.js +880 -0
  73. package/lib/pipeline/template-manager.js +525 -0
  74. package/lib/pipeline/xss-scanner.js +353 -0
  75. package/lib/setup-wizard.js +288 -0
  76. package/package.json +31 -0
@@ -0,0 +1,512 @@
1
+ // Copyright (c) 2026 defconxt. All rights reserved.
2
+ // Licensed under AGPL-3.0 — see LICENSE file for details.
3
+ // CIPHER is a trademark of defconxt.
4
+
5
+ /**
6
+ * framework.js — Mode-agnostic agent framework for CIPHER autonomous operations.
7
+ *
8
+ * Ported from autonomous/framework.py. Foundation types for the multi-mode agent system:
9
+ * - truncateOutput: standalone output truncation utility
10
+ * - ValidationResult: output validation with errors, warnings, and scoring
11
+ * - ModeAgentResult: structured result from agent execution
12
+ * - ToolRegistry: register and dispatch tools with flexible context
13
+ * - NullValidator: pass-through validator for modes without validation
14
+ * - ModeAgentConfig: configuration for a mode-specific agent
15
+ * - BaseAgent: generalized tool-use loop (extracted from SecurityAgent)
16
+ *
17
+ * All exports are named ESM exports. All imports lazy where needed.
18
+ *
19
+ * @module autonomous/framework
20
+ */
21
+
22
+ const debug = process.env.CIPHER_DEBUG === '1'
23
+ ? (/** @type {string} */ msg) => process.stderr.write(`[autonomous] ${msg}\n`)
24
+ : () => {};
25
+
26
+ // Maximum tool output length to prevent context window bloat
27
+ const MAX_OUTPUT_CHARS = 4000;
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Standalone utilities
31
+ // ---------------------------------------------------------------------------
32
+
33
+ /**
34
+ * Truncate tool output to prevent context window bloat.
35
+ *
36
+ * @param {string} output
37
+ * @param {number} [maxChars=4000]
38
+ * @returns {string}
39
+ */
40
+ export function truncateOutput(output, maxChars = MAX_OUTPUT_CHARS) {
41
+ if (output.length <= maxChars) return output;
42
+ return output.slice(0, maxChars) + `\n... [truncated, ${output.length} chars total]`;
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Result classes
47
+ // ---------------------------------------------------------------------------
48
+
49
+ /**
50
+ * Outcome of validating a mode agent's result.
51
+ */
52
+ export class ValidationResult {
53
+ /**
54
+ * @param {Object} opts
55
+ * @param {boolean} opts.valid
56
+ * @param {string[]} opts.errors
57
+ * @param {string[]} opts.warnings
58
+ * @param {number} [opts.score=1.0]
59
+ * @param {Object} [opts.metadata={}]
60
+ */
61
+ constructor({ valid, errors, warnings, score = 1.0, metadata = {} }) {
62
+ this.valid = valid;
63
+ this.errors = errors;
64
+ this.warnings = warnings;
65
+ this.score = score;
66
+ this.metadata = metadata;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Structured result from a mode agent execution.
72
+ */
73
+ export class ModeAgentResult {
74
+ /**
75
+ * @param {Object} opts
76
+ * @param {string} opts.mode
77
+ * @param {Object} [opts.outputData={}]
78
+ * @param {string} [opts.outputText='']
79
+ * @param {string[]} [opts.steps=[]]
80
+ * @param {number} [opts.tokensIn=0]
81
+ * @param {number} [opts.tokensOut=0]
82
+ * @param {number} [opts.toolCalls=0]
83
+ * @param {number} [opts.turnsUsed=0]
84
+ * @param {ValidationResult|null} [opts.validation=null]
85
+ * @param {string|null} [opts.error=null]
86
+ * @param {number} [opts.durationS=0]
87
+ */
88
+ constructor({
89
+ mode,
90
+ outputData = {},
91
+ outputText = '',
92
+ steps = [],
93
+ tokensIn = 0,
94
+ tokensOut = 0,
95
+ toolCalls = 0,
96
+ turnsUsed = 0,
97
+ validation = null,
98
+ error = null,
99
+ durationS = 0,
100
+ }) {
101
+ this.mode = mode;
102
+ this.outputData = outputData;
103
+ this.outputText = outputText;
104
+ this.steps = steps;
105
+ this.tokensIn = tokensIn;
106
+ this.tokensOut = tokensOut;
107
+ this.toolCalls = toolCalls;
108
+ this.turnsUsed = turnsUsed;
109
+ this.validation = validation;
110
+ this.error = error;
111
+ this.durationS = durationS;
112
+ }
113
+ }
114
+
115
+ // ---------------------------------------------------------------------------
116
+ // ToolRegistry
117
+ // ---------------------------------------------------------------------------
118
+
119
+ /**
120
+ * Registry for tool schemas and dispatch handlers.
121
+ *
122
+ * Tools are registered with an Anthropic-format schema and a handler callable.
123
+ * The handler signature is (context, input) => string.
124
+ */
125
+ export class ToolRegistry {
126
+ constructor() {
127
+ /** @type {Array<Object>} */
128
+ this._schemas = [];
129
+ /** @type {Map<string, Function>} */
130
+ this._dispatch = new Map();
131
+ }
132
+
133
+ /**
134
+ * Register a tool with its schema and handler.
135
+ *
136
+ * @param {string} name - Unique tool name
137
+ * @param {Object} schema - Anthropic-format tool schema dict
138
+ * @param {Function} handler - (context, input) => string
139
+ * @throws {Error} If a tool with this name is already registered
140
+ */
141
+ register(name, schema, handler) {
142
+ if (this._dispatch.has(name)) {
143
+ const registered = [...this._dispatch.keys()].sort().join(', ');
144
+ throw new Error(
145
+ `Tool already registered: '${name}'. Registered tools: ${registered}`
146
+ );
147
+ }
148
+ this._schemas.push(schema);
149
+ this._dispatch.set(name, handler);
150
+ }
151
+
152
+ /**
153
+ * Return a copy of all registered tool schemas.
154
+ * @returns {Array<Object>}
155
+ */
156
+ getSchemas() {
157
+ return [...this._schemas];
158
+ }
159
+
160
+ /**
161
+ * Dispatch a tool call to its handler.
162
+ *
163
+ * @param {string} name - Tool name from the LLM's tool_use block
164
+ * @param {Object} toolInput - Tool input parameters from the LLM
165
+ * @param {*} [context=null] - Arbitrary context passed to the handler
166
+ * @returns {string} Tool output string, truncated to MAX_OUTPUT_CHARS
167
+ * @throws {Error} If tool name is not recognized
168
+ */
169
+ dispatch(name, toolInput, context = null) {
170
+ const handler = this._dispatch.get(name);
171
+ if (!handler) {
172
+ const available = [...this._dispatch.keys()].sort().join(', ');
173
+ throw new Error(`Unknown tool: '${name}'. Available: ${available}`);
174
+ }
175
+
176
+ let result;
177
+ try {
178
+ result = handler(context, toolInput);
179
+ } catch (e) {
180
+ result = `TOOL ERROR: ${e.constructor.name}: ${e.message}`;
181
+ }
182
+
183
+ return truncateOutput(String(result));
184
+ }
185
+
186
+ /**
187
+ * Check if a tool is registered.
188
+ * @param {string} name
189
+ * @returns {boolean}
190
+ */
191
+ hasTool(name) {
192
+ return this._dispatch.has(name);
193
+ }
194
+
195
+ /**
196
+ * Return list of registered tool names.
197
+ * @returns {string[]}
198
+ */
199
+ toolNames() {
200
+ return [...this._dispatch.keys()];
201
+ }
202
+ }
203
+
204
+ // ---------------------------------------------------------------------------
205
+ // Validator protocol (duck-type: any object with validate(result) method)
206
+ // NullValidator — pass-through validator
207
+ // ---------------------------------------------------------------------------
208
+
209
+ /**
210
+ * Pass-through validator that always returns valid.
211
+ * Used for modes that don't need output validation.
212
+ */
213
+ export class NullValidator {
214
+ /**
215
+ * @param {ModeAgentResult} _result
216
+ * @returns {ValidationResult}
217
+ */
218
+ validate(_result) {
219
+ return new ValidationResult({ valid: true, errors: [], warnings: [], score: 1.0 });
220
+ }
221
+ }
222
+
223
+ // ---------------------------------------------------------------------------
224
+ // Mode configuration
225
+ // ---------------------------------------------------------------------------
226
+
227
+ /**
228
+ * Configuration for a mode-specific agent.
229
+ */
230
+ export class ModeAgentConfig {
231
+ /**
232
+ * @param {Object} opts
233
+ * @param {string} opts.mode
234
+ * @param {ToolRegistry} opts.toolRegistry
235
+ * @param {string} opts.systemPromptTemplate
236
+ * @param {Object} opts.validator - Any object with validate(result) method
237
+ * @param {number} [opts.maxTurns=30]
238
+ * @param {number} [opts.maxTokensPerTurn=4096]
239
+ * @param {string} [opts.outputFormat='json']
240
+ * @param {boolean} [opts.requiresSandbox=false]
241
+ * @param {Function|null} [opts.completionCheck=null] - (text: string) => boolean
242
+ * @param {Function|null} [opts.outputParser=null] - (text: string) => Object
243
+ */
244
+ constructor({
245
+ mode,
246
+ toolRegistry,
247
+ systemPromptTemplate,
248
+ validator,
249
+ maxTurns = 30,
250
+ maxTokensPerTurn = 4096,
251
+ outputFormat = 'json',
252
+ requiresSandbox = false,
253
+ completionCheck = null,
254
+ outputParser = null,
255
+ }) {
256
+ this.mode = mode;
257
+ this.toolRegistry = toolRegistry;
258
+ this.systemPromptTemplate = systemPromptTemplate;
259
+ this.validator = validator;
260
+ this.maxTurns = maxTurns;
261
+ this.maxTokensPerTurn = maxTokensPerTurn;
262
+ this.outputFormat = outputFormat;
263
+ this.requiresSandbox = requiresSandbox;
264
+ this.completionCheck = completionCheck;
265
+ this.outputParser = outputParser;
266
+ }
267
+ }
268
+
269
+ // ---------------------------------------------------------------------------
270
+ // BaseAgent — generalized tool-use loop
271
+ // ---------------------------------------------------------------------------
272
+
273
+ /**
274
+ * Mode-agnostic LLM agent with pluggable tools, prompts, and validators.
275
+ *
276
+ * Works with any Anthropic-SDK-compatible client (Ollama, Claude, LiteLLM).
277
+ */
278
+ export class BaseAgent {
279
+ /**
280
+ * @param {Object} opts
281
+ * @param {Object} opts.client - Anthropic-SDK-compatible LLM client
282
+ * @param {string} opts.model - Model name
283
+ * @param {ModeAgentConfig} opts.config - Mode-specific agent configuration
284
+ * @param {*} [opts.context=null] - Arbitrary context passed to tool handlers
285
+ * @param {Function|null} [opts.preToolHook=null] - (toolName, toolInput) => boolean
286
+ */
287
+ constructor({ client, model, config, context = null, preToolHook = null }) {
288
+ this._client = client;
289
+ this._model = model;
290
+ this._config = config;
291
+ this._context = context;
292
+ this._preToolHook = preToolHook;
293
+ }
294
+
295
+ /**
296
+ * Run the agent against a task.
297
+ *
298
+ * Executes a multi-turn tool-use conversation loop:
299
+ * 1. Render system prompt from config template + taskInput
300
+ * 2. Send initial user message
301
+ * 3. Process LLM responses: text blocks → step log, tool_use → dispatch
302
+ * 4. Check completionCheck on every text block and tool output
303
+ * 5. After loop: run outputParser, then validator
304
+ *
305
+ * @param {Object} taskInput - Dict of task parameters
306
+ * @returns {Promise<ModeAgentResult>}
307
+ */
308
+ async run(taskInput) {
309
+ const result = new ModeAgentResult({ mode: this._config.mode });
310
+ const startTime = performance.now() / 1000;
311
+
312
+ // Render system prompt from template
313
+ let system;
314
+ try {
315
+ system = this._config.systemPromptTemplate.replace(
316
+ /\{(\w+)\}/g,
317
+ (_, key) => {
318
+ if (key in taskInput) return String(taskInput[key]);
319
+ throw new Error(key);
320
+ }
321
+ );
322
+ } catch (e) {
323
+ result.error = `System prompt template error: missing key '${e.message}'`;
324
+ result.durationS = (performance.now() / 1000) - startTime;
325
+ return result;
326
+ }
327
+
328
+ // Build initial user message
329
+ const userMessage = taskInput.user_message || 'Begin the task.';
330
+
331
+ /** @type {Array<Object>} */
332
+ const messages = [
333
+ { role: 'user', content: userMessage },
334
+ ];
335
+
336
+ const tools = this._config.toolRegistry.getSchemas();
337
+ let completed = false;
338
+ let completedText = '';
339
+ let lastAssistantText = '';
340
+
341
+ // for...else pattern: exhausted flag
342
+ let exhausted = true;
343
+
344
+ for (let turn = 0; turn < this._config.maxTurns; turn++) {
345
+ result.turnsUsed = turn + 1;
346
+ debug(`BaseAgent [${this._config.mode}] turn ${turn + 1}/${this._config.maxTurns}`);
347
+
348
+ let response;
349
+ try {
350
+ response = await this._client.messages.create({
351
+ model: this._model,
352
+ max_tokens: this._config.maxTokensPerTurn,
353
+ system,
354
+ tools,
355
+ messages,
356
+ });
357
+ } catch (e) {
358
+ result.error = `LLM API error: ${e.constructor.name}: ${e.message}`;
359
+ exhausted = false;
360
+ break;
361
+ }
362
+
363
+ // Accumulate token usage
364
+ const usage = response?.usage;
365
+ if (usage) {
366
+ result.tokensIn += usage.input_tokens || 0;
367
+ result.tokensOut += usage.output_tokens || 0;
368
+ }
369
+
370
+ // Process response content blocks
371
+ /** @type {Array<Object>} */
372
+ const toolResults = [];
373
+ /** @type {Array<Object>} */
374
+ const assistantContent = [];
375
+ /** @type {string[]} */
376
+ const turnTextParts = [];
377
+
378
+ for (const block of response.content) {
379
+ if (block.type === 'text') {
380
+ const text = block.text;
381
+ assistantContent.push({ type: 'text', text });
382
+ turnTextParts.push(text);
383
+ result.steps.push(`[think] ${text.slice(0, 200)}`);
384
+
385
+ // Check completion on text
386
+ if (this._config.completionCheck !== null && this._config.completionCheck(text)) {
387
+ completed = true;
388
+ completedText = text;
389
+ }
390
+ } else if (block.type === 'tool_use') {
391
+ const toolName = block.name;
392
+ const toolInput = block.input;
393
+ const toolUseId = block.id;
394
+ result.toolCalls += 1;
395
+
396
+ assistantContent.push({
397
+ type: 'tool_use',
398
+ id: toolUseId,
399
+ name: toolName,
400
+ input: toolInput,
401
+ });
402
+
403
+ // Pre-tool hook (supervised mode)
404
+ if (this._preToolHook) {
405
+ const approved = this._preToolHook(toolName, toolInput);
406
+ if (!approved) {
407
+ result.steps.push(`[blocked] ${toolName}`);
408
+ toolResults.push({
409
+ type: 'tool_result',
410
+ tool_use_id: toolUseId,
411
+ content: 'Tool execution blocked by supervisor.',
412
+ });
413
+ continue;
414
+ }
415
+ }
416
+
417
+ // Build step description
418
+ let stepDesc = `[tool] ${toolName}`;
419
+ if (toolName === 'sandbox_exec') {
420
+ stepDesc += `: ${(toolInput.command || '').slice(0, 80)}`;
421
+ } else if (toolName === 'http_request') {
422
+ stepDesc += `: ${toolInput.method || 'GET'} ${toolInput.url || ''}`;
423
+ } else if (toolName === 'read_file') {
424
+ stepDesc += `: ${toolInput.path || ''}`;
425
+ }
426
+
427
+ debug(`Dispatching: ${stepDesc}`);
428
+ result.steps.push(stepDesc);
429
+
430
+ // Dispatch tool (ToolRegistry catches handler exceptions)
431
+ const toolOutput = this._config.toolRegistry.dispatch(
432
+ toolName, toolInput, this._context,
433
+ );
434
+
435
+ // Check completion on tool output
436
+ if (this._config.completionCheck !== null && this._config.completionCheck(toolOutput)) {
437
+ completed = true;
438
+ completedText = toolOutput;
439
+ }
440
+
441
+ toolResults.push({
442
+ type: 'tool_result',
443
+ tool_use_id: toolUseId,
444
+ content: toolOutput,
445
+ });
446
+ }
447
+ }
448
+
449
+ // Track last assistant text for outputParser
450
+ if (turnTextParts.length > 0) {
451
+ lastAssistantText = turnTextParts.join('');
452
+ }
453
+
454
+ // Add assistant response to message history
455
+ messages.push({ role: 'assistant', content: assistantContent });
456
+
457
+ // If completion check fired, we're done
458
+ if (completed) {
459
+ result.steps.push(
460
+ `[complete] Completion check passed: ${completedText.slice(0, 200)}`
461
+ );
462
+ exhausted = false;
463
+ break;
464
+ }
465
+
466
+ // If no tool_use in response, LLM is done
467
+ const stopReason = response.stop_reason ?? null;
468
+ if (stopReason !== 'tool_use') {
469
+ debug(`Agent stopped: stop_reason=${stopReason}`);
470
+ result.steps.push(`[end] Agent stopped (reason: ${stopReason})`);
471
+ exhausted = false;
472
+ break;
473
+ }
474
+
475
+ // Continue with tool results
476
+ if (toolResults.length > 0) {
477
+ messages.push({ role: 'user', content: toolResults });
478
+ }
479
+ }
480
+
481
+ // Loop exhausted without break (for...else equivalent)
482
+ if (exhausted) {
483
+ result.steps.push(`[limit] Max turns (${this._config.maxTurns}) reached`);
484
+ debug(`Agent exhausted ${this._config.maxTurns} turns`);
485
+ }
486
+
487
+ // --- Post-loop: output parsing ---
488
+ if (this._config.outputParser !== null) {
489
+ try {
490
+ result.outputData = this._config.outputParser(lastAssistantText);
491
+ } catch (e) {
492
+ const parseErr = `Output parser error: ${e.constructor.name}: ${e.message}`;
493
+ if (result.error) {
494
+ result.error += `; ${parseErr}`;
495
+ } else {
496
+ result.error = parseErr;
497
+ }
498
+ }
499
+ }
500
+
501
+ // Set output text
502
+ result.outputText = lastAssistantText;
503
+
504
+ // --- Post-loop: validation ---
505
+ result.validation = this._config.validator.validate(result);
506
+
507
+ // --- Duration ---
508
+ result.durationS = (performance.now() / 1000) - startTime;
509
+
510
+ return result;
511
+ }
512
+ }
@@ -0,0 +1,97 @@
1
+ // Copyright (c) 2026 defconxt. All rights reserved.
2
+ // Licensed under AGPL-3.0 — see LICENSE file for details.
3
+ // CIPHER is a trademark of defconxt.
4
+
5
+ /**
6
+ * Barrel export for the autonomous framework.
7
+ *
8
+ * Re-exports all framework primitives, validators, runner, and mode symbols.
9
+ *
10
+ * @module autonomous
11
+ */
12
+
13
+ // Framework primitives
14
+ export {
15
+ truncateOutput,
16
+ ValidationResult,
17
+ ModeAgentResult,
18
+ ToolRegistry,
19
+ NullValidator,
20
+ ModeAgentConfig,
21
+ BaseAgent,
22
+ } from './framework.js';
23
+
24
+ // Validators
25
+ export { SigmaValidator } from './validators/sigma.js';
26
+ export { ForensicValidator } from './validators/forensic.js';
27
+ export { PurpleValidator } from './validators/purple.js';
28
+ export { OSINTValidator } from './validators/osint.js';
29
+ export { DPIAValidator } from './validators/privacy.js';
30
+ export { ThreatModelValidator } from './validators/threat-model.js';
31
+
32
+ // Sigma validator helpers (used by PurpleValidator and tests)
33
+ export { stripCodeFences, parseYamlDocuments } from './validators/sigma.js';
34
+
35
+ // Runner — mode registry, FlagValidator, and dispatch
36
+ export {
37
+ registerMode,
38
+ availableModes,
39
+ initModes,
40
+ getModeRegistry,
41
+ FlagValidator,
42
+ FLAG_PATTERN,
43
+ _resetModes,
44
+ makeAgentClient,
45
+ runAutonomous,
46
+ } from './runner.js';
47
+
48
+ // Mode-specific exports needed downstream
49
+ export { ATTACK_TECHNIQUES } from './modes/blue.js';
50
+
51
+ // Phase 4 — Scheduler
52
+ export {
53
+ TaskPriority,
54
+ SchedulerState,
55
+ ScheduledTask,
56
+ TaskResult,
57
+ LastRequestTracker,
58
+ IdleDetector,
59
+ CipherScheduler,
60
+ createDefaultTasks,
61
+ } from './scheduler.js';
62
+
63
+ // Phase 4 — Researcher
64
+ export {
65
+ ResearchHypothesis,
66
+ ResearchExperiment,
67
+ SkillGapAnalyzer,
68
+ AutonomousResearcher,
69
+ } from './researcher.js';
70
+
71
+ // Phase 4 — Parallel
72
+ export {
73
+ AgentTask,
74
+ AgentResult,
75
+ WorkerPool,
76
+ ParallelScanner,
77
+ ParallelAnalyzer,
78
+ TaskOrchestrator,
79
+ } from './parallel.js';
80
+
81
+ // Phase 4 — Leaderboard
82
+ export {
83
+ SkillMetric,
84
+ DomainMetric,
85
+ LeaderboardEntry,
86
+ SkillLeaderboard,
87
+ } from './leaderboard.js';
88
+
89
+ // Phase 4 — Feedback Loop
90
+ export {
91
+ ImprovementStatus,
92
+ ImprovementCandidate,
93
+ ImprovementCycle,
94
+ SkillQualityAnalyzer,
95
+ FeedbackLoop,
96
+ connectLeaderboardToResearcher,
97
+ } from './feedback-loop.js';