-
Notifications
You must be signed in to change notification settings - Fork 0
Module Generation Orchestration for Themis Workflow #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add complete module generation orchestration for Themis workflow step 5, enabling course-aware module generation with real-time progress tracking. Components & UI: - ModuleGenerationList.svelte (812 lines): Arc-grouped module display with collapsible sections, status tracking, SSE streaming, preview modal, and comprehensive error handling - Progress summary with statistics (completed/total, generating, errors) - Individual and bulk generation controls - Module preview modal with XML display API & Backend: - /api/themis/module endpoint: Course-aware module generation API - Converts ModuleGenerationRequest to Metis-compatible format - Creates synthetic XML from module slot data and course context - Supports SSE streaming for real-time progress updates - Zod validation for type-safe requests/responses Prompt Enhancement: - buildCourseAwareModulePrompt(): Injects course context into base prompt - Includes course narrative, arc theme, and progression - Lists preceding modules to avoid content repetition - Integration guidelines for coherent course structure Schema & Types: - CourseContextSchema: Course narrative and progression data - ModuleSlotSchema: Module data structure - ModuleGenerationRequestSchema/ResponseSchema: API validation - Full TypeScript type inference via Zod Workflow Integration: - Added step 5 handlers to Themis generate page - Navigation: Structure Review → Generation → Overview - Auto-save progress via persisted stores Technical Highlights: - Reuses existing Metis generation pipeline with course awareness - SSE streaming via ReadableStream API - Automatic retry logic (max 3 attempts) - Module schema validation - localStorage persistence for resume capability - Themis colour palette for consistent branding Files Modified: 6 files, 1,132 insertions - Component: 812 lines - API endpoint: 168 lines - Prompt factory: +75 lines - Schema validation: +60 lines - Workflow integration: +15 lines - Status docs: updated 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add export functionality to the module generation page, allowing users to export course structure with generated modules at any time during the generation process. Changes: - Add ExportButton component to page header - Create exportable content reactive statement for course data - Update header layout with flex display for button placement - Add responsive styling for mobile devices UI Layout: - Header now displays title/description on left, export button on right - Export button uses secondary variant with medium size - Responsive design stacks elements vertically on mobile 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
SummaryThis PR implements module generation orchestration for the Themis workflow with comprehensive SSE streaming, state management, and course context integration. The architecture reuses existing Metis infrastructure while adding course-awareness through synthetic XML conversion. The code follows established patterns well, with strong type safety via Zod schemas. However, there are several areas requiring attention: race conditions in sequential generation, error handling edge cases, potential memory concerns with large courses, and missing test coverage. Critical Issues Found:
See full review details below. |
Code Quality and Best PracticesExcellent Patterns✅ Architectural Reuse - Clean Themis-to-Metis adapter pattern via convertToMetisFormat(), maintaining single responsibility while avoiding code duplication. ✅ Type Safety - Comprehensive Zod schemas with full TypeScript inference and proper validation boundaries at API entry points. ✅ Reactive State Management - Good use of Svelte reactive declarations with proper derived state from stores. Critical Issue: Missing Prompt Builder IntegrationLocation: src/routes/api/themis/module/+server.ts:62-65 The API endpoint imports Recommendation: Update Other Improvements Needed
|
Potential IssuesCritical Issues1. Race Condition in Sequential Generation (ModuleGenerationList.svelte:218-235) The
Fix: Refactor 2. SSE Stream Memory Leak (ModuleGenerationList.svelte:99-123) If component unmounts while stream is active, the reader is never cancelled. Stream continues consuming memory in background. Fix: Add 3. Buffer Handling Edge Case (ModuleGenerationList.svelte:113-114) If server never sends Fix: Add 4. Store Mutation Without Immutability (ModuleGenerationList.svelte:61-68) Direct mutation: 5. XML Injection Vulnerability (src/routes/api/themis/module/+server.ts:96-138) No escaping for XML special characters. If module title contains Fix: Create Medium Priority Issues
|
Performance ConsiderationsCourse Data Serialisation Cost (ModuleGenerationList.svelte:81-92) Entire Solution: Cache course context on server side with session/course ID, or memoize the context string. Store Update Frequency Three
For 20-module course = 40+ localStorage writes. Solution: Batch updates or debounce localStorage writes. getPrecedingModuleTitles Complexity (ModuleGenerationList.svelte:197-216) Time complexity O(n) called once per module generation. Could be memoized since it only depends on course structure. Arc Expansion State (ModuleGenerationList.svelte:30-34) Expanding first arc by default immediately renders all module cards. Consider virtual scrolling or default to collapsed state. Modal Re-rendering (ModuleGenerationList.svelte:419-440)
Positive Aspects✅ Efficient derived stores with |
Security Concerns1. No Request Rate Limiting (src/routes/api/themis/module/+server.ts) User can spam "Generate All" button, potentially:
Fix: Add rate limiting (recommend 5 requests per minute per IP using Upstash, Redis, or in-memory). 2. Unbounded Input Sizes (src/lib/schemas/apiValidator.ts:176-227) Schemas validate types but not sizes. Fix: Add max length constraints:
3. XML Injection Vulnerability User-controlled data flows into XML templates without escaping. Example attack: While not XSS, could break validation, cause parsing errors, or pollute content. 4. Error Messages Leak Implementation Details (src/routes/api/themis/module/+server.ts:74-84) Detailed errors reveal internal architecture. Sanitise based on NODE_ENV. 5. No CORS Configuration Ensure appropriate origin restrictions. Positive Security Practices✅ Zod validation at API boundary |
Test CoverageCurrent State: NO TESTS ❌This is the most critical gap in the PR. For 1,175 lines of new code touching core generation logic, API endpoints, and complex state management, the lack of tests is concerning. Immediate Priority (Block Merge)Before this PR can be merged, add at minimum:
Recommended Full Test SuiteUnit Tests:
Integration Tests:
Component Tests:
Test Infrastructure Needed
Coverage Goals
|
Recommendations Priority🔴 CRITICAL (Block Merge)
🟡 HIGH PRIORITY (Address Soon)
🟢 MEDIUM PRIORITY (Nice to Have)
Final ThoughtsThis is a solid feature implementation that follows project patterns well. The architecture is clean, type safety is excellent, and the SSE streaming approach is the right choice. However, the 5 critical issues (especially the unused prompt builder and missing tests) must be addressed before merge. The race condition and memory leak could cause production issues. Once these are fixed, this will be production-ready! 🚀 Looking forward to seeing the updates. Happy to review again once changes are made. |
CRITICAL FIX: The course-aware prompt was imported but never used. All module generation was using the standard Metis prompt without course context. Changes: - Add PromptBuilder type for custom prompt functions - Update RetryConfig and SSEStreamConfig to accept promptBuilder param - Modify retryHandler to use custom or default prompt builder - Update sseHandler to pass through promptBuilder - Wire buildCourseAwareModulePrompt into /api/themis/module endpoint Impact: - Modules now generated with full course context (narratives, arcs) - Preceding modules listed to avoid repetition - Thematic consistency maintained across course - Integration guidelines included in prompts This fixes the most critical issue from code review.
Replace setInterval polling in generateAll() with proper Promise-based sequential generation. The generateModule function now returns a Promise that resolves when SSE stream completes or errors. **Before**: - Polled generatingModuleId every 1s with setInterval - No timeout protection - Race condition between async operations **After**: - generateModule returns Promise<void> - Promise resolves on 'complete' or 'error' SSE event - Sequential await in generateAll() ensures proper ordering - Errors handled gracefully, continue to next module 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Prevent memory leaks by properly cancelling active ReadableStream readers when the ModuleGenerationList component unmounts. **Implementation**: - Track active readers in Set<ReadableStreamDefaultReader> - Add reader to set when SSE stream starts - Remove from set in finally block when stream completes - Cancel all active readers in onDestroy lifecycle hook **Before**: - Readers continued running after component unmount - Memory leak with abandoned SSE connections - No cleanup on navigation away **After**: - All active streams cancelled on unmount - Proper resource cleanup - Graceful error handling during cancellation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
SummaryThis PR successfully implements module generation orchestration for the Themis workflow with excellent architecture. The implementation follows established patterns, properly reuses existing infrastructure, and introduces a clean separation between Themis course context and Metis generation logic. The code is well-structured with strong typing and comprehensive SSE streaming support. However, there are several areas that need attention: the generateAll function has a problematic polling mechanism, error handling could be more robust, and there's no test coverage for this critical feature. |
🎯 Code Quality & Best PracticesExcellent Patterns1. Architecture & Reusability ✅
2. Type Safety ✅
3. Prompt Engineering ✅
4. User Experience ✅
Areas for Improvement1. Component Size
2. Magic Numbers
3. Code Duplication
4. British English Consistency ✅
|
🐛 Potential IssuesCritical Issues1. Race Condition in generateAll() 🔴 Problem at src/lib/components/themis/ModuleGenerationList.svelte:218-235 - Polling generatingModuleId every second is inefficient and could miss rapid state changes. Solution: Return a Promise from generateModule() that resolves when complete instead of polling. 2. Unbounded Interval in Error Cases 🔴
3. Missing SSE Error Handling 🟡 At src/lib/components/themis/ModuleGenerationList.svelte:105-123, JSON.parse could throw if SSE data is malformed. Solution: Wrap in try-catch for safe parsing. 4. Synthetic XML Escaping 🟡 At src/routes/api/themis/module/+server.ts:107-148, user input (title, description) is directly interpolated into XML without escaping. Risk: Malicious input could break XML structure or inject unintended content. Solution: Add XML escaping utility function. Minor Issues5. Type Safety with any 🟡
6. Missing Configuration 🟡 7. State Management Redundancy 🟡
|
⚡ Performance ConsiderationsCurrent Performance1. SSE Streaming ✅
2. Sequential Generation ✅
Potential Optimizations1. Large Course Scaling 🟡
2. Store Update Efficiency 🟡 3. XML Preview Rendering 🟡
4. Memory Management 🟡
|
🔒 Security ConcernsHigh Priority1. XML Injection 🔴
2. API Key Exposure ✅
Medium Priority3. Client-Side State Tampering 🟡
4. SSE Stream Injection 🟡
Low Priority5. CSRF Protection ✅
6. Rate Limiting
|
✅ Test CoverageCurrent StateNo test files found ❌ This is a significant gap for a feature this critical. The PR adds 1,197 lines of code with complex state management, async operations, and API interactions—all without automated tests. Recommended Test Coverage1. Unit Tests Needed
2. Integration Tests Needed
3. E2E Tests Needed
Testing Priority
Test InfrastructureThe project appears to have no test infrastructure set up. Recommended setup:
|
Overall AssessmentStrengths:
Critical Issues:
Recommendation: Request changes for critical issues before merging. The polling mechanism and XML escaping must be addressed. Test coverage should be added before or immediately after merge. |
Create reusable XML escaping utility and apply to all user-controlled
data in synthetic XML generation for Themis module endpoint.
**Implementation**:
- New utility: `src/lib/utils/xml/xmlEscape.ts`
- `escapeXml()` - Escapes &, <, >, ", '
- `escapeXmlArray()` - Batch escape for arrays
- Applied to all user data in `convertToMetisFormat()`:
- Module titles, descriptions, objectives, topics
- Course titles, narratives, progressions
- Arc narratives and progressions
- Preceding module titles
**Security Impact**:
Before: User input like `<script>alert('xss')</script>` could break XML
After: Properly escaped as `<script>alert('xss')</script>`
**Example**:
Input: `AI & Machine Learning: "Advanced" Topics`
Output: `AI & Machine Learning: "Advanced" Topics`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
SummaryThis PR implements the module generation orchestration (step 5) of the Themis workflow, enabling course-aware module generation with real-time progress tracking. The implementation is architecturally sound, reuses existing Metis infrastructure effectively, and includes excellent XML injection protection. However, there are several areas requiring attention: concurrency management in the UI, error handling completeness, memory management concerns, and the absence of automated tests. 🎯 Code Quality & Best PracticesStrengthsExcellent Architecture & Reuse
Type Safety
Code Style
Areas for Improvement1. Concurrency Management in UI Component The generatingModuleId state variable at src/lib/components/themis/ModuleGenerationList.svelte:16 only tracks a single module generation, but the generateAll() function at line 261 attempts sequential generation. Issue: If a user clicks "Generate All" and then clicks an individual "Generate" button, the UI may display inconsistent state. Recommendation: Consider using a Set to track multiple generating modules OR disable all buttons when batch generation is active with a separate flag isBatchGenerating. 2. Promise Resolution Pattern At src/lib/components/themis/ModuleGenerationList.svelte:87-101, the handleComplete function is only called inside the SSE event loop, but if the stream closes without sending a complete or error event, the promise may never resolve/reject, causing generateAll() to hang indefinitely. Recommendation: Add a timeout or ensure the promise resolves in the finally block if not already resolved. 🐛 Potential IssuesCritical Issues1. Reader Cleanup Race Condition At src/lib/components/themis/ModuleGenerationList.svelte:137-162, reader.cancel() calls are not awaited, so if unmount happens while a reader is mid-operation, the cleanup might not complete before the component is destroyed. Recommendation: Track promise rejectors alongside readers to ensure promises are rejected on cleanup. Consider using AbortController pattern for cleaner cancellation propagation. 2. JSON.parse Error Handling At src/lib/components/themis/ModuleGenerationList.svelte:154, SSE data is parsed without error handling. Malformed SSE data will throw an uncaught exception, breaking the entire generation flow. Recommendation: Wrap in try-catch and log/handle parsing errors gracefully. 3. Module State Mutation The currentCourse.update() calls mutate module objects directly. While Svelte will detect the change, this pattern is fragile and may cause issues if the store implementation changes. Recommendation: Consider creating new objects instead of mutating existing ones, following immutable update patterns. Minor Issues4. Type Safety
Recommendation: Define explicit types for better type safety and IntelliSense support. ⚡ Performance Considerations1. Memory Usage with Long Responses At src/lib/components/themis/ModuleGenerationList.svelte:140-150, the SSE stream accumulates chunks in a buffer with string concatenation. If module generation produces large XML outputs (multiple MB), this could cause performance degradation. Recommendation: Monitor buffer size and add a maximum size check. 2. Sequential Generation The generateAll() function processes modules sequentially. For a course with 10 modules taking 2 minutes each, this would require 20 minutes total. Recommendation: Document this design decision in code comments. This may be intentional to avoid rate limits, reduce costs, or maintain coherence. 🔒 Security ConcernsStrengthsExcellent XML Injection Protection ✅ The new xmlEscape.ts utility properly escapes all XML special characters and is correctly used throughout convertToMetisFormat(). Areas for Improvement1. Server-Side Input Validation While Zod validation is present, consider adding length limits for string fields to prevent excessive memory usage: courseNarrative: z.string().max(10000, 'Course narrative too long') 2. Error Message Information Disclosure At src/routes/api/themis/module/+server.ts:86-94, detailed error messages are returned to the client. Depending on the error, this could expose internal implementation details. Recommendation: Use generic error messages for production, but keep detailed logging server-side. 3. Rate Limiting Consideration The generateAll() function can trigger multiple expensive API calls. Consider implementing client-side throttling to prevent accidental rapid-fire requests. ✅ Test CoverageCritical Gap: No Automated TestsThe codebase currently has no test files, as confirmed by glob searches. This PR adds 1,300+ lines of complex functionality without any automated test coverage. Recommended Test CoverageUnit Tests Needed
Integration Tests Needed
RecommendationGiven the complexity of this feature and its critical role in the Themis workflow, strongly recommend adding at least:
Consider setting up a testing framework (Vitest for unit tests, Playwright for E2E) as a follow-up task. SummaryThis is a well-architected feature that thoughtfully extends the existing Metis infrastructure for course-aware generation. The code quality is generally high with good separation of concerns and strong type safety. The XML escaping implementation is particularly commendable. Before merging, please address:
Follow-up recommendations:
Great work overall! The course narrative integration is elegant and the real-time progress tracking will provide excellent UX. |
Code Review Fixes - Critical Issues ResolvedAddressed all 4 CRITICAL priority issues from code review: ✅ Fixed: Course-Aware Prompt Not Being Used (76e451c)Problem: Solution:
Impact: Course narratives, arc themes, and preceding module context now properly injected into AI generation prompts. ✅ Fixed: Race Condition in generateAll() (bb0f6ab)Problem: Used Solution:
Impact: No more race conditions, proper sequential execution, clean Promise-based flow. ✅ Fixed: Missing SSE Stream Cleanup (e382863)Problem: Solution:
Impact: Proper resource cleanup on component unmount, no memory leaks from abandoned SSE connections. ✅ Fixed: XML Injection Vulnerability (d9d608c)Problem: User-controlled data directly interpolated into XML without escaping (e.g., Solution:
Impact: Prevents XML/XSS injection attacks. Example:
Remaining Tasks (Lower Priority)HIGH Priority:
MEDIUM Priority:
These can be addressed in a follow-up PR or before merge if preferred. |
SummaryThis PR successfully implements course-aware module generation for the Themis workflow, building on the existing Metis infrastructure. The implementation is architecturally sound, properly reuses existing patterns (factories, SSE streaming, retry logic), and includes good security practices (XML escaping). However, there are some areas for improvement around error handling, SSE stream cleanup, and test coverage. The code is production-ready with the suggested refinements. 🎯 Code Quality & Best PracticesStrengthsArchitecture & Reuse
Code Organization
Documentation
Areas for Improvement1. Component Size
This would improve maintainability and testability. 2. Duplicate Store Updates function updateModuleInCourse(
moduleId: string,
updater: (module: ModuleSlot) => void
) {
currentCourse.update(course => {
if (!course) return course;
for (const arc of course.arcs) {
const module = arc.modules.find(m => m.id === moduleId);
if (module) {
updater(module);
break;
}
}
return course;
});
}3. British English Consistency
4. Magic Numbers const RESEARCH_TIMEOUT_MS = 300000; // 5 minutes
const STANDARD_TIMEOUT_MS = 120000; // 2 minutes🐛 Potential IssuesCritical1. Race Condition in SSE Stream Cleanup Recommendation: Use a cancellation flag: let cancelled = false;
onDestroy(() => {
cancelled = true;
activeReaders.forEach(reader => reader.cancel());
});
// In stream processing:
if (cancelled) break;2. SSE Parsing Vulnerability Recommendation: Wrap in try-catch: try {
const data = JSON.parse(line.slice(6));
handleSSEEvent(module.id, data);
handleComplete(data);
} catch (err) {
console.error('Invalid SSE data:', line, err);
// Handle gracefully - maybe continue or trigger error state
}3. Missing Error Handling in Recommendation: Add circuit breaker logic: let consecutiveErrors = 0;
const MAX_CONSECUTIVE_ERRORS = 3;
for (const module of arc.modules) {
try {
await generateModule(module, arc);
consecutiveErrors = 0; // Reset on success
} catch (error) {
consecutiveErrors++;
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
alert('Multiple generation failures. Stopping batch generation.');
return;
}
}
}Moderate4. Memory Leak Potential Recommendation: Clear handlers on cleanup or use AbortController pattern. 5. Alert() Usage 6. Type Safety Gap type SSEEvent =
| { type: 'complete'; xmlContent: string }
| { type: 'error'; message: string }
| { type: 'progress'; stage: string }
| { type: 'validation_started' }
| { type: 'validation_success' };Minor7. Console Logs in Production 8. Empty Confirm Dialog ⚡ Performance ConsiderationsGood Practices
Optimisation Opportunities1. Sequential Module Generation Recommendation: Consider controlled concurrency: async function generateAll(concurrency = 2) {
const queue = courseData.arcs.flatMap(arc =>
arc.modules.filter(m => m.status !== 'complete')
.map(m => ({ module: m, arc }))
);
while (queue.length > 0) {
const batch = queue.splice(0, concurrency);
await Promise.allSettled(
batch.map(({ module, arc }) => generateModule(module, arc))
);
}
}Trade-off: More concurrent requests increase API costs and may hit rate limits. Document this clearly for users. 2. Re-render Optimisation Recommendation: Use 3. Large XML Preview Recommendation: Consider syntax highlighting with lazy loading, or limit preview to first 5000 characters with a "show more" button. 4. LocalStorage Performance Recommendation: Debounce persistence or only persist on specific events (generation complete, navigation away). 🔒 Security ConcernsStrengths
Areas for Attention1. XSS in Error Messages Recommendation: Sanitise error messages or use <div class="error-message">
<strong>Error:</strong> {@text module.errorMessage}
</div>Note: Currently safe because error messages come from server code, but defensive programming is recommended. 2. XML Escaping Edge Case Recommendation: Add control character filtering: .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '');3. Rate Limiting Recommendation: Already partially addressed by sequential generation, but consider adding a cooldown or request queuing on the backend. 4. CORS and API Key Exposure ✅ Test CoverageCurrent State❌ No tests found - This is a significant gap for a feature with complex async logic and state management. Recommended Test CoverageUnit Tests Needed
Integration Tests Needed
Component Tests Needed
E2E Tests Needed
Testing Recommendations
Priority🔴 High Priority: API endpoint tests, XML escaping tests, store logic tests Recommendations SummaryMust Fix Before Merge
Should Fix Before Merge
Nice to Have (Follow-up PR)
Overall Assessment: This is solid work that follows the project's established patterns. The course-aware generation approach is elegant, and the reuse of Metis infrastructure is exemplary. With the critical fixes applied, this is ready to merge. 🚀 |
SummaryExcellent implementation of the Themis module generation orchestration feature. The code demonstrates strong architectural consistency by reusing established patterns (factories, SSE streaming, validation) and properly handling course context for coherent multi-module generation. The XML escaping utility addresses a critical security concern. Minor improvements suggested around error handling, race conditions in concurrent generation, and potential performance optimisations for large courses. Full review with collapsible sections posted separately due to length constraints... |
🎯 Code Quality & Best PracticesStrengths1. Architectural Consistency ✅
2. State Management ✅
3. Separation of Concerns ✅
Suggestions1. Magic Numbers - src/routes/api/themis/module/+server.ts:174 2. Type Safety - ModuleGenerationList.svelte:95,174 3. Hard-coded Experience Levels - src/routes/api/themis/module/+server.ts:176-178 4. Console Logging - ModuleGenerationList.svelte:175 |
🐛 Potential IssuesCritical1. Race Condition in generateAll() - ModuleGenerationList.svelte:261-275 The component only tracks a single generatingModuleId. Line 344 disables Generate All when ANY module is generating, but if a user manually triggers individual module generation while Generate All is paused, UI state could become confused. Recommendation: Either make generatingModuleId a Set to track multiple concurrent generations, or add explicit UI state to distinguish bulk vs single generation. 2. Missing Error Boundary in Modal - ModuleGenerationList.svelte:459-480 The preview modal doesn't verify xmlContent is non-empty. A module could have moduleData: {} with no xmlContent. Recommendation: Add optional chaining and fallback display Medium Priority3. Promise Rejection in Async IIFE - ModuleGenerationList.svelte:103-170 The async IIFE inside generateModule() could fail without being caught by outer promise handlers if an error occurs during stream reading setup. Attach .catch() to the IIFE. 4. Incomplete getPrecedingModuleTitles() Logic - ModuleGenerationList.svelte:240-259 Doesn't account for modules that might have failed generation. Consider filtering by status to only include completed modules. 5. No Timeout Handling - ModuleGenerationList.svelte:106-124 API has timeouts (2-5min) but component doesn't handle timeout errors specially. Users might see generic Generation failed message. |
⚡ Performance ConsiderationsCurrent Performance ProfileGood: Sequential generation prevents API rate limiting and manages resource usage effectively. Potential Optimisations1. Large Course Handling - ModuleGenerationList.svelte:23-25 For courses with 20+ modules, progress calculations run on every store update. totalModules is constant after mount, so calculate it once instead of on every reactive update. 2. Nested Store Updates - ModuleGenerationList.svelte:194-211 handleGenerationComplete() uses nested loops to find modules. For large courses, this is O(n*m). Consider maintaining a Map<moduleId, {arcIndex, moduleIndex}> for O(1) lookups. 3. Modal Rendering - ModuleGenerationList.svelte:459-480 The modal searches for the preview module on every render using flatMap and find. Compute this once when opening the modal instead. 4. SSE Buffer Management - ModuleGenerationList.svelte:140-159 String concatenation in SSE decoder is generally fine for typical payloads, but could be optimized with TextDecoderStream API for very large responses (though probably overkill here). Memory Management ✅Excellent: Proper cleanup of SSE readers in onDestroy() prevents memory leaks. |
🔒 Security ConcernsStrengths ✅1. XML Injection Prevention - src/lib/utils/xml/xmlEscape.ts The new escapeXml() utility is critical and correctly implemented with proper escaping order (ampersand first), handling all five XML special characters, and null/undefined safety. 2. Comprehensive Escaping in API - src/routes/api/themis/module/+server.ts:108-119 All user-provided data is properly escaped before XML embedding. This is excellent security practice. Concerns1. XSS in Module Preview Modal - ModuleGenerationList.svelte:472 Risk Level: Low (Svelte escapes by default, XML is validated before storage) The XML preview renders raw content. While Svelte escapes by default, XML comes from AI generation and could theoretically contain malicious content if AI is compromised or prompt-injected. Recommendation: Add Content Security Policy headers to prevent any script execution. 2. Course Context Data in Console Logs - ModuleGenerationList.svelte:175 SSE events may contain course narratives and sensitive educational content. This could leak proprietary curriculum data. Recommendation: Remove or use logging library with redaction for production builds. 3. Client-Side Course Data Exposure - ModuleGenerationList.svelte:112-123 Risk Level: Low (depends on business requirements) Entire courseContext is sent in request body. Course structure is fully exposed in browser network logs. If proprietary content, consider using session-based course IDs or request signing. Validation ✅Strong validation with Zod schemas ensures type safety and prevents malformed data from reaching the generation pipeline. |
✅ Test CoverageCurrent StateNo new test files were added in this PR. Given the scope (895-line component + API endpoint + utilities), this is a significant gap. Recommended Test Coverage1. Unit Tests for xmlEscape.ts ⭐ HIGH PRIORITY This is security-critical code that MUST be tested. Recommended tests:
2. Unit Tests for convertToMetisFormat() Test the XML generation and proper escaping of special characters in synthesized XML. 3. Integration Tests for API Endpoint Test the full request/response cycle with mocked Claude client. 4. Component Tests for ModuleGenerationList.svelte Using @testing-library/svelte:
5. E2E Tests (Lower priority) Full workflow test: configure course → generate structure → generate modules → export Coverage MetricsSuggested minimum coverage for this PR:
|
Additional NotesExcellent Decisions ✅
DocumentationThe PR description is exemplary with clear breakdown of changes. Consider adding:
Migration PathNo breaking changes detected. The feature integrates cleanly with existing workflows. ✅ Overall Assessment: Strong implementation that maintains architectural consistency while adding significant new functionality. Main gaps are around test coverage (especially for security-critical XML escaping) and some edge case error handling. The code is production-ready pending tests. Recommendation: Approve with minor revisions - add tests for xmlEscape.ts before merging, and consider addressing the race condition and modal error boundary issues. |
Overview
Implements step 5 of the Themis workflow: module generation orchestration. Users can now generate individual modules or entire courses with AI, tracking progress in real-time. Each module is generated with full course context (narratives, arc themes, preceding modules) to ensure thematic coherence and avoid content repetition.
Tip
No additional setup required. The feature uses existing Metis generation infrastructure with course-awareness extensions.
Changes
Component: ModuleGenerationList (857 lines)
Complete module generation orchestration interface with:
API Endpoint: /api/themis/module (168 lines)
Course-aware module generation API that:
Prompt Enhancement
File:
src/lib/factories/prompts/metisPromptFactory.ts(+75 lines)Added
buildCourseAwareModulePrompt()function that:Maintains full backward compatibility with standalone Metis generation.
Schema & Validation
File:
src/lib/schemas/apiValidator.ts(+60 lines)New schemas for type-safe API contracts:
All schemas provide full TypeScript type inference via Zod.
Workflow Integration
File:
src/routes/themis/generate/+page.svelte(+15 lines)handleModuleGenerationSubmit,handleModuleGenerationBack)Documentation
File:
docs/dev/status/Themis-MVP.mdUpdated status tracking to reflect milestone 2.7 progress.
Summary
This PR is like hiring a master chef who not only knows every recipe in the cookbook (Metis), but also understands the entire dinner party menu (course structure), remembers which dishes have already been served (preceding modules), and adjusts each course to complement the overall culinary narrative (arc themes). Instead of cooking each dish in isolation, the chef ensures every module fits perfectly into the multi-course meal, avoiding repetitive flavours whilst maintaining thematic coherence from appetizer to dessert. And they've got a live video feed showing exactly what's simmering on each burner (SSE streaming).