Claude Skill

code-review

Use this skill when you need a risk-driven code review of a PR/diff with severity-ranked findings and actionable fixes; triggers include code review, PR review,.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download naodeng-awesome-qa-skills-skills_en_testing-types_code-review-c44b892.zip · 27 KB
Part of naodeng/awesome-qa-skills — 97 skills

Install

skills CLI npx skills add https://github.com/naodeng/awesome-qa-skills/tree/main/skills/en/testing-types/code-review
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install naodeng-awesome-qa-skills@llmmart
Git git clone https://github.com/naodeng/awesome-qa-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole naodeng/awesome-qa-skills collection as a plugin from our marketplace. Git is the plain clone.

README

Code Review

Skill Overview

Risk-driven review of a PR / diff with severity-ranked findings and actionable fixes — catch logic, security, financial-loss, and maintainability defects before merge.

How to Use

  1. Open SKILL.md in this folder and confirm this skill fits your task.
  2. In your AI tool, call @skill code-review, then add the diff, business goal, stack, and upstream/downstream context.
  3. If you need a specific output format (table, checklist, report), include it directly in your request.

One-Click Install Script

Run from the repository root:

macOS / Linux

bash ./scripts/install-skills-mac.sh --tool codex --lang en --skill code-review

Windows PowerShell

powershell -ExecutionPolicy Bypass -File .\scripts\install-skills-windows.ps1 -Tool codex -Lang en -Skill code-review

Skill manifest

Code Review

Chinese version: See the corresponding Chinese skill.

When to Use

  • Need to review a PR / diff / commit and catch logic, security, financial-loss, or maintainability risks before merge.
  • Need a P0/P1/P2-ranked report with locations and actionable fix guidance.
  • Need a QA / engineering-quality lens beyond author self-review.

Workflow

  1. Read and follow the main prompt listed under Progressive disclosure (coverage, structure, quality bar).
  2. Before reviewing, confirm both an identifiable code version and its reviewable changes; if either is missing, return a blocked result and request the exact material.
  3. Add only project context that changes the result: change scope, business goal, stack, upstream/downstream deps, known risks, team norms.
  4. Treat role reports as optional, source-identified context; use Product and UI/UX reports only when this change touches their concerns.
  5. Default to Markdown; switch formats only when the user asks.

Core Constraints

  • Risk-driven: prioritize production failures, financial loss, security, and core maintainability — not naming/indent noise.
  • Evidence-based: prefer file path, line, or snippet plus trigger path and impact for each finding.
  • Two gates: require both identifiable code version (for example repository + PR / commit / branch / tag / revision) and reviewable change (for example diff/patch, changed-file contents, or an accessible base-to-head range). Code identity, change content, and role reports cannot substitute for one another.
  • If either gate is missing, explicitly return status: blocked and distinguish missing_code_identity from missing_reviewable_change; do not claim review completion, recommend merge, or invent code findings.
  • Role reports are optional. When using them, retain source_role. Product reports may add business-rule, state-flow, or acceptance context; UI/UX reports may add UI-state, feedback, responsive, or accessibility context only when relevant. Never present a role view as code fact.
  • Strict severity: P0 blocks merge, P1 should fix this iteration, P2 can be tech debt.
  • Separate confirmed facts from assumptions; do not invent endpoints, fields, environments, or root causes the user did not provide.
  • Critique the code, not the author; respect the current stack — do not demand framework/architecture rewrites without authorization.
  • Keep output executable: every finding needs a fix direction or before/after example.

Progressive Disclosure

  • Before producing output, read and follow prompts/code-review.md (minimum coverage, output structure, quality bar).
  • When Excel/CSV/JSON/Word is requested: read output-formats.md and honor the format.
  • When a ready-made template fits: use matching files under output-templates/.
  • For deeper review dimensions or severity rubrics: read references/review-dimensions.md.
  • For examples or calibration: read matching files under examples/.
  • For format conversion or helper checks: prefer existing scripts/ over reinventing.
  • For the shortest path: read quick-start.md.
  • For evaluating/regressing this skill: use evals/ with skill-up.

Pre-delivery Checklist

  • Followed the main prompt's output structure
  • Confirmed both code-identity and reviewable-change gates; if blocked, did not issue a completed review or merge recommendation
  • Minimum coverage focus: change summary, overall risk rating, P0/P1/P2 list, testability/observability, API/contract compatibility, fix order, residual risks and assumptions… (details in main prompt)
  • Covered the minimum checklist, or explained omissions
  • High-risk items have explicit P0/P1 severity with rationale
  • Did not invent details the user did not provide
  • Assumptions and gaps are marked

Common Pitfalls

  • Do not treat a code snippet or role report as code identity, or a PR / commit identifier as the diff; block when either gate is missing.
  • Do not activate Product or UI/UX concerns merely because a report exists; first establish relevance and retain its source.
  • Do not treat every item as equally important, or dump low-value style nits.
  • Do not skip assumptions and information gaps.
  • Do not force refactors outside the change under review.
  • Do not dump generic theory unrelated to this change.
