@phantomind/core 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 (265) hide show
  1. package/dist/adapters/aider.d.ts +12 -0
  2. package/dist/adapters/aider.d.ts.map +1 -0
  3. package/dist/adapters/aider.js +24 -0
  4. package/dist/adapters/aider.js.map +1 -0
  5. package/dist/adapters/base.d.ts +21 -0
  6. package/dist/adapters/base.d.ts.map +1 -0
  7. package/dist/adapters/base.js +83 -0
  8. package/dist/adapters/base.js.map +1 -0
  9. package/dist/adapters/claude-code.d.ts +12 -0
  10. package/dist/adapters/claude-code.d.ts.map +1 -0
  11. package/dist/adapters/claude-code.js +31 -0
  12. package/dist/adapters/claude-code.js.map +1 -0
  13. package/dist/adapters/cline.d.ts +12 -0
  14. package/dist/adapters/cline.d.ts.map +1 -0
  15. package/dist/adapters/cline.js +32 -0
  16. package/dist/adapters/cline.js.map +1 -0
  17. package/dist/adapters/codex.d.ts +18 -0
  18. package/dist/adapters/codex.d.ts.map +1 -0
  19. package/dist/adapters/codex.js +38 -0
  20. package/dist/adapters/codex.js.map +1 -0
  21. package/dist/adapters/continue.d.ts +12 -0
  22. package/dist/adapters/continue.d.ts.map +1 -0
  23. package/dist/adapters/continue.js +29 -0
  24. package/dist/adapters/continue.js.map +1 -0
  25. package/dist/adapters/copilot.d.ts +12 -0
  26. package/dist/adapters/copilot.d.ts.map +1 -0
  27. package/dist/adapters/copilot.js +31 -0
  28. package/dist/adapters/copilot.js.map +1 -0
  29. package/dist/adapters/cursor.d.ts +12 -0
  30. package/dist/adapters/cursor.d.ts.map +1 -0
  31. package/dist/adapters/cursor.js +34 -0
  32. package/dist/adapters/cursor.js.map +1 -0
  33. package/dist/adapters/index.d.ts +32 -0
  34. package/dist/adapters/index.d.ts.map +1 -0
  35. package/dist/adapters/index.js +64 -0
  36. package/dist/adapters/index.js.map +1 -0
  37. package/dist/adapters/windsurf.d.ts +12 -0
  38. package/dist/adapters/windsurf.d.ts.map +1 -0
  39. package/dist/adapters/windsurf.js +32 -0
  40. package/dist/adapters/windsurf.js.map +1 -0
  41. package/dist/adapters/zed.d.ts +12 -0
  42. package/dist/adapters/zed.d.ts.map +1 -0
  43. package/dist/adapters/zed.js +27 -0
  44. package/dist/adapters/zed.js.map +1 -0
  45. package/dist/agent/decomposer.d.ts +55 -0
  46. package/dist/agent/decomposer.d.ts.map +1 -0
  47. package/dist/agent/decomposer.js +172 -0
  48. package/dist/agent/decomposer.js.map +1 -0
  49. package/dist/agent/executor.d.ts +33 -0
  50. package/dist/agent/executor.d.ts.map +1 -0
  51. package/dist/agent/executor.js +260 -0
  52. package/dist/agent/executor.js.map +1 -0
  53. package/dist/agent/index.d.ts +8 -0
  54. package/dist/agent/index.d.ts.map +1 -0
  55. package/dist/agent/index.js +8 -0
  56. package/dist/agent/index.js.map +1 -0
  57. package/dist/agent/memory.d.ts +95 -0
  58. package/dist/agent/memory.d.ts.map +1 -0
  59. package/dist/agent/memory.js +211 -0
  60. package/dist/agent/memory.js.map +1 -0
  61. package/dist/agent/orchestrator.d.ts +54 -0
  62. package/dist/agent/orchestrator.d.ts.map +1 -0
  63. package/dist/agent/orchestrator.js +190 -0
  64. package/dist/agent/orchestrator.js.map +1 -0
  65. package/dist/agent/queue.d.ts +95 -0
  66. package/dist/agent/queue.d.ts.map +1 -0
  67. package/dist/agent/queue.js +231 -0
  68. package/dist/agent/queue.js.map +1 -0
  69. package/dist/agent/retry.d.ts +61 -0
  70. package/dist/agent/retry.d.ts.map +1 -0
  71. package/dist/agent/retry.js +162 -0
  72. package/dist/agent/retry.js.map +1 -0
  73. package/dist/agent/roles.d.ts +35 -0
  74. package/dist/agent/roles.d.ts.map +1 -0
  75. package/dist/agent/roles.js +269 -0
  76. package/dist/agent/roles.js.map +1 -0
  77. package/dist/cli/agent.d.ts +12 -0
  78. package/dist/cli/agent.d.ts.map +1 -0
  79. package/dist/cli/agent.js +85 -0
  80. package/dist/cli/agent.js.map +1 -0
  81. package/dist/cli/audit.d.ts +11 -0
  82. package/dist/cli/audit.d.ts.map +1 -0
  83. package/dist/cli/audit.js +63 -0
  84. package/dist/cli/audit.js.map +1 -0
  85. package/dist/cli/eval.d.ts +11 -0
  86. package/dist/cli/eval.d.ts.map +1 -0
  87. package/dist/cli/eval.js +79 -0
  88. package/dist/cli/eval.js.map +1 -0
  89. package/dist/cli/index.d.ts +9 -0
  90. package/dist/cli/index.d.ts.map +1 -0
  91. package/dist/cli/index.js +9 -0
  92. package/dist/cli/index.js.map +1 -0
  93. package/dist/cli/init.d.ts +13 -0
  94. package/dist/cli/init.d.ts.map +1 -0
  95. package/dist/cli/init.js +157 -0
  96. package/dist/cli/init.js.map +1 -0
  97. package/dist/cli/main.d.ts +7 -0
  98. package/dist/cli/main.d.ts.map +1 -0
  99. package/dist/cli/main.js +153 -0
  100. package/dist/cli/main.js.map +1 -0
  101. package/dist/cli/serve.d.ts +11 -0
  102. package/dist/cli/serve.d.ts.map +1 -0
  103. package/dist/cli/serve.js +23 -0
  104. package/dist/cli/serve.js.map +1 -0
  105. package/dist/cli/stats.d.ts +10 -0
  106. package/dist/cli/stats.d.ts.map +1 -0
  107. package/dist/cli/stats.js +68 -0
  108. package/dist/cli/stats.js.map +1 -0
  109. package/dist/cli/sync.d.ts +11 -0
  110. package/dist/cli/sync.d.ts.map +1 -0
  111. package/dist/cli/sync.js +49 -0
  112. package/dist/cli/sync.js.map +1 -0
  113. package/dist/cli/validate.d.ts +13 -0
  114. package/dist/cli/validate.d.ts.map +1 -0
  115. package/dist/cli/validate.js +125 -0
  116. package/dist/cli/validate.js.map +1 -0
  117. package/dist/config/index.d.ts +2 -0
  118. package/dist/config/index.d.ts.map +1 -0
  119. package/dist/config/index.js +2 -0
  120. package/dist/config/index.js.map +1 -0
  121. package/dist/config/loader.d.ts +25 -0
  122. package/dist/config/loader.d.ts.map +1 -0
  123. package/dist/config/loader.js +190 -0
  124. package/dist/config/loader.js.map +1 -0
  125. package/dist/context/embedder.d.ts +53 -0
  126. package/dist/context/embedder.d.ts.map +1 -0
  127. package/dist/context/embedder.js +235 -0
  128. package/dist/context/embedder.js.map +1 -0
  129. package/dist/context/engine.d.ts +82 -0
  130. package/dist/context/engine.d.ts.map +1 -0
  131. package/dist/context/engine.js +343 -0
  132. package/dist/context/engine.js.map +1 -0
  133. package/dist/context/index.d.ts +5 -0
  134. package/dist/context/index.d.ts.map +1 -0
  135. package/dist/context/index.js +5 -0
  136. package/dist/context/index.js.map +1 -0
  137. package/dist/context/learner.d.ts +44 -0
  138. package/dist/context/learner.d.ts.map +1 -0
  139. package/dist/context/learner.js +246 -0
  140. package/dist/context/learner.js.map +1 -0
  141. package/dist/context/versioning.d.ts +29 -0
  142. package/dist/context/versioning.d.ts.map +1 -0
  143. package/dist/context/versioning.js +81 -0
  144. package/dist/context/versioning.js.map +1 -0
  145. package/dist/index.d.ts +169 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +285 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/mcp/index.d.ts +2 -0
  150. package/dist/mcp/index.d.ts.map +1 -0
  151. package/dist/mcp/index.js +2 -0
  152. package/dist/mcp/index.js.map +1 -0
  153. package/dist/mcp/server.d.ts +31 -0
  154. package/dist/mcp/server.d.ts.map +1 -0
  155. package/dist/mcp/server.js +334 -0
  156. package/dist/mcp/server.js.map +1 -0
  157. package/dist/observability/audit.d.ts +61 -0
  158. package/dist/observability/audit.d.ts.map +1 -0
  159. package/dist/observability/audit.js +168 -0
  160. package/dist/observability/audit.js.map +1 -0
  161. package/dist/observability/cost-tracker.d.ts +71 -0
  162. package/dist/observability/cost-tracker.d.ts.map +1 -0
  163. package/dist/observability/cost-tracker.js +206 -0
  164. package/dist/observability/cost-tracker.js.map +1 -0
  165. package/dist/observability/dashboard.d.ts +52 -0
  166. package/dist/observability/dashboard.d.ts.map +1 -0
  167. package/dist/observability/dashboard.js +134 -0
  168. package/dist/observability/dashboard.js.map +1 -0
  169. package/dist/observability/index.d.ts +4 -0
  170. package/dist/observability/index.d.ts.map +1 -0
  171. package/dist/observability/index.js +4 -0
  172. package/dist/observability/index.js.map +1 -0
  173. package/dist/providers/anthropic.d.ts +14 -0
  174. package/dist/providers/anthropic.d.ts.map +1 -0
  175. package/dist/providers/anthropic.js +99 -0
  176. package/dist/providers/anthropic.js.map +1 -0
  177. package/dist/providers/base.d.ts +52 -0
  178. package/dist/providers/base.d.ts.map +1 -0
  179. package/dist/providers/base.js +68 -0
  180. package/dist/providers/base.js.map +1 -0
  181. package/dist/providers/deepseek.d.ts +15 -0
  182. package/dist/providers/deepseek.d.ts.map +1 -0
  183. package/dist/providers/deepseek.js +99 -0
  184. package/dist/providers/deepseek.js.map +1 -0
  185. package/dist/providers/gemini.d.ts +15 -0
  186. package/dist/providers/gemini.d.ts.map +1 -0
  187. package/dist/providers/gemini.js +118 -0
  188. package/dist/providers/gemini.js.map +1 -0
  189. package/dist/providers/groq.d.ts +15 -0
  190. package/dist/providers/groq.d.ts.map +1 -0
  191. package/dist/providers/groq.js +101 -0
  192. package/dist/providers/groq.js.map +1 -0
  193. package/dist/providers/index.d.ts +11 -0
  194. package/dist/providers/index.d.ts.map +1 -0
  195. package/dist/providers/index.js +11 -0
  196. package/dist/providers/index.js.map +1 -0
  197. package/dist/providers/mistral.d.ts +15 -0
  198. package/dist/providers/mistral.d.ts.map +1 -0
  199. package/dist/providers/mistral.js +99 -0
  200. package/dist/providers/mistral.js.map +1 -0
  201. package/dist/providers/ollama.d.ts +14 -0
  202. package/dist/providers/ollama.d.ts.map +1 -0
  203. package/dist/providers/ollama.js +122 -0
  204. package/dist/providers/ollama.js.map +1 -0
  205. package/dist/providers/openai.d.ts +14 -0
  206. package/dist/providers/openai.d.ts.map +1 -0
  207. package/dist/providers/openai.js +80 -0
  208. package/dist/providers/openai.js.map +1 -0
  209. package/dist/providers/openrouter.d.ts +15 -0
  210. package/dist/providers/openrouter.d.ts.map +1 -0
  211. package/dist/providers/openrouter.js +101 -0
  212. package/dist/providers/openrouter.js.map +1 -0
  213. package/dist/providers/router.d.ts +51 -0
  214. package/dist/providers/router.d.ts.map +1 -0
  215. package/dist/providers/router.js +198 -0
  216. package/dist/providers/router.js.map +1 -0
  217. package/dist/quality/anomaly.d.ts +32 -0
  218. package/dist/quality/anomaly.d.ts.map +1 -0
  219. package/dist/quality/anomaly.js +126 -0
  220. package/dist/quality/anomaly.js.map +1 -0
  221. package/dist/quality/consistency.d.ts +26 -0
  222. package/dist/quality/consistency.d.ts.map +1 -0
  223. package/dist/quality/consistency.js +156 -0
  224. package/dist/quality/consistency.js.map +1 -0
  225. package/dist/quality/dual-verifier.d.ts +22 -0
  226. package/dist/quality/dual-verifier.d.ts.map +1 -0
  227. package/dist/quality/dual-verifier.js +137 -0
  228. package/dist/quality/dual-verifier.js.map +1 -0
  229. package/dist/quality/hallucination-guard.d.ts +57 -0
  230. package/dist/quality/hallucination-guard.d.ts.map +1 -0
  231. package/dist/quality/hallucination-guard.js +245 -0
  232. package/dist/quality/hallucination-guard.js.map +1 -0
  233. package/dist/quality/index.d.ts +7 -0
  234. package/dist/quality/index.d.ts.map +1 -0
  235. package/dist/quality/index.js +7 -0
  236. package/dist/quality/index.js.map +1 -0
  237. package/dist/quality/regression.d.ts +44 -0
  238. package/dist/quality/regression.d.ts.map +1 -0
  239. package/dist/quality/regression.js +181 -0
  240. package/dist/quality/regression.js.map +1 -0
  241. package/dist/quality/secret-scanner.d.ts +36 -0
  242. package/dist/quality/secret-scanner.d.ts.map +1 -0
  243. package/dist/quality/secret-scanner.js +187 -0
  244. package/dist/quality/secret-scanner.js.map +1 -0
  245. package/dist/schemas/index.d.ts +2 -0
  246. package/dist/schemas/index.d.ts.map +1 -0
  247. package/dist/schemas/index.js +2 -0
  248. package/dist/schemas/index.js.map +1 -0
  249. package/dist/schemas/registry.d.ts +72 -0
  250. package/dist/schemas/registry.d.ts.map +1 -0
  251. package/dist/schemas/registry.js +483 -0
  252. package/dist/schemas/registry.js.map +1 -0
  253. package/dist/templates/engine.d.ts +70 -0
  254. package/dist/templates/engine.d.ts.map +1 -0
  255. package/dist/templates/engine.js +71 -0
  256. package/dist/templates/engine.js.map +1 -0
  257. package/dist/templates/index.d.ts +2 -0
  258. package/dist/templates/index.d.ts.map +1 -0
  259. package/dist/templates/index.js +2 -0
  260. package/dist/templates/index.js.map +1 -0
  261. package/dist/types.d.ts +912 -0
  262. package/dist/types.d.ts.map +1 -0
  263. package/dist/types.js +75 -0
  264. package/dist/types.js.map +1 -0
  265. package/package.json +85 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * PhantomMindAI — Cross-File Consistency Enforcer
