Skip to content

J. AI Context & Spec-Driven Engineering Assessment

← Back to README


Current State: AI Effectiveness is Degraded

The multi-repo structure, version fragmentation, and lack of typed contracts measurably reduce the quality of AI-assisted development across this ecosystem. This section quantifies the impact and provides a concrete documentation strategy.


How the Current Structure Impairs AI

1. Context Fragmentation

An AI session opened in reverb-backend has zero visibility into: - The response shapes expected by soreto-melissa service classes - The processor contracts used by soreto-zoe - The role enumeration defined in soreto-melissa/shared/constants.ts

The result: the AI rediscovers the same architecture in every session. When asked to implement a new API endpoint, it cannot see how that endpoint is consumed — so it produces a generic implementation instead of a type-correct one.

In a monorepo: One session sees the full system. The AI can read service/CampaignService.ts in melissa, understand the response shape expected, and implement the reverb-backend endpoint to match it in one pass.

2. Convention Inconsistency Produces Inconsistent Output

Four repos, four coding styles:

Convention reverb-backend reverb-react soreto-melissa soreto-zoe
Module system CJS (require) CJS + ESM ESM AMD (legacy)
Function style Callbacks → Promises Callbacks + hooks async/await async/await
Error handling Express middleware catch blocks try/catch try/catch
Variable declarations var / let var / const const const
Quotes Single Single Single Single
Indentation 2 spaces 2 spaces Next.js default 4 spaces (AMD)

An AI working on reverb-backend produces var and callback-style code. The same AI working on melissa produces const and async/await. Neither is wrong for its context, but the inconsistency means cross-repo code produced in the same session will look like it was written by different people.

In a monorepo with @soreto/eslint-config: One set of rules. The AI produces consistent output regardless of which app it's working in.

3. Type Contract Opacity

The largest single source of AI-generated errors in this ecosystem:

// soreto-melissa/service/CampaignService.ts — current state
static async getCampaignVersions(campaignId: string) {
  return BaseService.get(`campaign/${campaignId}/version`);
}
// Return type: Promise<AxiosResponse<any>>
// The AI has no idea what this returns.

Without typed contracts, the AI must guess at response shapes. Guesses lead to: - Incorrect property access (runtime undefined) - Missing null checks - Wrong pagination assumptions - Incorrect status code handling

With @soreto/types:

static async getCampaignVersions(campaignId: string): Promise<CampaignVersion[]> {
  const res = await BaseService.get<PaginatedResponse<CampaignVersion>>(`campaign/${campaignId}/version`);
  return res.data.data;
}

The AI now knows exactly what it's working with. Every downstream component that uses this service benefits.

4. Dependency Drift Causes Version-Specific Confusion

axios@0.18 (reverb-react), axios@0.27 (reverb-backend), axios@1.7 (melissa). The AI treats these as the same library, but: - axios@0.18 has no withCredentials in the same position - axios@1.7 has AxiosResponse type changes - Error handling changed significantly between axios@0.x and 1.x

When AI suggests a pattern from axios@1.7 in a reverb-react context, it silently produces broken code. In a monorepo with unified axios@1.7, this class of error disappears.


Monorepo Benefits for AI Development

Single Context Window

In a monorepo, claude code . or cursor . opens the full system:

claude code /path/to/soreto-platform

The AI can: - Read reverb-backend route implementations - Read melissa service consumers - Read soreto-zoe processor contracts - Propose a change that is correct across all three simultaneously

Currently, this requires three separate sessions with manual context-sharing between them.

Shared Types as AI Memory

@soreto/types acts as persistent, typed memory for the AI:

// The AI reads this ONCE and knows the full domain model
export interface Campaign {
  id: string;
  clientId: string;
  name: string;
  type: CampaignType;
  status: CampaignStatus;
  createdAt: Date;
  updatedAt: Date;
}

Without shared types, the AI infers entity shapes from database migrations, route handlers, and service files — a lossy inference process. With shared types, the entity is defined exactly once.


Documentation Strategy for AI-Optimized Development

Root CLAUDE.md (Monorepo Level)

# Soreto Platform — Engineering Guide

## System Overview
Four components form a single platform:
- **platform-api** (reverb-backend): Core REST API, PostgreSQL, Redis, Express
- **platform-ui** (soreto-melissa): Admin portal, Next.js 13, React 18
- **zoe**: Job scheduler, Bull queues, affiliate integrations
- **legacy-portal** (reverb-react): Modernizing → Next.js 16 + React 19 + Node 24 (rewrite in progress)