Files (awesome-qa-skills)
  • agents
    • openai.yaml 382 B
      version: 1
      metadata:
        key: "code-review"
      interface:
        display_name: "Code Review"
        short_description: "Risk-driven PR/diff code review with P0/P1/P2 findings and actionable fixes; triggers include code review and PR review."
        default_prompt: "Use the code-review skill to review this change with P0/P1/P2 findings and actionable fixes."
      policy:
        allow_implicit_invocation: true
      
  • evals
    • cases
      • basic-success.yaml 1.9 KB
        id: basic-success
        title: "Code review: ranked findings from a clear diff"
        description: |
          With a clear diff and business goal, return risk rating, P0/P1 severity, and actionable fixes.
        
        input:
          prompt: |
            Use code-review.
            Code identity: repository payments-api, PR #317, commit a91c2e4, baseline main@81fb730.
            Business goal: mark order paid after successful payment callback.
            This is the reviewable patch from the baseline to the commit:
            ```diff
            diff --git a/src/PaymentCallbackHandler.java b/src/PaymentCallbackHandler.java
            @@ public void onPaymentSuccess(String callbackId, long orderId) {
            -  if (!callbackLog.tryInsert(callbackId)) return;
            -  Order order = orderRepository.get(orderId);
            -  if (order.status() != OrderStatus.PENDING) return;
               orderService.markPaid(orderId);
            }
            ```
            Stack: Java Spring + MySQL.
            Produce a severity-ranked review; separate facts from assumptions.
        
        expect:
          must_contain:
            - "P0"
            - "idempot"
          must_not_contain:
            - "TODO"
            - "I cannot"
        
        judge:
          type: agent_judge
          model: openai/gpt-5
          criteria:
            - "The finding is grounded in the `PaymentCallbackHandler.java` patch: `callbackLog.tryInsert(callbackId)` and the `PENDING` state guard were removed before `markPaid`, rather than relying on an oral risk summary outside the patch."
            - "It ranks duplicate callback/state-transition risk as P0 and explains duplicate processing, state corruption, or financial impact without inventing whether `markPaid` has internal protection."
            - "Fix guidance addresses the removed idempotency and state gates, such as restoring/replacing atomic callback registration and conditional state transition, while noting that transaction boundaries still require verification."
            - "Facts and assumptions are separate, and the finding, location, impact, and fix remain evidence-traceable."
          pass_threshold: 0.8
        
      • edge-incomplete-input.yaml 1.6 KB
        id: edge-incomplete-input
        title: "Code review: block when both code identity and changes are missing"
        description: |
          With only a verbal description and neither code identity nor reviewable changes, return a structured blocked result rather than starting a formal review.
        
        input:
          prompt: |
            Use code-review to handle a review request.
            The team only says, "The points-redemption API changed and there may be a concurrency issue." There is no repository URL, PR, commit, branch, tag, release version, or revision; there is also no diff, patch, changed file, code snippet, or accessible base-to-head content.
            Explain whether a formal code review can start now and what the team must supply next.
        
        judge:
          type: agent_judge
          model: openai/gpt-5
          criteria:
            - "The output contains the stable field `status: blocked` and lists both `missing_code_identity` and `missing_reviewable_change` under `missing_gate`; synonymous field names or natural-language-only wording do not satisfy this criterion."
            - "It separately explains the missing identifiable code version and missing reviewable changes, requesting repository plus PR/commit/branch/tag/revision identity and a diff/patch, changed-file contents, or an explicit accessible base-to-head range."
            - "It contains no formal P0/P1/P2 findings, does not claim code review completion, does not invent concurrency defects, implementation facts, or test results, and gives no approve-merge, reject-merge, or other merge recommendation."
            - "The verbal concurrency concern remains an unverified risk lead or assumption rather than a confirmed code finding."
          pass_threshold: 1.0
        
      • edge-missing-code-version.yaml 3.3 KB
        id: edge-missing-code-version
        title: "Code review: block separately when code identity or reviewable changes are missing"
        description: |
          Three merge requests cover diff-only, identity-only, and both gates satisfied; the review should stably block the first two and conditionally use source-identified role reports for the third.
        
        input:
          prompt: |
            Use code-review to handle the three merge requests below independently and say whether each can enter formal code review now.
        
            Request A: a Product role report says, "Refund retries must not pay twice." The engineer pasted this change:
              - refundService.refund(orderId);
              + retry(3, () -> refundService.refund(orderId));
            There is no repository URL, PR, commit, branch, tag, or other code-version identifier.
        
            Request B: a UI/UX role report says, "The button should show a busy state while saving." The code identity is repository shop-web, PR #418, commit 64e8f20, branch feature/save-state; however, there is no diff, changed file, code snippet, or accessible repository content, only the statement "the save interaction was improved."
        
            Request C: code identity is repository shop-web, PR #419, commit b72a410, baseline main@64e8f20. Two optional role reports are supplied:
            - source_role: product: show a save-success message only after profile data is persisted, and do not lose the user's entered name.
            - source_role: ux: show a busy state and prevent duplicate clicks while saving; put failure feedback near the form.
            Reviewable patch:
            ```diff
            diff --git a/src/EditProfile.tsx b/src/EditProfile.tsx
            @@ async function submitProfile(form: ProfileForm) {
            -  setSaving(true);
               try {
            -    await saveProfile(form);
                 toast.success("Saved");
            +    saveProfile(form);
               } finally {
            -    setSaving(false);
               }
            }
            ```
        
            Keep A, B, and C as separate conclusions rather than combining them into one review.
        
        judge:
          type: agent_judge
          model: openai/gpt-5
          criteria:
            - "Request A contains the stable fields `status: blocked` and accurate `missing_gate: missing_code_identity`; it does not also report `missing_reviewable_change`, and specifically requests identity such as a PR, commit, branch, tag, or repository revision."
            - "Request B contains the stable fields `status: blocked` and accurate `missing_gate: missing_reviewable_change`; it does not also report `missing_code_identity`, and specifically requests a diff/patch, changed files, code snippets, or accessible base-to-head content."
            - "Requests A and B contain no formal P0/P1/P2 findings, do not claim review completion, and give no merge recommendation; Product and UI/UX reports do not substitute for missing gates or become code facts."
            - "Request C recognizes that both code identity and patch exist and performs a formal evidence-based review; findings are grounded in patch facts such as removal of `setSaving`, removal of `await`, premature success feedback, or an unawaited `saveProfile`, not merely in role-report claims."
            - "Request C uses the Product and UI/UX reports only because they are relevant and retains each as `source_role: product`, `source_role: ux`, or equivalent stable source fields; Product informs post-persistence success semantics, UI/UX informs busy/duplicate-click/feedback concerns, and neither is presented as code evidence."
          pass_threshold: 1.0
        
      • edge-risk-priority.yaml 2 KB
        id: edge-risk-priority
        title: "Code review: P0 vs P2 must reflect business impact"
        description: |
          When a financial-loss issue and a style-only change coexist, severities must differ and style must not be P0.
        
        input:
          prompt: |
            Use code-review.
            Code identity: repository refund-api, PR #52, commit 8fd3bc1, baseline main@a20d119.
            This is the reviewable patch from the baseline to that commit:
            ```diff
            diff --git a/src/RefundRetryHandler.java b/src/RefundRetryHandler.java
            @@ public void handle(String orderId, String refundRequestId) {
            -  refundService.refund(orderId, refundRequestId);
            +  retry(3, () -> refundService.refund(orderId));
            }
            diff --git a/src/RefundResponseParser.java b/src/RefundResponseParser.java
            @@ private Refund parse(Response response) {
            -  Refund tmp = parseRefund(response);
            -  return tmp;
            +  Refund data = parseRefund(response);
            +  return data;
            }
            ```
            Review the two changes separately and explain the severity difference; do not mark a pure rename as P0.
        
        expect:
          must_contain:
            - "P0"
            - "refund"
          must_not_contain:
            - "TODO"
            - "I cannot"
        
        judge:
          type: agent_judge
          model: openai/gpt-5
          criteria:
            - "It covers the two patches separately: `RefundRetryHandler.java` removes `refundRequestId` and retries a refund call without it, while `RefundResponseParser.java` only renames local variable `tmp` to `data`; it does not substitute an oral summary for patch evidence."
            - "It ranks the former double-refund/financial-loss risk as P0 because the retried call loses the explicit idempotency request identifier, while keeping any other internal refund-service protection as an unverified assumption."
            - "It recognizes the latter as a naming-only, behavior-neutral change and does not mark it P0; omitting it as noise or giving at most a low-priority note is acceptable."
            - "It does not merge the two changes into one finding, separates facts from assumptions, and grounds the severity difference in business impact."
          pass_threshold: 0.8
        
    • eval.yaml 489 B
      schema_version: v1alpha1
      
      environment:
        type: none
      
      skills:
        - source: local_path
          path: .
      
      engine:
        name: claude_code
      
      cases:
        files:
          - evals/cases/basic-success.yaml
          - evals/cases/edge-incomplete-input.yaml
          - evals/cases/edge-missing-code-version.yaml
          - evals/cases/edge-risk-priority.yaml
        defaults:
          timeout_seconds: 180
          max_turns: 8
          expect:
            exit_code: 0
            must_not_contain:
              - "TODO"
              - "I cannot"
      
      report:
        formats: [json]
      
  • examples
    • README.md 221 B
      # Examples
      
      Desensitized sample input/output for calibration. Replace with your real diff and strip any secrets.
      
      - `sample-diff-review.md`: a payment-callback change with idempotency risk, plus an expected review shape.
      
    • sample-diff-review.md 1.4 KB
      # Example: Payment Callback Missing Idempotency
      
      ## Input (redacted)
      
      **Business goal**: On successful payment callback, move the order from Pending Payment to Paid.
      
      **Stack**: Java / Spring; order state in MySQL.
      
      **Diff sketch**:
      
      ```java
      // OrderPaymentController.java
      @PostMapping("/callback/pay")
      public void onPaySuccess(@RequestBody PayCallback req) {
          orderService.markPaid(req.getOrderId());
          // no idempotency key / no state guard
      }
      ```
      
      ## Expected Review Focus (sketch)
      
      ### 1. Change Summary and Overall Assessment
      
      - Business goal: payment callback drives order state change
      - Overall risk: **High** (callbacks may retry; duplicate side effects possible)
      
      ### 2. Findings
      
      #### [P0 - Blocker]
      
      - File and location: `OrderPaymentController.java` (callback entry)
      - Category: idempotency / financial-loss risk
      - Risk: channel retries may re-enter `markPaid` and downstream side effects (coupons, ledger), causing bad state or duplicate fulfillment
      - Fix: idempotency on `orderId + paymentId`; allow only `PENDING -> PAID`; put side effects behind the same dedupe/transaction boundary
      
      #### [P1] / [P2]
      
      - Add as needed for missing signature verification, tracing, failure/retry semantics
      
      ### 5. Residual Risks and Gaps
      
      - Assumption: `markPaid` itself is not idempotent (implementation not provided)
      - Need: full `orderService.markPaid`, any existing dedupe table, callback signature checks
      
  • output-templates
    • template-csv.csv 206 B · in bundle
    • template-excel.tsv 358 B · in bundle
    • template-json.json 393 B
      {
        "meta": {
          "skill": "",
          "scope": "",
          "environment": "",
          "priority": ""
        },
        "inputs": {
          "requirement": "",
          "constraints": [],
          "risks": []
        },
        "execution": [
          { "step": 1, "action": "", "expected": "" }
        ],
        "results": {
          "status": "",
          "evidence": [],
          "defects": []
        },
        "next_actions": [
          { "owner": "", "eta": "", "action": "" }
        ]
      }
      
    • template-markdown.md 606 B
      # Code Review Report Template
      
      ## 1. Change Summary and Overall Assessment
      - Business goal understanding:
      - Change size:
      - Overall risk rating: High / Medium / Low
      - Rationale:
      
      ## 2. Findings
      
      ### [P0 - Blocker]
      - File and location:
      - Category:
      - Risk description:
      - Fix guidance:
      
      ### [P1 - Should fix this iteration]
      - (same structure; write "None" if empty)
      
      ### [P2 - Optional]
      - (same structure; write "None" if empty)
      
      ## 3. Testability and Observability
      - Testing gaps:
      - Logging / metrics / tracing:
      
      ## 4. Recommended Fix Order
      1.
      2.
      
      ## 5. Residual Risks and Gaps
      - Assumptions:
      - Missing info:
      
    • template-word.md 302 B
      QA Report
      =========
      
      1. Basic Information
      - Skill:
      - Scope:
      - Environment:
      - Priority:
      
      2. Requirement and Constraints
      - Requirement:
      - Constraints:
      - Risks:
      
      3. Test/Review Process
      - Step 1:
      - Step 2:
      - Step 3:
      
      4. Outcome
      - Status:
      - Evidence:
      - Defects:
      
      5. Follow-up Plan
      - Owner:
      - ETA:
      - Action:
      
    • template-xmind.md 317 B
      # QA Output Mindmap
      
      - QA Output
        - Meta
          - Skill
          - Scope
          - Environment
          - Priority
        - Inputs
          - Requirement
          - Constraints
          - Risks
        - Execution
          - Step 1
          - Step 2
          - Step 3
        - Results
          - Status
          - Evidence
          - Defects
        - Next Actions
          - Owner
          - ETA
          - Action
      
  • prompts
    • code-review.md 6.5 KB
      # Code Review Prompt
      
      Produce a risk-driven, evidence-based, actionable code review report for this PR / diff / commit, catching high-severity defects before merge.
      
      ## Role
      
      - Act as a senior code reviewer experienced in distributed systems, concurrency/consistency, financial-loss and security risks, API contracts, and testability.
      - Reject rubber-stamp “LGTM”; focus on real risks and executable fixes; critique code, not people.
      
      ## Input
      
      - identifiable code version: repository plus a PR, commit, branch, tag, release version, revision, or equivalent stable identity
      - reviewable changes for that version: diff/patch, changed-file contents, or an explicit accessible base-to-head repository range
      - Business goal, change scope, tech stack, upstream/downstream dependencies (APIs, messaging, DB, cache)
      - Team norms, known risks, past incidents, or related test findings (if any)
      - optional role reports with declared `source_role`; activate Product and UI/UX reports only when the change touches their concerns
      
      ## What to do
      
      1. Check the independent code-identity and reviewable-change gates first; if either is missing, stop the formal review and return a blocked result.
      2. Once both gates pass, understand the business goal and change focus; separate new logic from edits to existing paths.
      3. Scan for logic defects, concurrency/consistency, financial-loss/security, API compatibility, and testability/maintainability.
      4. Rank findings as P0/P1/P2 and provide actionable fix guidance.
      5. Return a structured review that supports merge decisions and follow-up.
      
      ## Execution Rules
      
      - **Risk-driven**: prioritize production outages, financial loss, security, main-path breakage, and severe maintainability damage; do not list naming/whitespace noise.
      - **Two code gates**: identifiable code version and reviewable changes must both exist. With only a diff/code snippet, use `missing_code_identity`; with only repository/PR/commit/branch identity, use `missing_reviewable_change`; when neither exists, list both. Any missing gate prevents formal finding severity and merge conclusions.
      - **Blocking is not a speculative first review**: a blocked result records supplied material, the missing gate, why evidence is insufficient, and the exact material required. Do not turn role opinions or verbal descriptions into confirmed code defects, test conclusions, or P0/P1/P2 findings.
      - **Optional role input**: role reports are not prerequisites and cannot replace either code gate. Use a Product report only for relevant business rules, state flows, or acceptance semantics. Use a UI/UX report only for relevant UI states, interaction feedback, responsive behavior, or accessibility. Retain `source_role` whenever citing role content and keep it separate from code facts.
      - **Evidence-based**: prefer path, line, or snippet with trigger path, repro conditions, and worst-case impact; if you cannot locate precisely, mark the information gap.
      - **Strict severity**:
        - **P0**: block merge (financial loss, severe security, reproducible deadlock/OOM, main-path breakage, etc.)
        - **P1**: fix this iteration (edge failures, likely races, clear performance issues, missing core observability, etc.)
        - **P2**: optional / tech debt (non-core smells, readability, minor perf)
      - **Actionable fixes**: every finding needs a concrete fix direction or before/after example; ban vague “please optimize this”.
      - **Respect constraints**: do not invent APIs/fields/environments; do not demand stack or architecture rewrites without authorization.
      - **Stay in scope**: do not force refactors outside this change; you may flag residual risks as tech debt.
      - **Secrets**: never put real tokens/passwords/keys in examples; use env vars or placeholders.
      - If input contains `{{variable_name}}` placeholders, keep them verbatim.
      
      ## Minimum Coverage Checklist
      
      Unless the user explicitly narrows the scope, make sure the result addresses these items:
      
      - change summary and business-goal understanding
      - overall risk rating (High / Medium / Low) with rationale
      - logic and state defects
      - concurrency / consistency / idempotency (when relevant)
      - financial-loss and security (including sensitive data leakage)
      - API / contract compatibility and upstream/downstream impact (when relevant)
      - testability and observability gaps
      - high-value maintainability / performance items only
      - P0 / P1 / P2 lists (write “None” if empty)
      - recommended fix order
      - residual risks, assumptions, and information gaps
      
      ## Output
      
      If either code gate is missing, stop and return only:
      
      ### Code Review Blocked
      
      - `status: blocked`
      - `missing_gate`: `missing_code_identity`, `missing_reviewable_change`, or both
      - supplied material and why it is insufficient
      - exact material required to proceed
      - blocking impact, unverified risk scope, and explicitly labeled assumptions (not code findings)
      - role-report sources and applicability, if supplied, with a statement that they are not code evidence
      
      Do not append completed severity findings, fix order, or a merge recommendation. Only when both gates pass, return the result in this order:
      
      ### 1. Change Summary and Overall Assessment
      
      - Business goal understanding
      - Change size (based on provided info; mark unknown)
      - Overall risk rating (High / Medium / Low) with one-line rationale
      
      ### 2. Findings (severity descending)
      
      #### [P0 - Blocker] (write “None” if empty)
      
      For each finding:
      
      - File and location
      - Category
      - Risk description (trigger path, repro conditions, worst-case impact)
      - Fix guidance (direction or before/after example)
      
      #### [P1 - Should fix this iteration] (write “None” if empty)
      
      Same structure as P0.
      
      #### [P2 - Optional] (write “None” if empty)
      
      Same structure as P0; keep the list short and high-value only.
      
      ### 3. Testability and Observability
      
      - Testing gaps or hard-to-test points
      - Logging / metrics / tracing suggestions (when relevant)
      
      ### 4. Recommended Fix Order
      
      - Order by merge blockers and business impact
      
      ### 5. Residual Risks and Gaps
      
      - Unverified items, assumptions, and missing diff/context
      
      ## Quality Bar
      
      - Focus on findings and risk, not long praise or generic theory.
      - Make every finding concrete; avoid “there is risk” without an example.
      - P0/P1 must cite business or technical impact.
      - Separate facts from assumptions. If non-gate context is incomplete, a limited review may mark gaps; if either code gate is missing, block.
      - When role reports are used, retain their sources and state how they relate to the change; do not require reading, installing, or linking to any role Skill's internal files.
      
  • references
    • review-dimensions.md 2.1 KB
      # Extra Review Dimensions (load on demand)
      
      Read this only when you need finer scan dimensions or severity calibration; do not dump the whole file into every review.
      
      ## 1. Logic and State
      
      - Null/guard gaps, bounds errors, incomplete state machines
      - Swallowed exceptions, silently ignored error codes
      - Resource leaks (connections, handles, locks, temp files)
      
      ## 2. Concurrency and Distributed Consistency
      
      - Races, lost updates, check-then-act
      - Broken idempotency (retries causing double charge/ship/write)
      - Misaligned distributed transaction boundaries; cache vs DB drift
      - Bad lock granularity, deadlock risk
      
      ## 3. Financial Loss and Security
      
      - Money/inventory precision (floats, rounding direction)
      - AuthZ gaps, duplicate pay/refund, promo stacking bugs
      - Injection (SQL/NoSQL/command/template), XSS
      - Sensitive leakage (plaintext tokens/passwords in logs, hardcoded secrets, missing redaction)
      
      ## 4. API Contract and Compatibility
      
      - Field add/remove/rename, type/enum changes, default-value semantics
      - Breaking forward/backward compatibility, corrupting existing data
      - Unexpected impact on callers, consumers, or batch jobs
      
      ## 5. Testability and Evolution
      
      - Hard-coded time/randomness, hard-to-mock dependencies
      - Missing assertion points or hard-to-build fixtures
      - Long methods/classes, misplaced responsibility, magic values, high complexity, tight coupling
      - Flag only high-value smells; avoid style nitpicking
      
      ## 6. Performance and Resources (high-value only)
      
      - N+1 queries, IO/RPC inside loops, unbounded copies
      - Clearly wrong pool/timeout/retry settings
      - Leak or unbounded cache growth signals
      
      ## 7. Error Handling and Observability
      
      - Whether failures are diagnosable or root cause is swallowed
      - Logs with TraceID / key business ids (and redaction)
      - Alertable metrics on core paths
      
      ## Severity Rubric
      
      | Level | Merge decision | Typical impact |
      | --- | --- | --- |
      | P0 | Must fix before merge | Financial loss, severe security, main-path failure |
      | P1 | Strongly fix this iteration | Likely edge failure, clear perf, core unobservability |
      | P2 | Tech debt OK | Non-core maintainability, minor opts |
      
  • scripts
    • batch_convert_templates.py 2.7 KB
      #!/usr/bin/env python3
      import argparse
      import subprocess
      import sys
      from pathlib import Path
      
      
      def detect_from(file: Path) -> str:
          ext = file.suffix.lower()
          if file.name.endswith('.word.md'):
              return 'markdown'
          return {
              '.md': 'markdown',
              '.markdown': 'markdown',
              '.json': 'json',
              '.csv': 'csv',
              '.tsv': 'excel',
              '.docx': 'word',
              '.xlsx': 'excel',
              '.xmind': 'xmind',
          }.get(ext, 'markdown')
      
      
      def run_convert(convert_script: Path, src: Path, to_fmt: str, out: Path) -> int:
          cmd = [sys.executable, str(convert_script), str(src), '--from', detect_from(src), '--to', to_fmt, '--output', str(out)]
          return subprocess.call(cmd)
      
      
      def main() -> None:
          parser = argparse.ArgumentParser(description='Batch convert all template files into target formats.')
          parser.add_argument('--templates-dir', type=Path, default=Path('output-templates'))
          parser.add_argument('--artifacts-dir', type=Path, default=Path('artifacts'))
          parser.add_argument('--targets', default='word,excel,xmind,json,csv,markdown', help='comma-separated target formats')
          parser.add_argument('--skip-same', action='store_true', help='skip conversion when source format equals target format')
          args = parser.parse_args()
      
          cwd = Path.cwd()
          templates_dir = (cwd / args.templates_dir).resolve()
          artifacts_dir = (cwd / args.artifacts_dir).resolve()
          artifacts_dir.mkdir(parents=True, exist_ok=True)
      
          local_convert = (Path(__file__).resolve().parent / 'convert_formats.py').resolve()
          targets = [t.strip() for t in args.targets.split(',') if t.strip()]
      
          if not templates_dir.exists():
              raise SystemExit(f'templates directory not found: {templates_dir}')
      
          files = [p for p in sorted(templates_dir.iterdir()) if p.is_file()]
          total = 0
          failed = 0
      
          for src in files:
              src_fmt = detect_from(src)
              for to_fmt in targets:
                  if args.skip_same and src_fmt == to_fmt:
                      continue
                  out_ext = {
                      'json': '.json',
                      'csv': '.csv',
                      'excel': '.tsv',
                      'markdown': '.md',
                      'word': '.word.md',
                      'xmind': '.xmind.md',
                  }[to_fmt]
                  out = artifacts_dir / f"{src.stem}.to-{to_fmt}{out_ext}"
                  total += 1
                  rc = run_convert(local_convert, src, to_fmt, out)
                  if rc != 0:
                      failed += 1
                      print(f'[FAILED] {src.name} -> {to_fmt}')
                  else:
                      print(f'[OK] {src.name} -> {out.name}')
      
          print(f'\nDone. total={total}, failed={failed}, artifacts={artifacts_dir}')
          if failed:
              raise SystemExit(1)
      
      
      if __name__ == '__main__':
          main()
      
    • convert_formats.py 10.4 KB
      #!/usr/bin/env python3
      import argparse
      import csv
      import json
      import re
      import zipfile
      from pathlib import Path
      from typing import Any
      from xml.etree import ElementTree as ET
      
      
      # ---- parsing ----
      def parse_markdown(path: Path) -> dict[str, Any]:
          text = path.read_text(encoding="utf-8", errors="ignore")
          lines = text.splitlines()
          headings: list[dict[str, Any]] = []
          for line in lines:
              m = re.match(r"^(#{1,6})\s+(.*)$", line.strip())
              if m:
                  headings.append({"level": len(m.group(1)), "title": m.group(2).strip()})
          return {"title": headings[0]["title"] if headings else path.stem, "headings": headings, "text": text}
      
      
      def parse_json(path: Path) -> dict[str, Any]:
          data = json.loads(path.read_text(encoding="utf-8", errors="ignore"))
          return {"title": path.stem, "data": data}
      
      
      def parse_csv_file(path: Path) -> dict[str, Any]:
          with path.open("r", encoding="utf-8", errors="ignore", newline="") as f:
              reader = csv.DictReader(f)
              rows = list(reader)
          return {"title": path.stem, "columns": reader.fieldnames or [], "rows": rows}
      
      
      def parse_docx(path: Path) -> dict[str, Any]:
          paragraphs: list[str] = []
          with zipfile.ZipFile(path) as zf:
              with zf.open("word/document.xml") as f:
                  root = ET.fromstring(f.read())
          ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
          for p in root.findall(".//w:p", ns):
              texts = [t.text for t in p.findall(".//w:t", ns) if t.text]
              s = "".join(texts).strip()
              if s:
                  paragraphs.append(s)
          return {"title": path.stem, "paragraphs": paragraphs}
      
      
      def _shared_strings(zf: zipfile.ZipFile) -> list[str]:
          out: list[str] = []
          try:
              with zf.open("xl/sharedStrings.xml") as f:
                  root = ET.fromstring(f.read())
              ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
              for si in root.findall(".//a:si", ns):
                  out.append("".join((t.text or "") for t in si.findall(".//a:t", ns)))
          except KeyError:
              pass
          return out
      
      
      def parse_xlsx(path: Path) -> dict[str, Any]:
          rows: list[list[str]] = []
          with zipfile.ZipFile(path) as zf:
              shared = _shared_strings(zf)
              with zf.open("xl/worksheets/sheet1.xml") as f:
                  root = ET.fromstring(f.read())
          ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
          for row in root.findall(".//a:sheetData/a:row", ns):
              vals = []
              for c in row.findall("a:c", ns):
                  t = c.attrib.get("t")
                  v = c.find("a:v", ns)
                  if v is None or v.text is None:
                      vals.append("")
                  elif t == "s":
                      idx = int(v.text)
                      vals.append(shared[idx] if 0 <= idx < len(shared) else "")
                  else:
                      vals.append(v.text)
              rows.append(vals)
          return {"title": path.stem, "rows": rows}
      
      
      def parse_xmind(path: Path) -> dict[str, Any]:
          with zipfile.ZipFile(path) as zf:
              names = set(zf.namelist())
              topics: list[str] = []
              if "content.json" in names:
                  data = json.loads(zf.read("content.json").decode("utf-8", errors="ignore"))
      
                  def walk(node: Any):
                      if isinstance(node, dict):
                          t = node.get("title")
                          if isinstance(t, str) and t.strip():
                              topics.append(t.strip())
                          for k in ("children", "topics", "rootTopic", "attached"):
                              walk(node.get(k))
                      elif isinstance(node, list):
                          for i in node:
                              walk(i)
      
                  walk(data)
              elif "content.xml" in names:
                  root = ET.fromstring(zf.read("content.xml"))
                  topics = [e.text.strip() for e in root.findall(".//title") if e.text and e.text.strip()]
              else:
                  raise ValueError("Unsupported XMind package structure")
          return {"title": topics[0] if topics else path.stem, "topics": topics}
      
      
      def detect_in_format(path: Path, forced: str | None) -> str:
          if forced and forced != "auto":
              return forced
          return {
              ".md": "markdown",
              ".markdown": "markdown",
              ".json": "json",
              ".csv": "csv",
              ".docx": "word",
              ".xlsx": "excel",
              ".xmind": "xmind",
              ".tsv": "excel",
          }.get(path.suffix.lower(), "markdown")
      
      
      def normalize(parsed: dict[str, Any]) -> dict[str, Any]:
          title = parsed.get("title") or "QA Output"
          sections: list[dict[str, Any]] = []
      
          if "text" in parsed:
              sections.append({"name": "content", "items": [{"key": "text", "value": parsed["text"]}]})
          if "headings" in parsed:
              sections.append({"name": "headings", "items": [{"key": "heading", "value": h.get("title", "")} for h in parsed["headings"]]})
          if "data" in parsed:
              data = parsed["data"]
              if isinstance(data, dict):
                  items = [{"key": k, "value": v} for k, v in list(data.items())[:100]]
                  sections.append({"name": "json_object", "items": items})
              elif isinstance(data, list):
                  sections.append({"name": "json_array", "items": [{"key": "row", "value": v} for v in data[:200]]})
              else:
                  sections.append({"name": "json_value", "items": [{"key": "value", "value": data}]})
          if "rows" in parsed:
              rows = parsed["rows"]
              sections.append({"name": "rows", "items": [{"key": f"row_{i+1}", "value": r} for i, r in enumerate(rows[:200])]})
          if "columns" in parsed:
              sections.append({"name": "columns", "items": [{"key": "column", "value": c} for c in parsed["columns"]]})
          if "paragraphs" in parsed:
              sections.append({"name": "paragraphs", "items": [{"key": f"p{i+1}", "value": p} for i, p in enumerate(parsed["paragraphs"][:200])]})
          if "topics" in parsed:
              sections.append({"name": "topics", "items": [{"key": "topic", "value": t} for t in parsed["topics"][:300]]})
      
          return {"title": title, "sections": sections}
      
      
      # ---- writers ----
      def write_json(model: dict[str, Any], output: Path) -> None:
          output.write_text(json.dumps(model, ensure_ascii=False, indent=2), encoding="utf-8")
      
      
      def _scalar(v: Any) -> str:
          if isinstance(v, (dict, list)):
              return json.dumps(v, ensure_ascii=False)
          return str(v)
      
      
      def write_csv(model: dict[str, Any], output: Path) -> None:
          with output.open("w", encoding="utf-8", newline="") as f:
              writer = csv.writer(f)
              writer.writerow(["section", "key", "value"])
              for s in model.get("sections", []):
                  for item in s.get("items", []):
                      writer.writerow([s.get("name", ""), item.get("key", ""), _scalar(item.get("value", ""))])
      
      
      def write_excel_tsv(model: dict[str, Any], output: Path) -> None:
          lines = ["Section\tKey\tValue"]
          for s in model.get("sections", []):
              for item in s.get("items", []):
                  lines.append(f"{s.get('name','')}\t{item.get('key','')}\t{_scalar(item.get('value','')).replace(chr(9), ' ')}")
          output.write_text("\n".join(lines) + "\n", encoding="utf-8")
      
      
      def write_markdown(model: dict[str, Any], output: Path) -> None:
          lines = [f"# {model.get('title', 'QA Output')}", ""]
          for s in model.get("sections", []):
              lines.append(f"## {s.get('name', 'section')}")
              for item in s.get("items", []):
                  lines.append(f"- **{item.get('key','key')}**: {_scalar(item.get('value',''))}")
              lines.append("")
          output.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8")
      
      
      def write_word_md(model: dict[str, Any], output: Path) -> None:
          lines = [model.get("title", "QA Output"), "=" * len(model.get("title", "QA Output")), ""]
          idx = 1
          for s in model.get("sections", []):
              lines.append(f"{idx}. {s.get('name', 'section').replace('_', ' ').title()}")
              for item in s.get("items", []):
                  lines.append(f"- {item.get('key','key')}: {_scalar(item.get('value',''))}")
              lines.append("")
              idx += 1
          output.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8")
      
      
      def write_xmind_md(model: dict[str, Any], output: Path) -> None:
          lines = [f"# {model.get('title', 'QA Output')}", "", f"- {model.get('title', 'QA Output')}"]
          for s in model.get("sections", []):
              lines.append(f"  - {s.get('name', 'section')}")
              for item in s.get("items", []):
                  lines.append(f"    - {item.get('key','key')}: {_scalar(item.get('value',''))}")
          output.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8")
      
      
      def default_output(input_path: Path, to_fmt: str) -> Path:
          ext = {
              "json": ".json",
              "csv": ".csv",
              "excel": ".tsv",
              "markdown": ".md",
              "word": ".word.md",
              "xmind": ".xmind.md",
          }[to_fmt]
          return input_path.with_name(input_path.stem + ".converted" + ext)
      
      
      def main() -> None:
          parser = argparse.ArgumentParser(description="Convert QA output files between common formats")
          parser.add_argument("input", type=Path, help="Input file path")
          parser.add_argument("--from", dest="from_fmt", default="auto", choices=["auto", "word", "excel", "xmind", "json", "csv", "markdown"])
          parser.add_argument("--to", required=True, choices=["word", "excel", "xmind", "json", "csv", "markdown"])
          parser.add_argument("--output", type=Path, help="Output file path")
          args = parser.parse_args()
      
          in_fmt = detect_in_format(args.input, args.from_fmt)
          if in_fmt == "word":
              parsed = parse_docx(args.input)
          elif in_fmt == "excel":
              if args.input.suffix.lower() == ".tsv":
                  rows = [line.rstrip("\n").split("\t") for line in args.input.read_text(encoding="utf-8", errors="ignore").splitlines() if line]
                  parsed = {"title": args.input.stem, "rows": rows}
              else:
                  parsed = parse_xlsx(args.input)
          elif in_fmt == "xmind":
              parsed = parse_xmind(args.input)
          elif in_fmt == "json":
              parsed = parse_json(args.input)
          elif in_fmt == "csv":
              parsed = parse_csv_file(args.input)
          else:
              parsed = parse_markdown(args.input)
      
          model = normalize(parsed)
          output = args.output or default_output(args.input, args.to)
      
          if args.to == "json":
              write_json(model, output)
          elif args.to == "csv":
              write_csv(model, output)
          elif args.to == "excel":
              write_excel_tsv(model, output)
          elif args.to == "markdown":
              write_markdown(model, output)
          elif args.to == "word":
              write_word_md(model, output)
          else:
              write_xmind_md(model, output)
      
          print(str(output))
      
      
      if __name__ == "__main__":
          main()
      
    • convert_output_formats.py 255 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL] + sys.argv[1:]))
      
    • convert_to_csv.py 270 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'csv'] + sys.argv[1:]))
      
    • convert_to_excel.py 272 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'excel'] + sys.argv[1:]))
      
    • convert_to_json.py 271 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'json'] + sys.argv[1:]))
      
    • convert_to_markdown.py 275 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'markdown'] + sys.argv[1:]))
      
    • convert_to_word.py 271 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'word'] + sys.argv[1:]))
      
    • convert_to_xmind.py 272 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'xmind'] + sys.argv[1:]))
      
    • parse_csv.py 272 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'csv'] + sys.argv[1:]))
      
    • parse_excel.py 274 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'excel'] + sys.argv[1:]))
      
    • parse_formats.py 5.9 KB
      #!/usr/bin/env python3
      import argparse
      import csv
      import json
      import re
      import zipfile
      from pathlib import Path
      from typing import Any
      from xml.etree import ElementTree as ET
      
      
      def parse_markdown(path: Path) -> dict[str, Any]:
          text = path.read_text(encoding="utf-8", errors="ignore")
          headings = []
          for line in text.splitlines():
              m = re.match(r"^(#{1,6})\s+(.*)$", line.strip())
              if m:
                  headings.append({"level": len(m.group(1)), "title": m.group(2).strip()})
          return {"format": "markdown", "headings": headings, "preview": text[:500]}
      
      
      def parse_json(path: Path) -> dict[str, Any]:
          data = json.loads(path.read_text(encoding="utf-8", errors="ignore"))
          if isinstance(data, dict):
              shape = {"type": "object", "keys": list(data.keys())[:50]}
          elif isinstance(data, list):
              shape = {"type": "array", "size": len(data)}
          else:
              shape = {"type": type(data).__name__}
          return {"format": "json", "shape": shape, "data": data}
      
      
      def parse_csv_file(path: Path) -> dict[str, Any]:
          with path.open("r", encoding="utf-8", errors="ignore", newline="") as f:
              reader = csv.DictReader(f)
              rows = list(reader)
          return {
              "format": "csv",
              "columns": reader.fieldnames or [],
              "row_count": len(rows),
              "sample_rows": rows[:10],
          }
      
      
      def parse_docx(path: Path) -> dict[str, Any]:
          paragraphs = []
          with zipfile.ZipFile(path) as zf:
              with zf.open("word/document.xml") as f:
                  root = ET.fromstring(f.read())
          ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
          for p in root.findall(".//w:p", ns):
              texts = [t.text for t in p.findall(".//w:t", ns) if t.text]
              joined = "".join(texts).strip()
              if joined:
                  paragraphs.append(joined)
          return {"format": "word", "paragraph_count": len(paragraphs), "paragraphs": paragraphs[:100]}
      
      
      def _read_shared_strings(zf: zipfile.ZipFile) -> list[str]:
          strings = []
          try:
              with zf.open("xl/sharedStrings.xml") as f:
                  root = ET.fromstring(f.read())
              ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
              for si in root.findall(".//a:si", ns):
                  parts = [t.text or "" for t in si.findall(".//a:t", ns)]
                  strings.append("".join(parts))
          except KeyError:
              pass
          return strings
      
      
      def parse_xlsx(path: Path) -> dict[str, Any]:
          rows_out: list[list[str]] = []
          with zipfile.ZipFile(path) as zf:
              shared = _read_shared_strings(zf)
              with zf.open("xl/worksheets/sheet1.xml") as f:
                  root = ET.fromstring(f.read())
          ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
          for row in root.findall(".//a:sheetData/a:row", ns):
              vals = []
              for c in row.findall("a:c", ns):
                  cell_type = c.attrib.get("t")
                  v = c.find("a:v", ns)
                  if v is None or v.text is None:
                      vals.append("")
                      continue
                  if cell_type == "s":
                      idx = int(v.text)
                      vals.append(shared[idx] if 0 <= idx < len(shared) else "")
                  else:
                      vals.append(v.text)
              rows_out.append(vals)
          return {"format": "excel", "row_count": len(rows_out), "sample_rows": rows_out[:20]}
      
      
      def parse_xmind(path: Path) -> dict[str, Any]:
          with zipfile.ZipFile(path) as zf:
              names = set(zf.namelist())
              if "content.json" in names:
                  data = json.loads(zf.read("content.json").decode("utf-8", errors="ignore"))
                  titles: list[str] = []
      
                  def walk(node: Any):
                      if isinstance(node, dict):
                          title = node.get("title")
                          if isinstance(title, str) and title.strip():
                              titles.append(title.strip())
                          for k in ("children", "topics", "rootTopic", "attached"):
                              walk(node.get(k))
                      elif isinstance(node, list):
                          for i in node:
                              walk(i)
      
                  walk(data)
                  return {"format": "xmind", "topic_count": len(titles), "topics": titles[:200]}
              if "content.xml" in names:
                  root = ET.fromstring(zf.read("content.xml"))
                  titles = [el.text.strip() for el in root.findall(".//title") if el.text and el.text.strip()]
                  return {"format": "xmind", "topic_count": len(titles), "topics": titles[:200]}
          raise ValueError("Unsupported XMind package structure")
      
      
      def detect_format(path: Path, forced: str | None) -> str:
          if forced and forced != "auto":
              return forced
          ext = path.suffix.lower()
          return {
              ".md": "markdown",
              ".markdown": "markdown",
              ".json": "json",
              ".csv": "csv",
              ".docx": "word",
              ".xlsx": "excel",
              ".xmind": "xmind",
          }.get(ext, "markdown")
      
      
      def main() -> None:
          parser = argparse.ArgumentParser(description="Parse common QA output formats into normalized JSON")
          parser.add_argument("input", type=Path, help="Input file path")
          parser.add_argument("--format", default="auto", choices=["auto", "word", "excel", "xmind", "json", "csv", "markdown"])
          parser.add_argument("--output", type=Path, help="Output JSON path (default: stdout)")
          args = parser.parse_args()
      
          fmt = detect_format(args.input, args.format)
          if fmt == "word":
              result = parse_docx(args.input)
          elif fmt == "excel":
              result = parse_xlsx(args.input)
          elif fmt == "xmind":
              result = parse_xmind(args.input)
          elif fmt == "json":
              result = parse_json(args.input)
          elif fmt == "csv":
              result = parse_csv_file(args.input)
          else:
              result = parse_markdown(args.input)
      
          result["source"] = str(args.input)
          out = json.dumps(result, ensure_ascii=False, indent=2)
          if args.output:
              args.output.write_text(out, encoding="utf-8")
          else:
              print(out)
      
      
      if __name__ == "__main__":
          main()
      
    • parse_json.py 273 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'json'] + sys.argv[1:]))
      
    • parse_markdown.py 277 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'markdown'] + sys.argv[1:]))
      
    • parse_output_formats.py 253 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL] + sys.argv[1:]))
      
    • parse_word.py 273 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'word'] + sys.argv[1:]))
      
    • parse_xmind.py 274 B
      #!/usr/bin/env python3
      import os
      import subprocess
      import sys
      LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py'))
      if __name__ == '__main__':
          raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'xmind'] + sys.argv[1:]))
      
  • output-formats.md 377 B
    # Output Formats
    
    This skill defaults to **Markdown**. If you need **Excel**, **CSV**, or **JSON**, say so explicitly at the end of your request.
    
    - **Excel**: ask for a tab-separated table you can paste into Excel.
    - **CSV**: ask for comma-separated output with a header row.
    - **JSON**: ask for JSON output.
    
    Structured fields can follow templates under `output-templates/`.
    
  • quick-start.md 962 B
    # Code Review - 5-Minute Quick Start
    
    ## Minimum Input
    
    Paste this to the AI (mark anything unknown):
    
    ```text
    Use code-review for this change.
    Business goal:
    Change scope / diff:
    Tech stack:
    Upstream/downstream deps:
    Known risks or team norms:
    ```
    
    ## Expected Output Shape
    
    1. Change summary + overall risk rating  
    2. P0 / P1 / P2 list (with location + fix guidance)  
    3. Testability and observability  
    4. Recommended fix order  
    5. Residual risks and gaps  
    
    ## Severity Cheat Sheet
    
    | Level | Meaning | Examples |
    | --- | --- | --- |
    | P0 | Block merge | Financial loss, severe security, main-path breakage |
    | P1 | Fix this iteration | Likely race, clear perf issue, missing core logs |
    | P2 | Optional / debt | Non-core smells, minor readability |
    
    ## Pre-submit Self-check
    
    - [ ] No naming/indent noise dump  
    - [ ] P0/P1 have impact rationale and location  
    - [ ] Every finding has an executable fix direction  
    - [ ] Assumptions and gaps are marked  
    
  • README.md 852 B
    # Code Review
    
    ## Skill Overview
    
    Risk-driven review of a PR / diff with severity-ranked findings and actionable fixes — catch logic, security, financial-loss, and maintainability defects before merge.
    
    ## How to Use
    
    1. Open `SKILL.md` in this folder and confirm this skill fits your task.
    2. In your AI tool, call `@skill code-review`, then add the diff, business goal, stack, and upstream/downstream context.
    3. If you need a specific output format (table, checklist, report), include it directly in your request.
    
    ## One-Click Install Script
    
    Run from the repository root:
    
    ### macOS / Linux
    
    ```bash
    bash ./scripts/install-skills-mac.sh --tool codex --lang en --skill code-review
    ```
    
    ### Windows PowerShell
    
    ```powershell
    powershell -ExecutionPolicy Bypass -File .\scripts\install-skills-windows.ps1 -Tool codex -Lang en -Skill code-review
    ```
    
  • SKILL.md 4.4 KB
    ---
    name: code-review
    description: Use this skill when you need a risk-driven code review of a PR/diff with severity-ranked findings and actionable fixes; triggers include code review, PR review,.
    ---
    
    # Code Review
    
    **Chinese version:** See the corresponding Chinese skill.
    
    ## When to Use
    
    - Need to review a PR / diff / commit and catch logic, security, financial-loss, or maintainability risks before merge.
    - Need a P0/P1/P2-ranked report with locations and actionable fix guidance.
    - Need a QA / engineering-quality lens beyond author self-review.
    
    ## Workflow
    
    1. Read and follow the main prompt listed under Progressive disclosure (coverage, structure, quality bar).
    2. Before reviewing, confirm both an identifiable code version and its reviewable changes; if either is missing, return a blocked result and request the exact material.
    3. Add only project context that changes the result: change scope, business goal, stack, upstream/downstream deps, known risks, team norms.
    4. Treat role reports as optional, source-identified context; use Product and UI/UX reports only when this change touches their concerns.
    5. Default to Markdown; switch formats only when the user asks.
    
    ## Core Constraints
    
    - Risk-driven: prioritize production failures, financial loss, security, and core maintainability — not naming/indent noise.
    - Evidence-based: prefer file path, line, or snippet plus trigger path and impact for each finding.
    - Two gates: require both identifiable code version (for example repository + PR / commit / branch / tag / revision) and reviewable change (for example diff/patch, changed-file contents, or an accessible base-to-head range). Code identity, change content, and role reports cannot substitute for one another.
    - If either gate is missing, explicitly return `status: blocked` and distinguish `missing_code_identity` from `missing_reviewable_change`; do not claim review completion, recommend merge, or invent code findings.
    - Role reports are optional. When using them, retain `source_role`. Product reports may add business-rule, state-flow, or acceptance context; UI/UX reports may add UI-state, feedback, responsive, or accessibility context only when relevant. Never present a role view as code fact.
    - Strict severity: P0 blocks merge, P1 should fix this iteration, P2 can be tech debt.
    - Separate confirmed facts from assumptions; do not invent endpoints, fields, environments, or root causes the user did not provide.
    - Critique the code, not the author; respect the current stack — do not demand framework/architecture rewrites without authorization.
    - Keep output executable: every finding needs a fix direction or before/after example.
    
    ## Progressive Disclosure
    
    - Before producing output, read and follow `prompts/code-review.md` (minimum coverage, output structure, quality bar).
    - When Excel/CSV/JSON/Word is requested: read `output-formats.md` and honor the format.
    - When a ready-made template fits: use matching files under `output-templates/`.
    - For deeper review dimensions or severity rubrics: read `references/review-dimensions.md`.
    - For examples or calibration: read matching files under `examples/`.
    - For format conversion or helper checks: prefer existing `scripts/` over reinventing.
    - For the shortest path: read `quick-start.md`.
    - For evaluating/regressing this skill: use `evals/` with skill-up.
    
    ## Pre-delivery Checklist
    
    - [ ] Followed the main prompt's output structure
    - [ ] Confirmed both code-identity and reviewable-change gates; if blocked, did not issue a completed review or merge recommendation
    - [ ] Minimum coverage focus: change summary, overall risk rating, P0/P1/P2 list, testability/observability, API/contract compatibility, fix order, residual risks and assumptions… (details in main prompt)
    - [ ] Covered the minimum checklist, or explained omissions
    - [ ] High-risk items have explicit P0/P1 severity with rationale
    - [ ] Did not invent details the user did not provide
    - [ ] Assumptions and gaps are marked
    
    ## Common Pitfalls
    
    - Do not treat a code snippet or role report as code identity, or a PR / commit identifier as the diff; block when either gate is missing.
    - Do not activate Product or UI/UX concerns merely because a report exists; first establish relevance and retain its source.
    - Do not treat every item as equally important, or dump low-value style nits.
    - Do not skip assumptions and information gaps.
    - Do not force refactors outside the change under review.
    - Do not dump generic theory unrelated to this change.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related