## PR Review Mode 1

Diagnoses a diff against the six production decay risks (R1–R6).

TypeScript

### Seven-service payment processor

55 / 100

A single method orchestrates seven services, creating a structural coupling trap where any change to payment, fraud, inventory, or notification touches the same method.

▸ Input code

    class PaymentProcessor {
      constructor(
        private db, private stripe, private mailer, private inventory,
        private analytics, private taxCalc, private fraudDetection
      ) {}

      async processPayment(orderId, cardToken) {
        const order = await this.db.orders.findById(orderId);
        const tax = this.taxCalc.calculate(order.items, order.shippingAddress.state);
        order.tax = tax;
        const fraudScore = await this.fraudDetection.evaluate({ amount: order.total + tax, card: cardToken, ... });
        if (fraudScore > 0.8) { await this.mailer.send(...); await this.analytics.track('fraud_hold', ...); return {...}; }
        const charge = await this.stripe.charges.create({ amount: Math.round((order.total + tax) * 100), ... });
        for (const item of order.items) {
          await this.inventory.decrement(item.sku, item.quantity);
          if (await this.inventory.getStock(item.sku) < 10) { await this.mailer.send('warehouse@company.com', ...); }
        }
        order.status = 'paid'; order.chargeId = charge.id; await this.db.orders.save(order);
        await this.mailer.send(order.customerEmail, 'Payment Received', `Charge: $${order.total + tax}`);
        await this.analytics.track('payment_success', { orderId, amount: order.total + tax });
        return { status: 'paid', chargeId: charge.id };
      }
    }

#### 🔴 Change Propagation — Seven-service constructor signals a God Class

Symptom: One class injects seven dependencies; one method orchestrates all of them.
Source: Fowler — Refactoring — Divergent Change; Martin — Clean Architecture — SRP
Remedy: Decompose into FraudCheckService, InventoryDeductionService, PaymentNotifier — inject 3, not 7.

#### 🔴 Change Propagation — Inventory loop embeds warehouse notification policy

Symptom: A low-stock check (`< 10`) fires a warehouse email with hardcoded recipient inside the payment loop.
Source: Fowler — Refactoring — Shotgun Surgery; Hunt & Thomas — Orthogonality
Remedy: Publish a `StockLevelChanged` domain event a separate notifier subscribes to.

#### 🟡 Knowledge Duplication — `order.total + tax` computed three times

Symptom: The same expression appears on three lines with no shared name.
Source: Hunt & Thomas — DRY; Fowler — Refactoring — Duplicate Code
Remedy: Expose a computed `order.grandTotal`.

#### 🟡 Domain Model Distortion — `Order` is a mutable data bag

Symptom: `order.tax`, `order.status`, `order.chargeId` are all set externally; the object holds no behaviour.
Remedy: Give `Order` state-transition methods: `order.recordPayment(chargeId)`.

## Architecture Audit Mode 2

Maps module dependencies, renders a colour-coded graph, and flags layering and cycle violations.

TypeScript

### Dependency Inversion violation

50 / 100

Domain entities import infrastructure directly, and a near-cycle forms between Product and PricingService.

    graph TD
      subgraph API["API Layer"]
        OrderController; UserController
      end
      subgraph Services["Service Layer"]
        OrderService; PricingService; UserService
      end
      subgraph Domain["Domain Layer"]
        Order; User; Product
      end
      subgraph Infra["Infrastructure Layer"]
        PostgresClient; RedisCache; StripeClient
      end
      OrderController --> OrderService
      UserController --> UserService
      UserService --> OrderService
      OrderService --> Order
      OrderService --> PostgresClient
      PricingService --> Product
      PricingService --> StripeClient
      Order --> PostgresClient
      User --> RedisCache
      Product --> PricingService
      classDef critical fill:#ff6b6b,stroke:#c92a2a,color:#fff
      classDef warning fill:#ffd43b,stroke:#e67700
      classDef clean fill:#51cf66,stroke:#2b8a3e,color:#fff
      class Order,User,Product critical
      class OrderService,PricingService,UserService warning
      class OrderController,UserController,PostgresClient,RedisCache,StripeClient clean

#### 🔴 Dependency Disorder — Domain layer directly imports infrastructure

