tryassay 0.15.0 → 0.16.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.
@@ -0,0 +1,373 @@
1
+ /**
2
+ * IntegrationVerifier — deterministic wiring checks for generated applications.
3
+ *
4
+ * Catches four classes of integration failure that compile clean but don't work:
5
+ * 1. Missing Router provider (pages use react-router hooks but no Router wraps them)
6
+ * 2. Missing IPC handlers (preload invokes channels with no main-process handler)
7
+ * 3. Stub functions (async functions that return literal objects without doing real work)
8
+ * 4. Unreachable pages (page files exist but are never imported from the entry point)
9
+ *
10
+ * Zero LLM calls. Deterministic. Uses only node:fs/promises, node:path, and regex.
11
+ */
12
+ import { readdir, readFile } from 'node:fs/promises';
13
+ import { join, relative, basename, extname } from 'node:path';
14
+ export class IntegrationVerifier {
15
+ projectPath;
16
+ framework;
17
+ constructor(projectPath, framework) {
18
+ this.projectPath = projectPath;
19
+ this.framework = framework;
20
+ }
21
+ async verify() {
22
+ const start = Date.now();
23
+ const checks = [];
24
+ // Run all checks
25
+ checks.push(...await this.checkRoutingProvider());
26
+ if (this.framework === 'electron' || await this.hasPreloadFiles()) {
27
+ checks.push(...await this.checkIpcHandlerCoverage());
28
+ checks.push(...await this.checkStubFunctions());
29
+ }
30
+ checks.push(...await this.checkUnreachablePages());
31
+ const passedCount = checks.filter(c => c.verdict === 'PASS').length;
32
+ const failedCount = checks.filter(c => c.verdict === 'FAIL').length;
33
+ return {
34
+ checks,
35
+ passedCount,
36
+ failedCount,
37
+ verdict: failedCount > 0 ? 'FAIL' : 'PASS',
38
+ framework: this.framework,
39
+ totalDurationMs: Date.now() - start,
40
+ };
41
+ }
42
+ // ── Check 1: Routing Provider ──────────────────────────────
43
+ /**
44
+ * Scan all .tsx files for react-router hook usage.
45
+ * If found, verify a Router provider exists in the entry point chain.
46
+ */
47
+ async checkRoutingProvider() {
48
+ const tsxFiles = await this.findFiles(this.projectPath, /\.(tsx|jsx)$/);
49
+ const routerHookPattern = /\b(useNavigate|useParams|useLocation|useSearchParams|useMatch|useRoutes)\b/;
50
+ const routerProviderPattern = /\b(BrowserRouter|HashRouter|MemoryRouter|RouterProvider|createBrowserRouter|createHashRouter|createMemoryRouter)\b/;
51
+ // Find files that use router hooks
52
+ const filesUsingHooks = [];
53
+ for (const file of tsxFiles) {
54
+ const content = await readFile(file, 'utf-8');
55
+ if (routerHookPattern.test(content)) {
56
+ filesUsingHooks.push(file);
57
+ }
58
+ }
59
+ if (filesUsingHooks.length === 0) {
60
+ return []; // No router hooks used — nothing to check
61
+ }
62
+ // Check if ANY file in the project contains a Router provider
63
+ let providerFound = false;
64
+ let providerFile = '';
65
+ for (const file of tsxFiles) {
66
+ const content = await readFile(file, 'utf-8');
67
+ if (routerProviderPattern.test(content)) {
68
+ providerFound = true;
69
+ providerFile = relative(this.projectPath, file);
70
+ break;
71
+ }
72
+ }
73
+ if (providerFound) {
74
+ return [{
75
+ type: 'routing_provider',
76
+ verdict: 'PASS',
77
+ evidence: `Router provider found in ${providerFile}. ${filesUsingHooks.length} file(s) use router hooks.`,
78
+ file: providerFile,
79
+ severity: 'critical',
80
+ }];
81
+ }
82
+ const hookFiles = filesUsingHooks.map(f => relative(this.projectPath, f)).join(', ');
83
+ return [{
84
+ type: 'routing_provider',
85
+ verdict: 'FAIL',
86
+ evidence: `${filesUsingHooks.length} file(s) use react-router hooks (${hookFiles}) but no Router provider (BrowserRouter, HashRouter, etc.) found in any .tsx file.`,
87
+ file: hookFiles,
88
+ severity: 'critical',
89
+ }];
90
+ }
91
+ // ── Check 2: IPC Handler Coverage ──────────────────────────
92
+ /**
93
+ * Electron only. Scan preload files for ipcRenderer.invoke calls.
94
+ * Scan main/ipc files for ipcMain.handle calls.
95
+ * Report any channel invoked but not handled.
96
+ */
97
+ async checkIpcHandlerCoverage() {
98
+ const allFiles = await this.findFiles(this.projectPath, /\.(ts|tsx|js|jsx)$/);
99
+ // Find channels invoked in preload (renderer-side)
100
+ const invokedChannels = new Map(); // channel -> file
101
+ const invokePattern = /ipcRenderer\.invoke\(\s*['"`]([^'"`]+)['"`]/g;
102
+ for (const file of allFiles) {
103
+ const relPath = relative(this.projectPath, file);
104
+ if (!relPath.includes('preload'))
105
+ continue;
106
+ const content = await readFile(file, 'utf-8');
107
+ let match;
108
+ while ((match = invokePattern.exec(content)) !== null) {
109
+ invokedChannels.set(match[1], relPath);
110
+ }
111
+ }
112
+ if (invokedChannels.size === 0) {
113
+ return []; // No IPC invoke calls found
114
+ }
115
+ // Find channels handled in main process
116
+ const handledChannels = new Set();
117
+ const handlePattern = /ipcMain\.handle\(\s*['"`]([^'"`]+)['"`]/g;
118
+ // Also check for IPC_CHANNELS.CONSTANT patterns that resolve to string literals
119
+ const channelConstPattern = /ipcMain\.handle\(\s*(?:IPC_CHANNELS\.\w+|[\w.]+)\s*,/g;
120
+ for (const file of allFiles) {
121
+ const relPath = relative(this.projectPath, file);
122
+ // Check main process files (main/, ipc/, handlers/)
123
+ if (!relPath.includes('main') && !relPath.includes('ipc') && !relPath.includes('handler'))
124
+ continue;
125
+ const content = await readFile(file, 'utf-8');
126
+ // Direct string channel handles
127
+ let match;
128
+ while ((match = handlePattern.exec(content)) !== null) {
129
+ handledChannels.add(match[1]);
130
+ }
131
+ // Also resolve IPC_CHANNELS constants by scanning for their definitions
132
+ const constDefPattern = /['"`]([^'"`]+)['"`]\s*(?:,|as\s+const)/g;
133
+ if (relPath.includes('handler') || relPath.includes('ipc')) {
134
+ while ((match = constDefPattern.exec(content)) !== null) {
135
+ // Only add if it looks like a channel name (contains colon)
136
+ if (match[1].includes(':')) {
137
+ handledChannels.add(match[1]);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ // Also scan shared types for IPC_CHANNELS constant definitions
143
+ for (const file of allFiles) {
144
+ const relPath = relative(this.projectPath, file);
145
+ if (!relPath.includes('shared') && !relPath.includes('types'))
146
+ continue;
147
+ const content = await readFile(file, 'utf-8');
148
+ const channelValuePattern = /:\s*['"`]([^'"`]+)['"`]/g;
149
+ if (content.includes('IPC_CHANNELS')) {
150
+ let match;
151
+ while ((match = channelValuePattern.exec(content)) !== null) {
152
+ if (match[1].includes(':')) {
153
+ handledChannels.add(match[1]);
154
+ }
155
+ }
156
+ }
157
+ }
158
+ const checks = [];
159
+ for (const [channel, invokeFile] of invokedChannels) {
160
+ if (handledChannels.has(channel)) {
161
+ checks.push({
162
+ type: 'ipc_handler_coverage',
163
+ verdict: 'PASS',
164
+ evidence: `Channel '${channel}' invoked in ${invokeFile} has a matching handler.`,
165
+ file: invokeFile,
166
+ severity: 'critical',
167
+ });
168
+ }
169
+ else {
170
+ checks.push({
171
+ type: 'ipc_handler_coverage',
172
+ verdict: 'FAIL',
173
+ evidence: `Channel '${channel}' invoked in ${invokeFile} has NO handler in any main-process file.`,
174
+ file: invokeFile,
175
+ severity: 'critical',
176
+ });
177
+ }
178
+ }
179
+ return checks;
180
+ }
181
+ // ── Check 3: Stub Functions ────────────────────────────────
182
+ /**
183
+ * Find async functions in preload whose body is ONLY a return of a literal object
184
+ * without ipcRenderer.invoke, await, .query(), or fetch().
185
+ */
186
+ async checkStubFunctions() {
187
+ const allFiles = await this.findFiles(this.projectPath, /\.(ts|tsx|js|jsx)$/);
188
+ const checks = [];
189
+ for (const file of allFiles) {
190
+ const relPath = relative(this.projectPath, file);
191
+ if (!relPath.includes('preload'))
192
+ continue;
193
+ const content = await readFile(file, 'utf-8');
194
+ const lines = content.split('\n');
195
+ // Find async arrow functions that return a literal object without real work
196
+ // Pattern: async (params) => { return { ... }; } or async (params): Promise<...> => { return { ... }; }
197
+ // But NOT functions that contain ipcRenderer.invoke, await (something), fetch, .query()
198
+ const stubPattern = /async\s+\(([^)]*)\)\s*(?::\s*Promise<[^>]+>)?\s*=>\s*\{/g;
199
+ let match;
200
+ while ((match = stubPattern.exec(content)) !== null) {
201
+ const startIdx = match.index + match[0].length;
202
+ const bodyEnd = this.findMatchingBrace(content, startIdx - 1);
203
+ if (bodyEnd === -1)
204
+ continue;
205
+ const body = content.slice(startIdx, bodyEnd).trim();
206
+ const hasRealWork = /ipcRenderer\.invoke|await\s+[^{]|\.query\(|fetch\(|\.send\(|\.emit\(/.test(body);
207
+ const isLiteralReturn = /^\s*return\s+\{[^}]*\}\s*;?\s*$/.test(body);
208
+ if (isLiteralReturn && !hasRealWork) {
209
+ // Find the function name by looking at what precedes the async keyword
210
+ const preceding = content.slice(Math.max(0, match.index - 80), match.index);
211
+ const nameMatch = preceding.match(/(\w+)\s*:\s*$/);
212
+ const funcName = nameMatch ? nameMatch[1] : 'anonymous';
213
+ // Find line number
214
+ const lineNum = content.slice(0, match.index).split('\n').length;
215
+ checks.push({
216
+ type: 'stub_function',
217
+ verdict: 'FAIL',
218
+ evidence: `Function '${funcName}' at line ${lineNum} is a stub: returns a literal object without ipcRenderer.invoke or any real operation. Body: ${body.trim()}`,
219
+ file: relPath,
220
+ severity: 'high',
221
+ });
222
+ }
223
+ }
224
+ }
225
+ return checks;
226
+ }
227
+ // ── Check 4: Unreachable Pages ─────────────────────────────
228
+ /**
229
+ * Collect page files from pages/ directories.
230
+ * Build import graph from entry point.
231
+ * Report any page file not transitively imported.
232
+ */
233
+ async checkUnreachablePages() {
234
+ // Find page files
235
+ const allFiles = await this.findFiles(this.projectPath, /\.(tsx|jsx|ts|js)$/);
236
+ const pageFiles = allFiles.filter(f => {
237
+ const rel = relative(this.projectPath, f);
238
+ return rel.includes('pages/') || rel.includes('pages\\');
239
+ });
240
+ if (pageFiles.length === 0) {
241
+ return []; // No pages directory
242
+ }
243
+ // Find entry point (file with createRoot or ReactDOM.render)
244
+ let entryFile = null;
245
+ for (const file of allFiles) {
246
+ const content = await readFile(file, 'utf-8');
247
+ if (/createRoot|ReactDOM\.render/.test(content)) {
248
+ entryFile = file;
249
+ break;
250
+ }
251
+ }
252
+ if (!entryFile) {
253
+ return []; // No entry point found — can't trace imports
254
+ }
255
+ // Build transitive import graph from entry point
256
+ const reachable = new Set();
257
+ await this.traceImports(entryFile, reachable, allFiles);
258
+ const checks = [];
259
+ for (const pageFile of pageFiles) {
260
+ const relPath = relative(this.projectPath, pageFile);
261
+ const pageName = basename(pageFile, extname(pageFile));
262
+ if (reachable.has(pageFile)) {
263
+ checks.push({
264
+ type: 'unreachable_page',
265
+ verdict: 'PASS',
266
+ evidence: `Page '${pageName}' (${relPath}) is reachable from entry point.`,
267
+ file: relPath,
268
+ severity: 'high',
269
+ });
270
+ }
271
+ else {
272
+ checks.push({
273
+ type: 'unreachable_page',
274
+ verdict: 'FAIL',
275
+ evidence: `Page '${pageName}' (${relPath}) is NOT imported from the entry point chain. It exists as a file but is unreachable at runtime.`,
276
+ file: relPath,
277
+ severity: 'high',
278
+ });
279
+ }
280
+ }
281
+ return checks;
282
+ }
283
+ // ── Helpers ────────────────────────────────────────────────
284
+ /** Recursively find files matching a pattern. */
285
+ async findFiles(dir, pattern) {
286
+ const results = [];
287
+ try {
288
+ const entries = await readdir(dir, { withFileTypes: true });
289
+ for (const entry of entries) {
290
+ const fullPath = join(dir, entry.name);
291
+ if (entry.isDirectory()) {
292
+ if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git' || entry.name === 'out' || entry.name === 'build' || entry.name === '.next')
293
+ continue;
294
+ results.push(...await this.findFiles(fullPath, pattern));
295
+ }
296
+ else if (pattern.test(entry.name)) {
297
+ results.push(fullPath);
298
+ }
299
+ }
300
+ }
301
+ catch {
302
+ // Directory doesn't exist or can't be read
303
+ }
304
+ return results;
305
+ }
306
+ /** Check if the project has preload files (indicating Electron). */
307
+ async hasPreloadFiles() {
308
+ const files = await this.findFiles(this.projectPath, /\.(ts|tsx|js|jsx)$/);
309
+ return files.some(f => relative(this.projectPath, f).includes('preload'));
310
+ }
311
+ /** Find the matching closing brace for an opening brace at the given index. */
312
+ findMatchingBrace(content, openIdx) {
313
+ let depth = 0;
314
+ for (let i = openIdx; i < content.length; i++) {
315
+ if (content[i] === '{')
316
+ depth++;
317
+ else if (content[i] === '}') {
318
+ depth--;
319
+ if (depth === 0)
320
+ return i;
321
+ }
322
+ }
323
+ return -1;
324
+ }
325
+ /** Trace imports transitively from a file. */
326
+ async traceImports(file, visited, allFiles) {
327
+ if (visited.has(file))
328
+ return;
329
+ visited.add(file);
330
+ let content;
331
+ try {
332
+ content = await readFile(file, 'utf-8');
333
+ }
334
+ catch {
335
+ return;
336
+ }
337
+ // Match import statements: import ... from './path' or import './path'
338
+ const importPattern = /(?:import\s+(?:[\s\S]*?)\s+from\s+|import\s+)['"]([^'"]+)['"]/g;
339
+ // Also match dynamic imports: import('./path')
340
+ const dynamicImportPattern = /import\(\s*['"]([^'"]+)['"]\s*\)/g;
341
+ const importPaths = [];
342
+ let match;
343
+ while ((match = importPattern.exec(content)) !== null) {
344
+ importPaths.push(match[1]);
345
+ }
346
+ while ((match = dynamicImportPattern.exec(content)) !== null) {
347
+ importPaths.push(match[1]);
348
+ }
349
+ for (const importPath of importPaths) {
350
+ if (!importPath.startsWith('.'))
351
+ continue; // Skip node_modules imports
352
+ const resolved = this.resolveImport(file, importPath, allFiles);
353
+ if (resolved) {
354
+ await this.traceImports(resolved, visited, allFiles);
355
+ }
356
+ }
357
+ }
358
+ /** Resolve a relative import path to an actual file. */
359
+ resolveImport(fromFile, importPath, allFiles) {
360
+ const dir = join(fromFile, '..');
361
+ const base = join(dir, importPath);
362
+ // Try exact match, then with extensions
363
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js', '/index.jsx'];
364
+ const candidates = [base, ...extensions.map(ext => base + ext)];
365
+ for (const candidate of candidates) {
366
+ if (allFiles.includes(candidate)) {
367
+ return candidate;
368
+ }
369
+ }
370
+ return null;
371
+ }
372
+ }
373
+ //# sourceMappingURL=integration-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration-verifier.js","sourceRoot":"","sources":["../../src/runtime/integration-verifier.ts"],"names":[],"mappings":"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"}
@@ -1270,7 +1270,7 @@ export interface AppDescription {
1270
1270
  }
1271
1271
  export interface TechStackConfig {
1272
1272
  readonly language: 'typescript' | 'python';
1273
- readonly framework: 'next.js' | 'express' | 'sveltekit';
1273
+ readonly framework: 'next.js' | 'express' | 'sveltekit' | 'electron';
1274
1274
  readonly database: 'supabase' | 'postgresql' | 'sqlite';
1275
1275
  readonly styling?: string;
1276
1276
  readonly deployment?: string;
@@ -1285,6 +1285,7 @@ export interface ArchitecturePlan {
1285
1285
  readonly apiRoutes: readonly ApiRouteSpec[];
1286
1286
  readonly pages: readonly PageSpec[];
1287
1287
  readonly features: readonly FeaturePlan[];
1288
+ readonly ipcChannels?: readonly IpcChannel[];
1288
1289
  readonly dependencyOrder: readonly string[];
1289
1290
  readonly authPlan?: {
1290
1291
  readonly provider: string;
@@ -1325,6 +1326,14 @@ export interface ApiRouteSpec {
1325
1326
  readonly responseType?: string;
1326
1327
  readonly featureId?: string;
1327
1328
  }
1329
+ export interface IpcChannel {
1330
+ readonly channel: string;
1331
+ readonly direction: 'renderer-to-main' | 'main-to-renderer' | 'bidirectional';
1332
+ readonly description: string;
1333
+ readonly requestType?: string;
1334
+ readonly responseType?: string;
1335
+ readonly featureId?: string;
1336
+ }
1328
1337
  export interface PageSpec {
1329
1338
  readonly path: string;
1330
1339
  readonly component: string;
@@ -1339,6 +1348,7 @@ export interface FeaturePlan {
1339
1348
  readonly schemaEntities: readonly string[];
1340
1349
  readonly apiRoutes: readonly string[];
1341
1350
  readonly pages: readonly string[];
1351
+ readonly ipcChannels?: readonly string[];
1342
1352
  readonly complexityEstimate: 'trivial' | 'small' | 'medium' | 'large';
1343
1353
  }
1344
1354
  export type AppCreatePhase = {
@@ -1368,6 +1378,8 @@ export type AppCreatePhase = {
1368
1378
  readonly attempt: number;
1369
1379
  readonly maxAttempts: number;
1370
1380
  readonly errorCount: number;
1381
+ } | {
1382
+ readonly phase: 'integration_verifying';
1371
1383
  } | {
1372
1384
  readonly phase: 'cross_verifying';
1373
1385
  } | {
@@ -1392,6 +1404,7 @@ export interface AppCreateResult {
1392
1404
  readonly plan: ArchitecturePlan | null;
1393
1405
  readonly featureResults: readonly FeatureBuildResult[];
1394
1406
  readonly buildVerification: BuildVerificationResult | null;
1407
+ readonly integrationVerification: IntegrationVerificationResult | null;
1395
1408
  readonly crossVerification: CrossFeatureVerification | null;
1396
1409
  readonly totalDurationMs: number;
1397
1410
  readonly auditTrail: readonly AuditEntry[];
@@ -1416,11 +1429,27 @@ export interface CrossFeatureVerification {
1416
1429
  readonly verdict: 'PASS' | 'FAIL' | 'PARTIAL';
1417
1430
  }
1418
1431
  export interface CrossFeatureCheck {
1419
- readonly type: 'api_route_exists' | 'page_references_valid' | 'schema_entity_exists' | 'dependency_consistency';
1432
+ readonly type: 'api_route_exists' | 'page_references_valid' | 'schema_entity_exists' | 'dependency_consistency' | 'ipc_channel_exists';
1420
1433
  readonly description: string;
1421
1434
  readonly verdict: 'PASS' | 'FAIL';
1422
1435
  readonly evidence: string;
1423
1436
  }
1437
+ export type IntegrationCheckType = 'routing_provider' | 'ipc_handler_coverage' | 'stub_function' | 'unreachable_page';
1438
+ export interface IntegrationCheck {
1439
+ readonly type: IntegrationCheckType;
1440
+ readonly verdict: 'PASS' | 'FAIL';
1441
+ readonly evidence: string;
1442
+ readonly file: string;
1443
+ readonly severity: 'critical' | 'high' | 'medium';
1444
+ }
1445
+ export interface IntegrationVerificationResult {
1446
+ readonly checks: readonly IntegrationCheck[];
1447
+ readonly passedCount: number;
1448
+ readonly failedCount: number;
1449
+ readonly verdict: 'PASS' | 'FAIL';
1450
+ readonly framework: string;
1451
+ readonly totalDurationMs: number;
1452
+ }
1424
1453
  export type BuildStepStatus = 'pass' | 'fail' | 'skip' | 'timeout';
1425
1454
  export interface BuildStepResult {
1426
1455
  readonly step: 'install' | 'build' | 'start' | 'health_check';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tryassay",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "AI code verification CLI — find bugs that tests miss, linters ignore, and code review overlooks",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",