-
Notifications
You must be signed in to change notification settings - Fork 2
ralph: #22 — Difficulty Ladder System — add easy/medium/hard scaffolding levels to cases #55
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,254 @@ | ||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Difficulty Ladder System | ||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||
| * Generates difficulty variants (easy/medium/hard) from a base case. | ||||||||||||||||||||||||||||||||||||||||||
| * Each variant provides different levels of scaffolding/context. | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import { Case, CaseFile, CaseDifficulty } from './types'; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
| // Difficulty Levels | ||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Scaffolding level for a difficulty variant | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export interface ScaffoldingLevel { | ||||||||||||||||||||||||||||||||||||||||||
| /** How much context is provided */ | ||||||||||||||||||||||||||||||||||||||||||
| level: 'easy' | 'medium' | 'hard'; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** Additional files to include (beyond base case files) */ | ||||||||||||||||||||||||||||||||||||||||||
| additionalFiles?: CaseFile[]; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** Hints or guidance to add to the prompt */ | ||||||||||||||||||||||||||||||||||||||||||
| hints?: string[]; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** Whether to show the solution (for testing only) */ | ||||||||||||||||||||||||||||||||||||||||||
| showSolution?: boolean; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** Notes about this variant */ | ||||||||||||||||||||||||||||||||||||||||||
| notes?: string; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Difficulty ladder configuration for a case | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export interface DifficultyLadder { | ||||||||||||||||||||||||||||||||||||||||||
| /** Base case (the original task) */ | ||||||||||||||||||||||||||||||||||||||||||
| base: Case; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** Scaffolding levels for each difficulty */ | ||||||||||||||||||||||||||||||||||||||||||
| levels: Record<CaseDifficulty, ScaffoldingLevel>; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** Whether to auto-generate variants on load */ | ||||||||||||||||||||||||||||||||||||||||||
| autoGenerate?: boolean; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
| // Difficulty Ladder Generator | ||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Generate difficulty variants from a base case | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function generateDifficultyVariants(baseCase: Case): Case[] { | ||||||||||||||||||||||||||||||||||||||||||
| const variants: Case[] = []; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Create easy variant | ||||||||||||||||||||||||||||||||||||||||||
| const easyVariant = createVariant(baseCase, 'easy'); | ||||||||||||||||||||||||||||||||||||||||||
| if (easyVariant) variants.push(easyVariant); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Create medium variant | ||||||||||||||||||||||||||||||||||||||||||
| const mediumVariant = createVariant(baseCase, 'medium'); | ||||||||||||||||||||||||||||||||||||||||||
| if (mediumVariant) variants.push(mediumVariant); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Create hard variant | ||||||||||||||||||||||||||||||||||||||||||
| const hardVariant = createVariant(baseCase, 'hard'); | ||||||||||||||||||||||||||||||||||||||||||
| if (hardVariant) variants.push(hardVariant); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return variants; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Create a single difficulty variant | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| function createVariant(baseCase: Case, difficulty: CaseDifficulty): Case | null { | ||||||||||||||||||||||||||||||||||||||||||
| const level = baseCase.difficultyLadder?.levels[difficulty]; | ||||||||||||||||||||||||||||||||||||||||||
| if (!level) { | ||||||||||||||||||||||||||||||||||||||||||
| // No ladder defined, return null (use base case as-is) | ||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Combine base files with additional files | ||||||||||||||||||||||||||||||||||||||||||
| const allFiles = baseCase.files ? [...baseCase.files] : []; | ||||||||||||||||||||||||||||||||||||||||||
| if (level.additionalFiles) { | ||||||||||||||||||||||||||||||||||||||||||
| allFiles.push(...level.additionalFiles); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Build prompt with hints | ||||||||||||||||||||||||||||||||||||||||||
| let prompt = baseCase.prompt; | ||||||||||||||||||||||||||||||||||||||||||
| if (level.hints && level.hints.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||
| prompt += '\n\n' + level.hints.join('\n'); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Create variant case | ||||||||||||||||||||||||||||||||||||||||||
| const variant: Case = { | ||||||||||||||||||||||||||||||||||||||||||
| ...baseCase, | ||||||||||||||||||||||||||||||||||||||||||
| id: `${baseCase.id}-${difficulty}`, | ||||||||||||||||||||||||||||||||||||||||||
| title: `${baseCase.title} (${difficulty})`, | ||||||||||||||||||||||||||||||||||||||||||
| prompt, | ||||||||||||||||||||||||||||||||||||||||||
| files: allFiles, | ||||||||||||||||||||||||||||||||||||||||||
| difficulty, | ||||||||||||||||||||||||||||||||||||||||||
| // Don't include solution in variants (unless explicitly requested) | ||||||||||||||||||||||||||||||||||||||||||
| solution: level.showSolution ? baseCase.solution : undefined, | ||||||||||||||||||||||||||||||||||||||||||
| notes: level.notes, | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return variant; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Get the scaffolding level for a difficulty | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function getScaffoldingLevel(baseCase: Case, difficulty: CaseDifficulty): ScaffoldingLevel | null { | ||||||||||||||||||||||||||||||||||||||||||
| return baseCase.difficultyLadder?.levels[difficulty] || null; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Check if a case has a difficulty ladder defined | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function hasDifficultyLadder(baseCase: Case): boolean { | ||||||||||||||||||||||||||||||||||||||||||
| return !!baseCase.difficultyLadder; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
| // Difficulty Ladder Builder | ||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Builder for creating difficulty ladders | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export class DifficultyLadderBuilder { | ||||||||||||||||||||||||||||||||||||||||||
| private base: Case; | ||||||||||||||||||||||||||||||||||||||||||
| private levels: Partial<Record<CaseDifficulty, ScaffoldingLevel>> = {}; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| constructor(baseCase: Case) { | ||||||||||||||||||||||||||||||||||||||||||
| this.base = baseCase; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Set the easy level scaffolding | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| withEasy(hints?: string[], additionalFiles?: CaseFile[], notes?: string): this { | ||||||||||||||||||||||||||||||||||||||||||
| this.levels.easy = { | ||||||||||||||||||||||||||||||||||||||||||
| level: 'easy', | ||||||||||||||||||||||||||||||||||||||||||
| hints, | ||||||||||||||||||||||||||||||||||||||||||
| additionalFiles, | ||||||||||||||||||||||||||||||||||||||||||
| notes, | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| return this; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Set the medium level scaffolding | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| withMedium(hints?: string[], additionalFiles?: CaseFile[], notes?: string): this { | ||||||||||||||||||||||||||||||||||||||||||
| this.levels.medium = { | ||||||||||||||||||||||||||||||||||||||||||
| level: 'medium', | ||||||||||||||||||||||||||||||||||||||||||
| hints, | ||||||||||||||||||||||||||||||||||||||||||
| additionalFiles, | ||||||||||||||||||||||||||||||||||||||||||
| notes, | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| return this; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Set the hard level scaffolding | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| withHard(hints?: string[], additionalFiles?: CaseFile[], notes?: string): this { | ||||||||||||||||||||||||||||||||||||||||||
| this.levels.hard = { | ||||||||||||||||||||||||||||||||||||||||||
| level: 'hard', | ||||||||||||||||||||||||||||||||||||||||||
| hints, | ||||||||||||||||||||||||||||||||||||||||||
| additionalFiles, | ||||||||||||||||||||||||||||||||||||||||||
| notes, | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| return this; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Build the difficulty ladder | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| build(): DifficultyLadder { | ||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||
| base: this.base, | ||||||||||||||||||||||||||||||||||||||||||
| levels: this.levels as Record<CaseDifficulty, ScaffoldingLevel>, | ||||||||||||||||||||||||||||||||||||||||||
| autoGenerate: true, | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+182
to
+188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unsafe cast:
Either validate that all three levels are present and throw if not, or change Option A: Validate at build time build(): DifficultyLadder {
+ const required: CaseDifficulty[] = ['easy', 'medium', 'hard'];
+ for (const d of required) {
+ if (!this.levels[d]) {
+ throw new Error(`Missing scaffolding level: ${d}`);
+ }
+ }
return {
base: this.base,
levels: this.levels as Record<CaseDifficulty, ScaffoldingLevel>,
autoGenerate: true,
};
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
| // Default Scaffolding Strategies | ||||||||||||||||||||||||||||||||||||||||||
| // ============================================================================= | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Default scaffolding for easy level | ||||||||||||||||||||||||||||||||||||||||||
| * - More context, hints, and guidance | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function defaultEasyScaffolding(_baseCase: Case): ScaffoldingLevel { | ||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||
| level: 'easy', | ||||||||||||||||||||||||||||||||||||||||||
| hints: [ | ||||||||||||||||||||||||||||||||||||||||||
| 'This is an easy task. Focus on correctness and following best practices.', | ||||||||||||||||||||||||||||||||||||||||||
| 'You have all the context you need to complete this task.', | ||||||||||||||||||||||||||||||||||||||||||
| 'Take your time to understand the codebase before making changes.', | ||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||
| notes: 'Easy: Maximum scaffolding provided', | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Default scaffolding for medium level | ||||||||||||||||||||||||||||||||||||||||||
| * - Standard context, minimal hints | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function defaultMediumScaffolding(_baseCase: Case): ScaffoldingLevel { | ||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||
| level: 'medium', | ||||||||||||||||||||||||||||||||||||||||||
| hints: [ | ||||||||||||||||||||||||||||||||||||||||||
| 'Complete this task to the best of your ability.', | ||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||
| notes: 'Medium: Standard scaffolding', | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Default scaffolding for hard level | ||||||||||||||||||||||||||||||||||||||||||
| * - Minimal context, agent must discover | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function defaultHardScaffolding(_baseCase: Case): ScaffoldingLevel { | ||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||
| level: 'hard', | ||||||||||||||||||||||||||||||||||||||||||
| hints: [ | ||||||||||||||||||||||||||||||||||||||||||
| 'You need to figure out the best approach for this task.', | ||||||||||||||||||||||||||||||||||||||||||
| 'Explore the codebase to understand the context.', | ||||||||||||||||||||||||||||||||||||||||||
| 'Make reasonable assumptions and document them.', | ||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||
| notes: 'Hard: Minimal scaffolding', | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Create a difficulty ladder with default scaffolding | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| export function createDefaultLadder(_baseCase: Case): DifficultyLadder { | ||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||
| base: _baseCase, | ||||||||||||||||||||||||||||||||||||||||||
| levels: { | ||||||||||||||||||||||||||||||||||||||||||
| easy: defaultEasyScaffolding(_baseCase), | ||||||||||||||||||||||||||||||||||||||||||
| medium: defaultMediumScaffolding(_baseCase), | ||||||||||||||||||||||||||||||||||||||||||
| hard: defaultHardScaffolding(_baseCase), | ||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||
| autoGenerate: true, | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import type { ScaffoldingLevel } from './difficulty-ladder'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's check the imports structure
echo "=== types.ts imports from difficulty-ladder ==="
rg "from.*difficulty-ladder" src/cases/types.ts
echo ""
echo "=== difficulty-ladder.ts imports from types ==="
rg "from.*types" src/cases/difficulty-ladder.tsRepository: AnswerLayer/sniffbench Length of output: 281 🏁 Script executed: # Check if both files exist and get their contents
echo "=== Checking src/cases/types.ts imports section ==="
head -20 src/cases/types.ts
echo ""
echo "=== Checking src/cases/difficulty-ladder.ts imports section ==="
head -20 src/cases/difficulty-ladder.tsRepository: AnswerLayer/sniffbench Length of output: 1460 🏁 Script executed: # Search for DifficultyLadder definitions in both files
echo "=== DifficultyLadder in types.ts ==="
rg -A 10 "interface DifficultyLadder|type DifficultyLadder" src/cases/types.ts
echo ""
echo "=== DifficultyLadder in difficulty-ladder.ts ==="
rg -A 10 "interface DifficultyLadder|type DifficultyLadder" src/cases/difficulty-ladder.tsRepository: AnswerLayer/sniffbench Length of output: 697 🏁 Script executed: # Check what ScaffoldingLevel is and where it's defined/used
echo "=== ScaffoldingLevel definition ==="
rg -B 2 -A 5 "ScaffoldingLevel" src/cases/difficulty-ladder.ts | head -30
echo ""
echo "=== Uses of ScaffoldingLevel in types.ts ==="
rg "ScaffoldingLevel" src/cases/types.tsRepository: AnswerLayer/sniffbench Length of output: 1121 Circular dependency and duplicate type definitions between
Move 🤖 Prompt for AI Agents |
||
| /** | ||
| * Case and Rubric Schema Types | ||
| * | ||
|
|
@@ -39,6 +40,20 @@ export type CaseSource = 'bootstrap' | 'generated' | 'manual' | 'imported' | 'cl | |
| */ | ||
| export type CaseDifficulty = 'easy' | 'medium' | 'hard'; | ||
|
|
||
|
|
||
| /** | ||
| * Difficulty ladder configuration for a case | ||
| */ | ||
| export interface DifficultyLadder { | ||
| /** Base case (the original task) */ | ||
| base: Case; | ||
|
|
||
| /** Scaffolding levels for each difficulty */ | ||
| levels: Record<CaseDifficulty, ScaffoldingLevel>; | ||
|
|
||
| /** Whether to auto-generate variants on load */ | ||
| autoGenerate?: boolean; | ||
| } | ||
|
Comment on lines
+47
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This interface is declared identically in both files (here at lines 47-56 and in Additionally, 🤖 Prompt for AI Agents |
||
| /** | ||
| * Agent behavior expectations for a case | ||
| */ | ||
|
|
@@ -110,6 +125,9 @@ export interface Case { | |
| /** Additional notes or hints (not shown to agent) */ | ||
| notes?: string; | ||
|
|
||
| // Difficulty ladder configuration for generating variants | ||
| difficultyLadder?: DifficultyLadder; | ||
|
|
||
| // Metadata added by loader | ||
| /** Source file path (added by loader) */ | ||
| _sourcePath?: string; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variant inherits
difficultyLadderfrom base and silently dropsnotes.Two issues with the spread + overrides:
...baseCasecopies thedifficultyLadderproperty into every variant. Variants shouldn't carry the ladder configuration — it creates unnecessary circular nesting and bloats serialized output.notes: level.notesexplicitly setsnoteseven whenlevel.notesisundefined, which overwrites whateverbaseCase.notescontained (the spread would have preserved it). Use a conditional or nullish-coalescing pattern instead.Proposed fix
const variant: Case = { ...baseCase, id: `${baseCase.id}-${difficulty}`, title: `${baseCase.title} (${difficulty})`, prompt, files: allFiles, difficulty, - // Don't include solution in variants (unless explicitly requested) solution: level.showSolution ? baseCase.solution : undefined, - notes: level.notes, + notes: level.notes ?? baseCase.notes, + difficultyLadder: undefined, // variants shouldn't carry the ladder };📝 Committable suggestion
🤖 Prompt for AI Agents