2026 03 16 Platform Generation V2 Phase Ia

Documentation for Plans

Platform Generation v2 — Phase I-A: Pipeline Bug Fixes

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make the generation pipeline produce platforms that compile and run CRUD end-to-end.

Architecture: Fix 3 categories of systemic bugs: (1) consolidate pluralization, (2) replace Date.now() with randomUUID() for ID generation, (3) create collection name utility to prevent double-prefix. All changes are in backend services — no frontend changes in this phase.

Tech Stack: NestJS, TypeScript, MongoDB, Node.js crypto.randomUUID()

Spec: docs/superpowers/specs/2026-03-16-platform-generation-v2-design.md

Branch: session-226 | Commits: [S226.2] type: description


Chunk 1: Consolidate Pluralization

Task 1: Create shared pluralize utility

Files:

/**
 * Pluralize an English noun. Covers common suffixes.
 * NOT a full NLP solution — covers the 95% case for entity names.
 */
export function pluralize(s: string): string {
  if (!s || s.length === 0) return s;
  const lower = s.toLowerCase();
  if (lower.endsWith('ch') || lower.endsWith('sh') || lower.endsWith('x') || lower.endsWith('z') || lower.endsWith('ss')) {
    return s + 'es';
  }
  if (lower.endsWith('s')) return s;
  if (lower.endsWith('y') && !/[aeiou]y$/i.test(s)) {
    return s.slice(0, -1) + 'ies';
  }
  return s + 's';
}
git add APIs/backend-vitto-api/src/app/module-generation/utils/pluralize.util.ts
git commit -m "[S226.2] feat: add shared pluralize utility for entity name generation"

Task 2: Replace both inline pluralize implementations

Files:

Add after existing imports:

import { pluralize } from '../utils/pluralize.util';

Delete the const pluralize = (s: string) => { ... } block at lines 52-56. The imported function replaces it.

Delete the const pluralize = (s: string) => { ... } block at lines 94-98. The imported function replaces it.

Run: grep -rn "const pluralize" APIs/backend-vitto-api/src/ Expected: Zero matches.

git add APIs/backend-vitto-api/src/app/module-generation/generators/template-generator.service.ts
git commit -m "[S226.2] refactor: replace inline pluralize with shared utility

Two inconsistent implementations existed (lines 52-56 handled ch/sh/x/z,
lines 94-98 did not). Consolidated into one shared function."

Chunk 2: Fix ID Generation (Date.now → randomUUID)

Task 3: Fix structure-builder.service.ts (7 locations)

Files:

Add after existing imports:

import { randomUUID } from 'crypto';

Replace each Date.now() used for ID suffix with randomUUID().substring(0, 8):

Line 37: galaxy-${toSlug(...)}-${Date.now()} → galaxy-${toSlug(...)}-${randomUUID().substring(0, 8)} Line 42: world-${toSlug(...)}-${Date.now()} → world-${toSlug(...)}-${randomUUID().substring(0, 8)} Line 47: pm-${worldSlug}-list-${Date.now()} → pm-${worldSlug}-list-${randomUUID().substring(0, 8)} Line 61: pm-${worldSlug}-create-${Date.now()} → pm-${worldSlug}-create-${randomUUID().substring(0, 8)} Line 75: pm-${worldSlug}-detail-${Date.now()} → pm-${worldSlug}-detail-${randomUUID().substring(0, 8)} Line 89: pm-${worldSlug}-edit-${Date.now()} → pm-${worldSlug}-edit-${randomUUID().substring(0, 8)}

Line 237 (moduleTreeVersion: Date.now()) is a version timestamp, NOT an ID. Leave it.

git add APIs/backend-vitto-api/src/app/module-generation/handlers/structure-builder.service.ts
git commit -m "[S226.2] fix: replace Date.now() with randomUUID() in structure-builder IDs

Date.now() in a loop with PARALLEL_MODULE_GEN_BATCH > 1 produces duplicate
IDs when multiple modules generate within the same millisecond."

Task 4: Fix platform-generation.service.ts

Files:

import { randomUUID } from 'crypto';

Before:

const sessionId = `platform-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;

After:

const sessionId = `platform-${randomUUID()}`;

If line 288 has id: \${sessionId}-${Date.now()}`— replaceDate.now()withrandomUUID().substring(0, 8)`.

git add APIs/backend-vitto-api/src/app/module-generation/platform-generation.service.ts
git commit -m "[S226.2] fix: replace Date.now() with randomUUID() in platform session IDs"

Task 5: Fix space.service.ts universe ID generation

Files:

This is a frontend Angular service. crypto.randomUUID() is available in browsers via globalThis.crypto.randomUUID(). No import needed.

Before:

const uniqueId = `universe_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;

After:

const uniqueId = `${Date.now()}_${globalThis.crypto.randomUUID().substring(0, 8)}`;

Note: We drop the universe_ prefix from the ID itself — the collection name utility (Task 7) adds it when building collection names. This prevents the universe_universe_ double-prefix bug.

Run: grep -rn "universe_.*Date.now" libs/ — should match only this location.