Symptom: `Order.ts` imports `PostgresClient`; `User.ts` imports `RedisCache`.
Source: Martin — Clean Architecture — Dependency Inversion Principle
Remedy: Define `IOrderRepository`/`IUserRepository` in the domain; move infra refs to `infra/`.

#### 🔴 Dependency Disorder — Product → PricingService (upward dependency)

Symptom: Near-cycle `PricingService → Product → PricingService`.
Source: Martin — Clean Architecture — Acyclic Dependencies Principle
Remedy: Pass pricing as a value object or define `IPricingPolicy` in the domain.
Go

### Circular dependency across packages

45 / 100

`auth → user → notification → auth` forms a strongly connected component — Go refuses to compile it.

    graph TD
      subgraph pkg["pkg/"]
        auth["auth"]; user["user"]; notification["notification"]; billing["billing"]
      end
      auth --> user
      user --> notification
      notification -.->|circular| auth
      billing --> user
      classDef critical fill:#ff6b6b,stroke:#c92a2a,color:#fff
      classDef warning fill:#ffd43b,stroke:#e67700
      class auth,user,notification critical
      class billing warning

#### 🔴 Dependency Disorder — Circular dependency auth → user → notification → auth

Symptom: Three packages form a cycle; none compile, test, or deploy independently.
Source: Martin — Clean Architecture — Acyclic Dependencies Principle
Remedy: Extract interfaces into `pkg/contracts`; each package implements the interface its consumer defines.

#### 🟡 Domain Model Distortion — Bounded contexts crossed with no anti-corruption layer

Symptom: Identity, profile, and notification contexts import each other with no translation layer.
Source: Evans — DDD — Bounded Context; Anti-Corruption Layer
Remedy: Define thin adapters at each context boundary.
Java

### Textbook Clean Architecture

98 / 100

Dependencies flow inward, infra implements domain ports, no cycles. brooks-lint reports clean code as clean — and still offers one forward-looking suggestion.

    graph TD
      subgraph API["API Layer"]
        OrderController; UserController
      end
      subgraph Application["Application Layer"]
        OrderService; UserService
      end
      subgraph Domain["Domain Layer"]
        OrderModel["Order"]; UserModel["User"]; OrderRepository["OrderRepository (interface)"]; UserRepository["UserRepository (interface)"]
      end
      subgraph Infra["Infrastructure Layer"]
        JpaOrderRepository; JpaUserRepository
      end
      OrderController --> OrderService
      UserController --> UserService
      OrderService --> OrderModel
      OrderService --> OrderRepository
      UserService --> UserModel
      UserService --> UserRepository
      JpaOrderRepository --> OrderRepository
      JpaUserRepository --> UserRepository
      classDef clean fill:#51cf66,stroke:#2b8a3e,color:#fff
      class OrderController,UserController,OrderService,UserService,OrderModel,UserModel,OrderRepository,UserRepository,JpaOrderRepository,JpaUserRepository clean

#### 🟢 Suggestion — Monitor application service growth

Symptom: `OrderService` and `UserService` are symmetric siblings that may accrue responsibilities without a split policy.
Source: Brooks — The Mythical Man-Month — Conceptual Integrity
Remedy: Document a "one service per use-case cluster" rule now, before the pattern calcifies.

## Tech Debt Assessment Mode 3

Classifies debt across the decay risks and scores each finding by Pain × Spread priority.

Java

### Shotgun Surgery across six files

56 / 100

Adding a currency means editing six files in six unrelated layers — three Critical findings that share one root cause.

Risk | Findings | Avg Priority | Classification
--- | --- | --- | ---
Change Propagation | 2 | 6.5 | Mixed (1 Critical + 1 Scheduled)
Knowledge Duplication | 1 | 9.0 | Critical
Domain Model Distortion | 1 | 9.0 | Critical
Cognitive Overload | 1 | 6.0 | Scheduled

#### 🔴 Change Propagation — Shotgun Surgery across six modules Pain × Spread: 9

Symptom: Adding EUR requires editing 6 files in 6 distinct layers with no architectural relationship.
Source: Fowler — Refactoring — Shotgun Surgery; Hunt & Thomas — Orthogonality
Remedy: Introduce a `Money` value object and a `MoneyFormatter` service.

#### 🔴 Knowledge Duplication — `$` as a magic literal in five files Pain × Spread: 9

