MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / review

Method review

src/orchestration/qa-node.ts:53–122  ·  view source on GitHub ↗
(node: TaskNode, result: WorkerResult, signal?: AbortSignal)

Source from the content-addressed store, hash-verified

51 constructor(private hooks: QaHooks = {}) {}
52
53 async review(node: TaskNode, result: WorkerResult, signal?: AbortSignal): Promise<QaVerdict> {
54 const blockers: string[] = [];
55 const warnings: string[] = [];
56
57 // 0. Did the worker produce the files it was supposed to?
58 const wrote = new Set(result.fileEdits.map(e => e.path));
59 for (const expected of node.targetFiles) {
60 if (!wrote.has(expected)) {
61 blockers.push(`Expected file not produced: ${expected}`);
62 }
63 }
64 // Did it write outside its allowed set?
65 for (const e of result.fileEdits) {
66 if (node.targetFiles.length > 0 && !node.targetFiles.includes(e.path)) {
67 warnings.push(`Wrote file outside assigned scope: ${e.path}`);
68 }
69 }
70
71 // 1. STATIC parse check.
72 for (const edit of result.fileEdits) {
73 const parseErr = await this.parseCheck(edit.path, edit.content);
74 if (parseErr) blockers.push(parseErr);
75 }
76
77 // 1b. Optional typecheck (scoped).
78 if (this.hooks.typecheck && blockers.length === 0) {
79 try {
80 const errs = await this.hooks.typecheck(result.fileEdits.map(e => ({ path: e.path, content: e.content })), signal);
81 for (const err of errs) blockers.push(err);
82 } catch (e: any) {
83 logger.debug('Typecheck hook threw (non-fatal)', { err: e?.message });
84 warnings.push(`Typecheck could not run: ${e?.message ?? String(e)}`);
85 }
86 }
87
88 // 2. DESIGN audit for visual kinds.
89 if ((node.kind === 'component' || node.kind === 'style') && this.hooks.designAudit && blockers.length === 0) {
90 try {
91 const issues = await this.hooks.designAudit(result.fileEdits.map(e => ({ path: e.path, content: e.content })));
92 for (const issue of issues) {
93 if (issue.severity === 'high') blockers.push(`Design: ${issue.message}`);
94 else warnings.push(`Design: ${issue.message}`);
95 }
96 } catch (e: any) {
97 logger.debug('Design audit hook threw (non-fatal)', { err: e?.message });
98 warnings.push(`Design audit could not run: ${e?.message ?? String(e)}`);
99 }
100 }
101
102 // 3. VISION review when requested and everything else passed.
103 let visual: QaVerdict['visual'];
104 if (node.visualReview && this.hooks.visualReview && blockers.length === 0) {
105 try {
106 const v = await this.hooks.visualReview(node, signal);
107 visual = { screenshotPath: v.screenshotPath, notes: v.notes };
108 if (!v.ok) blockers.push(`Visual review failed: ${v.notes}`);
109 } catch (e: any) {
110 logger.debug('Visual review hook threw (non-fatal)', { err: e?.message });

Callers 1

executeMethod · 0.95

Calls 7

parseCheckMethod · 0.95
typecheckMethod · 0.80
debugMethod · 0.80
designAuditMethod · 0.80
visualReviewMethod · 0.80
hasMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected