S255 Handoff

Documentation for Sessions

S255 Handoff — Platform Generation Quality & Universe Data Lifecycle

Session: 255 | Date: 2026-03-23 | Status: Complete Branch: session-252-256_5 (shared with concurrent sessions)


What Was Done

1. Generation Pipeline — Template Variable Resolution (CRITICAL FIX)

Problem: Every generated file had undefined in its name: models/undefined.model.ts, components/undefined-list/undefined-list.component.ts.

Root Cause: preGenerateTemplateFiles() set entityName and entityNamePlural, but interpolate() read entity, Entity, entities, Entities — completely different variable names. JavaScript .replace() converts undefined to the string "undefined".

Secondary Bug: extractPrimaryEntity("manage players") returned "players" (plural). The pluralizer then produced "playerses".

Fix:

Files:

Verified: Test generation produces player.model.ts, player-list.component.ts correctly.


2. Preview Runtime — SDK Stub Contract Fixes

All fixes in libs/libs-structural/platform-preview/src/lib/config/sdk-preview-stubs.ts:

Fix Before After
deleteFn signature Called with string Called with string[] (matches real API)
update() body Sent raw data Wraps in { data } (matches backend)
query() response Only { data, total } Both { items, totalItems } AND { data, total }
read() implementation return of(null) Real HTTP fetch
Form validation No check before submit Blocks invalid forms, calls markAllAsTouched()
GgsToggleComponent Missing Added with ControlValueAccessor
GgsTableComponent Missing Added with data/loading inputs

3. Preview Runtime — JIT Compiler Loading

Problem: @angular/compiler is not available error in blob URL preview iframe.

Root Cause: rspack drops import '@angular/compiler' (side-effect-only external). esm.sh may not trigger Angular's publishFacade().

Fix (three layers):

  1. Named import: import { VERSION } from '@angular/compiler' (prevents rspack from dropping)
  2. Prerequisite script: also imports @angular/platform-browser-dynamic (registers JIT internally)
  3. Explicit: if (compiler.publishFacade) compiler.publishFacade(globalThis)

Files:


4. Universe Deletion Cascade

Problem: Deleting a universe left orphaned data in 6+ collections and git repos.

Fix: Added cascade cleanup to SpacesService.deleteUniverse():

Data Status
generation_manifests Now cleaned
deployments Now cleaned
draft_sessions Now cleaned
Galaxies Now cleaned (method existed, was never called)
Git repository (GitLab/Hetzner/Local) Now cleaned
Backend-ai-api data Still orphaned (intentional — no hard cross-service dependency)

Files:


5. Other Preview Improvements

Change File
VFS-aware import path fixer bundler-filesystem.service.ts
API_BASE_URL injection into stubs preview.service.ts
Modulepreload hints for CDN preview-server.service.ts
Debounce 150ms → 800ms preview.service.ts

What Was NOT Done (Future Work)

High Priority

  1. Cross-service orphan cleanup for backend-ai-api data

    • Configuration sessions, generated modules, deployment snapshots remain when universe is deleted
    • Recommended: Event-driven cascade (emit UniverseDeleted event from backend-api, backend-ai-api subscribes and cleans its own data)
    • Alternative: Scheduled orphan cleanup job that scans for universeIds that no longer exist
  2. Full E2E generation test

    • The Vitto backend (port 3003) was down due to MongoDB timeout to Hetzner (34.56.108.77:27017)
    • Once Hetzner MongoDB is reachable, test full generation → preview flow
  3. Preview stub filter implementation

    • setFilter, removeFilter, clearFilters are currently no-ops
    • Filters appear functional in UI but don't actually filter the list
    • Need to implement client-side filtering in the stub's doLoad() function
  4. GgsCrudFormShellComponent missing saveError input

    • Shell component has no @Input() saveError — save failures don't display in the shell
    • Either add the input to the stub or update the prompt to have generated templates handle errors outside the shell

Medium Priority

  1. Automated prompt-stub audit

    • Currently manual. Should be a script that parses implement.prompt.md for SDK imports/components and verifies each has a matching stub export
    • Could run as a pre-commit hook or CI check
  2. SCSS flattener v2

    • Current flattener handles nesting + & only. Variables, mixins, @use are not supported
    • If generated code ever uses these, need dart-sass WASM compiler

Key Architectural Decisions

  1. No hard cross-service dependencies: Universe deletion in backend-api does NOT call backend-ai-api. Each backend must be able to operate independently.

  2. Stubs mirror real contracts: Preview stubs must exactly match the real useCrudList/useCrudForm/useCrudDetail signatures from libs/core/module-base. Any drift causes runtime errors.

  3. Three-layer JIT defense: CDN module loading is unreliable — multiple fallback paths ensure Angular JIT compiler is available regardless of how esm.sh packages modules.

  4. Template variable defensive fallbacks: Both the producer (preGenerateTemplateFiles) and consumer (interpolate) now handle missing variables gracefully.


Files Modified in S255

Backend API (APIs/backend-api/)

Backend AI API (APIs/backend-ai-api/)

Platform Preview (libs/libs-structural/platform-preview/)

Vitto Studio (libs/libs-structural/vitto-studio/)


MCP Decisions Logged

ID Type Summary
dev_1774273985474_i19atie bugfix Template variable resolution (undefined filenames)
dev_1774273994975_bl5j5mp bugfix deleteFn contract mismatch (string vs string[])
dev_1774274007253_fwb2mv4 bugfix JIT compiler not available in preview
dev_1774274035712_v7gypzh architecture Universe deletion cascade (6 orphaned data types)
dev_1774274043708_kdsd7xj bugfix update() body wrapping + query() response mapping
dev_1774274051363_jlljnra implementation Missing GgsToggle/GgsTable stubs + form validation

Conventions Added

ID Category Rule
conv_..._5axoh generation-pipeline ALL canonical template variable forms must be populated
conv_..._4vk8w preview-stubs Every SDK component in prompts must have matching stub
conv_..._8ycl8 data-lifecycle Cascade deletion must be non-blocking, no cross-service hard deps