Symptom: The string `"$"` appears in 5 independent locations with no shared constant.
Source: Hunt & Thomas — DRY; McConnell — Code Complete — Ch. 12
Remedy: Use `Currency.getSymbol(Locale)` in `MoneyFormatter`; remove all `"$"` literals.

#### 🔴 Domain Model Distortion — No `Money` type exists Pain × Spread: 9

Symptom: All price/amount fields are raw `double`.
Source: Evans — DDD — Domain Model; Fowler — Refactoring — Data Class
Remedy: Introduce `record Money(BigDecimal amount, Currency currency)`.
Recommended focus: All three Critical findings share one root cause — the absence of a `Money` value object. One intervention collapses three findings.

## Test Quality Review Mode 4

Audits an existing suite against six test-space decay risks (T1–T6).

TypeScript

### Mock abuse

60 / 100

Seven mocks per test, 14 lines of setup vs 6 of assertions — the service is never tested against a real collaborator, and the return value is never checked.

▸ Input test

    it('should place an order successfully', () => {
      const mockDb = mock<Database>();
      const mockPayment = mock<PaymentGateway>();
      const mockInventory = mock<InventoryService>();
      const mockMailer = mock<MailService>();
      const mockAudit = mock<AuditLogger>();
      const mockCache = mock<CacheService>();
      const mockMetrics = mock<MetricsCollector>();
      const service = new OrderService(mockDb, mockPayment, mockInventory, mockMailer, mockAudit, mockCache, mockMetrics);
      const result = await service.placeOrder('1', 'item-1', 2);

      expect(mockPayment.charge).toHaveBeenCalledWith('ch_1', 2000);
      expect(mockInventory.check).toHaveBeenCalledWith('item-1', 2);
      expect(mockMailer.send).toHaveBeenCalled();
      expect(mockAudit.log).toHaveBeenCalledWith('ORDER_PLACED', expect.anything());
      expect(mockCache.invalidate).toHaveBeenCalledWith('orders:1');
      expect(mockMetrics.increment).toHaveBeenCalledWith('orders.placed');
    });

#### 🔴 Mock Abuse — Seven mocks per test; setup dominates logic

Symptom: 7 mock objects; 14 lines of setup vs 6 of assertions. No real collaborator is ever exercised.
Source: Osherove — The Art of Unit Testing (mock count > 3); Meszaros — xUnit Test Patterns
Remedy: Reduce mocks to ≤ 3, use in-memory fakes, assert on `result` first.

#### 🔴 Mock Abuse — All six assertions verify mock calls, not behaviour

Symptom: Every assertion is `toHaveBeenCalledWith`; `result` is captured but never asserted.
Consequence: A `placeOrder` that calls every mock yet returns `null` or double-charges still passes.
Remedy: Assert observable output: `expect(result.status).toBe('confirmed')`.
Python

### Inverted test pyramid

55 / 100

Only 16% of tests are unit tests; an E2E-heavy suite takes ~9 minutes and blocks fast CI feedback.

▸ Suite overview

    tests/
    ├── e2e/           47 tests, avg 8s each   (~6 min)
    ├── integration/   83 tests, avg 2s each   (~3 min)
    └── unit/          24 tests, avg 10ms each (~0.2s)

    Total: 154 tests, ~9 min
    Actual  ratio:  Unit 16% : Integration 54% : E2E 30%
    Target  ratio:  Unit 70% : Integration 20% : E2E 10%

#### 🔴 Architecture Mismatch — Fully inverted test pyramid

Symptom: Only 24 of 154 tests (16%) are unit tests; E2E + integration = 84%.
Source: Google — How Google Tests Software — 70:20:10; Meszaros — xUnit Test Patterns
Remedy: Target 70% unit; reduce E2E to 5–8 critical smoke tests.

#### 🔴 Architecture Mismatch — 9-minute suite blocks CI fast-feedback

Symptom: Full suite ~542s, dominated by 8s E2E tests.
Remedy: Split CI: (1) unit only, < 60s, blocks merge; (2) integration + E2E async, non-blocking.

#### 🟡 Coverage Illusion — Core domain untested at unit level

Symptom: `tests/unit/` covers only validators and formatters — no checkout, login, order, or payment.
Source: Feathers — Working Effectively with Legacy Code
Remedy: Start with `test_checkout_flow.py` and `test_payment_api.py`.