## Key Conventions
- Package manager: npm with workspaces (built into npm 7+; all repos already use npm)
- Node version: 24 LTS (enforced via .nvmrc)
- Language: TypeScript everywhere (reverb-backend migration in progress)
- Shared types: @soreto/types — always use these for API shapes
- API client: @soreto/api-client — never call reverb-backend with raw axios from zoe

## Running Locally
[instructions]

## Environment Variables
[link to .env.example in each app]

Per-App CLAUDE.md

Each apps/*/CLAUDE.md contains: - App purpose and domain responsibility - Key directories and what they contain - Environment variables required - How to run locally and test - Current tech debt items (linked to audit)

docs/spec/DOMAIN_MODEL.md

# Domain Model

## Campaign
A campaign is a referral promotion set up by a client...

### Key relationships
- Campaign has many CampaignVersions (A/B test variants)
- CampaignVersion has many SharedUrls (one per user)
- SharedUrl generates Orders when a referred user purchases

## Order
An order is created when a customer completes a purchase after clicking a SharedUrl...

This document is the single source of truth for what the business entities mean. AI tools read this and produce implementations aligned with the actual domain.

docs/spec/API_ENDPOINTS.md

A machine-readable (or easily parseable) inventory of all reverb-backend routes:

## POST /auth/login
Auth: none
Body: (uses HTTP Basic auth header)
Response: sets `reverbToken` cookie
Success: 200

## GET /campaign
Auth: bearer token / cookie
Query: { clientId?, status?, page?, pageSize? }
Response: PaginatedResponse<Campaign>
Success: 200

This document — combined with @soreto/types — gives the AI enough context to produce correct implementations on the first attempt.

ADR Templates

Architecture Decision Records prevent repeated debates about the same decisions:

docs/adr/
├── 001-monorepo-migration.md          — WHY we moved to a monorepo
├── 002-node-version-standardization.md — WHY we chose Node 24
├── 003-typescript-adoption-backend.md  — WHY we're adding TS to reverb-backend
├── 004-modernize-reverb-react.md       — WHY reverb-react is being rewritten to Next.js 16
├── 005-seneca-replacement.md           — WHY we replaced/kept seneca
└── 006-api-contract-first.md           — WHY we use @soreto/types

Format:

# ADR-001: Monorepo Migration
Status: Accepted
Date: 2026-05-19

## Context
[Why this decision was needed]

## Decision
[What was decided]

## Consequences
[What changes as a result]

## Alternatives Considered
[What else was evaluated and why it was rejected]

AI Tooling Perspective

Claude Code

Benefits most from: - A root CLAUDE.md that describes the full system - @soreto/types for type inference - Consistent module system (ESM everywhere) - Per-package CLAUDE.md files

Cursor

Benefits most from: - TypeScript project references so the IDE understands cross-package imports - @soreto/api-client so autocomplete works on the reverb client - Unified tsconfig.json with path aliases

Copilot

Benefits most from: - Consistent patterns (fewer "which style should I use?" decisions) - Named test files that describe behavior (campaign.service.test.ts, not test.js) - JSDoc on service methods (transitional period before full TypeScript)

Future Autonomous Agents

Benefits most from: - Machine-readable docs/spec/API_ENDPOINTS.md - @soreto/types as the ground truth for entity shapes - ADRs that explain WHY decisions were made (not just what) - Well-scoped packages with clear package.json descriptions


Priority Documentation Artifacts

Artifact Location Priority Owner
Root CLAUDE.md /CLAUDE.md HIGH Platform Engineer
Domain model spec docs/spec/DOMAIN_MODEL.md HIGH Backend Lead
API endpoints inventory docs/spec/API_ENDPOINTS.md HIGH Backend Lead
Per-app CLAUDE.md apps/*/CLAUDE.md MEDIUM Each app owner
Inter-repo coupling map docs/dependencies/COUPLING.md MEDIUM Platform Engineer
ADR: monorepo migration docs/adr/001-... MEDIUM Principal Architect
ADR: Node standardization docs/adr/002-... MEDIUM Principal Architect
Feature parity checklist docs/migration/REVERB_REACT_PARITY.md HIGH Full-stack Engineer
Upgrade blockers docs/dependencies/UPGRADE_BLOCKERS.md MEDIUM Backend Lead