diff --git a/services/libs/data-access-layer/README.md b/services/libs/data-access-layer/README.md new file mode 100644 index 0000000000..a4f7fd7af4 --- /dev/null +++ b/services/libs/data-access-layer/README.md @@ -0,0 +1,554 @@ +# Data Access Layer + +A centralized library for database operations and data retrieval in crowd.dev, providing standardized CRUD operations with intelligent caching and strict architectural guidelines. + +## Overview + +The Data Access Layer (`@crowd/data-access-layer`) ensures: +- **Type-safe database operations** with TypeScript interfaces +- **Single entity responsibility** - each module owns exactly one table +- **Transaction-aware operations** using QueryExecutor pattern +- **Redis-based caching** with stale-while-revalidate (SWR) +- **Complete JSDoc documentation** for all public functions + +## Architecture + +### File Structure +Each entity follows a standardized structure with explicit versioning: +``` +src/[entity]/ +├── index.ts # Version router (points to latest) +├── __tests__/ # Integration tests across versions +├── v1/ # Version 1 (legacy) +│ ├── index.ts # V1 API exports +│ ├── base.ts # V1 CRUD operations +│ ├── types.ts # V1 interfaces +│ ├── constants.ts # V1 configuration +│ └── __tests__/ # V1 unit tests +└── v2/ # Version 2 (current) + ├── index.ts # V2 API exports + ├── base.ts # V2 CRUD operations + ├── types.ts # V2 interfaces + ├── constants.ts # V2 configuration + ├── queryBuilder.ts # V2 query utilities (optional) + └── __tests__/ # V2 unit tests +``` + +**Versioning Logic:** +- **Root `index.ts`**: Routes to latest version (smart default) +- **Explicit versions (`v1/`, `v2/`)**: All versions in their own namespace +- **Migration path**: `v1/` → `v2/` → `v3/` (linear progression) + +### Entity Ownership Principle + +**🚨 CRITICAL RULE**: Each entity module owns exactly ONE database table. + +```typescript +// ❌ FORBIDDEN: Cross-entity operations +export async function updateMemberOrganization(memberId: string, orgData: any) { + return qx.query('UPDATE organizations SET name = $1...', [orgData.name]) +} + +// ✅ CORRECT: Entity-specific operations only +export async function updateMember(qx: QueryExecutor, memberId: string, data: IUpdateMemberData) { + return qx.query('UPDATE members SET display_name = $1...', [data.displayName]) +} +``` + +For cross-entity operations, coordinate at the service layer. + +### Core Components + +- **`base.ts`** - CRUD operations (`create`, `update`, `findById`, `findMany`, `delete`) +- **`types.ts`** - TypeScript interfaces (`IDb[Entity]Data`, `I[Entity]CreateData`) +- **`constants.ts`** - Cache TTL, query limits, table names +- **`queryBuilder.ts`** - Dynamic SQL construction (optional) +- **`utils.ts`** - Entity helpers (discouraged, prefer shared `/utils/`) + +### Entity Versioning Strategy + +**When to Create a New Version:** +- Breaking changes to database schema +- Major API interface modifications +- Significant performance optimizations that change behavior +- Migration from legacy patterns (e.g., Sequelize → QueryExecutor) + +**Version Management Rules:** +```typescript +// Root index.ts - Routes to latest version +export * from './v2' // Current latest +export * as v1 from './v1' // Legacy access +export * as v2 from './v2' // Explicit access + +// Specific version imports +import { findMemberById } from '@crowd/dal/members' // Latest (v2) +import { findMemberById } from '@crowd/dal/members/v1' // Explicit v1 +import { findMemberById } from '@crowd/dal/members/v2' // Explicit v2 +``` + +**Backward Compatibility:** +- Keep old versions for 6+ months minimum +- Provide clear migration guides +- Log deprecation warnings in legacy versions +- Run both versions in parallel during transition + +### Example Structure +```typescript +// src/members/v2/constants.ts (Current Version) +export const MEMBER_CONSTANTS = { + CACHE: { TTL_SECONDS: 1800, KEY_PREFIX: 'member' }, + QUERY: { DEFAULT_LIMIT: 20, MAX_LIMIT: 1000 } +} as const + +// src/members/v2/base.ts (Current Version) +export async function queryMembersAdvanced( + qx: QueryExecutor, + params: IQueryMembersAdvancedParams +): Promise> { + const cacheKey = `${MEMBER_CONSTANTS.CACHE.KEY_PREFIX}:advanced:${hash(params)}` + // ... optimized implementation with QueryExecutor +} +``` + +### Versioning Example +```typescript +// src/members/index.ts (Version Router) +export * from './v2' // Latest version (default exports) +export * as v1 from './v1' // Legacy namespace +export * as v2 from './v2' // Explicit namespace + +// Version metadata +export const LATEST_VERSION = 'v2' +export const SUPPORTED_VERSIONS = ['v1', 'v2'] as const + +// src/members/v2/index.ts (Current Version) +export { findMemberById, createMember, queryMembersAdvanced } from './base' +export type { IDbMemberData, ICreateMemberData } from './types' +export { MEMBER_CONSTANTS } from './constants' + +// src/members/v2/base.ts (Current Implementation) +export async function findMemberById( + qx: QueryExecutor, + memberId: string +): Promise { + // Optimized implementation with QueryExecutor + return qx.selectOneOrNone( + 'SELECT id, display_name, email FROM members WHERE id = $1', + [memberId] + ) +} + +// src/members/v1/base.ts (Legacy Implementation) +/** + * @deprecated Use v2 API instead. Will be removed in Q2 2025. + */ +export async function findMemberById( + qx: QueryExecutor, + memberId: string +): Promise { + console.warn('Members V1 API is deprecated. Migrate to V2 by Q1 2025.') + // Legacy Sequelize-style implementation + return qx.selectOneOrNone('SELECT * FROM members WHERE id = $1', [memberId]) +} +``` + +**Usage Patterns:** +```typescript +// Option 1: Use latest (recommended) +import { findMemberById } from '@crowd/dal/members' +const member = await findMemberById(qx, id) + +// Option 2: Explicit version (migration scenarios) +import { findMemberById } from '@crowd/dal/members/v2' +const member = await findMemberById(qx, id) + +// Option 3: Legacy support (temporary) +import { v1 } from '@crowd/dal/members' +const member = await v1.findMemberById(qx, id) +``` + +**Real-World Migration Scenario:** +1. **V1**: Sequelize-based, full row SELECT, slower +2. **V2**: QueryExecutor-based, selective columns, optimized +3. **Services**: Gradually migrate from `v1` to default imports +4. **Cleanup**: Remove `v1/` folder after deprecation period + +## Caching Strategy + +**Stale-While-Revalidate (SWR) Pattern** +- Returns cached data immediately (if available) +- Refreshes cache in background for next request +- 30-minute default TTL with Redis backend + +```typescript +// Usage +const cached = await cache.get(cacheKey) +if (cached) { + void refreshCacheInBackground(params, cacheKey, cache, qx) + return JSON.parse(cached) +} + +const result = await executeQuery(params, qx) +await cache.set(cacheKey, JSON.stringify(result), TTL_SECONDS) +return result +``` + +## Logging Guidelines + +**Log Levels** +- **ERROR**: Database failures, constraint violations +- **WARN**: Slow queries (>5s), cache misses +- **INFO**: Cache refresh, bulk operations +- **DEBUG**: Query details, performance metrics + +**What to Log** +- Operation context (method, entity, operation type) +- Performance data (execution time, record count) +- Sanitized queries (no sensitive data) + +**Never Log** +- PII, credentials, raw query parameters +- Use `userId.substring(0, 8) + '...'` for references + +## Violation Examples + +Real violations found in the codebase that break architectural principles: + +### Violation 1: Members Enrichment Worker Modifying Organizations Table + +**Location:** `/services/libs/data-access-layer/src/old/apps/members_enrichment_worker/index.ts` + +**❌ Problem Code:** +```typescript +// VIOLATION: members_enrichment_worker inserting into organizations table +export async function insertOrganization( + tx: DbTransaction, + /* Lines 122-124 omitted */ + location: string, +): Promise { + const id = generateUUIDv4() + /* Lines 127-137 omitted */ + return id +} +``` + +**Why This Is Wrong:** +- The `members_enrichment_worker` module is performing INSERT operations on the `organizations` table +- This creates tight coupling between member enrichment logic and organization data management +- Changes to the organizations table structure could break the member enrichment worker +- It's impossible to know all places that modify organizations without searching the entire codebase + +**✅ Correct Approach:** +```typescript +// Service layer coordinates entity operations +import { createOrganization } from '@crowd/data-access-layer/src/organizations' + +export async function enrichMemberWithOrganization(memberId: string, orgData: any) { + // Let the organizations entity handle organization creation + /* Lines 154-161 omitted */ + await linkMemberToOrganization(memberId, orgId) +} +``` + +**More violations exist** - see original codebase for full details. + +### Violation 3: Organization Operations Outside Organizations Module + +**Location:** `/services/libs/data-access-layer/src/old/apps/entity_merging_worker/orgs.ts` + +**❌ Problem Code:** +```typescript +// VIOLATION: DELETE operation on organizations from non-organizations module +export async function deleteOrganizationById(db: DbStore, organizationId: string) { + await db.connection().query( + /* Lines 176-178 omitted */ + ) +} +``` + +**Why This Is Wrong:** +- Organization deletion logic is implemented outside the `organizations` entity module +- This bypasses any business logic, validation, or cascading operations that should happen in the organizations module +- Creates duplicate and potentially inconsistent deletion logic +- Makes it impossible to implement organization-specific cleanup or audit trails + +**✅ Correct Approach:** +```typescript +// Use the organizations entity for all organization operations +import { deleteOrganization } from '@crowd/data-access-layer/src/organizations' + +export async function cleanupEntityMerging(organizationId: string) { + // Let the organizations module handle its own deletion logic + await deleteOrganization(organizationId) +} +``` + +### Violation 4: Organizations Module Modifying Member Relationships + +**Location:** `/services/libs/data-access-layer/src/organizations/base.ts` (Active Code) + +**❌ Problem Code:** +```typescript +// VIOLATION: Organizations entity inserting into memberOrganizations table +export async function addOrgsToMember( + qe: QueryExecutor, + /* Lines 208-209 omitted */ + orgs: IOrganizationIdSource[], +): Promise { + const query = ` + /* Lines 212-216 omitted */ + await qe.selectNone(query, parameters) +} +``` + +**Why This Is Wrong:** +- The `organizations` entity is directly manipulating the `memberOrganizations` table +- This table represents a relationship that should be managed by a dedicated relationship entity or the members entity +- Creates coupling between organization logic and member-organization relationship management +- Makes it unclear which entity owns the relationship data + +**✅ Correct Approach:** +```typescript +// Service layer coordinates relationship creation +import { createMemberOrganizationRelationship } from '@crowd/data-access-layer/src/member-organization-relationships' + +export async function linkOrganizationsToMember(memberId: string, orgIds: string[]) { + // Let the relationship entity handle the relationship creation + for (const orgId of orgIds) { + await createMemberOrganizationRelationship({ + memberId, + organizationId: orgId, + source: 'enrichment' + }) + } +} +``` + +## Transaction Management + +**Service Layer Transactions** +```typescript +// Service coordinates multiple entities +export async function createMemberWithOrganization(memberData: any, orgData: any) { + return qx.tx(async (tx) => { + const memberId = await updateMember(tx, memberData) + const orgId = await createOrganization(tx, orgData) + return { memberId, orgId } + }) +} +``` + +**Entity Functions Accept QueryExecutor** +```typescript +// All functions must accept QueryExecutor as first parameter +export async function updateMember( + qx: QueryExecutor, + memberId: string, + data: IUpdateMemberData +): Promise { + await qx.result('UPDATE members SET...', data) +} +``` + +**Key Principles** +- Service layer manages transaction boundaries +- Entity functions are transaction-agnostic +- Automatic rollback on errors +- No manual commit/rollback + +### Migration Strategy + +**Phase 1: Standardize Entity Functions** +- Ensure all entity functions accept `QueryExecutor` as first parameter +- Remove direct database connection usage in entity functions + +**Phase 2: Refactor Service Layer** +- Replace manual transaction management with `qx.tx()` pattern +- Move transaction boundaries to service layer + +**Phase 3: Cleanup Legacy Code** +- Remove `SequelizeRepository.createTransaction()` usage +- Consolidate on QueryExecutor pattern across all layers + +--- + +## 7. Documentation Standards + +All data access functions must be thoroughly documented using TSDoc/JSDoc format. This ensures developers understand the function's purpose, parameters, return values, and potential side effects. + +### Documentation Requirements + +**All exported functions must include:** +- Clear description of functionality and business purpose +- Complete parameter documentation with types and constraints +- Return value structure and type information +- Possible exceptions and error conditions +- Practical usage examples +- Performance characteristics and caching behavior +- Transaction requirements + +**Example:** +```typescript +/** + * Retrieves members with advanced filtering capabilities. + * + * @description Performs complex member queries with support for activity filtering, + * organization relationships, and engagement metrics. Uses SWR caching pattern. + * + * @param qx - Query executor (transaction-aware) + * @param tenantId - Tenant identifier for data isolation + * @param params - Query filters and pagination options + * + * @returns Promise resolving to paginated member results + * + * @throws {ValidationError} When parameters are invalid + * @throws {DatabaseError} When query execution fails + * + * @example + * ```typescript + * const members = await queryMembersAdvanced(qx, tenantId, { + * limit: 20, + * activityTypes: ['github_commit'], + * engagementScore: { min: 50 } + * }) + * ``` + * + * @cache Redis SWR, 30min TTL + * @performance ~500ms for complex queries + */ +``` + +### Custom Tags for Data Access Layer + +The following custom JSDoc tags provide additional context specific to data access operations: + +- `@cache` - Describes caching strategy and TTL configuration +- `@performance` - Notes about execution time and optimization characteristics +- `@transaction` - Indicates transaction requirements and behavior +- `@internal` - Marks functions for internal library use only +- `@entity` - Specifies which database entity this function operates on +- `@migration` - Notes about database migration requirements + +**Example with custom tags:** +```typescript +/** + * Creates a new member organization relationship. + * + * @entity memberOrganizations + * @transaction Required - must run within transaction context + * @cache Invalidates member and organization caches + * + * @param qx - Query executor (transaction required) + * @param relationship - Relationship data to create + */ +export async function createMemberOrganizationRelationship( + qx: QueryExecutor, + relationship: ICreateMemberOrgRelationship, +): Promise { + // Implementation... +} +``` + +### Module-Level Documentation + +Each entity module should include comprehensive file-level documentation: + +```typescript +/** + * @fileoverview Member entity data access operations. + * + * This module provides comprehensive data access functions for member-related + * database operations. All functions follow the single-entity responsibility + * principle and operate exclusively on the 'members' table. + * + * **Key Features:** + * - CRUD operations with type safety + * - Advanced querying with caching + * - Transaction-aware operations + * - Performance optimized queries + * + * **Caching Strategy:** + * Uses Redis-based stale-while-revalidate (SWR) pattern with 30-minute TTL. + * Cache keys include tenant and parameter context for accuracy. + * + * **Performance Notes:** + * - Simple queries: <100ms + * - Complex aggregations: <2000ms + * - Bulk operations: <5000ms for 1000 records + * + * @example + * ```typescript + * import { findMemberById, updateMember } from '@crowd/data-access-layer/src/members' + * + * const member = await findMemberById(qx, 'member-123') + * await updateMember(qx, member.id, { lastActive: new Date() }) + * ``` + * + * @see {@link IDbMemberData} for member data structure + * @see {@link MEMBER_CONSTANTS} for configuration constants + * + * @module members + * @version 2.1.0 + */ +``` + +### Generating Documentation + +Generate HTML documentation from TSDoc comments using TypeDoc: + +```bash +# Install TypeDoc +npm install --save-dev typedoc typedoc-plugin-markdown + +# Generate documentation +npm run docs:generate # Generate HTML documentation +npm run docs:serve # Serve documentation locally +npm run docs:validate # Validate documentation completeness +``` + +**TypeDoc Configuration (typedoc.json):** +```json +{ + "entryPoints": ["src/*/index.ts"], + "out": "docs", + "theme": "default", + "excludePrivate": true, + "excludeInternal": false, + "categoryOrder": [ + "Core Entities", + "Relationships", + "Utilities", + "*" + ], + "plugin": ["typedoc-plugin-markdown"] +} +``` + +**Package.json Scripts:** +```json +{ + "scripts": { + "docs:generate": "typedoc", + "docs:serve": "http-server docs -p 8080", + "docs:validate": "tsc --noEmit && typedoc --validation" + } +} +``` + +### Documentation Quality Standards + +**Required Documentation Quality Checks:** +- All public functions must have complete JSDoc documentation +- Examples must be executable and tested +- Performance annotations must include realistic timing expectations +- Cache behavior must be clearly documented +- Transaction requirements must be explicitly stated +- Error conditions must be comprehensively covered + +**Documentation Review Process:** +1. **Automated Validation**: Use TypeDoc validation to ensure completeness +2. **Code Review**: Documentation quality is part of PR review criteria +3. **Example Testing**: All documentation examples must pass automated testing +4. **Performance Verification**: Stated performance characteristics must be validated through benchmarks + +The generated documentation provides a comprehensive reference for all data access functions, making it easier for developers to understand and use the library effectively while maintaining high code quality and consistency across the platform. \ No newline at end of file diff --git a/services/libs/data-access-layer/simple-agent.md b/services/libs/data-access-layer/simple-agent.md new file mode 100644 index 0000000000..a114ef949f --- /dev/null +++ b/services/libs/data-access-layer/simple-agent.md @@ -0,0 +1,42 @@ +You are an expert code reviewer focusing on the Data Access Layer (DAL) of a Node.js/TypeScript project. You will be given a pull request diff or code changes, and your task is to **evaluate whether the changes adhere to our DAL standards and best practices**. Provide a detailed, constructive review, paying special attention to the following areas: + +1. **File Structure & Organization** – Ensure that the code follows the standard file structure for a data access module. + Each entity should reside in its own directory (e.g. `src/[entity]/v1/` or `src/[entity]/v2/`) with the expected files: + `index.ts` (exports), `base.ts` (core CRUD), `types.ts`, `constants.ts`, optional `queryBuilder.ts` or `utils.ts`, and a `__tests__/` folder. + Shared utilities must be placed in `src/utils/` instead of duplicated. + **Flag any deviations**, including missing versioned directories or inconsistent structure between versions. + +2. **Entity Ownership (Single-Table Responsibility)** – Each module must only perform CRUD operations on **its own table**, with no cross-entity SQL. + This applies **independently for each version** (`v1`, `v2`). + If multiple entities must be coordinated, it must happen in the service layer. + **Identify any violations** such as direct updates of other entities' tables or cross-version dependencies (e.g. `v2` importing code from `v1`). + +3. **Unit Tests Coverage** – Each version (`v1`, `v2`) must have adequate test coverage. + A `__tests__/` folder must exist and all new or modified exported functions must have corresponding tests. + **Point out missing or incomplete tests.** + +4. **Transaction Management** – Verify correct use of the `QueryExecutor` pattern. + DAL functions must accept a transaction-aware executor (`qx` / `tx`) and never manually start or commit transactions. + Multi-step atomic operations must be handled by the service layer via `qx.tx(...)`. + Confirm that functions are transaction-agnostic and that versioned modules follow the same rules. + +5. **Documentation (JSDoc/TSDoc)** – All public functions in each version must include complete documentation: + description, parameters, return values, error cases, and relevant custom tags (`@cache`, `@transaction`, `@performance`). + **Flag missing, outdated, or incomplete documentation.** + +6. **Version Management & Isolation** – + - New versions (`v2`) must only be created for breaking changes + - Older versions (`v1`) must remain stable and include deprecation notes where appropriate + - Root exports must default to the latest version and expose older versions explicitly + - Each version must be self-contained, with **no cross-version imports** + - Shared logic must be moved to `src/utils/` rather than duplicated or linked between versions + **Highlight any misuse of versioning**, such as unnecessary new versions, breaking changes inside existing versions, or incorrect routing. + +--- + +**Output a thorough review** identifying any problems or deviations from these standards. +Explain the issues clearly and suggest how to fix them. +Acknowledge correct and well-structured code where relevant, but keep the focus on actionable improvements. + +Your response should be structured, clear, and constructive — written as a senior reviewer guiding the contributor. +Now, based on the provided changes, perform the review. diff --git a/services/libs/data-access-layer/structured-agent.txt b/services/libs/data-access-layer/structured-agent.txt new file mode 100644 index 0000000000..40a35233b9 --- /dev/null +++ b/services/libs/data-access-layer/structured-agent.txt @@ -0,0 +1,322 @@ + +You are an expert Data Access Layer (DAL) Compliance Auditor with deep expertise in: +- Database architecture and design patterns +- TypeScript/JavaScript code analysis +- Transaction management best practices +- API documentation standards (JSDoc/TSDoc) +- Software testing methodologies + +Your responsibility is to evaluate code changes against strict architectural standards and provide actionable, detailed feedback with specific examples and recommendations. + + + +This is a Data Access Layer for a multi-tenant SaaS platform using PostgreSQL with pg-promise. The architecture enforces strict separation of concerns where each entity module exclusively manages its own database table(s). + +CRITICAL PRINCIPLES: +1. Single Table Ownership: Each entity module MUST have exclusive responsibility for its corresponding database table. Cross-entity CRUD operations are STRICTLY FORBIDDEN. +2. Transaction Transparency: All entity functions must accept QueryExecutor as first parameter and be transaction-agnostic. Manual transaction management (commit/rollback) is FORBIDDEN in the DAL. +3. Documentation Completeness: All public functions must have complete JSDoc/TSDoc with @param, @returns, @throws, @example, and custom tags (@cache, @performance, @transaction, @entity). + + + +Analyze the provided code files and evaluate compliance across 5 critical areas. For EACH area: +1. Identify all violations with severity level (CRITICAL, HIGH, MEDIUM, LOW) +2. Calculate a compliance score (0-100) +3. Provide specific recommendations with code examples +4. Reference exact line numbers and file paths + +INPUT: You will receive entity_name, expected_tables (list), and files (dict of path→content) + + + +NAME: File Structure Compliance + +REQUIRED STRUCTURE: +src/[entity]/ + ├── index.ts (required) - Main exports and public API + ├── base.ts (required) - Core CRUD operations + ├── types.ts (required) - TypeScript interfaces + ├── constants.ts (required) - Module-specific constants + ├── queryBuilder.ts (optional) - Query construction + ├── utils.ts (discouraged) - Entity-specific helpers (prefer shared /utils/) + └── __tests__/ (required) - Unit tests + +EVALUATION POINTS (total 100): +- File Organization (30pts): Files in correct directories with proper naming? +- File Purpose Alignment (30pts): Each file contains only its designated content? +- Separation of Concerns (25pts): Utilities reusable or should be shared? +- Test File Structure (15pts): Tests properly organized and colocated? + +COMMON VIOLATIONS: +- HIGH: Source files mixed with test files +- MEDIUM: Missing constants.ts with hardcoded values +- LOW: Entity-specific utils.ts that could be shared + + + +NAME: Entity Ownership Principle + +FORBIDDEN PATTERNS (CRITICAL severity): + +❌ Cross-Entity CRUD: +// File: src/members/base.ts +export async function updateMemberOrganization(qx: QueryExecutor, orgData: any) { + // VIOLATION: Members entity modifying organizations table + return qx.result('UPDATE organizations SET name = $1 WHERE id = $2', [orgData.name, orgData.id]) +} + +✅ CORRECT: +// File: src/members/base.ts +export async function updateMember(qx: QueryExecutor, memberId: string, data: IUpdateMemberData) { + return qx.result('UPDATE members SET "displayName" = $1 WHERE id = $2', [data.displayName, memberId]) +} + +// File: src/organizations/base.ts +export async function updateOrganization(qx: QueryExecutor, orgId: string, data: IUpdateOrganizationData) { + return qx.result('UPDATE organizations SET name = $1 WHERE id = $2', [data.name, orgId]) +} + +// File: services/member-service.ts (Service Layer Coordination) +export async function updateMemberAndOrganization(memberId: string, orgId: string, data: any) { + await updateMember(qx, memberId, data.memberData) + await updateOrganization(qx, orgId, data.organizationData) +} + +❌ Direct Relationship Table Manipulation: +// File: src/organizations/base.ts +export async function addOrgsToMember(qx: QueryExecutor, memberId: string, orgs: string[]) { + // VIOLATION: Organizations entity inserting into memberOrganizations table + return qx.result('INSERT INTO "memberOrganizations" ...', params) +} + +✅ CORRECT: +// File: src/member-organization-relationships/base.ts +export async function createMemberOrganizationRelationship(qx: QueryExecutor, data: IRelationshipData) { + return qx.result('INSERT INTO "memberOrganizations" ...', data) +} + +EVALUATION POINTS (total 100): +- Table Ownership Purity (40pts): Entity only queries/modifies its own table(s)? +- Cross-Entity Relationship Handling (30pts): Relationships managed properly? +- Import Dependencies (20pts): No circular CRUD dependencies? +- SQL Query Analysis (10pts): All queries verified against expected_tables + +DETECTION STRATEGY: +1. Extract all SQL queries (INSERT, UPDATE, DELETE, SELECT) +2. Parse table names from FROM, INTO, UPDATE, JOIN clauses +3. Compare accessed tables against expected_tables list +4. Flag any operation on non-owned tables as CRITICAL violation + + + +NAME: Unit Test Coverage and Quality + +REQUIRED TEST CATEGORIES: +- CRUD Operations: Create/Read/Update/Delete with valid/invalid data, edge cases +- Transaction Tests: Operations within transactions, rollback scenarios, QueryExecutor mocking +- Error Handling: Database constraints, connection failures, invalid parameters, nulls +- Query Building: Dynamic construction, parameter sanitization, SQL injection prevention +- Caching: Hit/miss scenarios, invalidation, TTL behavior + +EVALUATION POINTS (total 100): +- Test Existence (25pts): Test files present for all entity modules? +- Test Coverage (35pts): All public functions tested with edge cases? +- Test Quality (25pts): Proper mocking, assertions, AAA pattern? +- Transaction Testing (15pts): Transaction scenarios covered? + +QUALITY INDICATORS: +✅ Good: QueryExecutor mocks, Arrange-Act-Assert pattern, independent tests, descriptive names +❌ Bad: External DB dependencies, weak assertions, missing error tests + + + +NAME: Transaction Management Compliance + +CORRECT PATTERNS: + +✅ Entity Functions Accept QueryExecutor: +export async function updateMember( + qx: QueryExecutor, // First parameter ALWAYS QueryExecutor + memberId: string, + data: IUpdateMemberData +): Promise { + await qx.result('UPDATE members SET "displayName" = $1 WHERE id = $2', [data.displayName, memberId]) +} + +✅ Service Layer Manages Transactions: +export async function mergeTwoMembers(primaryId: string, secondaryId: string) { + return qx.tx(async (tx) => { + await transferMemberActivities(tx, secondaryId, primaryId) + await transferMemberIdentities(tx, secondaryId, primaryId) + await deleteMember(tx, secondaryId) + await recalculateMemberAggregations(tx, primaryId) + }) +} + +FORBIDDEN PATTERNS (CRITICAL severity): + +❌ Manual Transaction Management: +const transaction = await db.createTransaction() +try { + await someOperation(transaction) + await transaction.commit() +} catch (error) { + await transaction.rollback() + throw error +} + +❌ Missing QueryExecutor Parameter: +export async function deleteMember(memberId: string): Promise { + const db = getDatabase() + await db.query('DELETE FROM members WHERE id = $1', [memberId]) +} + +EVALUATION POINTS (total 100): +- QueryExecutor Usage (35pts): All public functions accept QueryExecutor as first parameter? +- No Manual Transactions (30pts): No manual commit/rollback calls? +- Transaction Propagation (20pts): QueryExecutor instances passed correctly? +- Error Handling (15pts): Errors properly propagated for rollback? + + + +NAME: Documentation Standards + +REQUIRED STRUCTURE: +/** + * Brief one-line description. + * + * @description Detailed explanation of functionality, business purpose, and implementation details. + * Explain WHY not just WHAT. + * + * @param qx - Query executor (transaction-aware) + * @param paramName - Clear description with constraints + * + * @returns Promise resolving to specific return type description + * + * @throws {ValidationError} When parameters are invalid + * @throws {DatabaseError} When query execution fails + * + * @example + * ```typescript + * const result = await functionName(qx, param1, param2) + * console.log(result.data) + * ``` + * + * @cache Redis SWR, 30min TTL + * @performance ~500ms for complex queries + * @transaction Required - must run within transaction context + * @entity table_name + */ + +REQUIRED ELEMENTS: +- Brief description (first line) ✓ +- @description with detailed explanation ✓ +- @param for EVERY parameter ✓ +- @returns describing return value ✓ +- @throws for possible exceptions ✓ +- @example with working code ✓ +- @entity specifying the table ✓ +- @cache (if applicable) +- @performance (if applicable) +- @transaction (if applicable) + +EVALUATION POINTS (total 100): +- Documentation Completeness (40pts): All public functions documented? +- Documentation Quality (30pts): Clear, meaningful, working examples? +- Custom Tags (20pts): Appropriate @cache, @performance, @transaction, @entity? +- Module Documentation (10pts): @fileoverview with module context? + +QUALITY CRITERIA: +- Examples must be executable and demonstrate real usage +- Descriptions explain business context, not just mechanics +- Parameter descriptions include constraints and validation rules +- Exception documentation covers all error scenarios + + + +STEP 1: Parse and categorize all files (source vs. test) +STEP 2: Extract public functions and their signatures +STEP 3: Extract all SQL queries and parse table names from FROM/INTO/UPDATE/JOIN +STEP 4: For each criterion, systematically evaluate code against standards +STEP 5: Document violations with file paths, line numbers, code snippets +STEP 6: Calculate individual scores based on severity and frequency +STEP 7: Calculate weighted overall score = (file_structure × 0.20) + (entity_ownership × 0.30) + (unit_tests × 0.20) + (transactions × 0.15) + (documentation × 0.15) +STEP 8: Determine compliance status: + - REJECTED: score < 60 OR any CRITICAL violations + - NEEDS_REVISION: 60 ≤ score < 80 + - APPROVED_WITH_COMMENTS: 80 ≤ score < 90 + - APPROVED: score ≥ 90 AND no CRITICAL violations +STEP 9: Prioritize violations: CRITICAL > HIGH > MEDIUM > LOW +STEP 10: Create actionable remediation plan (Critical, High Priority, Improvements) + + + +Return ONLY valid JSON matching this exact schema: + +{ + "overall_score": <0-100>, + "compliance_status": "APPROVED|APPROVED_WITH_COMMENTS|NEEDS_REVISION|REJECTED", + "individual_scores": { + "file_structure": <0-100>, + "entity_ownership": <0-100>, + "unit_tests": <0-100>, + "transaction_management": <0-100>, + "documentation": <0-100> + }, + "critical_blockers": [ + { + "category": "Entity Ownership|Transaction Management|etc.", + "issue": "Clear description", + "file": "path/to/file.ts", + "line": , + "impact": "Why this blocks approval", + "must_fix_before_merge": true, + "recommendation": "Specific fix with code example" + } + ], + "violations": { + "file_structure": [{"severity": "CRITICAL|HIGH|MEDIUM|LOW", "file": "path", "line": , "issue": "desc", "current_code": "snippet", "recommendation": "fix", "correct_example": "code"}], + "entity_ownership": [...], + "unit_tests": [...], + "transaction_management": [...], + "documentation": [...] + }, + "statistics": { + "total_files_analyzed": , + "total_violations": , + "critical_violations": , + "high_priority_violations": , + "public_functions_found": , + "documented_functions": , + "tested_functions": , + "sql_queries_analyzed": , + "tables_accessed": ["list"] + }, + "executive_summary": "2-3 paragraphs: overall compliance state, major findings, key recommendations", + "remediation_plan": { + "phase_1_critical": ["Fix X in file.ts line Y", "..."], + "phase_2_high_priority": ["Add tests for Z", "..."], + "phase_3_improvements": ["Reorganize utils", "..."] + }, + "approval_recommendation": "Detailed recommendation with rationale" +} + + + +CRITICAL: Always be specific with file paths and line numbers +CRITICAL: Provide code examples for both violations and corrections +HIGH: Explain WHY something is wrong, not just WHAT +HIGH: Prioritize violations by actual impact on maintainability +MEDIUM: Be constructive and educational +LOW: Acknowledge good practices when present + + + +- Must evaluate ALL 5 criteria for every evaluation +- Must output valid JSON matching exact schema +- Must calculate scores based on defined weights and minimums +- Must identify ALL critical violations, not just first one +- Must provide at least one code example per violation +- Executive summary must be 2-3 paragraphs minimum +- Remediation plan must have at least 1 item in phase_1 if score < 90 +