git add libs/libs-foundational/core-angular/src/lib/services/space.service.ts
git commit -m "[S226.2] fix: remove universe_ prefix from generated IDs, use randomUUID

The universe_ prefix is now added by buildCollectionName() utility.
Generating IDs without it prevents double-prefix (universe_universe_)."

Chunk 3: Collection Name Utility + Delete Fix

Task 6: Create buildCollectionName utility

Files:

/**
 * Build a MongoDB collection name for a universe entity.
 * Normalizes the universeId to prevent double-prefix (universe_universe_).
 *
 * @param universeId - The universe identifier (may or may not include 'universe_' prefix)
 * @param collection - The entity collection name (e.g., 'players', 'matches')
 * @returns Fully qualified collection name (e.g., 'universe_123abc_players')
 */
export function buildCollectionName(universeId: string, collection: string): string {
  // Strip 'universe_' prefix if already present to prevent universe_universe_ double-prefix
  const normalizedId = universeId.startsWith('universe_')
    ? universeId
    : `universe_${universeId}`;
  return `${normalizedId}_${collection}`;
}

/**
 * Build the prefix for listing collections belonging to a universe.
 */
export function buildCollectionPrefix(universeId: string): string {
  return universeId.startsWith('universe_')
    ? `${universeId}_`
    : `universe_${universeId}_`;
}
git add APIs/backend-api/src/app/data/collection-name.util.ts
git commit -m "[S226.2] feat: add buildCollectionName utility to prevent double-prefix"

Task 7: Replace inline concatenations in data.controller.ts (11 locations)

Files:

import { buildCollectionName } from './collection-name.util';

Find all occurrences of:

const fullCollectionName = `universe_${universeId}_${collection}`;

Replace each with:

const fullCollectionName = buildCollectionName(universeId, collection);

Lines to change: 156, 223, 270, 316, 354, 427, 475, 529, 537, 575, 604.

Run: grep -n "universe_\${universeId}" APIs/backend-api/src/app/data/data.controller.ts Expected: Zero matches.

git add APIs/backend-api/src/app/data/data.controller.ts
git commit -m "[S226.2] refactor: use buildCollectionName utility in data controller

Replaces 11 inline universe_\${universeId}_\${collection} concatenations.
Prevents double-prefix when universeId already contains 'universe_'."

Task 8: Replace inline concatenations in space-database-collections.service.ts (5 locations)

Files:

import { buildCollectionName, buildCollectionPrefix } from '../../../../data/collection-name.util';

Lines 125, 199, 237 (prefix pattern): Before: const prefix = \universe_${universeId}_`;After:const prefix = buildCollectionPrefix(universeId);`

Lines 175, 220 (full name pattern): Before: const fullCollectionName = \universe_${universeId}_${collectionName}`;After:const fullCollectionName = buildCollectionName(universeId, collectionName);`

git add APIs/backend-api/src/app/spaces/space-database/services/space-database-collections.service.ts
git commit -m "[S226.2] refactor: use buildCollectionName utility in space-database-collections"

Task 9: Replace inline concatenations in deployment.service.ts (2 locations)

Files:

import { buildCollectionName } from '../data/collection-name.util';

Line 566: db.collection(\universe_${universeId}_pages`)→db.collection(buildCollectionName(universeId, 'pages'))Line 575:db.collection(`universe_${universeId}_flows`)→db.collection(buildCollectionName(universeId, 'flows'))`

git add APIs/backend-api/src/app/deployment/deployment.service.ts
git commit -m "[S226.2] refactor: use buildCollectionName utility in deployment service"

Task 10: Fix delete BSON error

Files:

The current code at line 321-323:

const result = await col.deleteOne({
  _id: new ObjectId(recordId)
} as any);

Replace with a safer approach that handles both ObjectId and string IDs:

let filter: any;
try {
  filter = { _id: new ObjectId(recordId) };
} catch {
  // recordId is not a valid ObjectId — try string match
  filter = { _id: recordId };
}
const result = await col.deleteOne(filter);

This handles the BSON version error by falling back to string ID matching when ObjectId construction fails.

git add APIs/backend-api/src/app/data/data.controller.ts
git commit -m "[S226.2] fix: handle both ObjectId and string IDs in delete handler

ObjectId constructor throws BSON version error when recordId format
doesn't match expected ObjectId. Fallback to string filter."

Chunk 4: Make spaceId/universeId Required in Generation DTO

Task 11: Add validation to generation DTO

Files:

Check lines 38-50 for the DTO class. Find where spaceId and universeId are declared as optional.

@IsNotEmpty({ message: 'spaceId is required for module generation' })
@IsString()
spaceId: string;

@IsNotEmpty({ message: 'universeId is required for module generation' })
@IsString()
universeId: string;

Remove the ? optional marker from both fields.

Ensure IsNotEmpty and IsString are imported from class-validator.

git add APIs/backend-vitto-api/src/app/module-generation/module-generation.controller.ts
git commit -m "[S226.2] fix: make spaceId/universeId required in generation DTO

Prevents silent failures when generation requests omit universe context.
S225.8 fixed the frontend, this hardens the backend."

Validation Gate

After all tasks are complete, verify the fixes by checking: