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.
Files changed (300) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +377 -0
  3. package/README.md +377 -0
  4. package/dist/bin/magi-benchmark.d.ts +14 -0
  5. package/dist/bin/magi-benchmark.js +93 -0
  6. package/dist/bin/magi-mcp.d.ts +8 -0
  7. package/dist/bin/magi-mcp.js +28 -0
  8. package/dist/bin/magi.d.ts +2 -0
  9. package/dist/bin/magi.js +634 -0
  10. package/dist/src/adapters/base.d.ts +34 -0
  11. package/dist/src/adapters/base.js +149 -0
  12. package/dist/src/adapters/claude.d.ts +29 -0
  13. package/dist/src/adapters/claude.js +65 -0
  14. package/dist/src/adapters/codex.d.ts +21 -0
  15. package/dist/src/adapters/codex.js +41 -0
  16. package/dist/src/adapters/gemini.d.ts +18 -0
  17. package/dist/src/adapters/gemini.js +31 -0
  18. package/dist/src/adapters/registry.d.ts +19 -0
  19. package/dist/src/adapters/registry.js +59 -0
  20. package/dist/src/audit/hash-chain.d.ts +21 -0
  21. package/dist/src/audit/hash-chain.js +70 -0
  22. package/dist/src/audit/types.d.ts +25 -0
  23. package/dist/src/audit/types.js +1 -0
  24. package/dist/src/audit/writer.d.ts +18 -0
  25. package/dist/src/audit/writer.js +100 -0
  26. package/dist/src/benchmark/golden-tasks.d.ts +9 -0
  27. package/dist/src/benchmark/golden-tasks.js +476 -0
  28. package/dist/src/benchmark/reporter.d.ts +5 -0
  29. package/dist/src/benchmark/reporter.js +107 -0
  30. package/dist/src/benchmark/runner.d.ts +30 -0
  31. package/dist/src/benchmark/runner.js +224 -0
  32. package/dist/src/benchmark/scorer.d.ts +12 -0
  33. package/dist/src/benchmark/scorer.js +124 -0
  34. package/dist/src/benchmark/types.d.ts +54 -0
  35. package/dist/src/benchmark/types.js +1 -0
  36. package/dist/src/cache/deliberation-cache.d.ts +49 -0
  37. package/dist/src/cache/deliberation-cache.js +127 -0
  38. package/dist/src/cli/commands/config-cmd.d.ts +11 -0
  39. package/dist/src/cli/commands/config-cmd.js +190 -0
  40. package/dist/src/cli/commands/demo.d.ts +12 -0
  41. package/dist/src/cli/commands/demo.js +66 -0
  42. package/dist/src/cli/commands/setup.d.ts +7 -0
  43. package/dist/src/cli/commands/setup.js +182 -0
  44. package/dist/src/cli/i18n.d.ts +89 -0
  45. package/dist/src/cli/i18n.js +176 -0
  46. package/dist/src/cli/interactive-select.d.ts +27 -0
  47. package/dist/src/cli/interactive-select.js +130 -0
  48. package/dist/src/cli/tui-setup.d.ts +24 -0
  49. package/dist/src/cli/tui-setup.js +42 -0
  50. package/dist/src/config/cli-detector.d.ts +37 -0
  51. package/dist/src/config/cli-detector.js +99 -0
  52. package/dist/src/config/user-config.d.ts +81 -0
  53. package/dist/src/config/user-config.js +134 -0
  54. package/dist/src/context/auto-collector.d.ts +43 -0
  55. package/dist/src/context/auto-collector.js +337 -0
  56. package/dist/src/context/manager.d.ts +35 -0
  57. package/dist/src/context/manager.js +162 -0
  58. package/dist/src/context/serializer.d.ts +20 -0
  59. package/dist/src/context/serializer.js +52 -0
  60. package/dist/src/demo/recorded-deliberation.d.ts +13 -0
  61. package/dist/src/demo/recorded-deliberation.js +277 -0
  62. package/dist/src/engine/angel-detector.d.ts +83 -0
  63. package/dist/src/engine/angel-detector.js +334 -0
  64. package/dist/src/engine/at-field.d.ts +40 -0
  65. package/dist/src/engine/at-field.js +195 -0
  66. package/dist/src/engine/berserk-orchestrator.d.ts +66 -0
  67. package/dist/src/engine/berserk-orchestrator.js +378 -0
  68. package/dist/src/engine/change-metrics.d.ts +56 -0
  69. package/dist/src/engine/change-metrics.js +214 -0
  70. package/dist/src/engine/consensus.d.ts +20 -0
  71. package/dist/src/engine/consensus.js +146 -0
  72. package/dist/src/engine/dead-sea-scrolls.d.ts +132 -0
  73. package/dist/src/engine/dead-sea-scrolls.js +610 -0
  74. package/dist/src/engine/drift-detector.d.ts +39 -0
  75. package/dist/src/engine/drift-detector.js +225 -0
  76. package/dist/src/engine/dummy-plug.d.ts +44 -0
  77. package/dist/src/engine/dummy-plug.js +190 -0
  78. package/dist/src/engine/engram-manager.d.ts +55 -0
  79. package/dist/src/engine/engram-manager.js +306 -0
  80. package/dist/src/engine/events.d.ts +130 -0
  81. package/dist/src/engine/events.js +44 -0
  82. package/dist/src/engine/gospel.d.ts +30 -0
  83. package/dist/src/engine/gospel.js +129 -0
  84. package/dist/src/engine/hallucination-detector.d.ts +33 -0
  85. package/dist/src/engine/hallucination-detector.js +215 -0
  86. package/dist/src/engine/human-resolver.d.ts +19 -0
  87. package/dist/src/engine/human-resolver.js +89 -0
  88. package/dist/src/engine/instrumentality.d.ts +64 -0
  89. package/dist/src/engine/instrumentality.js +297 -0
  90. package/dist/src/engine/iruel-battle.d.ts +79 -0
  91. package/dist/src/engine/iruel-battle.js +319 -0
  92. package/dist/src/engine/kernel/deliberation-kernel.d.ts +12 -0
  93. package/dist/src/engine/kernel/deliberation-kernel.js +303 -0
  94. package/dist/src/engine/kernel/index.d.ts +8 -0
  95. package/dist/src/engine/kernel/index.js +7 -0
  96. package/dist/src/engine/kernel/phase-runner.d.ts +10 -0
  97. package/dist/src/engine/kernel/phase-runner.js +155 -0
  98. package/dist/src/engine/kernel/post-processor.d.ts +17 -0
  99. package/dist/src/engine/kernel/post-processor.js +131 -0
  100. package/dist/src/engine/kernel/types.d.ts +107 -0
  101. package/dist/src/engine/kernel/types.js +1 -0
  102. package/dist/src/engine/kernel/unit-executor.d.ts +6 -0
  103. package/dist/src/engine/kernel/unit-executor.js +132 -0
  104. package/dist/src/engine/lcl-manager.d.ts +44 -0
  105. package/dist/src/engine/lcl-manager.js +143 -0
  106. package/dist/src/engine/middleware/cache.d.ts +7 -0
  107. package/dist/src/engine/middleware/cache.js +29 -0
  108. package/dist/src/engine/middleware/chain.d.ts +18 -0
  109. package/dist/src/engine/middleware/chain.js +45 -0
  110. package/dist/src/engine/middleware/firewall.d.ts +8 -0
  111. package/dist/src/engine/middleware/firewall.js +24 -0
  112. package/dist/src/engine/middleware/index.d.ts +4 -0
  113. package/dist/src/engine/middleware/index.js +3 -0
  114. package/dist/src/engine/middleware/types.d.ts +43 -0
  115. package/dist/src/engine/middleware/types.js +1 -0
  116. package/dist/src/engine/nebuchadnezzar-key.d.ts +61 -0
  117. package/dist/src/engine/nebuchadnezzar-key.js +203 -0
  118. package/dist/src/engine/neon-genesis.d.ts +52 -0
  119. package/dist/src/engine/neon-genesis.js +203 -0
  120. package/dist/src/engine/objective-judge.d.ts +53 -0
  121. package/dist/src/engine/objective-judge.js +214 -0
  122. package/dist/src/engine/offline-mode.d.ts +18 -0
  123. package/dist/src/engine/offline-mode.js +46 -0
  124. package/dist/src/engine/orchestrator.d.ts +79 -0
  125. package/dist/src/engine/orchestrator.js +58 -0
  126. package/dist/src/engine/secret-cipher.d.ts +26 -0
  127. package/dist/src/engine/secret-cipher.js +114 -0
  128. package/dist/src/engine/seele-council.d.ts +90 -0
  129. package/dist/src/engine/seele-council.js +482 -0
  130. package/dist/src/engine/self-destruct.d.ts +61 -0
  131. package/dist/src/engine/self-destruct.js +231 -0
  132. package/dist/src/engine/self-evolution.d.ts +64 -0
  133. package/dist/src/engine/self-evolution.js +368 -0
  134. package/dist/src/engine/sync-rate.d.ts +45 -0
  135. package/dist/src/engine/sync-rate.js +151 -0
  136. package/dist/src/engine/type666-firewall.d.ts +76 -0
  137. package/dist/src/engine/type666-firewall.js +343 -0
  138. package/dist/src/engine/umbilical-cable.d.ts +41 -0
  139. package/dist/src/engine/umbilical-cable.js +192 -0
  140. package/dist/src/index.d.ts +106 -0
  141. package/dist/src/index.js +426 -0
  142. package/dist/src/mcp/server.d.ts +38 -0
  143. package/dist/src/mcp/server.js +196 -0
  144. package/dist/src/metrics/token-tracker.d.ts +38 -0
  145. package/dist/src/metrics/token-tracker.js +112 -0
  146. package/dist/src/parsers/json-extractor.d.ts +9 -0
  147. package/dist/src/parsers/json-extractor.js +239 -0
  148. package/dist/src/parsers/opinion-schema.d.ts +81 -0
  149. package/dist/src/parsers/opinion-schema.js +147 -0
  150. package/dist/src/parsers/unstructured-parser.d.ts +20 -0
  151. package/dist/src/parsers/unstructured-parser.js +122 -0
  152. package/dist/src/pipelines/architecture.d.ts +10 -0
  153. package/dist/src/pipelines/architecture.js +9 -0
  154. package/dist/src/pipelines/bug-analysis.d.ts +9 -0
  155. package/dist/src/pipelines/bug-analysis.js +8 -0
  156. package/dist/src/pipelines/code-review.d.ts +10 -0
  157. package/dist/src/pipelines/code-review.js +30 -0
  158. package/dist/src/pipelines/custom.d.ts +14 -0
  159. package/dist/src/pipelines/custom.js +29 -0
  160. package/dist/src/pipelines/registry.d.ts +9 -0
  161. package/dist/src/pipelines/registry.js +20 -0
  162. package/dist/src/prompts/personas.d.ts +6 -0
  163. package/dist/src/prompts/personas.js +44 -0
  164. package/dist/src/prompts/schemas.d.ts +4 -0
  165. package/dist/src/prompts/schemas.js +24 -0
  166. package/dist/src/prompts/templates.d.ts +6 -0
  167. package/dist/src/prompts/templates.js +91 -0
  168. package/dist/src/repl/accessibility.d.ts +23 -0
  169. package/dist/src/repl/accessibility.js +46 -0
  170. package/dist/src/repl/banner.d.ts +4 -0
  171. package/dist/src/repl/banner.js +28 -0
  172. package/dist/src/repl/boot-animation.d.ts +13 -0
  173. package/dist/src/repl/boot-animation.js +143 -0
  174. package/dist/src/repl/completer.d.ts +21 -0
  175. package/dist/src/repl/completer.js +168 -0
  176. package/dist/src/repl/context.d.ts +24 -0
  177. package/dist/src/repl/context.js +42 -0
  178. package/dist/src/repl/display-utils.d.ts +13 -0
  179. package/dist/src/repl/display-utils.js +65 -0
  180. package/dist/src/repl/event-listener.d.ts +18 -0
  181. package/dist/src/repl/event-listener.js +112 -0
  182. package/dist/src/repl/export-formatter.d.ts +8 -0
  183. package/dist/src/repl/export-formatter.js +73 -0
  184. package/dist/src/repl/ghost-text.d.ts +31 -0
  185. package/dist/src/repl/ghost-text.js +119 -0
  186. package/dist/src/repl/handoff-animation.d.ts +15 -0
  187. package/dist/src/repl/handoff-animation.js +65 -0
  188. package/dist/src/repl/history.d.ts +16 -0
  189. package/dist/src/repl/history.js +130 -0
  190. package/dist/src/repl/job-registry.d.ts +26 -0
  191. package/dist/src/repl/job-registry.js +80 -0
  192. package/dist/src/repl/magi-repl.d.ts +72 -0
  193. package/dist/src/repl/magi-repl.js +1008 -0
  194. package/dist/src/repl/multiline-input.d.ts +45 -0
  195. package/dist/src/repl/multiline-input.js +78 -0
  196. package/dist/src/repl/prompt-builder.d.ts +19 -0
  197. package/dist/src/repl/prompt-builder.js +36 -0
  198. package/dist/src/repl/repl-state.d.ts +5 -0
  199. package/dist/src/repl/repl-state.js +19 -0
  200. package/dist/src/repl/result-display.d.ts +8 -0
  201. package/dist/src/repl/result-display.js +195 -0
  202. package/dist/src/repl/session-stats.d.ts +26 -0
  203. package/dist/src/repl/session-stats.js +119 -0
  204. package/dist/src/repl/slash-commands.d.ts +60 -0
  205. package/dist/src/repl/slash-commands.js +725 -0
  206. package/dist/src/repl/terminal-sanitize.d.ts +14 -0
  207. package/dist/src/repl/terminal-sanitize.js +19 -0
  208. package/dist/src/reporters/console.d.ts +7 -0
  209. package/dist/src/reporters/console.js +78 -0
  210. package/dist/src/reporters/json.d.ts +2 -0
  211. package/dist/src/reporters/json.js +3 -0
  212. package/dist/src/reporters/markdown.d.ts +2 -0
  213. package/dist/src/reporters/markdown.js +65 -0
  214. package/dist/src/reporters/streaming.d.ts +20 -0
  215. package/dist/src/reporters/streaming.js +178 -0
  216. package/dist/src/tui/activity-log.d.ts +23 -0
  217. package/dist/src/tui/activity-log.js +67 -0
  218. package/dist/src/tui/animations.d.ts +39 -0
  219. package/dist/src/tui/animations.js +167 -0
  220. package/dist/src/tui/ansi.d.ts +28 -0
  221. package/dist/src/tui/ansi.js +51 -0
  222. package/dist/src/tui/boot-sequence.d.ts +11 -0
  223. package/dist/src/tui/boot-sequence.js +98 -0
  224. package/dist/src/tui/colors.d.ts +101 -0
  225. package/dist/src/tui/colors.js +71 -0
  226. package/dist/src/tui/header.d.ts +24 -0
  227. package/dist/src/tui/header.js +122 -0
  228. package/dist/src/tui/index.d.ts +3 -0
  229. package/dist/src/tui/index.js +3 -0
  230. package/dist/src/tui/keypress.d.ts +25 -0
  231. package/dist/src/tui/keypress.js +95 -0
  232. package/dist/src/tui/layout.d.ts +74 -0
  233. package/dist/src/tui/layout.js +171 -0
  234. package/dist/src/tui/magi-tui.d.ts +101 -0
  235. package/dist/src/tui/magi-tui.js +754 -0
  236. package/dist/src/tui/panel.d.ts +45 -0
  237. package/dist/src/tui/panel.js +292 -0
  238. package/dist/src/tui/screen-buffer.d.ts +54 -0
  239. package/dist/src/tui/screen-buffer.js +262 -0
  240. package/dist/src/tui/status-bar.d.ts +25 -0
  241. package/dist/src/tui/status-bar.js +124 -0
  242. package/dist/src/tui/terminal-detect.d.ts +26 -0
  243. package/dist/src/tui/terminal-detect.js +44 -0
  244. package/dist/src/tui/tui-helpers.d.ts +12 -0
  245. package/dist/src/tui/tui-helpers.js +37 -0
  246. package/dist/src/types/adapter.d.ts +75 -0
  247. package/dist/src/types/adapter.js +36 -0
  248. package/dist/src/types/config.d.ts +108 -0
  249. package/dist/src/types/config.js +85 -0
  250. package/dist/src/types/consensus.d.ts +55 -0
  251. package/dist/src/types/consensus.js +17 -0
  252. package/dist/src/types/core.d.ts +178 -0
  253. package/dist/src/types/core.js +85 -0
  254. package/dist/src/types/magi-api.d.ts +62 -0
  255. package/dist/src/types/magi-api.js +7 -0
  256. package/dist/src/types/phase-h.d.ts +142 -0
  257. package/dist/src/types/phase-h.js +7 -0
  258. package/dist/src/types/phase-i.d.ts +186 -0
  259. package/dist/src/types/phase-i.js +6 -0
  260. package/dist/src/types/phase-k.d.ts +259 -0
  261. package/dist/src/types/phase-k.js +6 -0
  262. package/dist/src/types/phase-l.d.ts +199 -0
  263. package/dist/src/types/phase-l.js +6 -0
  264. package/dist/src/types/pipeline.d.ts +37 -0
  265. package/dist/src/types/pipeline.js +2 -0
  266. package/dist/src/utils/abstain-factory.d.ts +2 -0
  267. package/dist/src/utils/abstain-factory.js +18 -0
  268. package/dist/src/utils/errors.d.ts +34 -0
  269. package/dist/src/utils/errors.js +59 -0
  270. package/dist/src/utils/file-validator.d.ts +50 -0
  271. package/dist/src/utils/file-validator.js +124 -0
  272. package/dist/src/utils/fire-and-forget.d.ts +5 -0
  273. package/dist/src/utils/fire-and-forget.js +10 -0
  274. package/dist/src/utils/flag-validator.d.ts +21 -0
  275. package/dist/src/utils/flag-validator.js +79 -0
  276. package/dist/src/utils/freeze.d.ts +8 -0
  277. package/dist/src/utils/freeze.js +16 -0
  278. package/dist/src/utils/language-detector.d.ts +16 -0
  279. package/dist/src/utils/language-detector.js +159 -0
  280. package/dist/src/utils/latency-tracker.d.ts +45 -0
  281. package/dist/src/utils/latency-tracker.js +100 -0
  282. package/dist/src/utils/logger.d.ts +33 -0
  283. package/dist/src/utils/logger.js +112 -0
  284. package/dist/src/utils/process.d.ts +40 -0
  285. package/dist/src/utils/process.js +253 -0
  286. package/dist/src/utils/retry.d.ts +12 -0
  287. package/dist/src/utils/retry.js +30 -0
  288. package/dist/src/utils/safe-fs.d.ts +38 -0
  289. package/dist/src/utils/safe-fs.js +56 -0
  290. package/dist/src/utils/safe-json-parse.d.ts +15 -0
  291. package/dist/src/utils/safe-json-parse.js +49 -0
  292. package/dist/src/utils/sanitize.d.ts +14 -0
  293. package/dist/src/utils/sanitize.js +186 -0
  294. package/dist/src/utils/semaphore.d.ts +22 -0
  295. package/dist/src/utils/semaphore.js +57 -0
  296. package/dist/src/utils/shutdown.d.ts +6 -0
  297. package/dist/src/utils/shutdown.js +51 -0
  298. package/dist/src/utils/tty.d.ts +5 -0
  299. package/dist/src/utils/tty.js +7 -0
  300. 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
+ }