Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .planning/session.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ Agents should read this file before substantive work and update it as work progr

## Session Log

### 2026-03-10 (backward-compat blocker fixes)
- Implemented three backward-compatibility fixes identified during code review:
- B1: `Slide.fromMap()` now migrates legacy `comments` field to `notes` (prevents silent data loss for old JSON payloads)
- B2: `Block.fromMap()` now normalizes legacy `type: "column"` to `ContentBlock.key` (prevents runtime crash for old serialized data)
- B3: Added 3 regression tests: legacy comments migration, notes-over-comments precedence, legacy column type normalization
- Validation: all 709 core tests pass (3 new + 706 existing)
- Committed and pushed to `claude/general-session-jBtv7`

### 2026-03-09 (review: release-next vs main in progress)
- Started a code review of `release/next` against `main` using merge base `5fc2298e7580b9ef47d45cc29bc5a801d42bd622`.
- Review focus: concrete regressions only, prioritized by user-visible/runtime impact, with verification against diff context and existing tests/call sites.
Expand Down
4 changes: 3 additions & 1 deletion packages/core/lib/src/models/block_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ sealed class Block with BlockMappable {
);

factory Block.fromMap(Map<String, Object?> map) {
final type = map['type'] as String;
var type = map['type'] as String;
// Normalize legacy 'column' type to 'block'.
if (type == 'column') type = ContentBlock.key;
return switch (type) {
SectionBlock.key => SectionBlock.fromMap(map),
ContentBlock.key => ContentBlock.fromMap(map),
Expand Down
10 changes: 8 additions & 2 deletions packages/core/lib/src/models/slide_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ class Slide with SlideMappable {
this.notes = const [],
});

factory Slide.fromMap(Map<String, Object?> map) =>
SlideMapper.fromMap(Map<String, dynamic>.from(map));
factory Slide.fromMap(Map<String, Object?> map) {
final normalized = Map<String, dynamic>.from(map);
// Migrate legacy 'comments' field to 'notes'.
if (normalized.containsKey('comments') && !normalized.containsKey('notes')) {
normalized['notes'] = normalized.remove('comments');
}
return SlideMapper.fromMap(normalized);
}

/// Validation schema for slide data.
static final schema = slideSchema.extend({
Expand Down
8 changes: 8 additions & 0 deletions packages/core/test/src/models/block_model_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,14 @@ void main() {
expect((block as WidgetBlock).name, 'Test');
});

test('normalizes legacy column type to block', () {
final map = {'type': 'column', 'content': 'Legacy content'};
final block = Block.fromMap(map);

expect(block, isA<ContentBlock>());
expect((block as ContentBlock).content, 'Legacy content');
});

test('throws for unknown type', () {
final map = {'type': 'unknown'};
expect(() => Block.fromMap(map), throwsArgumentError);
Expand Down
19 changes: 19 additions & 0 deletions packages/core/test/src/models/slide_model_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,25 @@ void main() {
expect(slide.notes, ['Comment 1', 'Comment 2']);
});

test('migrates legacy comments field to notes', () {
final slide = Slide.fromMap({
'key': 'legacy',
'comments': ['Old comment 1', 'Old comment 2'],
});

expect(slide.notes, ['Old comment 1', 'Old comment 2']);
});

test('prefers notes over comments when both present', () {
final slide = Slide.fromMap({
'key': 'both',
'notes': ['New note'],
'comments': ['Old comment'],
});

expect(slide.notes, ['New note']);
});

test('tolerates null options for legacy payloads', () {
final slide = Slide.fromMap({'key': 'legacy-slide', 'options': null});

Expand Down