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,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HallucinationDetector — Detects fabricated content in MAGI opinions
|
|
3
|
+
*
|
|
4
|
+
* Stateless detector that identifies 4 types of hallucinations:
|
|
5
|
+
* 1. Fabricated file paths (generic placeholder paths)
|
|
6
|
+
* 2. Abnormal line numbers (impossibly large or zero)
|
|
7
|
+
* 3. Vote-reasoning mismatch (contradictory vote + reasoning)
|
|
8
|
+
* 4. Fabricated references (non-existent RFC/CVE numbers)
|
|
9
|
+
*
|
|
10
|
+
* Part of B-02 LCL (shared consciousness pool).
|
|
11
|
+
*/
|
|
12
|
+
// ── Constants ────────────────────────────────────────────────────
|
|
13
|
+
/** Paths that are commonly valid and should not be flagged */
|
|
14
|
+
const VALID_PATH_PREFIXES = [
|
|
15
|
+
'/dev/', '/tmp/', '/usr/', '/etc/', '/var/', '/bin/', '/sbin/',
|
|
16
|
+
'/opt/', '/lib/', '/proc/', '/sys/', '/home/', '/root/',
|
|
17
|
+
];
|
|
18
|
+
/** Generic placeholder path patterns that indicate fabrication */
|
|
19
|
+
const FABRICATED_PATH_PATTERNS = [
|
|
20
|
+
/\/path\/to\//i,
|
|
21
|
+
/\/foo\/bar\//i,
|
|
22
|
+
/\/example\//i,
|
|
23
|
+
/\/some\//i,
|
|
24
|
+
/\/my\//i,
|
|
25
|
+
/\/test\/fake\//i,
|
|
26
|
+
];
|
|
27
|
+
/** Threshold above which line numbers are suspicious */
|
|
28
|
+
const LINE_NUMBER_THRESHOLD = 50000;
|
|
29
|
+
/** Negative sentiment keywords for vote-reasoning mismatch */
|
|
30
|
+
const NEGATIVE_KEYWORDS = [
|
|
31
|
+
'terrible', 'awful', 'dangerous', 'critical', 'vulnerability',
|
|
32
|
+
'broken', 'fatal', 'catastrophic', 'unacceptable', 'severe',
|
|
33
|
+
'disastrous', 'horrible', 'unsafe', 'exploit', 'malicious',
|
|
34
|
+
];
|
|
35
|
+
/** Positive sentiment keywords for vote-reasoning mismatch */
|
|
36
|
+
const POSITIVE_KEYWORDS = [
|
|
37
|
+
'excellent', 'great', 'clean', 'solid', 'well-structured',
|
|
38
|
+
'impressive', 'robust', 'elegant', 'optimal', 'perfect',
|
|
39
|
+
'outstanding', 'brilliant', 'exemplary', 'superb', 'flawless',
|
|
40
|
+
];
|
|
41
|
+
/** Minimum confidence threshold for purification */
|
|
42
|
+
const PURIFY_CONFIDENCE_THRESHOLD = 0.7;
|
|
43
|
+
// ── HallucinationDetector ────────────────────────────────────────
|
|
44
|
+
export class HallucinationDetector {
|
|
45
|
+
/**
|
|
46
|
+
* Run all hallucination checks on an opinion.
|
|
47
|
+
* Returns an array of reports (empty if no hallucinations detected).
|
|
48
|
+
*/
|
|
49
|
+
detect(opinion) {
|
|
50
|
+
const text = `${opinion.reasoning} ${opinion.keyPoints.join(' ')} ${opinion.suggestions?.join(' ') ?? ''}`;
|
|
51
|
+
const reports = [];
|
|
52
|
+
reports.push(...this.checkFilePaths(text));
|
|
53
|
+
reports.push(...this.checkLineNumbers(text));
|
|
54
|
+
reports.push(...this.checkVoteReasoningMismatch(opinion));
|
|
55
|
+
reports.push(...this.checkFabricatedReferences(text));
|
|
56
|
+
return reports;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a purified copy of the opinion with hallucinations annotated.
|
|
60
|
+
* Only purifies reports with confidence >= PURIFY_CONFIDENCE_THRESHOLD.
|
|
61
|
+
*/
|
|
62
|
+
purify(opinion, reports) {
|
|
63
|
+
const actionableReports = reports.filter(r => r.confidence >= PURIFY_CONFIDENCE_THRESHOLD);
|
|
64
|
+
if (actionableReports.length === 0) {
|
|
65
|
+
return opinion;
|
|
66
|
+
}
|
|
67
|
+
let reasoning = opinion.reasoning;
|
|
68
|
+
const keyPoints = [...opinion.keyPoints];
|
|
69
|
+
const suggestions = opinion.suggestions ? [...opinion.suggestions] : undefined;
|
|
70
|
+
for (const report of actionableReports) {
|
|
71
|
+
if (report.location) {
|
|
72
|
+
const loc = report.location;
|
|
73
|
+
const replacement = `[PURIFIED: ${report.type}]`;
|
|
74
|
+
reasoning = reasoning.replaceAll(loc, replacement);
|
|
75
|
+
for (let i = 0; i < keyPoints.length; i++) {
|
|
76
|
+
const kp = keyPoints[i];
|
|
77
|
+
if (kp !== undefined) {
|
|
78
|
+
keyPoints[i] = kp.replaceAll(loc, replacement);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (suggestions) {
|
|
82
|
+
for (let i = 0; i < suggestions.length; i++) {
|
|
83
|
+
const sg = suggestions[i];
|
|
84
|
+
if (sg !== undefined) {
|
|
85
|
+
suggestions[i] = sg.replaceAll(loc, replacement);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Reduce confidence proportionally to hallucination severity
|
|
92
|
+
const avgConfidence = actionableReports.reduce((sum, r) => sum + r.confidence, 0) / actionableReports.length;
|
|
93
|
+
const penalty = avgConfidence * 0.2 * actionableReports.length;
|
|
94
|
+
const adjustedConfidence = Math.max(0.1, opinion.confidence - penalty);
|
|
95
|
+
return {
|
|
96
|
+
...opinion,
|
|
97
|
+
reasoning,
|
|
98
|
+
keyPoints,
|
|
99
|
+
suggestions,
|
|
100
|
+
confidence: Math.round(adjustedConfidence * 100) / 100,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ── Private check methods ──────────────────────────────────────
|
|
104
|
+
/** Detect fabricated file paths like /path/to/xxx, /foo/bar/baz.ts */
|
|
105
|
+
checkFilePaths(text) {
|
|
106
|
+
const reports = [];
|
|
107
|
+
// Match Unix-style absolute paths
|
|
108
|
+
const pathRegex = /(?:^|\s)(\/[a-zA-Z0-9_.-]+(?:\/[a-zA-Z0-9_.-]+){2,})/g;
|
|
109
|
+
let match;
|
|
110
|
+
while ((match = pathRegex.exec(text)) !== null) {
|
|
111
|
+
const filePath = match[1] ?? '';
|
|
112
|
+
if (!filePath)
|
|
113
|
+
continue;
|
|
114
|
+
// Skip known valid paths
|
|
115
|
+
if (VALID_PATH_PREFIXES.some(prefix => filePath.startsWith(prefix))) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Check against fabricated patterns
|
|
119
|
+
if (FABRICATED_PATH_PATTERNS.some(pattern => pattern.test(filePath))) {
|
|
120
|
+
reports.push({
|
|
121
|
+
type: 'fabricated-path',
|
|
122
|
+
description: `Suspected fabricated file path: ${filePath}`,
|
|
123
|
+
confidence: filePath.includes('/path/to/') ? 0.9 : 0.7,
|
|
124
|
+
location: filePath,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return reports;
|
|
129
|
+
}
|
|
130
|
+
/** Detect abnormal line numbers (line 0, line > 50000) */
|
|
131
|
+
checkLineNumbers(text) {
|
|
132
|
+
const reports = [];
|
|
133
|
+
const lineRegex = /\bline\s+(\d+)\b/gi;
|
|
134
|
+
let match;
|
|
135
|
+
while ((match = lineRegex.exec(text)) !== null) {
|
|
136
|
+
const lineNum = parseInt(match[1] ?? '', 10);
|
|
137
|
+
if (Number.isNaN(lineNum))
|
|
138
|
+
continue;
|
|
139
|
+
if (lineNum === 0 || lineNum > LINE_NUMBER_THRESHOLD) {
|
|
140
|
+
reports.push({
|
|
141
|
+
type: 'abnormal-line-number',
|
|
142
|
+
description: `Abnormal line number: ${lineNum}${lineNum === 0 ? ' (line 0 does not exist)' : ` (exceeds ${LINE_NUMBER_THRESHOLD})`}`,
|
|
143
|
+
confidence: 0.8,
|
|
144
|
+
location: match[0],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return reports;
|
|
149
|
+
}
|
|
150
|
+
/** Detect mismatch between vote and reasoning sentiment */
|
|
151
|
+
checkVoteReasoningMismatch(opinion) {
|
|
152
|
+
const reports = [];
|
|
153
|
+
const lowerReasoning = opinion.reasoning.toLowerCase();
|
|
154
|
+
const negativeCount = NEGATIVE_KEYWORDS.filter(kw => lowerReasoning.includes(kw)).length;
|
|
155
|
+
const positiveCount = POSITIVE_KEYWORDS.filter(kw => lowerReasoning.includes(kw)).length;
|
|
156
|
+
if (opinion.vote === 'APPROVE' && negativeCount >= 2 && negativeCount > positiveCount) {
|
|
157
|
+
const confidence = Math.min(0.8, 0.6 + negativeCount * 0.05);
|
|
158
|
+
reports.push({
|
|
159
|
+
type: 'vote-reasoning-mismatch',
|
|
160
|
+
description: `APPROVE vote contradicts negative reasoning (${negativeCount} negative keywords found)`,
|
|
161
|
+
confidence: Math.round(confidence * 100) / 100,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (opinion.vote === 'REJECT' && positiveCount >= 2 && positiveCount > negativeCount) {
|
|
165
|
+
const confidence = Math.min(0.8, 0.6 + positiveCount * 0.05);
|
|
166
|
+
reports.push({
|
|
167
|
+
type: 'vote-reasoning-mismatch',
|
|
168
|
+
description: `REJECT vote contradicts positive reasoning (${positiveCount} positive keywords found)`,
|
|
169
|
+
confidence: Math.round(confidence * 100) / 100,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return reports;
|
|
173
|
+
}
|
|
174
|
+
/** Detect fabricated RFC/CVE references */
|
|
175
|
+
checkFabricatedReferences(text) {
|
|
176
|
+
const reports = [];
|
|
177
|
+
// RFC numbers: valid RFCs are currently in the range 1-9999 (roughly)
|
|
178
|
+
const rfcRegex = /\bRFC\s+(\d+)\b/gi;
|
|
179
|
+
let match;
|
|
180
|
+
while ((match = rfcRegex.exec(text)) !== null) {
|
|
181
|
+
const rfcNumStr = match[1] ?? '';
|
|
182
|
+
const rfcNum = parseInt(rfcNumStr, 10);
|
|
183
|
+
if (Number.isNaN(rfcNum))
|
|
184
|
+
continue;
|
|
185
|
+
if (rfcNum > 99000) {
|
|
186
|
+
reports.push({
|
|
187
|
+
type: 'fabricated-reference',
|
|
188
|
+
description: `Suspected fabricated RFC number: RFC ${rfcNum}`,
|
|
189
|
+
confidence: 0.85,
|
|
190
|
+
location: match[0],
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// CVE numbers: format is CVE-YYYY-NNNN+
|
|
195
|
+
const cveRegex = /\bCVE-(\d{4})-(\d+)\b/gi;
|
|
196
|
+
while ((match = cveRegex.exec(text)) !== null) {
|
|
197
|
+
const yearStr = match[1] ?? '';
|
|
198
|
+
const seqStr = match[2] ?? '';
|
|
199
|
+
const year = parseInt(yearStr, 10);
|
|
200
|
+
const seqNum = parseInt(seqStr, 10);
|
|
201
|
+
if (Number.isNaN(year) || Number.isNaN(seqNum))
|
|
202
|
+
continue;
|
|
203
|
+
// Future years or absurdly high sequence numbers
|
|
204
|
+
if (year > 2026 || seqNum > 90000) {
|
|
205
|
+
reports.push({
|
|
206
|
+
type: 'fabricated-reference',
|
|
207
|
+
description: `Suspected fabricated CVE: CVE-${yearStr}-${seqStr}`,
|
|
208
|
+
confidence: 0.85,
|
|
209
|
+
location: match[0],
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return reports;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MagiOpinion } from '../types/core.js';
|
|
2
|
+
import type { ConsensusResult, VoteSummary } from '../types/consensus.js';
|
|
3
|
+
/**
|
|
4
|
+
* Human-in-the-loop resolver for deadlock situations.
|
|
5
|
+
*
|
|
6
|
+
* When the MAGI units cannot reach consensus, presents the deadlocked
|
|
7
|
+
* opinions to the user and asks them to make the final call.
|
|
8
|
+
*
|
|
9
|
+
* Only activates in TTY mode. Non-TTY environments fall back to
|
|
10
|
+
* the standard DEADLOCK result.
|
|
11
|
+
*/
|
|
12
|
+
export declare class HumanResolver {
|
|
13
|
+
isAvailable(): boolean;
|
|
14
|
+
resolve(opinions: MagiOpinion[], votes: VoteSummary): Promise<ConsensusResult>;
|
|
15
|
+
private printDeadlockBanner;
|
|
16
|
+
private printOpinionsSummary;
|
|
17
|
+
private promptUserDecision;
|
|
18
|
+
private buildResult;
|
|
19
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline/promises';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
/**
|
|
4
|
+
* Human-in-the-loop resolver for deadlock situations.
|
|
5
|
+
*
|
|
6
|
+
* When the MAGI units cannot reach consensus, presents the deadlocked
|
|
7
|
+
* opinions to the user and asks them to make the final call.
|
|
8
|
+
*
|
|
9
|
+
* Only activates in TTY mode. Non-TTY environments fall back to
|
|
10
|
+
* the standard DEADLOCK result.
|
|
11
|
+
*/
|
|
12
|
+
export class HumanResolver {
|
|
13
|
+
isAvailable() {
|
|
14
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
15
|
+
}
|
|
16
|
+
async resolve(opinions, votes) {
|
|
17
|
+
this.printDeadlockBanner();
|
|
18
|
+
this.printOpinionsSummary(opinions);
|
|
19
|
+
const choice = await this.promptUserDecision(opinions);
|
|
20
|
+
return this.buildResult(choice, opinions, votes);
|
|
21
|
+
}
|
|
22
|
+
printDeadlockBanner() {
|
|
23
|
+
console.error('');
|
|
24
|
+
console.error(chalk.yellow.bold(' ══════════════════════════════════════'));
|
|
25
|
+
console.error(chalk.yellow.bold(' DEADLOCK — Human decision required'));
|
|
26
|
+
console.error(chalk.yellow.bold(' ══════════════════════════════════════'));
|
|
27
|
+
console.error('');
|
|
28
|
+
}
|
|
29
|
+
printOpinionsSummary(opinions) {
|
|
30
|
+
for (let i = 0; i < opinions.length; i++) {
|
|
31
|
+
const o = opinions[i];
|
|
32
|
+
const voteColor = o.vote === 'APPROVE' ? chalk.green : o.vote === 'REJECT' ? chalk.red : chalk.yellow;
|
|
33
|
+
console.error(` [${i + 1}] ${chalk.bold(o.unit)}: ${voteColor(o.vote)} (${(o.confidence * 100).toFixed(0)}%)`);
|
|
34
|
+
console.error(chalk.gray(` ${o.reasoning.slice(0, 120)}`));
|
|
35
|
+
if (o.keyPoints.length > 0) {
|
|
36
|
+
console.error(chalk.gray(` Key: ${o.keyPoints.slice(0, 2).join(', ')}`));
|
|
37
|
+
}
|
|
38
|
+
console.error('');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async promptUserDecision(opinions) {
|
|
42
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
43
|
+
try {
|
|
44
|
+
const options = opinions.map((o, i) => `${i + 1}=${o.unit}`).join(', ');
|
|
45
|
+
const answer = await rl.question(chalk.cyan(` Choose a unit's position (${options}) or A=approve / R=reject: `));
|
|
46
|
+
const trimmed = answer.trim().toUpperCase();
|
|
47
|
+
// Direct vote
|
|
48
|
+
if (trimmed === 'A' || trimmed === 'APPROVE') {
|
|
49
|
+
const reason = await rl.question(chalk.gray(' Reason (Enter to skip): '));
|
|
50
|
+
return { vote: 'APPROVE', reasoning: reason.trim() || 'Human override: approved' };
|
|
51
|
+
}
|
|
52
|
+
if (trimmed === 'R' || trimmed === 'REJECT') {
|
|
53
|
+
const reason = await rl.question(chalk.gray(' Reason (Enter to skip): '));
|
|
54
|
+
return { vote: 'REJECT', reasoning: reason.trim() || 'Human override: rejected' };
|
|
55
|
+
}
|
|
56
|
+
// Unit selection by number
|
|
57
|
+
const idx = parseInt(trimmed, 10) - 1;
|
|
58
|
+
if (idx >= 0 && idx < opinions.length) {
|
|
59
|
+
const selected = opinions[idx];
|
|
60
|
+
return { vote: selected.vote, reasoning: `Human selected ${selected.unit}'s position` };
|
|
61
|
+
}
|
|
62
|
+
// Invalid input → default to first unit
|
|
63
|
+
console.error(chalk.yellow(' Invalid input, defaulting to first unit\'s position.'));
|
|
64
|
+
const first = opinions[0];
|
|
65
|
+
return { vote: first.vote, reasoning: `Human defaulted to ${first.unit}'s position` };
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
rl.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
buildResult(choice, opinions, votes) {
|
|
72
|
+
const decision = choice.vote === 'APPROVE' ? 'MAJORITY_APPROVE' : 'MAJORITY_REJECT';
|
|
73
|
+
const confidences = opinions.map((o) => o.confidence);
|
|
74
|
+
const avgConfidence = confidences.length > 0
|
|
75
|
+
? confidences.reduce((sum, c) => sum + c, 0) / confidences.length
|
|
76
|
+
: 0;
|
|
77
|
+
const dissent = opinions
|
|
78
|
+
.filter((o) => o.vote !== choice.vote && o.vote !== 'ABSTAIN')
|
|
79
|
+
.map((o) => ({ unit: o.unit, vote: o.vote, reasoning: o.reasoning }));
|
|
80
|
+
return {
|
|
81
|
+
decision,
|
|
82
|
+
method: 'human',
|
|
83
|
+
votes,
|
|
84
|
+
confidence: avgConfidence,
|
|
85
|
+
summary: `MAGI DECISION: ${decision.replace(/_/g, ' ')} (via HUMAN)\n${choice.reasoning}`,
|
|
86
|
+
dissent: dissent.length > 0 ? dissent : undefined,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A-05 補完計画 (Instrumentality) — Deadlock Fusion Engine
|
|
3
|
+
*
|
|
4
|
+
* When deliberation reaches a deadlock after 3+ rounds, this engine
|
|
5
|
+
* fuses all unit opinions into a single synthesized assessment.
|
|
6
|
+
*
|
|
7
|
+
* The fusion process:
|
|
8
|
+
* 1. Detect deadlock conditions (shouldTrigger)
|
|
9
|
+
* 2. Build a weighted fusion prompt from all opinions
|
|
10
|
+
* 3. Execute via the primary adapter (MELCHIOR)
|
|
11
|
+
* 4. Parse and validate the fused opinion
|
|
12
|
+
* 5. Apply confidence discount (0.85x) since the opinion is derived
|
|
13
|
+
*
|
|
14
|
+
* Emits: 'instrumentality:triggered', 'fusion:complete'
|
|
15
|
+
*/
|
|
16
|
+
import type { MagiTask, MagiOpinion, DeliberationRound } from '../types/core.js';
|
|
17
|
+
import type { FusionWeights, InstrumentalityResult } from '../types/phase-i.js';
|
|
18
|
+
import type { MagiEventBus } from './events.js';
|
|
19
|
+
import type { AdapterRegistry } from '../adapters/registry.js';
|
|
20
|
+
export declare class InstrumentalityEngine {
|
|
21
|
+
private readonly adapters;
|
|
22
|
+
private readonly eventBus;
|
|
23
|
+
constructor(adapters: AdapterRegistry, eventBus?: MagiEventBus);
|
|
24
|
+
/**
|
|
25
|
+
* Determine whether Instrumentality should trigger.
|
|
26
|
+
*
|
|
27
|
+
* Conditions:
|
|
28
|
+
* - consensusDecision is 'DEADLOCK'
|
|
29
|
+
* - At least MIN_ROUNDS_FOR_TRIGGER rounds have been completed
|
|
30
|
+
*/
|
|
31
|
+
shouldTrigger(rounds: DeliberationRound[], consensusDecision: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Fuse multiple unit opinions into a single synthesized opinion.
|
|
34
|
+
*
|
|
35
|
+
* Steps:
|
|
36
|
+
* 1. Build effective weights (defaults + custom overrides)
|
|
37
|
+
* 2. Construct the fusion prompt
|
|
38
|
+
* 3. Execute via MELCHIOR (first registered adapter)
|
|
39
|
+
* 4. Parse and validate the response
|
|
40
|
+
* 5. Apply confidence discount and return FusedOpinion
|
|
41
|
+
*/
|
|
42
|
+
fuse(opinions: MagiOpinion[], task: MagiTask, weights?: FusionWeights): Promise<InstrumentalityResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Build a structured fusion prompt from all opinions.
|
|
45
|
+
* Each opinion is presented as a section with its assigned weight.
|
|
46
|
+
*/
|
|
47
|
+
buildFusionPrompt(opinions: MagiOpinion[], task: MagiTask, weights: FusionWeights): string;
|
|
48
|
+
/**
|
|
49
|
+
* Estimate the token cost of a fusion operation.
|
|
50
|
+
* Includes the prompt construction + expected output.
|
|
51
|
+
*/
|
|
52
|
+
estimateTokenCost(opinions: MagiOpinion[], task: MagiTask): number;
|
|
53
|
+
/**
|
|
54
|
+
* Build effective fusion weights.
|
|
55
|
+
* Uses defaults for known units (MELCHIOR, BALTHASAR, CASPER).
|
|
56
|
+
* Unknown units receive equal weight distributed from remaining allocation.
|
|
57
|
+
*/
|
|
58
|
+
private buildEffectiveWeights;
|
|
59
|
+
/**
|
|
60
|
+
* Parse the adapter response into a validated opinion payload.
|
|
61
|
+
* Tries structured output first, then JSON extraction from raw text.
|
|
62
|
+
*/
|
|
63
|
+
private parseResponse;
|
|
64
|
+
}
|