magi-ai 0.1.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.
- package/LICENSE +21 -0
- package/README.ja.md +377 -0
- package/README.md +377 -0
- package/dist/bin/magi-benchmark.d.ts +14 -0
- package/dist/bin/magi-benchmark.js +93 -0
- package/dist/bin/magi-mcp.d.ts +8 -0
- package/dist/bin/magi-mcp.js +28 -0
- package/dist/bin/magi.d.ts +2 -0
- package/dist/bin/magi.js +634 -0
- package/dist/src/adapters/base.d.ts +34 -0
- package/dist/src/adapters/base.js +149 -0
- package/dist/src/adapters/claude.d.ts +29 -0
- package/dist/src/adapters/claude.js +65 -0
- package/dist/src/adapters/codex.d.ts +21 -0
- package/dist/src/adapters/codex.js +41 -0
- package/dist/src/adapters/gemini.d.ts +18 -0
- package/dist/src/adapters/gemini.js +31 -0
- package/dist/src/adapters/registry.d.ts +19 -0
- package/dist/src/adapters/registry.js +59 -0
- package/dist/src/audit/hash-chain.d.ts +21 -0
- package/dist/src/audit/hash-chain.js +70 -0
- package/dist/src/audit/types.d.ts +25 -0
- package/dist/src/audit/types.js +1 -0
- package/dist/src/audit/writer.d.ts +18 -0
- package/dist/src/audit/writer.js +100 -0
- package/dist/src/benchmark/golden-tasks.d.ts +9 -0
- package/dist/src/benchmark/golden-tasks.js +476 -0
- package/dist/src/benchmark/reporter.d.ts +5 -0
- package/dist/src/benchmark/reporter.js +107 -0
- package/dist/src/benchmark/runner.d.ts +30 -0
- package/dist/src/benchmark/runner.js +224 -0
- package/dist/src/benchmark/scorer.d.ts +12 -0
- package/dist/src/benchmark/scorer.js +124 -0
- package/dist/src/benchmark/types.d.ts +54 -0
- package/dist/src/benchmark/types.js +1 -0
- package/dist/src/cache/deliberation-cache.d.ts +49 -0
- package/dist/src/cache/deliberation-cache.js +127 -0
- package/dist/src/cli/commands/config-cmd.d.ts +11 -0
- package/dist/src/cli/commands/config-cmd.js +190 -0
- package/dist/src/cli/commands/demo.d.ts +12 -0
- package/dist/src/cli/commands/demo.js +66 -0
- package/dist/src/cli/commands/setup.d.ts +7 -0
- package/dist/src/cli/commands/setup.js +182 -0
- package/dist/src/cli/i18n.d.ts +89 -0
- package/dist/src/cli/i18n.js +176 -0
- package/dist/src/cli/interactive-select.d.ts +27 -0
- package/dist/src/cli/interactive-select.js +130 -0
- package/dist/src/cli/tui-setup.d.ts +24 -0
- package/dist/src/cli/tui-setup.js +42 -0
- package/dist/src/config/cli-detector.d.ts +37 -0
- package/dist/src/config/cli-detector.js +99 -0
- package/dist/src/config/user-config.d.ts +81 -0
- package/dist/src/config/user-config.js +134 -0
- package/dist/src/context/auto-collector.d.ts +43 -0
- package/dist/src/context/auto-collector.js +337 -0
- package/dist/src/context/manager.d.ts +35 -0
- package/dist/src/context/manager.js +162 -0
- package/dist/src/context/serializer.d.ts +20 -0
- package/dist/src/context/serializer.js +52 -0
- package/dist/src/demo/recorded-deliberation.d.ts +13 -0
- package/dist/src/demo/recorded-deliberation.js +277 -0
- package/dist/src/engine/angel-detector.d.ts +83 -0
- package/dist/src/engine/angel-detector.js +334 -0
- package/dist/src/engine/at-field.d.ts +40 -0
- package/dist/src/engine/at-field.js +195 -0
- package/dist/src/engine/berserk-orchestrator.d.ts +66 -0
- package/dist/src/engine/berserk-orchestrator.js +378 -0
- package/dist/src/engine/change-metrics.d.ts +56 -0
- package/dist/src/engine/change-metrics.js +214 -0
- package/dist/src/engine/consensus.d.ts +20 -0
- package/dist/src/engine/consensus.js +146 -0
- package/dist/src/engine/dead-sea-scrolls.d.ts +132 -0
- package/dist/src/engine/dead-sea-scrolls.js +610 -0
- package/dist/src/engine/drift-detector.d.ts +39 -0
- package/dist/src/engine/drift-detector.js +225 -0
- package/dist/src/engine/dummy-plug.d.ts +44 -0
- package/dist/src/engine/dummy-plug.js +190 -0
- package/dist/src/engine/engram-manager.d.ts +55 -0
- package/dist/src/engine/engram-manager.js +306 -0
- package/dist/src/engine/events.d.ts +130 -0
- package/dist/src/engine/events.js +44 -0
- package/dist/src/engine/gospel.d.ts +30 -0
- package/dist/src/engine/gospel.js +129 -0
- package/dist/src/engine/hallucination-detector.d.ts +33 -0
- package/dist/src/engine/hallucination-detector.js +215 -0
- package/dist/src/engine/human-resolver.d.ts +19 -0
- package/dist/src/engine/human-resolver.js +89 -0
- package/dist/src/engine/instrumentality.d.ts +64 -0
- package/dist/src/engine/instrumentality.js +297 -0
- package/dist/src/engine/iruel-battle.d.ts +79 -0
- package/dist/src/engine/iruel-battle.js +319 -0
- package/dist/src/engine/kernel/deliberation-kernel.d.ts +12 -0
- package/dist/src/engine/kernel/deliberation-kernel.js +303 -0
- package/dist/src/engine/kernel/index.d.ts +8 -0
- package/dist/src/engine/kernel/index.js +7 -0
- package/dist/src/engine/kernel/phase-runner.d.ts +10 -0
- package/dist/src/engine/kernel/phase-runner.js +155 -0
- package/dist/src/engine/kernel/post-processor.d.ts +17 -0
- package/dist/src/engine/kernel/post-processor.js +131 -0
- package/dist/src/engine/kernel/types.d.ts +107 -0
- package/dist/src/engine/kernel/types.js +1 -0
- package/dist/src/engine/kernel/unit-executor.d.ts +6 -0
- package/dist/src/engine/kernel/unit-executor.js +132 -0
- package/dist/src/engine/lcl-manager.d.ts +44 -0
- package/dist/src/engine/lcl-manager.js +143 -0
- package/dist/src/engine/middleware/cache.d.ts +7 -0
- package/dist/src/engine/middleware/cache.js +29 -0
- package/dist/src/engine/middleware/chain.d.ts +18 -0
- package/dist/src/engine/middleware/chain.js +45 -0
- package/dist/src/engine/middleware/firewall.d.ts +8 -0
- package/dist/src/engine/middleware/firewall.js +24 -0
- package/dist/src/engine/middleware/index.d.ts +4 -0
- package/dist/src/engine/middleware/index.js +3 -0
- package/dist/src/engine/middleware/types.d.ts +43 -0
- package/dist/src/engine/middleware/types.js +1 -0
- package/dist/src/engine/nebuchadnezzar-key.d.ts +61 -0
- package/dist/src/engine/nebuchadnezzar-key.js +203 -0
- package/dist/src/engine/neon-genesis.d.ts +52 -0
- package/dist/src/engine/neon-genesis.js +203 -0
- package/dist/src/engine/objective-judge.d.ts +53 -0
- package/dist/src/engine/objective-judge.js +214 -0
- package/dist/src/engine/offline-mode.d.ts +18 -0
- package/dist/src/engine/offline-mode.js +46 -0
- package/dist/src/engine/orchestrator.d.ts +79 -0
- package/dist/src/engine/orchestrator.js +58 -0
- package/dist/src/engine/secret-cipher.d.ts +26 -0
- package/dist/src/engine/secret-cipher.js +114 -0
- package/dist/src/engine/seele-council.d.ts +90 -0
- package/dist/src/engine/seele-council.js +482 -0
- package/dist/src/engine/self-destruct.d.ts +61 -0
- package/dist/src/engine/self-destruct.js +231 -0
- package/dist/src/engine/self-evolution.d.ts +64 -0
- package/dist/src/engine/self-evolution.js +368 -0
- package/dist/src/engine/sync-rate.d.ts +45 -0
- package/dist/src/engine/sync-rate.js +151 -0
- package/dist/src/engine/type666-firewall.d.ts +76 -0
- package/dist/src/engine/type666-firewall.js +343 -0
- package/dist/src/engine/umbilical-cable.d.ts +41 -0
- package/dist/src/engine/umbilical-cable.js +192 -0
- package/dist/src/index.d.ts +106 -0
- package/dist/src/index.js +426 -0
- package/dist/src/mcp/server.d.ts +38 -0
- package/dist/src/mcp/server.js +196 -0
- package/dist/src/metrics/token-tracker.d.ts +38 -0
- package/dist/src/metrics/token-tracker.js +112 -0
- package/dist/src/parsers/json-extractor.d.ts +9 -0
- package/dist/src/parsers/json-extractor.js +239 -0
- package/dist/src/parsers/opinion-schema.d.ts +81 -0
- package/dist/src/parsers/opinion-schema.js +147 -0
- package/dist/src/parsers/unstructured-parser.d.ts +20 -0
- package/dist/src/parsers/unstructured-parser.js +122 -0
- package/dist/src/pipelines/architecture.d.ts +10 -0
- package/dist/src/pipelines/architecture.js +9 -0
- package/dist/src/pipelines/bug-analysis.d.ts +9 -0
- package/dist/src/pipelines/bug-analysis.js +8 -0
- package/dist/src/pipelines/code-review.d.ts +10 -0
- package/dist/src/pipelines/code-review.js +30 -0
- package/dist/src/pipelines/custom.d.ts +14 -0
- package/dist/src/pipelines/custom.js +29 -0
- package/dist/src/pipelines/registry.d.ts +9 -0
- package/dist/src/pipelines/registry.js +20 -0
- package/dist/src/prompts/personas.d.ts +6 -0
- package/dist/src/prompts/personas.js +44 -0
- package/dist/src/prompts/schemas.d.ts +4 -0
- package/dist/src/prompts/schemas.js +24 -0
- package/dist/src/prompts/templates.d.ts +6 -0
- package/dist/src/prompts/templates.js +91 -0
- package/dist/src/repl/accessibility.d.ts +23 -0
- package/dist/src/repl/accessibility.js +46 -0
- package/dist/src/repl/banner.d.ts +4 -0
- package/dist/src/repl/banner.js +28 -0
- package/dist/src/repl/boot-animation.d.ts +13 -0
- package/dist/src/repl/boot-animation.js +143 -0
- package/dist/src/repl/completer.d.ts +21 -0
- package/dist/src/repl/completer.js +168 -0
- package/dist/src/repl/context.d.ts +24 -0
- package/dist/src/repl/context.js +42 -0
- package/dist/src/repl/display-utils.d.ts +13 -0
- package/dist/src/repl/display-utils.js +65 -0
- package/dist/src/repl/event-listener.d.ts +18 -0
- package/dist/src/repl/event-listener.js +112 -0
- package/dist/src/repl/export-formatter.d.ts +8 -0
- package/dist/src/repl/export-formatter.js +73 -0
- package/dist/src/repl/ghost-text.d.ts +31 -0
- package/dist/src/repl/ghost-text.js +119 -0
- package/dist/src/repl/handoff-animation.d.ts +15 -0
- package/dist/src/repl/handoff-animation.js +65 -0
- package/dist/src/repl/history.d.ts +16 -0
- package/dist/src/repl/history.js +130 -0
- package/dist/src/repl/job-registry.d.ts +26 -0
- package/dist/src/repl/job-registry.js +80 -0
- package/dist/src/repl/magi-repl.d.ts +72 -0
- package/dist/src/repl/magi-repl.js +1008 -0
- package/dist/src/repl/multiline-input.d.ts +45 -0
- package/dist/src/repl/multiline-input.js +78 -0
- package/dist/src/repl/prompt-builder.d.ts +19 -0
- package/dist/src/repl/prompt-builder.js +36 -0
- package/dist/src/repl/repl-state.d.ts +5 -0
- package/dist/src/repl/repl-state.js +19 -0
- package/dist/src/repl/result-display.d.ts +8 -0
- package/dist/src/repl/result-display.js +195 -0
- package/dist/src/repl/session-stats.d.ts +26 -0
- package/dist/src/repl/session-stats.js +119 -0
- package/dist/src/repl/slash-commands.d.ts +60 -0
- package/dist/src/repl/slash-commands.js +725 -0
- package/dist/src/repl/terminal-sanitize.d.ts +14 -0
- package/dist/src/repl/terminal-sanitize.js +19 -0
- package/dist/src/reporters/console.d.ts +7 -0
- package/dist/src/reporters/console.js +78 -0
- package/dist/src/reporters/json.d.ts +2 -0
- package/dist/src/reporters/json.js +3 -0
- package/dist/src/reporters/markdown.d.ts +2 -0
- package/dist/src/reporters/markdown.js +65 -0
- package/dist/src/reporters/streaming.d.ts +20 -0
- package/dist/src/reporters/streaming.js +178 -0
- package/dist/src/tui/activity-log.d.ts +23 -0
- package/dist/src/tui/activity-log.js +67 -0
- package/dist/src/tui/animations.d.ts +39 -0
- package/dist/src/tui/animations.js +167 -0
- package/dist/src/tui/ansi.d.ts +28 -0
- package/dist/src/tui/ansi.js +51 -0
- package/dist/src/tui/boot-sequence.d.ts +11 -0
- package/dist/src/tui/boot-sequence.js +98 -0
- package/dist/src/tui/colors.d.ts +101 -0
- package/dist/src/tui/colors.js +71 -0
- package/dist/src/tui/header.d.ts +24 -0
- package/dist/src/tui/header.js +122 -0
- package/dist/src/tui/index.d.ts +3 -0
- package/dist/src/tui/index.js +3 -0
- package/dist/src/tui/keypress.d.ts +25 -0
- package/dist/src/tui/keypress.js +95 -0
- package/dist/src/tui/layout.d.ts +74 -0
- package/dist/src/tui/layout.js +171 -0
- package/dist/src/tui/magi-tui.d.ts +101 -0
- package/dist/src/tui/magi-tui.js +754 -0
- package/dist/src/tui/panel.d.ts +45 -0
- package/dist/src/tui/panel.js +292 -0
- package/dist/src/tui/screen-buffer.d.ts +54 -0
- package/dist/src/tui/screen-buffer.js +262 -0
- package/dist/src/tui/status-bar.d.ts +25 -0
- package/dist/src/tui/status-bar.js +124 -0
- package/dist/src/tui/terminal-detect.d.ts +26 -0
- package/dist/src/tui/terminal-detect.js +44 -0
- package/dist/src/tui/tui-helpers.d.ts +12 -0
- package/dist/src/tui/tui-helpers.js +37 -0
- package/dist/src/types/adapter.d.ts +75 -0
- package/dist/src/types/adapter.js +36 -0
- package/dist/src/types/config.d.ts +108 -0
- package/dist/src/types/config.js +85 -0
- package/dist/src/types/consensus.d.ts +55 -0
- package/dist/src/types/consensus.js +17 -0
- package/dist/src/types/core.d.ts +178 -0
- package/dist/src/types/core.js +85 -0
- package/dist/src/types/magi-api.d.ts +62 -0
- package/dist/src/types/magi-api.js +7 -0
- package/dist/src/types/phase-h.d.ts +142 -0
- package/dist/src/types/phase-h.js +7 -0
- package/dist/src/types/phase-i.d.ts +186 -0
- package/dist/src/types/phase-i.js +6 -0
- package/dist/src/types/phase-k.d.ts +259 -0
- package/dist/src/types/phase-k.js +6 -0
- package/dist/src/types/phase-l.d.ts +199 -0
- package/dist/src/types/phase-l.js +6 -0
- package/dist/src/types/pipeline.d.ts +37 -0
- package/dist/src/types/pipeline.js +2 -0
- package/dist/src/utils/abstain-factory.d.ts +2 -0
- package/dist/src/utils/abstain-factory.js +18 -0
- package/dist/src/utils/errors.d.ts +34 -0
- package/dist/src/utils/errors.js +59 -0
- package/dist/src/utils/file-validator.d.ts +50 -0
- package/dist/src/utils/file-validator.js +124 -0
- package/dist/src/utils/fire-and-forget.d.ts +5 -0
- package/dist/src/utils/fire-and-forget.js +10 -0
- package/dist/src/utils/flag-validator.d.ts +21 -0
- package/dist/src/utils/flag-validator.js +79 -0
- package/dist/src/utils/freeze.d.ts +8 -0
- package/dist/src/utils/freeze.js +16 -0
- package/dist/src/utils/language-detector.d.ts +16 -0
- package/dist/src/utils/language-detector.js +159 -0
- package/dist/src/utils/latency-tracker.d.ts +45 -0
- package/dist/src/utils/latency-tracker.js +100 -0
- package/dist/src/utils/logger.d.ts +33 -0
- package/dist/src/utils/logger.js +112 -0
- package/dist/src/utils/process.d.ts +40 -0
- package/dist/src/utils/process.js +253 -0
- package/dist/src/utils/retry.d.ts +12 -0
- package/dist/src/utils/retry.js +30 -0
- package/dist/src/utils/safe-fs.d.ts +38 -0
- package/dist/src/utils/safe-fs.js +56 -0
- package/dist/src/utils/safe-json-parse.d.ts +15 -0
- package/dist/src/utils/safe-json-parse.js +49 -0
- package/dist/src/utils/sanitize.d.ts +14 -0
- package/dist/src/utils/sanitize.js +186 -0
- package/dist/src/utils/semaphore.d.ts +22 -0
- package/dist/src/utils/semaphore.js +57 -0
- package/dist/src/utils/shutdown.d.ts +6 -0
- package/dist/src/utils/shutdown.js +51 -0
- package/dist/src/utils/tty.d.ts +5 -0
- package/dist/src/utils/tty.js +7 -0
- package/package.json +82 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { readFile, rename, readdir, unlink, stat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { computeEntryHash } from './hash-chain.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import { safeMkdir, safeAppendFile } from '../utils/safe-fs.js';
|
|
6
|
+
import { safeJsonParse } from '../utils/safe-json-parse.js';
|
|
7
|
+
const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
8
|
+
const DEFAULT_MAX_FILES = 5;
|
|
9
|
+
const LOG_FILE_NAME = 'magi-audit.jsonl';
|
|
10
|
+
export class AuditLogWriter {
|
|
11
|
+
config;
|
|
12
|
+
lastHash = '';
|
|
13
|
+
currentFile;
|
|
14
|
+
currentSize = 0;
|
|
15
|
+
writeQueue = Promise.resolve();
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.currentFile = join(config.logDir, LOG_FILE_NAME);
|
|
19
|
+
}
|
|
20
|
+
/** Initialize: create log directory with 0o700, set current file, recover lastHash from existing log */
|
|
21
|
+
async initialize() {
|
|
22
|
+
await safeMkdir(this.config.logDir);
|
|
23
|
+
try {
|
|
24
|
+
const content = await readFile(this.currentFile, 'utf-8');
|
|
25
|
+
const lines = content.trimEnd().split('\n');
|
|
26
|
+
const lastLine = lines[lines.length - 1];
|
|
27
|
+
if (lastLine) {
|
|
28
|
+
const lastEntry = safeJsonParse(lastLine);
|
|
29
|
+
this.lastHash = lastEntry.hash;
|
|
30
|
+
}
|
|
31
|
+
const stats = await stat(this.currentFile);
|
|
32
|
+
this.currentSize = stats.size;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
logger.debug('AuditLogWriter: log file not found, starting fresh', { error: String(err) });
|
|
36
|
+
this.lastHash = '';
|
|
37
|
+
this.currentSize = 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Write a single entry, auto-rotate if needed. Serializes concurrent calls. */
|
|
41
|
+
async write(event, deliberationId, data) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
this.writeQueue = this.writeQueue.then(async () => {
|
|
44
|
+
try {
|
|
45
|
+
const entry = await this.writeEntry(event, deliberationId, data);
|
|
46
|
+
resolve(entry);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
reject(err);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** Get the current log file path */
|
|
55
|
+
get logFile() {
|
|
56
|
+
return this.currentFile;
|
|
57
|
+
}
|
|
58
|
+
async writeEntry(event, deliberationId, data) {
|
|
59
|
+
const maxSize = this.config.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
60
|
+
if (this.currentSize > 0 && this.currentSize >= maxSize) {
|
|
61
|
+
await this.rotate();
|
|
62
|
+
}
|
|
63
|
+
const partial = {
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
event,
|
|
66
|
+
deliberationId,
|
|
67
|
+
data,
|
|
68
|
+
prevHash: this.lastHash,
|
|
69
|
+
};
|
|
70
|
+
const hash = computeEntryHash(partial);
|
|
71
|
+
const entry = { ...partial, hash };
|
|
72
|
+
const line = JSON.stringify(entry) + '\n';
|
|
73
|
+
await safeAppendFile(this.currentFile, line);
|
|
74
|
+
this.lastHash = hash;
|
|
75
|
+
this.currentSize += Buffer.byteLength(line, 'utf-8');
|
|
76
|
+
return entry;
|
|
77
|
+
}
|
|
78
|
+
/** Rotate: rename current to timestamped, clean old files beyond maxFiles */
|
|
79
|
+
async rotate() {
|
|
80
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
81
|
+
const rotatedName = `magi-audit-${timestamp}.jsonl`;
|
|
82
|
+
const rotatedPath = join(this.config.logDir, rotatedName);
|
|
83
|
+
await rename(this.currentFile, rotatedPath);
|
|
84
|
+
// Reset state for new file
|
|
85
|
+
this.currentSize = 0;
|
|
86
|
+
this.lastHash = '';
|
|
87
|
+
// Clean old rotated files if exceeding maxFiles
|
|
88
|
+
const maxFiles = this.config.maxFiles ?? DEFAULT_MAX_FILES;
|
|
89
|
+
const allFiles = await readdir(this.config.logDir);
|
|
90
|
+
const rotatedFiles = allFiles
|
|
91
|
+
.filter((f) => f.startsWith('magi-audit-') && f.endsWith('.jsonl'))
|
|
92
|
+
.sort();
|
|
93
|
+
if (rotatedFiles.length > maxFiles) {
|
|
94
|
+
const toDelete = rotatedFiles.slice(0, rotatedFiles.length - maxFiles);
|
|
95
|
+
for (const file of toDelete) {
|
|
96
|
+
await unlink(join(this.config.logDir, file));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GoldenTask } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* 16 golden tasks for benchmarking MAGI quality.
|
|
4
|
+
*
|
|
5
|
+
* - APPROVE tasks (3): false-positive detection
|
|
6
|
+
* - REJECT tasks (13): true-positive detection
|
|
7
|
+
* - Security tasks use type: 'code-review' (no SecurityAuditPipeline yet)
|
|
8
|
+
*/
|
|
9
|
+
export declare const GOLDEN_TASKS: readonly GoldenTask[];
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 16 golden tasks for benchmarking MAGI quality.
|
|
3
|
+
*
|
|
4
|
+
* - APPROVE tasks (3): false-positive detection
|
|
5
|
+
* - REJECT tasks (13): true-positive detection
|
|
6
|
+
* - Security tasks use type: 'code-review' (no SecurityAuditPipeline yet)
|
|
7
|
+
*/
|
|
8
|
+
export const GOLDEN_TASKS = [
|
|
9
|
+
// ── Code Review ──────────────────────────────────────────────
|
|
10
|
+
{
|
|
11
|
+
id: 'cr-001',
|
|
12
|
+
category: 'code-review',
|
|
13
|
+
task: {
|
|
14
|
+
type: 'code-review',
|
|
15
|
+
title: 'Off-by-one error in slice boundary',
|
|
16
|
+
description: 'Review the following code for correctness issues.',
|
|
17
|
+
artifacts: [{
|
|
18
|
+
type: 'snippet',
|
|
19
|
+
language: 'typescript',
|
|
20
|
+
content: `function getLastN<T>(arr: T[], n: number): T[] {
|
|
21
|
+
// Should return last n elements
|
|
22
|
+
return arr.slice(arr.length - n - 1);
|
|
23
|
+
}`,
|
|
24
|
+
}],
|
|
25
|
+
},
|
|
26
|
+
expectation: {
|
|
27
|
+
expectedVote: 'REJECT',
|
|
28
|
+
mustDetectPoints: ['off-by-one', 'slice', 'boundary', 'off by one'],
|
|
29
|
+
weight: 1.0,
|
|
30
|
+
rationale: 'slice(arr.length - n - 1) returns n+1 elements instead of n',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'cr-002',
|
|
35
|
+
category: 'code-review',
|
|
36
|
+
task: {
|
|
37
|
+
type: 'code-review',
|
|
38
|
+
title: 'Race condition in check-then-act pattern',
|
|
39
|
+
description: 'Review the following code for concurrency issues.',
|
|
40
|
+
artifacts: [{
|
|
41
|
+
type: 'snippet',
|
|
42
|
+
language: 'typescript',
|
|
43
|
+
content: `import { existsSync, writeFileSync, readFileSync } from 'fs';
|
|
44
|
+
|
|
45
|
+
async function safeWrite(path: string, data: string): Promise<void> {
|
|
46
|
+
if (!existsSync(path)) {
|
|
47
|
+
writeFileSync(path, data);
|
|
48
|
+
} else {
|
|
49
|
+
const existing = readFileSync(path, 'utf-8');
|
|
50
|
+
writeFileSync(path, existing + data);
|
|
51
|
+
}
|
|
52
|
+
}`,
|
|
53
|
+
}],
|
|
54
|
+
},
|
|
55
|
+
expectation: {
|
|
56
|
+
expectedVote: 'REJECT',
|
|
57
|
+
mustDetectPoints: ['race condition', 'TOCTOU', 'check-then-act', 'time-of-check', 'concurrent', 'data race'],
|
|
58
|
+
weight: 1.5,
|
|
59
|
+
rationale: 'TOCTOU race: file can be created/modified between existsSync and writeFileSync',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'cr-003',
|
|
64
|
+
category: 'code-review',
|
|
65
|
+
task: {
|
|
66
|
+
type: 'code-review',
|
|
67
|
+
title: 'Memory leak from unremoved event listener',
|
|
68
|
+
description: 'Review the following React component for resource management issues.',
|
|
69
|
+
artifacts: [{
|
|
70
|
+
type: 'snippet',
|
|
71
|
+
language: 'typescript',
|
|
72
|
+
content: `import { useEffect, useState } from 'react';
|
|
73
|
+
|
|
74
|
+
function useWindowSize() {
|
|
75
|
+
const [size, setSize] = useState({ w: 0, h: 0 });
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
const handler = () => setSize({ w: window.innerWidth, h: window.innerHeight });
|
|
79
|
+
window.addEventListener('resize', handler);
|
|
80
|
+
// Missing cleanup: return () => window.removeEventListener('resize', handler);
|
|
81
|
+
}, []);
|
|
82
|
+
|
|
83
|
+
return size;
|
|
84
|
+
}`,
|
|
85
|
+
}],
|
|
86
|
+
},
|
|
87
|
+
expectation: {
|
|
88
|
+
expectedVote: 'REJECT',
|
|
89
|
+
mustDetectPoints: ['memory leak', 'event listener', 'cleanup', 'removeEventListener', 'unmount'],
|
|
90
|
+
weight: 1.0,
|
|
91
|
+
rationale: 'useEffect never removes the resize listener, causing memory leak on unmount',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: 'cr-004',
|
|
96
|
+
category: 'code-review',
|
|
97
|
+
task: {
|
|
98
|
+
type: 'code-review',
|
|
99
|
+
title: 'Null reference without optional chaining',
|
|
100
|
+
description: 'Review the following code for null safety issues.',
|
|
101
|
+
artifacts: [{
|
|
102
|
+
type: 'snippet',
|
|
103
|
+
language: 'typescript',
|
|
104
|
+
content: `interface User {
|
|
105
|
+
profile?: {
|
|
106
|
+
address?: {
|
|
107
|
+
city: string;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function getCity(user: User): string {
|
|
113
|
+
return user.profile.address.city;
|
|
114
|
+
}`,
|
|
115
|
+
}],
|
|
116
|
+
},
|
|
117
|
+
expectation: {
|
|
118
|
+
expectedVote: 'REJECT',
|
|
119
|
+
mustDetectPoints: ['null', 'undefined', 'optional chaining', 'TypeError', 'optional'],
|
|
120
|
+
weight: 1.0,
|
|
121
|
+
rationale: 'Accessing .profile.address.city without optional chaining throws when profile/address is undefined',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: 'cr-005',
|
|
126
|
+
category: 'code-review',
|
|
127
|
+
task: {
|
|
128
|
+
type: 'code-review',
|
|
129
|
+
title: 'Well-implemented Result type pattern',
|
|
130
|
+
description: 'Review the following utility code for correctness.',
|
|
131
|
+
artifacts: [{
|
|
132
|
+
type: 'snippet',
|
|
133
|
+
language: 'typescript',
|
|
134
|
+
content: `type Result<T, E = Error> =
|
|
135
|
+
| { ok: true; value: T }
|
|
136
|
+
| { ok: false; error: E };
|
|
137
|
+
|
|
138
|
+
function tryParse(json: string): Result<unknown> {
|
|
139
|
+
try {
|
|
140
|
+
return { ok: true, value: JSON.parse(json) };
|
|
141
|
+
} catch (e) {
|
|
142
|
+
return { ok: false, error: e instanceof Error ? e : new Error(String(e)) };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function unwrap<T>(result: Result<T>): T {
|
|
147
|
+
if (!result.ok) throw result.error;
|
|
148
|
+
return result.value;
|
|
149
|
+
}`,
|
|
150
|
+
}],
|
|
151
|
+
},
|
|
152
|
+
expectation: {
|
|
153
|
+
expectedVote: 'APPROVE',
|
|
154
|
+
mustDetectPoints: ['Result', 'type-safe', 'error handling', 'pattern'],
|
|
155
|
+
mustNotDetectPoints: ['vulnerability', 'critical bug', 'security risk'],
|
|
156
|
+
weight: 1.0,
|
|
157
|
+
rationale: 'Clean Result type pattern with proper error handling — should be approved',
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
// ── Architecture ─────────────────────────────────────────────
|
|
161
|
+
{
|
|
162
|
+
id: 'arch-001',
|
|
163
|
+
category: 'architecture',
|
|
164
|
+
task: {
|
|
165
|
+
type: 'architecture-decision',
|
|
166
|
+
title: 'Monolith vs Microservices for MVP',
|
|
167
|
+
description: `We are building an internal tool for a team of 5 developers.
|
|
168
|
+
Expected users: ~50. Expected traffic: ~100 requests/day.
|
|
169
|
+
Should we use a monolithic architecture or microservices?
|
|
170
|
+
|
|
171
|
+
Proposal: Use a single Node.js + PostgreSQL monolith with modular internal structure.`,
|
|
172
|
+
},
|
|
173
|
+
expectation: {
|
|
174
|
+
expectedVote: 'APPROVE',
|
|
175
|
+
mustDetectPoints: ['monolith', 'simple', 'appropriate', 'scale'],
|
|
176
|
+
mustNotDetectPoints: ['microservices required'],
|
|
177
|
+
weight: 1.0,
|
|
178
|
+
rationale: 'Monolith is the right choice for a small team/low traffic MVP',
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
id: 'arch-002',
|
|
183
|
+
category: 'architecture',
|
|
184
|
+
task: {
|
|
185
|
+
type: 'architecture-decision',
|
|
186
|
+
title: 'Tightly coupled design with circular dependencies',
|
|
187
|
+
description: `Review this proposed module structure:
|
|
188
|
+
|
|
189
|
+
- UserService imports OrderService
|
|
190
|
+
- OrderService imports PaymentService
|
|
191
|
+
- PaymentService imports UserService (for user credit check)
|
|
192
|
+
- All services share a single mutable state object
|
|
193
|
+
|
|
194
|
+
Each service directly instantiates its dependencies with \`new\`.`,
|
|
195
|
+
},
|
|
196
|
+
expectation: {
|
|
197
|
+
expectedVote: 'REJECT',
|
|
198
|
+
mustDetectPoints: ['circular dependency', 'tight coupling', 'coupled', 'circular', 'dependency injection', 'mutable state'],
|
|
199
|
+
weight: 1.5,
|
|
200
|
+
rationale: 'Circular dependencies + shared mutable state + no DI = unmaintainable',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
id: 'arch-003',
|
|
205
|
+
category: 'architecture',
|
|
206
|
+
task: {
|
|
207
|
+
type: 'architecture-decision',
|
|
208
|
+
title: 'Singleton Logger implementation',
|
|
209
|
+
description: `Proposal: Implement a singleton logger for the application.
|
|
210
|
+
|
|
211
|
+
\`\`\`typescript
|
|
212
|
+
class Logger {
|
|
213
|
+
private static instance: Logger;
|
|
214
|
+
private constructor(private level: string) {}
|
|
215
|
+
static getInstance(): Logger {
|
|
216
|
+
if (!Logger.instance) Logger.instance = new Logger('info');
|
|
217
|
+
return Logger.instance;
|
|
218
|
+
}
|
|
219
|
+
info(msg: string) { console.log(\`[INFO] \${msg}\`); }
|
|
220
|
+
error(msg: string) { console.error(\`[ERROR] \${msg}\`); }
|
|
221
|
+
}
|
|
222
|
+
\`\`\`
|
|
223
|
+
|
|
224
|
+
This will be used as the standard logging mechanism across the application.`,
|
|
225
|
+
},
|
|
226
|
+
expectation: {
|
|
227
|
+
expectedVote: 'APPROVE',
|
|
228
|
+
mustDetectPoints: ['singleton', 'logger', 'pattern', 'acceptable'],
|
|
229
|
+
weight: 1.0,
|
|
230
|
+
rationale: 'Singleton logger is a well-established, acceptable pattern',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: 'arch-004',
|
|
235
|
+
category: 'architecture',
|
|
236
|
+
task: {
|
|
237
|
+
type: 'architecture-decision',
|
|
238
|
+
title: 'Over-abstracted factory pattern (YAGNI violation)',
|
|
239
|
+
description: `Proposal for a configuration system:
|
|
240
|
+
|
|
241
|
+
- AbstractConfigProvider (base class)
|
|
242
|
+
- ConfigProviderFactory (creates providers)
|
|
243
|
+
- ConfigProviderRegistry (registers factories)
|
|
244
|
+
- ConfigProviderAdapter (adapts between formats)
|
|
245
|
+
- ConfigProviderProxy (lazy loading)
|
|
246
|
+
- ConfigProviderDecorator (adds caching)
|
|
247
|
+
|
|
248
|
+
Currently we only have one config source: a JSON file.
|
|
249
|
+
No plans for additional sources in the roadmap.`,
|
|
250
|
+
},
|
|
251
|
+
expectation: {
|
|
252
|
+
expectedVote: 'REJECT',
|
|
253
|
+
mustDetectPoints: ['YAGNI', 'over-engineer', 'abstraction', 'complex', 'unnecessary', 'overdesign'],
|
|
254
|
+
weight: 1.0,
|
|
255
|
+
rationale: '6 classes for one JSON file is extreme over-engineering',
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: 'arch-005',
|
|
260
|
+
category: 'architecture',
|
|
261
|
+
task: {
|
|
262
|
+
type: 'architecture-decision',
|
|
263
|
+
title: 'API design missing error handling',
|
|
264
|
+
description: `Proposed REST API endpoints:
|
|
265
|
+
|
|
266
|
+
- POST /api/users — creates user, returns 200 with user object
|
|
267
|
+
- GET /api/users/:id — returns user or empty body
|
|
268
|
+
- PUT /api/users/:id — updates user, returns 200
|
|
269
|
+
- DELETE /api/users/:id — deletes user, returns 200
|
|
270
|
+
|
|
271
|
+
No error response format defined. No validation middleware.
|
|
272
|
+
No rate limiting. No authentication mentioned.`,
|
|
273
|
+
},
|
|
274
|
+
expectation: {
|
|
275
|
+
expectedVote: 'REJECT',
|
|
276
|
+
mustDetectPoints: ['error handling', 'validation', 'authentication', 'status code', 'error response'],
|
|
277
|
+
weight: 1.0,
|
|
278
|
+
rationale: 'API design lacks error responses, validation, auth, and proper status codes',
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
// ── Bug Analysis ─────────────────────────────────────────────
|
|
282
|
+
{
|
|
283
|
+
id: 'bug-001',
|
|
284
|
+
category: 'bug-analysis',
|
|
285
|
+
task: {
|
|
286
|
+
type: 'bug-analysis',
|
|
287
|
+
title: 'Infinite recursion causing stack overflow',
|
|
288
|
+
description: 'Investigate the following code that crashes with "Maximum call stack size exceeded".',
|
|
289
|
+
artifacts: [{
|
|
290
|
+
type: 'snippet',
|
|
291
|
+
language: 'typescript',
|
|
292
|
+
content: `interface TreeNode {
|
|
293
|
+
value: number;
|
|
294
|
+
children: TreeNode[];
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function flatten(node: TreeNode): number[] {
|
|
298
|
+
const result = [node.value];
|
|
299
|
+
for (const child of node.children) {
|
|
300
|
+
result.push(...flatten(child));
|
|
301
|
+
}
|
|
302
|
+
return result;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Bug: circular reference
|
|
306
|
+
const root: TreeNode = { value: 1, children: [] };
|
|
307
|
+
const child: TreeNode = { value: 2, children: [root] }; // circular!
|
|
308
|
+
root.children.push(child);
|
|
309
|
+
flatten(root); // Stack overflow`,
|
|
310
|
+
}],
|
|
311
|
+
},
|
|
312
|
+
expectation: {
|
|
313
|
+
expectedVote: 'REJECT',
|
|
314
|
+
mustDetectPoints: ['infinite recursion', 'stack overflow', 'circular', 'cycle', 'recursive'],
|
|
315
|
+
weight: 1.0,
|
|
316
|
+
rationale: 'Circular reference causes infinite recursion in flatten()',
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
id: 'bug-002',
|
|
321
|
+
category: 'bug-analysis',
|
|
322
|
+
task: {
|
|
323
|
+
type: 'bug-analysis',
|
|
324
|
+
title: 'Swallowed async error in Promise chain',
|
|
325
|
+
description: 'Investigate why errors from this async operation are silently lost.',
|
|
326
|
+
artifacts: [{
|
|
327
|
+
type: 'snippet',
|
|
328
|
+
language: 'typescript',
|
|
329
|
+
content: `async function fetchData(url: string): Promise<unknown> {
|
|
330
|
+
try {
|
|
331
|
+
const response = await fetch(url);
|
|
332
|
+
const data = await response.json();
|
|
333
|
+
return data;
|
|
334
|
+
} catch {
|
|
335
|
+
// Error silently swallowed — no logging, no rethrow, no fallback
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async function processAll(urls: string[]) {
|
|
341
|
+
const results = urls.map(url => fetchData(url));
|
|
342
|
+
// Missing await — fires and forgets
|
|
343
|
+
Promise.all(results);
|
|
344
|
+
}`,
|
|
345
|
+
}],
|
|
346
|
+
},
|
|
347
|
+
expectation: {
|
|
348
|
+
expectedVote: 'REJECT',
|
|
349
|
+
mustDetectPoints: ['swallow', 'error handling', 'catch', 'silent', 'await', 'fire and forget'],
|
|
350
|
+
weight: 1.0,
|
|
351
|
+
rationale: 'Empty catch block swallows errors; Promise.all result not awaited',
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
id: 'bug-003',
|
|
356
|
+
category: 'bug-analysis',
|
|
357
|
+
task: {
|
|
358
|
+
type: 'bug-analysis',
|
|
359
|
+
title: 'Sort comparator treating numbers as strings',
|
|
360
|
+
description: 'Investigate why sorting produces incorrect results for numeric arrays.',
|
|
361
|
+
artifacts: [{
|
|
362
|
+
type: 'snippet',
|
|
363
|
+
language: 'typescript',
|
|
364
|
+
content: `function sortNumbers(arr: number[]): number[] {
|
|
365
|
+
return [...arr].sort();
|
|
366
|
+
// Default sort converts to strings: [1, 10, 2, 20, 3]
|
|
367
|
+
// Should be: arr.sort((a, b) => a - b)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Example: sortNumbers([10, 1, 20, 2, 3])
|
|
371
|
+
// Expected: [1, 2, 3, 10, 20]
|
|
372
|
+
// Actual: [1, 10, 2, 20, 3]`,
|
|
373
|
+
}],
|
|
374
|
+
},
|
|
375
|
+
expectation: {
|
|
376
|
+
expectedVote: 'REJECT',
|
|
377
|
+
mustDetectPoints: ['sort', 'string comparison', 'lexicographic', 'comparator', 'numeric'],
|
|
378
|
+
weight: 1.0,
|
|
379
|
+
rationale: 'Default Array.sort() uses lexicographic comparison, not numeric',
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
// ── Security (using code-review type) ────────────────────────
|
|
383
|
+
{
|
|
384
|
+
id: 'sec-001',
|
|
385
|
+
category: 'security',
|
|
386
|
+
task: {
|
|
387
|
+
type: 'code-review',
|
|
388
|
+
title: 'SQL injection vulnerability',
|
|
389
|
+
description: 'Security review of database query code.',
|
|
390
|
+
artifacts: [{
|
|
391
|
+
type: 'snippet',
|
|
392
|
+
language: 'typescript',
|
|
393
|
+
content: `import { Pool } from 'pg';
|
|
394
|
+
|
|
395
|
+
const pool = new Pool();
|
|
396
|
+
|
|
397
|
+
async function getUser(userId: string) {
|
|
398
|
+
const query = \`SELECT * FROM users WHERE id = '\${userId}'\`;
|
|
399
|
+
const result = await pool.query(query);
|
|
400
|
+
return result.rows[0];
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Called with user input from HTTP request:
|
|
404
|
+
// app.get('/user/:id', (req, res) => getUser(req.params.id))`,
|
|
405
|
+
}],
|
|
406
|
+
},
|
|
407
|
+
expectation: {
|
|
408
|
+
expectedVote: 'REJECT',
|
|
409
|
+
mustDetectPoints: ['SQL injection', 'parameterized', 'prepared statement', 'sanitize', 'injection'],
|
|
410
|
+
weight: 2.0,
|
|
411
|
+
rationale: 'Direct string interpolation in SQL query allows SQL injection',
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
id: 'sec-002',
|
|
416
|
+
category: 'security',
|
|
417
|
+
task: {
|
|
418
|
+
type: 'code-review',
|
|
419
|
+
title: 'XSS via innerHTML',
|
|
420
|
+
description: 'Security review of DOM manipulation code.',
|
|
421
|
+
artifacts: [{
|
|
422
|
+
type: 'snippet',
|
|
423
|
+
language: 'typescript',
|
|
424
|
+
content: `function renderComment(comment: { author: string; text: string }) {
|
|
425
|
+
const container = document.getElementById('comments');
|
|
426
|
+
if (container) {
|
|
427
|
+
container.innerHTML += \`
|
|
428
|
+
<div class="comment">
|
|
429
|
+
<strong>\${comment.author}</strong>
|
|
430
|
+
<p>\${comment.text}</p>
|
|
431
|
+
</div>
|
|
432
|
+
\`;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// comment.text comes directly from user input via form submission`,
|
|
437
|
+
}],
|
|
438
|
+
},
|
|
439
|
+
expectation: {
|
|
440
|
+
expectedVote: 'REJECT',
|
|
441
|
+
mustDetectPoints: ['XSS', 'innerHTML', 'cross-site scripting', 'sanitize', 'escape', 'script injection'],
|
|
442
|
+
weight: 2.0,
|
|
443
|
+
rationale: 'User input inserted via innerHTML without escaping enables XSS',
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
id: 'sec-003',
|
|
448
|
+
category: 'security',
|
|
449
|
+
task: {
|
|
450
|
+
type: 'code-review',
|
|
451
|
+
title: 'Path traversal vulnerability',
|
|
452
|
+
description: 'Security review of file serving code.',
|
|
453
|
+
artifacts: [{
|
|
454
|
+
type: 'snippet',
|
|
455
|
+
language: 'typescript',
|
|
456
|
+
content: `import { readFileSync } from 'fs';
|
|
457
|
+
import { join } from 'path';
|
|
458
|
+
|
|
459
|
+
function serveFile(userPath: string): string {
|
|
460
|
+
const filePath = join('/app/public', userPath);
|
|
461
|
+
return readFileSync(filePath, 'utf-8');
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Called from HTTP handler:
|
|
465
|
+
// app.get('/files/*', (req, res) => res.send(serveFile(req.params[0])))
|
|
466
|
+
// Attacker sends: GET /files/../../etc/passwd`,
|
|
467
|
+
}],
|
|
468
|
+
},
|
|
469
|
+
expectation: {
|
|
470
|
+
expectedVote: 'REJECT',
|
|
471
|
+
mustDetectPoints: ['path traversal', 'directory traversal', '../', 'resolve', 'normalize', 'sanitize path'],
|
|
472
|
+
weight: 2.0,
|
|
473
|
+
rationale: 'join() does not prevent ../ traversal; attacker can read arbitrary files',
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BenchmarkResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a Markdown benchmark report comparing single-Claude vs MAGI 3-body results.
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateReport(singleResult: BenchmarkResult | null, magiResult: BenchmarkResult | null): string;
|