3
+ * Detect naming, pattern, and architecture inconsistencies.
4
+ */
5
+ import type { ConsistencyReport } from '../types.js';
6
+ export declare class ConsistencyEnforcer {
7
+ private projectRoot;
8
+ constructor(projectRoot: string);
9
+ /**
10
+ * Run full consistency scan
11
+ */
12
+ scan(scope?: 'naming' | 'pattern' | 'architecture' | 'all'): Promise<ConsistencyReport>;
13
+ /**
14
+ * Check naming convention consistency
15
+ */
16
+ private checkNamingConsistency;
17
+ /**
18
+ * Check async pattern consistency
19
+ */
20
+ private checkPatternConsistency;
21
+ /**
22
+ * Check architecture layer consistency
23
+ */
24
+ private checkArchitectureConsistency;
25
+ }
26
+ //# sourceMappingURL=consistency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consistency.d.ts","sourceRoot":"","sources":["../../src/quality/consistency.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAEvE,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAI/B;;OAEG;IACG,IAAI,CAAC,KAAK,GAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,KAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsCpG;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6C9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgC/B;;OAEG;IACH,OAAO,CAAC,4BAA4B;CAoCrC"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * PhantomMindAI — Cross-File Consistency Enforcer
3
+ * Detect naming, pattern, and architecture inconsistencies.
4
+ */
5
+ import { readFile } from 'node:fs/promises';
6
+ import { join, extname } from 'node:path';
7
+ import fastGlob from 'fast-glob';
8
+ export class ConsistencyEnforcer {
9
+ projectRoot;
10
+ constructor(projectRoot) {
11
+ this.projectRoot = projectRoot;
12
+ }
13
+ /**
14
+ * Run full consistency scan
15
+ */
16
+ async scan(scope = 'all') {
17
+ const start = Date.now();
18
+ const issues = [];
19
+ const files = await fastGlob('**/*.{ts,tsx,js,jsx,swift,go,py}', {
20
+ cwd: this.projectRoot,
21
+ ignore: ['node_modules/**', 'dist/**', '.git/**'],
22
+ });
23
+ const fileContents = new Map();
24
+ for (const file of files) {
25
+ try {
26
+ const content = await readFile(join(this.projectRoot, file), 'utf-8');
27
+ fileContents.set(file, content);
28
+ }
29
+ catch {
30
+ continue;
31
+ }
32
+ }
33
+ if (scope === 'all' || scope === 'naming') {
34
+ issues.push(...this.checkNamingConsistency(fileContents));
35
+ }
36
+ if (scope === 'all' || scope === 'pattern') {
37
+ issues.push(...this.checkPatternConsistency(fileContents));
38
+ }
39
+ if (scope === 'all' || scope === 'architecture') {
40
+ issues.push(...this.checkArchitectureConsistency(fileContents));
41
+ }
42
+ return {
43
+ issues,
44
+ scannedFiles: files.length,
45
+ duration: Date.now() - start,
46
+ };
47
+ }
48
+ /**
49
+ * Check naming convention consistency
50
+ */
51
+ checkNamingConsistency(files) {
52
+ const issues = [];
53
+ const errorTypes = new Map();
54
+ const serviceTypes = new Map();
55
+ for (const [file, content] of files) {
56
+ // Check error type naming
57
+ const errorMatches = content.match(/(?:class|type|interface)\s+(\w*(?:Error|Exception|Failure)\w*)/g) ?? [];
58
+ for (const match of errorMatches) {
59
+ const name = match.split(/\s+/).pop();
60
+ const suffix = name.endsWith('Error') ? 'Error' : name.endsWith('Exception') ? 'Exception' : 'Failure';
61
+ const list = errorTypes.get(suffix) ?? [];
62
+ list.push(file);
63
+ errorTypes.set(suffix, list);
64
+ }
65
+ // Check service naming
66
+ const serviceMatches = content.match(/(?:class|type|interface)\s+(\w*(?:Service|Manager|Controller|Handler)\w*)/g) ?? [];
67
+ for (const match of serviceMatches) {
68
+ const name = match.split(/\s+/).pop();
69
+ for (const suffix of ['Service', 'Manager', 'Controller', 'Handler']) {
70
+ if (name.endsWith(suffix)) {
71
+ const list = serviceTypes.get(suffix) ?? [];
72
+ list.push(file);
73
+ serviceTypes.set(suffix, list);
74
+ }
75
+ }
76
+ }
77
+ }
78
+ // Flag if multiple error naming conventions
79
+ if (errorTypes.size > 1) {
80
+ const allFiles = [...errorTypes.values()].flat();
81
+ issues.push({
82
+ type: 'naming',
83
+ description: `Mixed error type naming: ${[...errorTypes.keys()].join(', ')}. Use one convention.`,
84
+ files: [...new Set(allFiles)],
85
+ suggestion: 'Standardize error types to use a single suffix (e.g., always "Error").',
86
+ autoFixable: false,
87
+ });
88
+ }
89
+ return issues;
90
+ }
91
+ /**
92
+ * Check async pattern consistency
93
+ */
94
+ checkPatternConsistency(files) {
95
+ const issues = [];
96
+ const asyncPatterns = new Map();
97
+ for (const [file, content] of files) {
98
+ const ext = extname(file);
99
+ if (ext !== '.ts' && ext !== '.tsx' && ext !== '.js' && ext !== '.jsx')
100
+ continue;
101
+ // Check for mixed callback and async/await
102
+ const hasCallbacks = /\.then\s*\(/.test(content);
103
+ const hasAsyncAwait = /async\s+/.test(content);
104
+ if (hasCallbacks && hasAsyncAwait) {
105
+ const list = asyncPatterns.get('mixed') ?? [];
106
+ list.push(file);
107
+ asyncPatterns.set('mixed', list);
108
+ }
109
+ }
110
+ if (asyncPatterns.has('mixed') && (asyncPatterns.get('mixed')?.length ?? 0) > 2) {
111
+ issues.push({
112
+ type: 'pattern',
113
+ description: 'Mixed async patterns: both .then() callbacks and async/await used.',
114
+ files: asyncPatterns.get('mixed'),
115
+ suggestion: 'Prefer async/await consistently over .then() callbacks.',
116
+ autoFixable: false,
117
+ });
118
+ }
119
+ return issues;
120
+ }
121
+ /**
122
+ * Check architecture layer consistency
123
+ */
124
+ checkArchitectureConsistency(files) {
125
+ const issues = [];
126
+ for (const [file, content] of files) {
127
+ // Check if ViewModels import from data layer directly
128
+ if (file.includes('ViewModel') || file.includes('viewmodel') || file.includes('view-model')) {
129
+ if (content.includes('import') && (content.match(/from\s+['"].*(?:database|db|sql|prisma|mongoose|typeorm)/i) ||
130
+ content.match(/from\s+['"].*(?:repository|repo)/i))) {
131
+ issues.push({
132
+ type: 'architecture',
133
+ description: `ViewModel directly imports data layer in ${file}.`,
134
+ files: [file],
135
+ suggestion: 'ViewModels should access data through a service/use-case layer, not directly.',
136
+ autoFixable: false,
137
+ });
138
+ }
139
+ }
140
+ // Check if Views import from data layer
141
+ if (file.includes('View') || file.includes('Component') || file.includes('.vue') || file.includes('.svelte')) {
142
+ if (content.match(/from\s+['"].*(?:database|db|sql|prisma|mongoose|typeorm)/i)) {
143
+ issues.push({
144
+ type: 'architecture',
145
+ description: `View/Component directly imports data layer in ${file}.`,
146
+ files: [file],
147
+ suggestion: 'Views should never access the data layer directly.',
148
+ autoFixable: false,
149
+ });
150
+ }
151
+ }
152
+ }
153
+ return issues;
154
+ }
155
+ }
156
+ //# sourceMappingURL=consistency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consistency.js","sourceRoot":"","sources":["../../src/quality/consistency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * PhantomMindAI — Dual-Model Verifier
3
+ * Verify critical outputs with a second model from a different provider.
4
+ */
5
+ import type { ProviderRouter } from '../providers/router.js';
6
+ import type { ContextEngine } from '../context/engine.js';
7
+ import type { VerificationResult, PhantomConfig } from '../types.js';
8
+ export declare class DualVerifier {
9
+ private router;
10
+ private contextEngine;
11
+ private config;
12
+ constructor(router: ProviderRouter, contextEngine: ContextEngine, config: PhantomConfig);
13
+ /**
14
+ * Verify generated content using a second model
15
+ */
16
+ verify(generatedContent: string, taskDescription: string, sourceFile?: string): Promise<VerificationResult>;
17
+ /**
18
+ * Parse the verification model's response
19
+ */
20
+ private parseVerificationResponse;
21
+ }
22
+ //# sourceMappingURL=dual-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-verifier.d.ts","sourceRoot":"","sources":["../../src/quality/dual-verifier.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAyC,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5G,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa;IAMvF;;OAEG;IACG,MAAM,CACV,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,EACvB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAqG9B;;OAEG;IACH,OAAO,CAAC,yBAAyB;CAuBlC"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * PhantomMindAI — Dual-Model Verifier
3
+ * Verify critical outputs with a second model from a different provider.
4
+ */
5
+ export class DualVerifier {
6
+ router;
7
+ contextEngine;
8
+ config;
9
+ constructor(router, contextEngine, config) {
10
+ this.router = router;
11
+ this.contextEngine = contextEngine;
12
+ this.config = config;
13
+ }
14
+ /**
15
+ * Verify generated content using a second model
16
+ */
17
+ async verify(generatedContent, taskDescription, sourceFile) {
18
+ const start = Date.now();
19
+ // Get project context for verification
20
+ const context = await this.contextEngine.getProjectContext({
21
+ file: sourceFile,
22
+ maxTokens: 2000,
23
+ includeSkills: true,
24
+ includeRules: true,
25
+ });
26
+ const contextText = context.layers.map(l => l.content).join('\n\n');
27
+ const verificationPrompt = `You are a code reviewer verifying AI-generated output against project conventions.
28
+
29
+ ## Project Context
30
+ ${contextText}
31
+
32
+ ## Task Description
33
+ ${taskDescription}
34
+
35
+ ## Generated Content
36
+ \`\`\`
37
+ ${generatedContent}
38
+ \`\`\`
39
+
40
+ ## Review Checklist
41
+ 1. Does this conform to the project conventions described above?
42
+ 2. Are there unhandled edge cases?
43
+ 3. Any security concerns (injection, auth bypass, data exposure)?
44
+ 4. Any performance concerns?
45
+ 5. Are there correctness issues?
46
+
47
+ Respond in this exact JSON format:
48
+ {
49
+ "approved": true/false,
50
+ "issues": [
51
+ {
52
+ "severity": "error|warning|info",
53
+ "category": "convention|security|edge-case|performance|correctness",
54
+ "description": "description of the issue",
55
+ "suggestion": "how to fix it",
56
+ "line": null
57
+ }
58
+ ]
59
+ }
60
+
61
+ Only respond with the JSON, no other text.`;
62
+ // Use the verification provider
63
+ const verificationProvider = this.config.quality.dualVerificationProvider ?? 'openai';
64
+ const provider = this.router.getProvider(verificationProvider) ?? this.router.getSlotProvider('fallback');
65
+ if (!provider) {
66
+ return {
67
+ approved: true,
68
+ provider: verificationProvider,
69
+ model: 'unavailable',
70
+ issues: [{
71
+ severity: 'info',
72
+ category: 'correctness',
73
+ description: 'Verification provider not available. Skipped.',
74
+ }],
75
+ duration: Date.now() - start,
76
+ cost: { inputTokens: 0, outputTokens: 0, totalTokens: 0, estimatedCost: 0 },
77
+ };
78
+ }
79
+ try {
80
+ const response = await provider.complete({
81
+ prompt: verificationPrompt,
82
+ temperature: 0.1,
83
+ maxTokens: 2000,
84
+ });
85
+ const parsed = this.parseVerificationResponse(response.content);
86
+ return {
87
+ approved: parsed.approved,
88
+ provider: verificationProvider,
89
+ model: response.model,
90
+ issues: parsed.issues,
91
+ duration: Date.now() - start,
92
+ cost: response.usage,
93
+ };
94
+ }
95
+ catch (error) {
96
+ return {
97
+ approved: true,
98
+ provider: verificationProvider,
99
+ model: 'error',
100
+ issues: [{
101
+ severity: 'info',
102
+ category: 'correctness',
103
+ description: `Verification failed: ${error.message}`,
104
+ }],
105
+ duration: Date.now() - start,
106
+ cost: { inputTokens: 0, outputTokens: 0, totalTokens: 0, estimatedCost: 0 },
107
+ };
108
+ }
109
+ }
110
+ /**
111
+ * Parse the verification model's response
112
+ */
113
+ parseVerificationResponse(content) {
114
+ try {
115
+ // Extract JSON from response
116
+ const jsonMatch = content.match(/\{[\s\S]*\}/);
117
+ if (!jsonMatch) {
118
+ return { approved: true, issues: [] };
119
+ }
120
+ const parsed = JSON.parse(jsonMatch[0]);
121
+ return {
122
+ approved: parsed.approved ?? true,
123
+ issues: (parsed.issues ?? []).map((issue) => ({
124
+ severity: issue.severity ?? 'info',
125
+ category: issue.category ?? 'correctness',
126
+ description: issue.description ?? '',
127
+ suggestion: issue.suggestion,
128
+ line: issue.line,
129
+ })),
130
+ };
131
+ }
132
+ catch {
133
+ return { approved: true, issues: [] };
134
+ }
135
+ }
136
+ }
137
+ //# sourceMappingURL=dual-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-verifier.js","sourceRoot":"","sources":["../../src/quality/dual-verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * PhantomMindAI — Hallucination Guard
3
+ * Pre-write check that detects when AI references non-existent entities.
4
+ */
5
+ import type { HallucinationCheck } from '../types.js';
6
+ export declare class HallucinationGuard {
7
+ private projectRoot;
8
+ private packageNames;
9
+ private projectFiles;
10
+ private projectTypes;
11
+ constructor(projectRoot: string);
12
+ /**
13
+ * Check content for hallucinations
14
+ */
15
+ check(content: string, fileName?: string): Promise<HallucinationCheck[]>;
16
+ /**
17
+ * Check import statements against actual dependencies
18
+ */
19
+ private checkImports;
20
+ /**
21
+ * Check file path references
22
+ */
23
+ private checkFilePaths;
24
+ /**
25
+ * Check type/class references in TypeScript
26
+ */
27
+ private checkTypeReferences;
28
+ /**
29
+ * Get all package names from package.json
30
+ */
31
+ private getPackageNames;
32
+ /**
33
+ * Get list of all project files
34
+ */
35
+ private getProjectFiles;
36
+ /**
37
+ * Check if a file path exists
38
+ */
39
+ private fileExists;
40
+ /**
41
+ * Check if a module is a Node.js built-in
42
+ */
43
+ private isNodeBuiltin;
44
+ /**
45
+ * Find similar strings using edit distance
46
+ */
47
+ private findSimilar;
48
+ /**
49
+ * Simple string similarity (Dice coefficient)
50
+ */
51
+ private similarity;
52
+ /**
53
+ * Clear cached data
54
+ */
55
+ clearCache(): void;
56
+ }
57
+ //# sourceMappingURL=hallucination-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucination-guard.d.ts","sourceRoot":"","sources":["../../src/quality/hallucination-guard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,YAAY,CAA4B;gBAEpC,WAAW,EAAE,MAAM;IAI/B;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAuBjF;;OAEG;YACW,YAAY;IA4D1B;;OAEG;YACW,cAAc;IA8B5B;;OAEG;YACW,mBAAmB;IAKjC;;OAEG;YACW,eAAe;IAuB7B;;OAEG;YACW,eAAe;IAiB7B;;OAEG;YACW,UAAU;IASxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBlB;;OAEG;IACH,UAAU,IAAI,IAAI;CAKnB"}
@@ -0,0 +1,245 @@
1
+ /**
2
+ * PhantomMindAI — Hallucination Guard
3
+ * Pre-write check that detects when AI references non-existent entities.
4
+ */
5
+ import { readFile, access } from 'node:fs/promises';
6
+ import { join, extname } from 'node:path';
7
+ import fastGlob from 'fast-glob';
8
+ export class HallucinationGuard {
9
+ projectRoot;
10
+ packageNames = null;
11
+ projectFiles = null;
12
+ projectTypes = null;
13
+ constructor(projectRoot) {
14
+ this.projectRoot = projectRoot;
15
+ }
16
+ /**
17
+ * Check content for hallucinations
18
+ */
19
+ async check(content, fileName = 'unknown') {
20
+ const checks = [];
21
+ const lines = content.split('\n');
22
+ for (let i = 0; i < lines.length; i++) {
23
+ const line = lines[i];
24
+ // Check import statements
25
+ const importChecks = await this.checkImports(line, fileName, i + 1);
26
+ checks.push(...importChecks);
27
+ // Check file path references
28
+ const fileChecks = await this.checkFilePaths(line, fileName, i + 1);
29
+ checks.push(...fileChecks);
30
+ // Check type/class references
31
+ const typeChecks = await this.checkTypeReferences(line, fileName, i + 1);
32
+ checks.push(...typeChecks);
33
+ }
34
+ return checks.filter(c => !c.exists);
35
+ }
36
+ /**
37
+ * Check import statements against actual dependencies
38
+ */
39
+ async checkImports(line, file, lineNum) {
40
+ const checks = [];
41
+ // TypeScript/JavaScript imports
42
+ const tsImportMatch = line.match(/(?:import|from)\s+['"]([^'"./][^'"]*)['"]/);
43
+ if (tsImportMatch) {
44
+ const pkgName = tsImportMatch[1].startsWith('@')
45
+ ? tsImportMatch[1].split('/').slice(0, 2).join('/')
46
+ : tsImportMatch[1].split('/')[0];
47
+ const packages = await this.getPackageNames();
48
+ const exists = packages.has(pkgName) || this.isNodeBuiltin(pkgName);
49
+ checks.push({
50
+ type: 'import',
51
+ reference: pkgName,
52
+ exists,
53
+ suggestions: exists ? undefined : this.findSimilar(pkgName, [...packages]),
54
+ file,
55
+ line: lineNum,
56
+ });
57
+ }
58
+ // Swift imports
59
+ const swiftImportMatch = line.match(/^import\s+(\w+)/);
60
+ if (swiftImportMatch && !tsImportMatch) {
61
+ const module = swiftImportMatch[1];
62
+ const swiftBuiltins = new Set([
63
+ 'Foundation', 'UIKit', 'SwiftUI', 'Combine', 'CoreData', 'MapKit',
64
+ 'WebKit', 'AVFoundation', 'CoreLocation', 'StoreKit', 'WidgetKit',
65
+ 'ActivityKit', 'SwiftData', 'Observation', 'XCTest', 'Testing',
66
+ ]);
67
+ checks.push({
68
+ type: 'import',
69
+ reference: module,
70
+ exists: swiftBuiltins.has(module),
71
+ suggestions: this.findSimilar(module, [...swiftBuiltins]),
72
+ file,
73
+ line: lineNum,
74
+ });
75
+ }
76
+ // Python imports
77
+ const pyImportMatch = line.match(/^(?:from|import)\s+([\w.]+)/);
78
+ if (pyImportMatch && !tsImportMatch && !swiftImportMatch) {
79
+ const module = pyImportMatch[1].split('.')[0];
80
+ // We can't fully validate Python imports without pip list, so mark as exists
81
+ checks.push({
82
+ type: 'import',
83
+ reference: module,
84
+ exists: true,
85
+ file,
86
+ line: lineNum,
87
+ });
88
+ }
89
+ return checks;
90
+ }
91
+ /**
92
+ * Check file path references
93
+ */
94
+ async checkFilePaths(line, file, lineNum) {
95
+ const checks = [];
96
+ // Match quoted file paths that look like relative paths
97
+ const pathMatches = line.matchAll(/['"](\.\/?[^'"]+\.(ts|js|tsx|jsx|swift|go|py|json|yaml|yml|md))['"]/g);
98
+ for (const match of pathMatches) {
99
+ const refPath = match[1];
100
+ const exists = await this.fileExists(refPath);
101
+ if (!exists) {
102
+ const projectFiles = await this.getProjectFiles();
103
+ const baseName = refPath.split('/').pop() ?? '';
104
+ const suggestions = [...projectFiles]
105
+ .filter(f => f.includes(baseName.replace(extname(baseName), '')))
106
+ .slice(0, 3);
107
+ checks.push({
108
+ type: 'file',
109
+ reference: refPath,
110
+ exists: false,
111
+ suggestions,
112
+ file,
113
+ line: lineNum,
114
+ });
115
+ }
116
+ }
117
+ return checks;
118
+ }
119
+ /**
120
+ * Check type/class references in TypeScript
121
+ */
122
+ async checkTypeReferences(line, file, lineNum) {
123
+ // Skip checking type references for performance — rely on TypeScript compiler
124
+ return [];
125
+ }
126
+ /**
127
+ * Get all package names from package.json
128
+ */
129
+ async getPackageNames() {
130
+ if (this.packageNames)
131
+ return this.packageNames;
132
+ this.packageNames = new Set();
133
+ try {
134
+ const pkgJson = await readFile(join(this.projectRoot, 'package.json'), 'utf-8');
135
+ const pkg = JSON.parse(pkgJson);
136
+ const deps = {
137
+ ...pkg.dependencies,
138
+ ...pkg.devDependencies,
139
+ ...pkg.peerDependencies,
140
+ };
141
+ for (const name of Object.keys(deps)) {
142
+ this.packageNames.add(name);
143
+ }
144
+ }
145
+ catch {
146
+ // No package.json
147
+ }
148
+ return this.packageNames;
149
+ }
150
+ /**
151
+ * Get list of all project files
152
+ */
153
+ async getProjectFiles() {
154
+ if (this.projectFiles)
155
+ return this.projectFiles;
156
+ try {
157
+ const files = await fastGlob('**/*', {
158
+ cwd: this.projectRoot,
159
+ ignore: ['node_modules/**', 'dist/**', '.git/**'],
160
+ onlyFiles: true,
161
+ });
162
+ this.projectFiles = new Set(files);
163
+ }
164
+ catch {
165
+ this.projectFiles = new Set();
166
+ }
167
+ return this.projectFiles;
168
+ }
169
+ /**
170
+ * Check if a file path exists
171
+ */
172
+ async fileExists(refPath) {
173
+ try {
174
+ await access(join(this.projectRoot, refPath));
175
+ return true;
176
+ }
177
+ catch {
178
+ return false;
179
+ }
180
+ }
181
+ /**
182
+ * Check if a module is a Node.js built-in
183
+ */
184
+ isNodeBuiltin(name) {
185
+ const builtins = new Set([
186
+ 'assert', 'buffer', 'child_process', 'cluster', 'console', 'constants',
187
+ 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https',
188
+ 'module', 'net', 'os', 'path', 'perf_hooks', 'process', 'punycode',
189
+ 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'sys',
190
+ 'timers', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'wasi',
191
+ 'worker_threads', 'zlib',
192
+ 'node:assert', 'node:buffer', 'node:child_process', 'node:cluster',
193
+ 'node:crypto', 'node:dgram', 'node:dns', 'node:events', 'node:fs',
194
+ 'node:http', 'node:https', 'node:module', 'node:net', 'node:os',
195
+ 'node:path', 'node:perf_hooks', 'node:process', 'node:readline',
196
+ 'node:stream', 'node:string_decoder', 'node:timers', 'node:tls',
197
+ 'node:tty', 'node:url', 'node:util', 'node:v8', 'node:vm',
198
+ 'node:worker_threads', 'node:zlib', 'node:test',
199
+ ]);
200
+ return builtins.has(name) || name.startsWith('node:');
201
+ }
202
+ /**
203
+ * Find similar strings using edit distance
204
+ */
205
+ findSimilar(target, candidates, maxResults = 3) {
206
+ const scored = candidates
207
+ .map(c => ({ name: c, score: this.similarity(target, c) }))
208
+ .filter(c => c.score > 0.3)
209
+ .sort((a, b) => b.score - a.score);
210
+ return scored.slice(0, maxResults).map(s => s.name);
211
+ }
212
+ /**
213
+ * Simple string similarity (Dice coefficient)
214
+ */
215
+ similarity(a, b) {
216
+ if (a === b)
217
+ return 1;
218
+ if (a.length < 2 || b.length < 2)
219
+ return 0;
220
+ const aBigrams = new Map();
221
+ for (let i = 0; i < a.length - 1; i++) {
222
+ const bigram = a.slice(i, i + 2).toLowerCase();
223
+ aBigrams.set(bigram, (aBigrams.get(bigram) ?? 0) + 1);
224
+ }
225
+ let matches = 0;
226
+ for (let i = 0; i < b.length - 1; i++) {
227
+ const bigram = b.slice(i, i + 2).toLowerCase();
228
+ const count = aBigrams.get(bigram) ?? 0;
229
+ if (count > 0) {
230
+ aBigrams.set(bigram, count - 1);
231
+ matches++;
232
+ }
233
+ }
234
+ return (2 * matches) / (a.length + b.length - 2);
235
+ }
236
+ /**
237
+ * Clear cached data
238
+ */
239
+ clearCache() {
240
+ this.packageNames = null;
241
+ this.projectFiles = null;
242
+ this.projectTypes = null;
243
+ }
244
+ }
245
+ //# sourceMappingURL=hallucination-guard.js.map