Skip to main content

Code review · review diff before PR merge

Feed the PR diff to Qwen3.8-flash; it gives a merge verdict and blocking / suggestion / nit findings, each with concrete impact and fix.

Hand the diff to the model; it returns a merge verdict and blocking / suggestion / nit findings.
Disclaimer: All content on this page is AI-generated, for reference only, and does not constitute any performance guarantee. Actual results and Credits consumption are subject to the console "Usage Details".
This walkthrough uses a 6-file PR diff (new search endpoint + add caching + change payment settlement): hand the diff to qwen3.8-flash, ask for merge verdict, tiered findings (each with concrete consequence and fix), and a false-positive self-check list. The diff includes 7 test points, one of which is a decoy to test for false positives. The same input was run with thinking off and on to compare the two modes. Call chain: qwen3.8-flash (6-file diff in one input → merge verdict + tiered findings + false-positive checklist). Thinking off suits pre-commit second-level screening; thinking on for a final pass before merge.

Steps: hand the PR diff to the model for review

Send the diff along with the prompt below to qwen3.8-flash. The diff below is excerpted for readability (the tested input is the full diff across 6 files). After excerpting, the input is shorter, so the number and wording of output items may differ from what is shown on this page. For reference only
You are a code reviewer. Below is the full diff of a PR about to be merged. Review and give your verdict.

Return only a JSON object, no other text, with this fixed structure:

{
  "verdict": "approve or request_changes",
  "summary": "Two or three sentences: what this PR does and why you give this verdict",
  "issues": [
    {
      "file":     "file path",
      "where":    "which function or which change",
      "severity": "blocking or suggestion or nit",
      "problem":  "what the issue is, one sentence",
      "impact":   "what concrete consequence it causes; don't write vague 'may be risky'",
      "fix":      "how to fix; provide code if possible"
    }
  ],
  "not_issues": [
    {"file": "file path", "looks_like": "what it looks like", "why_ok": "why it's not an issue based on this diff"}
  ],
  "missing_tests": ["tests that should be added but weren't; empty array if none"]
}

Review requirements:
- severity has only three levels, fixed meaning: blocking = can't merge without fix; suggestion = should fix but doesn't block merge; nit = style/taste.
  Don't rate style issues as blocking; don't rate real breakage as nit.
- Each issue's impact must state a concrete consequence (who sees what error, how data goes wrong); no vague risk descriptions.
- Judge based on actual diff content; don't guess from function names, file names, or code not shown.
- Spot cross-file issues: if caller and callee are in the same diff and signature/args don't match, must point out.
- If something looks suspicious but is actually fine based on this diff, put it in not_issues with reasoning; don't pad the issue list.

PR diff to review:
diff --git a/src/api/orders.py b/src/api/orders.py
@@ -12,6 +12,21 @@ from src.service.order_service import OrderService
 
+@app.route("/api/orders/search")
+def search_orders():
+    """Search orders by status and keyword, for ops backend"""
+    status = request.args.get("status", "paid")
+    kw = request.args.get("kw", "")
+    tenant = g.current_tenant_id
+    sql = (
+        f"SELECT id, uid, amount, status FROM orders "
+        f"WHERE tenant_id = {tenant} AND status = '{status}' "
+        f"AND title LIKE '%{kw}%' ORDER BY created_at DESC LIMIT 200"
+    )
+    rows = db.execute(sql).fetchall()
+    tmp1 = [dict(r) for r in rows]
+    return jsonify(tmp1)
+

diff --git a/src/service/order_service.py b/src/service/order_service.py
@@ -30,10 +30,25 @@ class OrderService:
 
-    def list_by_user(self, uid):
-        return db.query(Order).filter(Order.uid == uid).all()
+    def list_by_user(self, uid):
+        key = f"order:list:{uid}"
+        hit = self.cache.get(key)
+        if hit is not None:
+            return json.loads(hit)
+        rows = (db.query(Order)
+                  .filter(Order.uid == uid,
+                          Order.tenant_id == g.current_tenant_id)
+                  .all())
+        self.cache.set(key, json.dumps([r.to_dict() for r in rows]), ex=300)
+        return rows
+
+
+def build_report(month: int):
+    """Generate order report for a given month"""
+    if month < 1 or month > 12:
+        raise ValueError("month out of range")
+    return _aggregate(month)

diff --git a/src/api/report.py b/src/api/report.py
@@ -5,6 +5,11 @@ from src.service.order_service import build_report
 
+@app.route("/api/orders/report")
+def order_report():
+    month = request.args["month"]
+    data = build_report(month)
+    return jsonify(data)

diff --git a/src/service/payment.py b/src/service/payment.py
@@ -58,10 +58,16 @@ class PaymentService:
     def settle(self, order_id):
         order = self._load(order_id)
-        self.gateway.charge(order.uid, order.amount)
-        order.status = "paid"
-        db.commit()
+        try:
+            self.gateway.charge(order.uid, order.amount)
+        except Exception:
+            pass
+        order.status = "paid"
+        db.commit()
+        self.notifier.push(order.uid, "payment successful")

diff --git a/src/util/etag.py b/src/util/etag.py
@@ -0,0 +1,9 @@
+import hashlib
+
+
+def make_etag(payload: bytes) -> str:
+    """Compute an ETag for the response body, used only for negotiated caching, no credentials involved"""
+    return hashlib.md5(payload).hexdigest()

diff --git a/src/api/handler.py b/src/api/handler.py
@@ -33,8 +33,7 @@ def handle_request(req):
     ctx = build_context(req)
-    print("DEBUG ctx:", ctx)
-    resp = dispatch(ctx, timeout=cfg.timeout)
+    resp = dispatch(ctx, timeout=300)
     return resp
Key parameters:
# Pre-commit second-level screening: thinking off
{
  "model": "qwen3.8-flash",
  "messages": [{"role": "user", "content": "…git diff body…"}],
  "enable_thinking": false
}

# Final pass before merge: don't pass enable_thinking, use default thinking on
Under OpenAI-compatible mode, enable_thinking goes at the top level of the request body; flash defaults to thinking on.

Notes

  • Consumption: This playbook uses text generation (qwen3.8-flash). Thinking off: no reasoning cost; thinking on: output ~10× larger, mostly reasoning chain—cost estimation can't just look at the review report length.
  • Measured result: Thinking-off read 6 files, verdict request_changes, findings 4 blocking + 1 suggestion + 1 nit, hit 5 of 7 test points—SQL injection (gave parameterized fix), except Exception: pass swallowing charge failure (wrote "goods delivered without payment" consequence), cross-file type mismatch (caller passes string, callee signature is int); decoy not false-positived (hashlib.md5 for ETag put in not_issues).
  • Note: Thinking-off missed "cache key uses only uid without tenant_id, causing cross-tenant data bleed" (needs combining two changes to spot); switching to thinking-on hit all 7, flagged that one as blocking, but time and output volume rose significantly (this behavioral difference was consistent across an independent reproduction). Recommend two passes: thinking-off for pre-commit second-level screening, thinking-on for a final merge gate.
  • Note: Thinking-off summary mentioned items not in the issues list; when integrating or citing, use issues as source of truth; both configs are assistive only, not a replacement for human review.
  • Data boundary: Code in context means content goes to the server. Replace real secrets, internal addresses, and customer data with placeholders before submitting; keep code structure, the model can still spot issues.
Model Playground
Fine-tuning
Model Compression
Statistics and Monitoring
Support