J. AI Context & Spec-Driven Engineering Assessment
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 |