-
Notifications
You must be signed in to change notification settings - Fork 0
feat(themis): Module coherence with smart titles and overview-first generation #27
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 foundation for smart title handling and overview-first generation: - New TitleInput type with three modes: - undefined: AI decides based on context - prompt: AI generates from guidance - literal: Use exact value - New ModuleOverview interface: - generatedTitle/generatedTheme (if not literal) - learningObjectives (what learners gain) - prerequisites (what they need first) - keyConceptsIntroduced (new topics covered) - Updated Arc interface: - titleInput/themeInput fields - Maintains backward-compatible title/theme strings - Updated ModuleSlot interface: - titleInput/themeInput fields - overview field for lightweight generation - Deprecates learningObjectives/keyTopics in favor of overview - Migration utility (migrations.ts): - Converts legacy string titles to TitleInput format - Safe idempotent migration - Helper functions for title display/creation - Store integration: - Auto-migration on localStorage deserialization - Overview date handling Addresses roadmap tasks: - 1.1.2.2: Flexible title inputs - 2.1.2: Overview-first generation structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Comprehensive guide for picking up the module coherence work including: - Problem statement and solution approach - What's been completed (types, migrations) - What's next (UI components, API, prompts) - Architecture decisions and rationale - Testing strategy - Phase 2 preview - Quick start commands Reference document for context switching. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Create TitleInputField component to support three input modes: - undefined: AI decides title - prompt: AI uses user guidance - literal: Exact user-provided title Updated planners to use new component: - ArcStructurePlanner: Uses TitleInputField for arc titles and themes - ModuleWithinArcPlanner: Uses TitleInputField for module titles Updated validation logic to work with TitleInput structure. Updated auto-suggest functions to use prompt-based titles. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Create lightweight overview generation system before full modules: Overview API Endpoint (/api/themis/module/overview): - Generates ModuleOverview structure (objectives, prerequisites, concepts) - JSON-based response (non-streaming for simplicity) - 60s timeout (much faster than full module generation) - Validates overview structure with 3-5 item requirements - Supports retry logic with validation errors Prompt Builder (buildModuleOverviewPrompt): - Helper: buildTitleGuidance - handles undefined/prompt/literal inputs - Helper: buildKnowledgeContextSection - aggregates preceding module knowledge - Accumulates concepts from previous modules to avoid repetition - Explicit "DO NOT REPEAT" instructions for coherence - JSON output format for clean parsing Benefits: - Fast iteration (~30s vs 60-120s for full modules) - Better planning before committing to full generation - Knowledge accumulation prevents content repetition - Cost-effective for course structure exploration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Create comprehensive utility for tracking learner knowledge progression: Core Functions: - buildKnowledgeContext(): Aggregates all preceding module data - getPrecedingModules(): Gets all modules before a target module - hasCompleteOverview(): Validates overview completeness - getKnowledgeCoverageStats(): Provides course-wide statistics LearnerKnowledgeContext Structure: - coveredTopics: Deduplicated list of all concepts introduced - acquiredSkills: All learning objectives achieved - fulfilledPrerequisites: Prerequisites met so far - journeyNarrative: Natural language summary of progress - currentCapabilities: What learners can do now - topicsToAvoidRepeating: Explicit list for AI guidance Features: - Deduplication of concepts and skills across modules - Temporal awareness (respects arc and module order) - Narrative generation for human-readable summaries - Statistics for tracking overview coverage This utility powers the coherence system by ensuring each module knows exactly what learners have already covered. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Major documentation update for module coherence feature: Phase 1 Summary: - Complete implementation details for all 5 commits - Files created (TitleInputField, overview API, knowledge builder) - Files modified (types, migrations, planners, prompts) - Key features explained (smart titles, overviews, context) Phase 2 Implementation Plan: - Detailed component modification instructions - UI workflow recommendations (two-step generation) - Store update patterns - Testing checklist Quick Start Guide: - Branch status verification - What works now vs what's next - Key files reference - API endpoint documentation - Next session checklist Architecture Notes: - Why two-step generation - Knowledge context flow diagram - Migration safety guarantees Success Criteria: - Phase 1 checklist (all complete) - Phase 2 checklist (ready to start) - Phase 3 preview (future enhancements) This doc provides everything needed to continue from a fresh context.
Implements Phase 2 of module coherence feature, adding UI for overview generation: **Type System Updates:** - Add 'overview-ready' status to ModuleStatus type - Update moduleStatusCounts derived store to track new status **Store Functions:** - Add updateModuleWithOverview() helper function - Updates module with overview data and status - Automatically applies generated title/theme if available **ModuleGenerationList Updates:** - Add generateOverview() function with API integration - Update generateModule() to use knowledge context from preceding modules - Add handleGenerateOverview event handler - Pass knowledge context to full module generation **UI Components:** - ModuleCard: Add two-button workflow (Overview → Full Module) - "Generate Overview" button for 'planned' modules - "Generate Full Module" button for 'overview-ready' modules - Display overview content (objectives, prerequisites, concepts) - New status icon (◐) for overview-ready state - ArcSection: Pass through generateOverview event **Workflow:** 1. User creates module structure 2. Click "Generate Overview" (fast, ~30s) 3. Review objectives, prerequisites, concepts 4. Click "Generate Full Module" with context 5. Full module generated with knowledge of previous content **Benefits:** - Faster iteration (review structure before committing) - Better coherence (each overview informs the next) - Cost effective (cheaper to regenerate overviews) - Skip option available (direct to full generation) Related to milestone 2.1 (module-to-module coherence) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Fixes 500 error and migration issues when using overview generation:
**API Validation Schemas:**
- Add 'overview-ready' to status enum in ModuleSlotSchema (apiValidator.ts)
- Add 'overview-ready' to status enum in overview API endpoint
**Migration System (migrations.ts):**
- Remove early return optimization that skipped module migration
- Always migrate all arcs and modules (idempotent operations)
- Ensures modules get titleInput even if arcs already have new structure
**TitleInputField Component:**
- Add safety check for undefined value prop
- Provide default { type: 'undefined' } fallback
- Update internal state reactively when value prop changes
**Issues Fixed:**
1. 500 error: Status validation failed when sending 'overview-ready' modules
2. Undefined titleInput: Partially migrated data caused crashes
3. Migration inconsistency: Modules weren't migrated if arcs were
All validation schemas now consistent with new module status lifecycle.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Fixes 500 error in overview generation endpoint: **Issue:** Overview API was trying to use Anthropic SDK directly (client.messages.create()) but createChatClient() returns a LangChain ChatAnthropic client. **Solution:** - Use LangChain's .invoke() method instead of .messages.create() - Pass temperature and maxTokens to client creation - Handle response.content which can be string or array - Extract JSON from response text properly **Error Fixed:** TypeError: Cannot read properties of undefined (reading 'create') Now overview generation uses consistent LangChain API like full module generation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Fixes issue where retry button always attempted full generation even if overview failed. **Problem:** When an overview generation failed, clicking retry would attempt full generation instead of retrying the overview. This also affected the edge case where a user skipped directly to full generation without an overview. **Solution:** Added `lastAttemptedGeneration` field to ModuleSlot to track what was last tried: - Set to 'overview' when overview generation starts - Set to 'full' when full generation starts - Used by retry logic to determine correct action **Changes:** 1. Added `lastAttemptedGeneration?: 'overview' | 'full'` to ModuleSlot type 2. Added `setLastAttemptedGeneration()` helper in moduleStoreHelpers 3. Updated both generation functions to set this field at start 4. Added `handleRetry()` in ModuleCard that checks field and retries correctly 5. Updated button text to show what will be retried **Behavior:** - "Retry Overview" - if overview generation failed - "Retry Generation" - if full generation failed - Defaults to full generation if field not set (backward compatibility) Now retry correctly attempts the same type of generation that failed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
SummaryThis PR implements a well-architected enhancement to Themis that introduces flexible AI-guided title generation and overview-first module generation. The implementation demonstrates excellent type safety through discriminated unions, comprehensive backward compatibility via migration utilities, and thoughtful separation of concerns. The knowledge context builder effectively prevents content repetition across modules. Minor areas for improvement include better error handling consistency, extracting magic numbers to configuration, and adding automated tests. 🎯 Code Quality & Best PracticesExcellent PatternsType Safety with Discriminated Unions export type TitleInput =
| { type: 'undefined' }
| { type: 'prompt'; value: string }
| { type: 'literal'; value: string };This makes invalid states unrepresentable and provides excellent autocomplete. Well done! Idempotent Migration Pattern Reusable Component Design Knowledge Context Builder Architecture
Minor Improvements Needed1. Component Safety Check (src/lib/components/themis/TitleInputField.svelte:10-11) const safeValue = value || { type: 'undefined' as const };This safety check is good, but the prop should be properly typed as required or have a proper default. Consider: export let value: TitleInput = { type: 'undefined' };2. Reactive Statement Side Effects (TitleInputField.svelte:24-32) function handleTypeChange() {
if (inputType === 'undefined') {
onChange({ type: 'undefined' });
} else {
onChange({ type: inputType, value: inputValue });
}
}Then bind to 3. Magic Numbers Should Be Configurable
Consider extracting to a shared configuration file: // src/lib/config/generation.ts
export const GENERATION_CONFIG = {
overview: {
timeoutMs: 60000,
maxRetries: 3,
validation: {
minObjectives: 3,
maxObjectives: 5,
minPrerequisites: 1,
minKeyConcepts: 3,
maxKeyConcepts: 5
}
}
};4. Type Assertion Should Be Avoided body.moduleSlot as ModuleSlotThe Zod validation should already ensure this is a valid 🐛 Potential IssuesCritical1. JSON Parsing Without Error Context (overview/+server.ts:108) const overview = JSON.parse(jsonMatch[0]);If the AI returns malformed JSON, the error message won't include the actual response text for debugging. Consider: try {
const overview = JSON.parse(jsonMatch[0]);
} catch (parseError) {
console.error('Failed to parse JSON response:', jsonMatch[0]);
throw new Error(`JSON parse failed: ${parseError.message}`);
}2. Inconsistent Validation Error Handling Moderate3. Race Condition Risk in Module Generation 4. Missing Null Checks in Knowledge Context Builder .flatMap(m => m.overview!.keyConceptsIntroduced)The non-null assertion operator .flatMap(m => m.overview?.keyConceptsIntroduced || [])5. Migration Applies to Every Store Load data = migrateCourseData(data);While idempotent migrations are safe, running them on every localStorage load adds overhead. Consider:
Minor6. Array Deduplication Could Be More Efficient const coveredTopics = [...new Set(
modulesWithOverviews.flatMap(m => m.overview!.keyConceptsIntroduced)
)];7. Potential XSS in Module Card Display ⚡ Performance ConsiderationsGood Practices1. Efficient Overview Generation 2. Proper Filtering Before Iteration const modulesWithOverviews = precedingModules.filter(m => m.overview);Potential Optimizations1. Derived Store Efficiency 2. LocalStorage Size Concerns
3. Unnecessary JSON Parsing const jsonMatch = responseText.match(/\{[\s\S]*\}/);Will match from the first 4. Prompt Building Could Be Cached 5. Component Re-renders 🔒 Security ConcernsLow Risk1. API Key Exposure in Logs 2. Input Validation title: z.string().max(500),
description: z.string().max(5000),3. SSRF Risk in Research Feature 4. localStorage XSS Mitigation Best Practices Applied✅ Environment variable validation (overview/+server.ts:55-60) ✅ Test CoverageCurrent StateThe PR description mentions "Manual testing checklist completed" with specific items verified. However, no automated tests are included in the changed files. Critical Test Gaps1. TitleInput Type System
2. Knowledge Context Builder describe('buildKnowledgeContext', () => {
it('returns empty context for first module');
it('aggregates data from multiple preceding modules');
it('deduplicates topics and skills');
it('handles modules without overviews gracefully');
});
describe('getPrecedingModules', () => {
it('returns empty array for first module');
it('includes modules from previous arcs');
it('orders modules correctly');
});3. API Endpoint
4. Component Tests
RecommendationsGiven the complexity and importance of this feature:
Testing the Knowledge Context FeatureTo manually verify the anti-repetition feature works:
This could be automated with snapshot tests of the generated prompts. Overall AssessmentStrengths:
Key Recommendations:
Approval Status: ✅ Recommended for merge after addressing critical issues (#1 JSON parsing error context) and adding basic unit tests for core utilities. The feature is well-implemented and the manual testing is thorough, but automated tests are essential for long-term maintenance. |
Overview
This PR implements a two-part enhancement to Themis that eliminates content repetition across modules and provides flexible AI-guided title generation.
Problem Solved
Previously, generated modules would repeat content from earlier modules because:
Solution
1. Smart Title System
2. Overview-First Generation
Key Benefits
✅ Reduced repetition: Each module knows what previous modules covered
✅ Faster iteration: Review 10 overviews in ~5min vs 10 full modules in ~20min
✅ Better planning: See entire course structure before committing
✅ Cost savings: Overviews are cheaper to regenerate
✅ Flexible titling: Let AI decide, guide it, or specify exact titles
Implementation Details
Type System
TitleInputtype (undefined/prompt/literal)ModuleOverviewinterface (objectives, prerequisites, concepts)LearnerKnowledgeContextinterface (accumulated knowledge)'overview-ready'UI Components
TitleInputField.svelte- Reusable input component with three modesArcStructurePlannerandModuleWithinArcPlannerwith new inputsModuleCard- Two-step workflow UI (Generate Overview → Generate Full Module)ModuleGenerationList- Overview and full generation orchestrationAPI Endpoints
POST /api/themis/module/overview- Fast overview generationPOST /api/themis/module- Full generation with knowledge contextUtilities
knowledgeContextBuilder.ts- Aggregates preceding module datamigrations.ts- Auto-migration for legacy data (backward compatible)metisPromptFactory.ts- Overview prompt builder with context awarenessFiles Changed
Created (4 files)
src/lib/components/themis/TitleInputField.sveltesrc/routes/api/themis/module/overview/+server.tssrc/lib/utils/themis/knowledgeContextBuilder.tssrc/lib/utils/themis/migrations.tsModified (9 files)
src/lib/types/themis.ts- Type system updatessrc/lib/schemas/apiValidator.ts- New status enum valuesrc/lib/stores/themisStores.ts- Overview update logicsrc/lib/components/themis/ArcStructurePlanner.sveltesrc/lib/components/themis/ModuleWithinArcPlanner.sveltesrc/lib/components/themis/ModuleGenerationList.sveltesrc/lib/components/themis/ModuleCard.sveltesrc/lib/factories/prompts/metisPromptFactory.tsdocs/dev/wip/module-coherence-continuation.mdTesting
Manual testing checklist completed:
User Workflow
Two-Step Generation (Recommended)
Quick Generation (Alternative)
Documentation
Complete implementation guide available in
docs/dev/wip/module-coherence-continuation.mdIncludes:
Breaking Changes
None. All changes are backward compatible:
titleInputconvertstitleto literal modeoverviewis gracefully handled (optional field)Commits
Related
Ready for review and merge. All functionality tested and documented.