Skip to content
Merged

v2 #24

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
370 commits
Select commit Hold shift + click to select a range
96db8e2
feat: Add GIFSettings struct with tests for GIF export configuration
syi0808 Feb 23, 2026
e6bb259
feat: Add ExportFormat enum and GIF fields to RenderSettings with bac…
syi0808 Feb 23, 2026
b7e23df
feat: Add GIFEncoder using CGImageDestination with tests
syi0808 Feb 23, 2026
3f8d806
feat: Add GIF export path to ExportEngine with format branching
syi0808 Feb 23, 2026
9d912d1
feat: Add GIF format picker, settings, and file size warnings to expo…
syi0808 Feb 23, 2026
98d3c26
feat: Register all GIF export files in Xcode project and fix GIF magi…
syi0808 Feb 23, 2026
4ae90c3
feat: Add design system foundation with token files
syi0808 Feb 23, 2026
c1aaf13
feat: Add reusable component library
syi0808 Feb 23, 2026
460c5d0
refactor: Apply design system to core views
syi0808 Feb 23, 2026
f389c3b
refactor: Apply design system tokens to RecordingView
syi0808 Feb 23, 2026
b6d82a7
refactor: Apply design tokens to Timeline, Recording, and Preview views
syi0808 Feb 23, 2026
1d3f32f
refactor: Apply design tokens to secondary views
syi0808 Feb 23, 2026
bcb42af
feat: Add Reduce Motion accessibility utilities
syi0808 Feb 23, 2026
e3ef200
refactor: Add accessibility labels and Reduce Motion support
syi0808 Feb 23, 2026
82af7ad
feat: Implement custom DMG styling with a background image and icon a…
syi0808 Feb 23, 2026
0f896e7
feat: Add microphone source selection to capture toolbar
syi0808 Feb 23, 2026
a0469b0
fix: Replace display-dependent deviceRGB with explicit sRGB color space
syi0808 Feb 23, 2026
b567d16
feat: Add color space selection for video export
syi0808 Feb 23, 2026
dd49bd2
feat: Add text labels and adjust sizing for system audio and micropho…
syi0808 Feb 23, 2026
23eb4ef
perf: Only set CIContext workingColorSpace for wide-gamut exports
syi0808 Feb 23, 2026
78f2e23
feat: Improve camera smoothness with spring zooms and smoother panning
syi0808 Feb 23, 2026
53ebba5
fix: Detect AVAssetWriter failure during export to prevent hang
syi0808 Feb 23, 2026
c7ceed5
fix: Only set AVVideoColorPropertiesKey for explicit color space sele…
syi0808 Feb 23, 2026
c0ee627
refactor: Remove V1 RecordingView full-page recording screen
syi0808 Feb 23, 2026
77fd7f8
fix: Hold frames across VFR gaps in preview playback
syi0808 Feb 23, 2026
b817803
feat: Add VFRRecordingManager for variable frame rate capture
syi0808 Feb 23, 2026
94c7c5b
feat: Support high frame rate capture and export (30-240fps)
syi0808 Feb 23, 2026
0aa0e7b
refactor: Isolate color space handling to export-only path
syi0808 Feb 23, 2026
41fde5f
fix: Use lookahead buffer for correct VFR frame holding
syi0808 Feb 23, 2026
6bb9d83
refactor: Extract VFR gap filling into CFRFrameReader wrapper
syi0808 Feb 23, 2026
e1856ab
fix: Ensure completion callback on all RenderCoordinator failure paths
syi0808 Feb 23, 2026
4b6ce19
Implement a fixed timescale for scrub cache keys and return overwritt…
syi0808 Feb 23, 2026
59db4ed
feat: Adjust corner radius slider range and set default window inset …
syi0808 Feb 23, 2026
d75586c
feat: Hide the main window when starting a new recording and reorder …
syi0808 Feb 23, 2026
ab90ec2
feat: Introduce an optional spring-based cursor smoothing pipeline as…
syi0808 Feb 24, 2026
05b0e6d
Fix SmartZoom V2 producing excessive overlapping camera segments
syi0808 Feb 24, 2026
1eb9bb4
Fix remaining SmartZoom V2 quality issues: wrong center and typing mi…
syi0808 Feb 24, 2026
b572a7d
fix: Improve cursor hotspot accuracy by deriving values from design p…
syi0808 Feb 24, 2026
88c4634
Replace zoomOutAndIn with single-phase zoomOutAndPan/zoomInAndPan tra…
syi0808 Feb 24, 2026
48a5893
feat: Add numerous new source files for smart generation, camera/curs…
syi0808 Feb 24, 2026
1e6d267
fix: Use viewer's zoom for viewport distance in TransitionPlanner
syi0808 Feb 24, 2026
da00f7b
feat: Add spatial segmentation to SceneSegmenter
syi0808 Feb 24, 2026
2ff142e
fix: Use first caret position for typing scene center
syi0808 Feb 24, 2026
21d3aba
feat: Pre-smooth mouse positions in smart generation pipeline
syi0808 Feb 24, 2026
7adf922
claude
syi0808 Feb 24, 2026
0fb137a
feat: Preserve click element info through serialization
syi0808 Feb 25, 2026
59cf0fd
feat: Replace fixed clicking zoom with ROI-based dynamic range
syi0808 Feb 25, 2026
f1e6007
feat: Make StaticHoldController cursor-aware to prevent off-screen cu…
syi0808 Feb 25, 2026
be849d1
feat: Smarter transitions with same-zoom tolerance and actual end pos…
syi0808 Feb 25, 2026
0fd438b
feat: Add frame-based ROI fallback using Vision saliency data
syi0808 Feb 25, 2026
d5058c3
feat: Add post-click context detection to smart generation pipeline
syi0808 Feb 25, 2026
0583a15
feat: Replace print() with structured Logger across 25 files
syi0808 Feb 26, 2026
da8396f
refactor: Decompose AppState into focused child ObservableObjects
syi0808 Feb 26, 2026
215a307
feat: Add continuous camera system with spring-damper physics simulation
syi0808 Feb 25, 2026
5047913
feat: Integrate continuous camera directly with rendering pipeline
syi0808 Feb 26, 2026
6c74f16
fix: Add NSLock to protect RecordingCoordinator capture state from da…
syi0808 Feb 26, 2026
6560c3c
fix: Add lock protection and defensive timer invalidation to MouseDat…
syi0808 Feb 26, 2026
34d7df3
perf: Replace O(n) isDirty scan with binary search in preview caches
syi0808 Feb 26, 2026
1cc4893
perf: Add LRU eviction policy to CursorImageProvider cache
syi0808 Feb 26, 2026
314585e
perf: Add LRU eviction to EffectCompositor keystroke pill cache
syi0808 Feb 26, 2026
a16bb4d
refactor: Move AudioMixer export queue to instance property
syi0808 Feb 26, 2026
b8d3a6a
refactor: Decompose EditorViewModel from 949 to 449 lines
syi0808 Feb 26, 2026
553b14c
refactor: Decompose TimelineView from 889 to 443 lines
syi0808 Feb 26, 2026
aaee2e2
refactor: Decompose Track.swift from 821 to 310 lines
syi0808 Feb 26, 2026
66b6f90
fix: Use actual NSScreen.backingScaleFactor instead of hardcoded 2.0
syi0808 Feb 26, 2026
742231c
fix: Replace force unwrap with guard let in drag event synthesis
syi0808 Feb 26, 2026
2a47a69
fix: Remove force unwraps across 10 files for crash safety
syi0808 Feb 26, 2026
306355b
feat: Add user-facing error dialogs for project open/save/export fail…
syi0808 Feb 26, 2026
f83fac5
fix: Replace force unwraps with guard let in ScreenCaptureManager del…
syi0808 Feb 26, 2026
3b16a1c
fix: Replace force unwrap with guard let in VideoWriter pixel buffer …
syi0808 Feb 26, 2026
326bfaa
fix: Replace force unwraps with if-let in MouseDataRecorder timer setup
syi0808 Feb 26, 2026
74eef36
fix: Replace force unwrap with guard let for movies directory lookup
syi0808 Feb 26, 2026
7970b5c
fix: Replace force unwraps with guard let in IntentClassifier span de…
syi0808 Feb 26, 2026
b9df02f
fix: Replace force unwrap with optional binding in ShotPlanner salien…
syi0808 Feb 26, 2026
00221aa
fix: Log JSON decoding failures in EventStreamAdapter instead of sile…
syi0808 Feb 26, 2026
b2dc873
fix: Log recent projects encode/decode failures in ProjectManager
syi0808 Feb 26, 2026
99b76a7
fix: Log seek failures in RenderCoordinator instead of silent try?
syi0808 Feb 26, 2026
187a872
fix: Log file operation failures in RecordingSession and VideoWriter
syi0808 Feb 26, 2026
42f6417
refactor: Decompose 6 large files into focused extensions
syi0808 Feb 26, 2026
4efe4e7
fix: Improve stability and concurrency safety across recording pipeline
syi0808 Feb 27, 2026
585eaf1
fix: Replace all CGColorSpace force unwraps with safe static constants
syi0808 Feb 27, 2026
181c96b
refactor: Decompose FrameEvaluator into per-track extension files
syi0808 Feb 27, 2026
4047bf3
refactor: Decompose PreviewEngine into focused extension files
syi0808 Feb 27, 2026
7b0409e
refactor: Decompose ExportEngine into format-specific extension files
syi0808 Feb 27, 2026
2f22adb
feat: Introduce `WaypointGenerator` and its tests as part of the new …
syi0808 Feb 27, 2026
5264ac4
feat: Introduce detailed typing waypoints with configurable intervals…
syi0808 Feb 27, 2026
76e697b
feat: improve transition planning, refine idle scene resolution, and …
syi0808 Feb 28, 2026
5bba031
feat: Improve idle scene resolution to ensure leading establishing sh…
syi0808 Mar 2, 2026
a44616a
feat: enhance intent classification by normalizing app identifiers, r…
syi0808 Mar 2, 2026
ecff053
refactor: extract shared types from SmartGeneratorV2
syi0808 Mar 7, 2026
1561675
refactor: rename SimulatedPath.swift to TimedTransform.swift
syi0808 Mar 7, 2026
ddb8fd1
refactor: remove CameraGenerationMethod, always use continuous camera
syi0808 Mar 7, 2026
b90e682
refactor: delete segment-based pipeline files and clean TimedTransform
syi0808 Mar 7, 2026
ef3a373
refactor: rename V2/ to SmartGeneration/
syi0808 Mar 7, 2026
dcf4d1b
docs: add dual-layer camera design and implementation plan
syi0808 Mar 7, 2026
81ce4d8
feat: unify zoom-pan response times for macro layer
syi0808 Mar 7, 2026
5d62d69
feat: remove detail waypoints from macro layer
syi0808 Mar 7, 2026
ad3086f
feat: implement urgency blending for smooth transitions
syi0808 Mar 7, 2026
1ea61f8
feat: implement soft clamping at boundaries
syi0808 Mar 7, 2026
80ae999
fix: relax soft clamping test to check smooth position change
syi0808 Mar 7, 2026
e4bdbe0
feat: add MicroTracker with dead zone and offset spring
syi0808 Mar 7, 2026
4575002
feat: integrate MicroTracker into camera pipeline
syi0808 Mar 7, 2026
913c45f
feat: camera-space cursor smoothing with idle stabilization
syi0808 Mar 7, 2026
590efc2
feat: cursor-driven camera architecture
syi0808 Mar 8, 2026
b019382
feat: improve camera smoothness and cursor tracking quality
syi0808 Mar 8, 2026
a033454
docs: add dead zone camera design
syi0808 Mar 9, 2026
1e3bde9
docs: add dead zone camera implementation plan
syi0808 Mar 9, 2026
c77b597
feat: add DeadZoneSettings and update position spring defaults
syi0808 Mar 9, 2026
9a0d3ee
test: add dead zone target computation tests
syi0808 Mar 9, 2026
58b0131
feat: implement DeadZoneTarget viewport-aware targeting
syi0808 Mar 9, 2026
00b0f28
test: add adaptive spring response tests
syi0808 Mar 9, 2026
5436ed1
feat: implement AdaptiveResponse for time-to-next-action spring speed
syi0808 Mar 9, 2026
a5ab012
feat: rewrite SpringDamperSimulator with dead zone targeting
syi0808 Mar 9, 2026
95ceba7
feat: remove MicroTracker from pipeline, pass intentSpans to simulator
syi0808 Mar 9, 2026
c50ced9
fix: update tests for new simulate() signature and start position
syi0808 Mar 9, 2026
104ae6e
test: update existing tests for dead zone architecture
syi0808 Mar 9, 2026
f222aad
fix: stop repeated permission dialogs from input monitoring check
syi0808 Mar 9, 2026
5743a99
chore: pbxproj
syi0808 Mar 9, 2026
c93ee20
chore: permissions
syi0808 Mar 9, 2026
d58e3cf
fix: wire ClickFeedbackConfig into click scale animation with spring …
syi0808 Mar 9, 2026
f73935b
fix: add dead zone hysteresis and widen gradient band for smoother pa…
syi0808 Mar 9, 2026
29fc7b6
fix: couple zoom and pan transitions via waypoint center blending
syi0808 Mar 9, 2026
78d6da9
fix: eliminate click animation bounce and tighten zoom-pan coupling
syi0808 Mar 9, 2026
ea0236f
fix: synchronize zoom and pan by targeting waypoint center during tra…
syi0808 Mar 9, 2026
15ba227
feat: improve camera simulation initial state, mouse smoothing, and c…
syi0808 Mar 10, 2026
688e638
fix: use declared UTType identifier for .screenize package open panels
syi0808 Mar 10, 2026
4ef886e
Add design doc for advanced generation settings
syi0808 Mar 10, 2026
f1dc254
Add implementation plan for advanced generation settings
syi0808 Mar 10, 2026
f7e1b06
feat: add GenerationSettings data model with 5 nested setting groups
syi0808 Mar 10, 2026
b66439f
feat: add GenerationSettingsManager with persistence and preset support
syi0808 Mar 10, 2026
23a0175
feat: add reusable setting control components (slider, range slider, …
syi0808 Mar 10, 2026
894848d
feat: add optional generationSettings override to ScreenizeProject
syi0808 Mar 10, 2026
ebb10c2
feat: add init(from: GenerationSettings) factories to all generator s…
syi0808 Mar 10, 2026
a61dc15
Add floating bar redesign design document
syi0808 Mar 10, 2026
4f6998e
Update floating bar redesign with detailed implementation plan
syi0808 Mar 10, 2026
8db0a0c
refactor: make WaypointGenerator lead times configurable via settings
syi0808 Mar 10, 2026
99df12f
refactor: make IntentClassifier accept configurable settings
syi0808 Mar 10, 2026
07ff237
feat: wire GenerationSettings into smart generation pipeline
syi0808 Mar 10, 2026
899c337
feat: add Advanced Generation Settings window with 5 collapsible sect…
syi0808 Mar 10, 2026
774cb96
feat: add menu bar item and toolbar button for Advanced Generation Se…
syi0808 Mar 10, 2026
bf419c3
feat: wire project-scope settings editing in Advanced Generation Sett…
syi0808 Mar 10, 2026
0cbc885
fix: address lint violations in generation settings
syi0808 Mar 10, 2026
c9e9fb4
fix: move smart generation pipeline off main thread to prevent UI freeze
syi0808 Mar 10, 2026
8c667ae
fix: prevent crash when zoom range min exceeds max in ShotSettings
syi0808 Mar 10, 2026
ece9773
fix: add safe range handling across entire smart generation pipeline
syi0808 Mar 10, 2026
f1fce6d
feat: add toolbar corner radius and whisper opacity design tokens
syi0808 Mar 10, 2026
964c426
feat: apply new visual style to CaptureToolbarPanel
syi0808 Mar 10, 2026
493285b
feat: position capture toolbar at bottom center of screen
syi0808 Mar 10, 2026
99d4ea1
feat: constrain floating toolbar drag to screen bounds
syi0808 Mar 10, 2026
238b3d1
feat: add restart and delete buttons to recording toolbar
syi0808 Mar 10, 2026
1ddd172
refactor: remove RecordingFloatingPanel, unify to CaptureToolbarPanel
syi0808 Mar 10, 2026
f2624e8
fix: unify floating bar UI/UX consistency
syi0808 Mar 10, 2026
30f9e9d
fix: unify all toolbar buttons to vertical icon-label layout
syi0808 Mar 10, 2026
bffe856
fix: force vertical icon-label layout for Mic and FrameRate menus
syi0808 Mar 10, 2026
9447bb1
fix: restore Mic and FrameRate menu click functionality
syi0808 Mar 10, 2026
a9c75ac
fix: restore Mic and FrameRate menu dropdowns with vertical layout
syi0808 Mar 10, 2026
73809bd
fix: use opaque hit target for Mic and FrameRate menu dropdowns
syi0808 Mar 10, 2026
1e1bb1f
fix: expand Mic and FrameRate menu hit area to full button box
syi0808 Mar 10, 2026
7338812
fix: replace SwiftUI Menu with NSMenu for Mic and FrameRate dropdowns
syi0808 Mar 10, 2026
5027fef
refactor: move continuousTransforms from Timeline to CameraSegment
syi0808 Mar 10, 2026
19e0ca5
fix: stop clearing continuousTransforms on segment edits
syi0808 Mar 10, 2026
3588468
refactor: update consumers to read segment-level continuousTransforms
syi0808 Mar 10, 2026
78ad32f
fix: harden isContinuous check and document single-segment assumption
syi0808 Mar 10, 2026
8d593ee
fix: rewrite cursor animation to use raw mouseDown/mouseUp events
syi0808 Mar 10, 2026
b5875e5
fix: finalize pending clicks before removing event monitors
syi0808 Mar 10, 2026
8fa2eb0
docs: add transparent background fallback design
syi0808 Mar 10, 2026
fb9fe45
docs: add transparent background fallback plan
syi0808 Mar 10, 2026
e2db5c6
docs: add smart generation startup center bias design
syi0808 Mar 10, 2026
053eaf9
docs: add smart generation startup center bias plan
syi0808 Mar 10, 2026
335d093
chore: ignore local worktrees
syi0808 Mar 10, 2026
ab79eab
fix: unify transparent fallback and test baseline
syi0808 Mar 10, 2026
0e006c8
feat: bias smart generation startup to center
syi0808 Mar 10, 2026
a261fc7
fix: make generation settings reset all scope-aware
syi0808 Mar 11, 2026
4d98c80
fix: stabilize cursor click feedback sizing
syi0808 Mar 11, 2026
837b986
docs: add segment-based smart generation design spec
syi0808 Mar 11, 2026
330af12
docs: add segment-based smart generation implementation plan
syi0808 Mar 11, 2026
2cf982e
feat: add GenerationMode enum to GenerationSettings
syi0808 Mar 11, 2026
4e95fb6
feat: add SegmentPlanner for segment-based smart generation
syi0808 Mar 11, 2026
0119f12
feat: add SegmentCameraGenerator for segment-based pipeline
syi0808 Mar 11, 2026
e73c6ae
feat: branch smart generation on mode selection
syi0808 Mar 11, 2026
99391e5
feat: add generation mode picker to generator panel
syi0808 Mar 11, 2026
f0519ad
docs: add spring target segments design spec
syi0808 Mar 11, 2026
d168f66
docs: add spring target segments implementation plan
syi0808 Mar 11, 2026
b550aa8
feat: emit per-click intent spans instead of merging into navigating
syi0808 Mar 11, 2026
efc053e
feat: replace duration-based scene merging with position-aware merging
syi0808 Mar 11, 2026
8d87a9c
feat: use spring interpolation and zero transition for segment camera
syi0808 Mar 11, 2026
96dd2bd
feat: add SegmentSpringSimulator for spring physics across segments
syi0808 Mar 11, 2026
67afb8f
feat: wire spring simulation into segment camera pipeline
syi0808 Mar 11, 2026
9506d00
fix: use easeInOut for segment fallback interpolation, spring physics…
syi0808 Mar 11, 2026
9e883b2
fix: adapt spring response to segment duration for smooth full-durati…
syi0808 Mar 11, 2026
02bc1e6
docs: add camera anticipation design spec
syi0808 Mar 11, 2026
711a8f8
docs: add camera anticipation implementation plan
syi0808 Mar 11, 2026
a77e746
docs: add camera segment kind design spec
syi0808 Mar 11, 2026
262ba63
docs: address spec review feedback for camera segment kind design
syi0808 Mar 11, 2026
37a0a35
feat: add camera anticipation for click, drag, scroll, switch actions
syi0808 Mar 11, 2026
ebc5bed
refactor: replace CameraSegment flat fields with CameraSegmentKind enum
syi0808 Mar 11, 2026
8f76e04
refactor: use switch on CameraSegmentKind in FrameEvaluator
syi0808 Mar 11, 2026
64d7161
refactor: update SegmentPlanner to emit .manual kind segments
syi0808 Mar 11, 2026
064070a
refactor: update SegmentSpringSimulator to use CameraSegmentKind
syi0808 Mar 11, 2026
0ea2834
refactor: update ContinuousCameraGenerator to emit .continuous kind
syi0808 Mar 11, 2026
5fefe1f
refactor: update MouseDataConverter to extract transforms via CameraS…
syi0808 Mar 11, 2026
f464e0d
refactor: update clipboard operations to use CameraSegmentKind
syi0808 Mar 11, 2026
3194542
refactor: update addTransformSegment to use .manual kind
syi0808 Mar 11, 2026
eae5b88
refactor: update inspector camera section for CameraSegmentKind
syi0808 Mar 11, 2026
92691e6
refactor: update segment binding fallback for CameraSegmentKind
syi0808 Mar 11, 2026
59fe863
fix: normalize center to screen midpoint at zoom 1.0
syi0808 Mar 11, 2026
c9cf1e0
refactor: update ProjectCreator default segment for CameraSegmentKind
syi0808 Mar 11, 2026
0a70808
refactor: update GeneratorPanelView preview segment for CameraSegment…
syi0808 Mar 11, 2026
4ef484e
refactor: update ContinuousCameraGeneratorTests for CameraSegmentKind
syi0808 Mar 11, 2026
d6fd906
fix: resolve CGFloat-to-Double type mismatch in test assertions
syi0808 Mar 11, 2026
a1c9b82
docs: add smart generation quality improvements design spec
syi0808 Mar 12, 2026
918badf
docs: address spec review feedback for smart generation improvements
syi0808 Mar 12, 2026
1f037f3
docs: add implementation plan for smart generation quality improvements
syi0808 Mar 12, 2026
0f49d6d
feat: add cursorSpeeds computation to SegmentCameraGenerator
syi0808 Mar 12, 2026
d30f864
feat: apply cursor speed factor to spring response in SegmentSpringSi…
syi0808 Mar 12, 2026
50259c9
feat: wire cursor speed computation into segment generation pipeline
syi0808 Mar 12, 2026
62e3fe8
feat: add zoom transition optimizer to eliminate unnecessary zoomOut …
syi0808 Mar 12, 2026
af4be9a
docs: add transition/hold segment split design spec
syi0808 Mar 12, 2026
d4d4c94
docs: address spec review feedback for transition/hold segment split
syi0808 Mar 12, 2026
f53a089
docs: add transition/hold segment split implementation plan
syi0808 Mar 12, 2026
198f053
feat: add cursorTravelTime to SegmentPlanner
syi0808 Mar 12, 2026
097a7dd
feat: split segments into transition + hold in SegmentPlanner
syi0808 Mar 12, 2026
e94768e
feat: wire mouseData into segment planning pipeline
syi0808 Mar 12, 2026
c287280
fix: resolve unused optional binding lint warning in SegmentPlanner
syi0808 Mar 12, 2026
223b2a8
fix: reset spring velocity for hold segments and prevent segment overlap
syi0808 Mar 12, 2026
a7a0b89
fix: dampen spring velocity at hold segments instead of zeroing
syi0808 Mar 12, 2026
b672eb9
fix: reduce hold segment velocity dampening to 30% retention
syi0808 Mar 12, 2026
59fdb5f
docs: add camera inspector and dead code cleanup design spec
syi0808 Mar 12, 2026
c458e46
docs: add camera inspector and dead code cleanup implementation plan
syi0808 Mar 13, 2026
645f342
refactor: remove dead interpolation field from CameraSegmentKind.manual
syi0808 Mar 13, 2026
f67842a
refactor: remove dead transitionToNext and SegmentTransition
syi0808 Mar 13, 2026
6eefe52
feat: add SpringSimulationCache for deferred spring simulation
syi0808 Mar 13, 2026
382f102
feat: wire SpringSimulationCache into render pipeline
syi0808 Mar 13, 2026
a20fd81
feat: keep camera segments as .manual, defer spring simulation to cache
syi0808 Mar 13, 2026
4fb7862
feat: add info label for continuous camera segments in inspector
syi0808 Mar 13, 2026
eb8b793
feat: add generation mode picker to advanced config
syi0808 Mar 13, 2026
23fc28b
feat: add copy transform from adjacent segment buttons in inspector
syi0808 Mar 13, 2026
eae48d2
feat: change add camera segment default duration to 2 seconds
syi0808 Mar 13, 2026
30f01ec
docs: add preset UX improvements design spec
syi0808 Mar 13, 2026
d562a08
docs: add preset UX improvements implementation plan
syi0808 Mar 13, 2026
19ab71d
feat: add Equatable conformance to RenderSettings
syi0808 Mar 13, 2026
880c019
feat: add sortOrder to RenderSettingsPreset with backward-compatible …
syi0808 Mar 13, 2026
5a8be7e
feat: add activePresetID, updatePreset, and reorderPresets to PresetM…
syi0808 Mar 13, 2026
22db0fd
feat: update preset picker chip row with active highlighting and gear…
syi0808 Mar 13, 2026
823fdef
feat: add preset management popover with rename, reorder, overwrite, …
syi0808 Mar 13, 2026
f445d5a
fix: use StateObject for PresetManager and add FocusState to inline r…
syi0808 Mar 13, 2026
0f4883b
fix: replace List with ScrollView in manage popover and use up/down b…
syi0808 Mar 13, 2026
c7e6d24
feat: improve save button label and add context menu to preset chips
syi0808 Mar 13, 2026
12862b8
feat: redesign preset chips with inline actions and border
syi0808 Mar 13, 2026
38a44b4
fix: move cursor scale to track-level property and fix shadow opacity…
syi0808 Mar 13, 2026
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
168 changes: 168 additions & 0 deletions .claude/skills/screenize-explorer/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
---
name: screenize-explorer
description: Explore and debug .screenize project packages. Lists projects, reads project.json, summarizes event streams, displays timeline segments, and shows recording statistics.
user-invocable: true
allowed-tools:
- Bash
- Read
- Glob
- Grep
- AskUserQuestion
---

<role>
You are a Screenize project data inspector. You help developers explore and debug .screenize package contents by reading JSON files and presenting structured summaries. You understand the Screenize data model including project metadata, event streams, timeline tracks, and render settings.
</role>

<context>
Screenize is a macOS screen recording app. Projects are stored as `.screenize` packages (macOS directory bundles that appear as single files in Finder).

### Package Structure

```
MyProject.screenize/
├── project.json # ScreenizeProject v5
└── recording/
├── recording.mp4 # Video file
├── metadata.json # PolyRecordingMetadata
├── mousemoves-0.json # [PolyMouseMoveEvent]
├── mouseclicks-0.json # [PolyMouseClickEvent]
├── keystrokes-0.json # [PolyKeystrokeEvent]
└── uistates-0.json # [PolyUIStateEvent]
```

### project.json Schema (v5)

Top-level fields:
- `id` (UUID), `version` (int), `name`, `createdAt`, `modifiedAt` (ISO 8601)
- `media`: `{ videoPath, mouseDataPath, pixelSize: {width, height}, frameRate, duration }`
- `captureMeta`: `{ displayID?, boundsPt: {x,y,width,height}, scaleFactor }`
- `timeline`: `{ tracks: [{type, data}], duration, trimStart, trimEnd? }`
- `renderSettings`: codec, quality, resolution, background, corners, shadow, padding, motionBlur
- `interop`: `{ sourceKind, eventBundleVersion, recordingMetadataPath, streams: {mouseMoves, mouseClicks, keystrokes, uiStates}, primaryVideoPath }`
- `frameAnalysisCache` (optional array), `frameAnalysisVersion`

### Timeline Track Types

Each track is wrapped as `{ type: "transform"|"cursor"|"keystroke", data: {...} }`:

**Camera track** (type: "transform"): segments with `startTime`, `endTime`, `startTransform: {zoom, center: {x, y}}`, `endTransform`, `interpolation`, `mode` ("manual"/"followCursor"), `cursorFollow`, `transitionToNext`

**Cursor track** (type: "cursor"): `useSmoothCursor`, segments with `startTime`, `endTime`, `style`, `visible`, `scale`, `clickFeedback`, `transitionToNext`

**Keystroke track** (type: "keystroke"): segments with `startTime`, `endTime`, `displayText`, `position`, `fadeInDuration`, `fadeOutDuration`

### Event Stream Formats

**metadata.json**: `{ formatVersion, recorderName, recorderVersion, createdAt, processTimeStartMs, processTimeEndMs, unixTimeStartMs, display: { widthPx, heightPx, scaleFactor } }`

**mousemoves-0.json**: Array of `{ type, processTimeMs, unixTimeMs, x, y, cursorId?, activeModifiers, button? }`. Coordinates: display-local pixels, top-left origin.

**mouseclicks-0.json**: Array of `{ type: "mouseDown"|"mouseUp", processTimeMs, unixTimeMs, x, y, button: "left"|"right", cursorId?, activeModifiers }`.

**keystrokes-0.json**: Array of `{ type: "keyDown"|"keyUp", processTimeMs, unixTimeMs, character?, isARepeat, activeModifiers }`.

**uistates-0.json**: Array of `{ processTimeMs, unixTimeMs, cursorX, cursorY, elementRole?, elementSubrole?, elementTitle?, elementAppName?, elementFrameX/Y/W/H?, elementIsClickable?, caretX/Y/W/H? }`.

### Computing Timeline Seconds

`timelineSec = (event.processTimeMs - metadata.processTimeStartMs) / 1000.0`
</context>

<workflow>
When invoked, follow these steps. All output must be in English.

## Step 1: Find Project

If the user provides a specific `.screenize` path as an argument, use it directly.

Otherwise, search for projects in these locations (in order):
1. `./projects/` relative to the current working directory
2. `~/Movies/Screenize/`

Use Glob to find `.screenize` packages:
```
pattern: projects/**/*.screenize
```
Comment on lines +79 to +86
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Second search path (~/Movies/Screenize/) is not covered by the provided Glob pattern.

Step 1 lists two locations to search (lines 79–81), but only one Glob pattern is given (line 85: projects/**/*.screenize). ~/Movies/Screenize/ is never matched, so a model following this skill will silently skip that location and the fallback will never trigger.

Add a second Glob call, or combine both patterns into the instructions:

📄 Suggested fix
 Use Glob to find `.screenize` packages:

pattern: projects/**/*.screenize

+
+If no results, also search the system default location:
+```
+pattern: ~/Movies/Screenize/**/*.screenize
+```
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 84-84: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/screenize-explorer/SKILL.md around lines 79 - 86, The
documented search lists two locations but the provided Glob pattern only covers
"projects/**/*.screenize" so the "~/Movies/Screenize/" path is never searched;
update the spec to include a second glob for that location or combine patterns
so both are matched — e.g., add a second pattern entry "pattern:
~/Movies/Screenize/**/*.screenize" or change the pattern list to include both
"projects/**/*.screenize" and "~/Movies/Screenize/**/*.screenize" so the
fallback location is actually scanned.


If multiple projects are found, list them with names and ask the user which one to inspect. If only one is found, use it automatically. If none are found, inform the user.

## Step 2: Package Overview

Read `project.json` from the package root. Present:

```
### Project: [name]
- **Version**: [version] | **ID**: [id]
- **Created**: [date] | **Modified**: [date]
- **Video**: [width]x[height] @ [fps] fps, [MM:SS duration]
- **Capture**: Display [id], [w]x[h] pt, scale [factor]x
- **Export**: [codec] / [quality] / [resolution]
- **Background**: [enabled/disabled]
- **Trim**: [start] - [end] (or "None")
```

## Step 3: Timeline Summary

For each track in the timeline:

### Camera Track ([N] segments)
Table with columns: `#`, `Time Range`, `Start Zoom`, `End Zoom`, `Center`, `Mode`, `Easing`

### Cursor Track ([N] segments, smooth: [yes/no])
Table with columns: `#`, `Time Range`, `Style`, `Visible`, `Scale`

### Keystroke Track ([N] segments)
Table with columns: `#`, `Time Range`, `Text`

## Step 4: Event Stream Statistics

Read `recording/metadata.json` first for processTimeStartMs.

For each event stream file that exists, read it (use Bash `wc -l` for very large files, or Read for moderate ones) and report:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

wc -l is an unreliable proxy for JSON array element count.

wc -l counts newlines, not array elements. A minified single-line JSON array (all events on one line) returns 1, while a pretty-printed file with multi-line objects returns a count far larger than the actual event count. Since line 163 directs the model to display only the count for large files, an inaccurate figure here would be directly surfaced to the user.

A more reliable approach is a lightweight Python one-liner, which also avoids the "wc -l for counting vs. Read for content" ambiguity in the constraints:

📄 Suggested fix
-For each event stream file that exists, read it (use Bash `wc -l` for very large files, or Read for moderate ones) and report:
+For each event stream file that exists, read it (use Read for moderate files; for very large files use Bash and a lightweight count: `python3 -c "import json,sys; print(len(json.load(open(sys.argv[1]))))" <path>`) and report:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
For each event stream file that exists, read it (use Bash `wc -l` for very large files, or Read for moderate ones) and report:
For each event stream file that exists, read it (use Read for moderate files; for very large files use Bash and a lightweight count: `python3 -c "import json,sys; print(len(json.load(open(sys.argv[1]))))" <path>`) and report:
🧰 Tools
🪛 LanguageTool

[style] ~122-~122: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...t exists, read it (use Bash wc -l for very large files, or Read for moderate ones) and r...

(EN_WEAK_ADJECTIVE)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/screenize-explorer/SKILL.md at line 122, Update the guidance
that currently tells readers to use Bash `wc -l` for large files in the sentence
starting "For each event stream file that exists, read it (use Bash `wc -l`..."
— replace that advice with a reliable approach: use a lightweight Python
one-liner that opens the file, parses the JSON array, and prints the array
length to get an accurate event count, and for truly massive files mention using
a streaming JSON iterator (e.g., ijson) to count elements without loading the
whole file; remove the ambiguous "wc -l vs Read" instruction so the doc
consistently recommends the Python method for correctness.


### Recording Metadata
- Recorder: [name] v[version]
- Display: [w]x[h] px @ [scale]x
- Duration: [computed] sec
- Created: [date]

### Mouse Moves
- Total: [count] events
- Time range: [first] - [last] sec
- Avg frequency: [count/duration] Hz

### Mouse Clicks
- Total: [count] ([downs] mouseDown, [ups] mouseUp)
- Left: [count] | Right: [count]

### Keystrokes
- Total: [count] ([downs] keyDown, [ups] keyUp)
- Characters: [first 20 unique non-nil characters]

### UI States
- Total: [count] samples
- Unique apps: [list]
- Unique roles: [list]

## Step 5: Deep Dive (Optional)

After showing the summary, ask the user if they want to:
1. View raw JSON of a specific file
2. Inspect events in a specific time range (e.g., "show clicks between 5.0-10.0 sec")
3. See detailed camera segment transitions with easing curves
4. List all UI element interactions in chronological order

Only proceed if the user requests one of these.
</workflow>

<constraints>
- All output in English.
- Format durations as MM:SS.mmm for precise values, MM:SS for summaries.
- Format coordinates to 3 decimal places.
- For large event files (>10000 events), show count only. For detail, show first 5 and last 5 with "..." between.
- Mark missing files as "[missing]" rather than erroring.
- Never modify any package files. This skill is read-only.
- Use the Read tool for JSON files, not cat via Bash.
- When reading JSON, use Bash `python3 -m json.tool` only if needed for formatting, otherwise Read directly.
</constraints>
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,7 @@ xcuserdata/
tools
release
private-docs
projects/

__pycache__
.worktrees/
145 changes: 145 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# AGENTS.md
Guidance for autonomous coding agents working in this repository.

## Repository Snapshot
- Project: **Screenize** (macOS screen recording and editing app)
- Language: **Swift**
- UI framework: **SwiftUI**
- Target platform: **macOS 13+**
- Build system: **Xcode project** (`Screenize.xcodeproj`)
- External dependency: **Sparkle** (via Swift Package Manager)

## Mandatory Agent Workflow
Follow this sequence for each meaningful work unit:
1. **START**: run the `work-context-finder` agent to check prior related work.
2. **WORK**: implement the task.
3. **FINISH**: execute `/log-work` using the `work-logger` skill.

Notes:
- This workflow is defined in `CLAUDE.md` and should be treated as repository policy.
- All generated logs/summaries/tags for vector DB workflows must be in English.

## Build, Lint, and Test Commands
Run all commands from repository root (`/Users/sung-yein/Workspace/screenize`).
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The repository root path is hardcoded to a user-specific directory. This should be generalized to be useful for any contributor. Using a placeholder like <repository-root> or simply stating "from the repository root" would be more appropriate.

Suggested change
Run all commands from repository root (`/Users/sung-yein/Workspace/screenize`).
Run all commands from the repository root.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hardcoded local path should be generic.

/Users/sung-yein/Workspace/screenize is a developer-specific absolute path. Agents running in different environments (CI, other developers, sandboxed) won't find this path.

📝 Suggested fix
-Run all commands from repository root (`/Users/sung-yein/Workspace/screenize`).
+Run all commands from the repository root.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Run all commands from repository root (`/Users/sung-yein/Workspace/screenize`).
Run all commands from the repository root.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` at line 23, Replace the developer-specific absolute path
`/Users/sung-yein/Workspace/screenize` in AGENTS.md with a generic
repository-root reference (e.g., "repository root", `$(pwd)`, or `$(git
rev-parse --show-toplevel)`) or a placeholder like `<repo-root>` so instructions
work across machines and CI; update the sentence "Run all commands from
repository root (`/Users/sung-yein/Workspace/screenize`)." to use the chosen
generic form.


### Build
```bash
xcodebuild -project Screenize.xcodeproj -scheme Screenize -configuration Debug build
```

### Lint
```bash
./scripts/lint.sh
```
Auto-fix lint violations where possible:
```bash
./scripts/lint.sh --fix
```

### Tests (Current Status + How To Run)
Current repository status:
- There is currently **no test target** configured in `Screenize.xcodeproj`.
- There are currently **no `*Tests*` files/directories** in the repo.
- Primary verification today is **successful build + lint**.

When tests are added, use these command patterns:

Run all tests for a scheme:
```bash
xcodebuild -project Screenize.xcodeproj -scheme Screenize -destination 'platform=macOS' test
```

Run a single test class:
```bash
xcodebuild -project Screenize.xcodeproj -scheme Screenize -destination 'platform=macOS' -only-testing:ScreenizeTests/MyFeatureTests test
```

Run a single test method:
```bash
xcodebuild -project Screenize.xcodeproj -scheme Screenize -destination 'platform=macOS' -only-testing:ScreenizeTests/MyFeatureTests/testExample test
```

Tip: if scheme/target names differ, inspect with:
```bash
xcodebuild -list -project Screenize.xcodeproj
```

### Permission Reset Helpers (Local Dev)
If screen/microphone permission state is broken:
```bash
tccutil reset ScreenCapture com.screenize.Screenize
tccutil reset Microphone com.screenize.Screenize
```

## Code Style and Conventions

### Language and Documentation
- Write **all code, comments, commit messages, and docs in English**.
- Keep comments focused on non-obvious intent or constraints.

### Imports
- Use explicit imports required by each file (avoid unnecessary imports).
- Keep import blocks clean and grouped at the file top.
- Prefer Apple frameworks first; avoid wildcard or indirect import patterns.

### Formatting and Lint Rules
This repo uses SwiftLint (`.swiftlint.yml`) with key limits:
- `line_length`: warning 140, error 200
- `file_length`: warning 600, error 1000
- `function_body_length`: warning 80, error 150
- `type_body_length`: warning 400, error 600
- `function_parameter_count`: warning 8, error 12
- `nesting`: type level 2, function level 5
- `force_cast`: warning only (required in some AXValue APIs)
- `force_try`: error

General formatting expectations:
- Use clear `// MARK:` sectioning in larger files.
- Keep methods small and focused.
- Respect existing spacing and brace style already used in nearby code.

### Types, Concurrency, and State
- Prefer strong, domain-specific types over untyped dictionaries.
- Use `@MainActor` for major app/state classes and UI-facing state.
- Use `Sendable` and safe queue/concurrency boundaries where relevant.
- Use async/await patterns consistently with existing code.
- Keep singleton usage aligned with existing architecture (`AppState.shared`, `ProjectManager.shared`).
Comment on lines +102 to +106
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Vary sentence starts for readability.

Three consecutive bullets start with “Use”, which reads monotonous. Consider rephrasing one or two.

🧰 Tools
🪛 LanguageTool

[style] ~105-~105: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...oncurrency boundaries where relevant. - Use async/await patterns consistently with ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 102 - 106, The three consecutive bullets that begin
with "Use" (the lines referencing `@MainActor`, Sendable, and async/await) read
monotonous; reword one or two to vary sentence starts while keeping their
meaning and references to `@MainActor`, Sendable, async/await, and singletons like
AppState.shared/ProjectManager.shared intact — e.g., start one with "Annotate
major app/state classes with `@MainActor`", another with "Prefer types that
conform to Sendable and enforce safe concurrency boundaries", or "Adopt
async/await consistently with existing code" so the list flows better without
changing technical content.


### Naming Conventions
- Use descriptive Swift names in standard Apple style.
- Use `Manager` / `Coordinator` suffixes for orchestration components.
- Keep keyframe/timeline terms consistent with domain model naming.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

AGENTS.md references terminology and features that this PR removes.

Three items are now stale given this PR's changes:

  • Line 111: mentions "keyframe/timeline terms" — the domain model is migrating to "segment"-based naming.
  • Line 123: instructs "Keep timeline keyframes sorted by time within tracks" — should reference segments.
  • Line 129: says "Respect existing migration path for legacy .fsproj handling" — but this PR removes .fsproj support entirely.

Since this file is being added in the same PR, it should reflect the post-migration state.

Also applies to: 123-123, 129-129

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` at line 111, Update AGENTS.md to reflect the post-migration naming
and removed legacy support: replace the phrase "keyframe/timeline terms" with
"segment-based naming" (or "segments"), change "Keep timeline keyframes sorted
by time within tracks" to "Keep segments sorted by start time within tracks" (or
equivalent segment-sorting guidance), and remove or replace "Respect existing
migration path for legacy `.fsproj` handling" with a note that `.fsproj` support
has been removed and no migration path is provided; ensure the three phrases
mentioned are edited to use "segment" terminology and the `.fsproj` sentence is
deleted or rewritten accordingly.

- Use imperative, behavior-first function names for actions.

### Error Handling and Logging
- Prefer typed error propagation (`throw`) when callers can act on failures.
- In UI/state layers, convert errors to user-visible messages when appropriate.
- Avoid silent failure unless intentionally best-effort.
- Keep logs concise and contextual; avoid noisy debug output in stable paths.

### Architecture-Specific Rules
- Internal coordinate standard is **NormalizedPoint** (`0...1`, bottom-left origin).
- Convert coordinate spaces only at API boundaries using `CoordinateConverter`.
- Keep timeline keyframes sorted by time within tracks.
- Preserve three-phase flow: recording -> editor -> export.

### File and Project System Expectations
- Project package format is `.screenize` with `project.json` and `recording/` media.
- Persist relative media paths in project JSON; resolve absolute URLs at load boundaries.

## Git and Change Hygiene for Agents
- Do not revert unrelated local changes in a dirty worktree.
- Keep edits scoped to the requested task.
- Prefer small, reviewable diffs.
- Use imperative commit messages when committing (if requested).

## Cursor / Copilot Rule Files
Checked paths:
- `.cursor/rules/`
- `.cursorrules`
- `.github/copilot-instructions.md`

Current status:
- No Cursor rules or Copilot instruction files were found in this repository.

If these files are added later, update this document to mirror any required agent constraints.
60 changes: 59 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,65 @@

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Core Principles

- **Simplicity First**: Make every change as simple as possible. Impact minimal code.
- **No Laziness**: Find root causes. No temporary fixes. Senior developer standards.
- **Minimal Impact**: Changes should only touch what's necessary. Avoid introducing bugs.

## Workflow Orchestration

### Plan Node Default

- Enter plan mode for ANY non-trivial task (3+ steps or architectural decisions).
- If something goes sideways, STOP and re-plan immediately — don't keep pushing.
- Use plan mode for verification steps, not just building.
- Write detailed specs upfront to reduce ambiguity.

### Subagent Strategy

- Use subagents liberally to keep main context window clean.
- Offload research, exploration, and parallel analysis to subagents.
- For complex problems, throw more compute at it via subagents.
- One task per subagent for focused execution.

### Self-Improvement Loop

- After ANY correction from the user: update `tasks/lessons.md` with the pattern.
- Write rules for yourself that prevent the same mistake.
- Ruthlessly iterate on these lessons until mistake rate drops.
- Review lessons at session start for relevant project.

### Verification Before Done

- Never mark a task complete without proving it works.
- Diff behavior between main and your changes when relevant.
- Ask yourself: "Would a staff engineer approve this?"
- Run build, check logs, demonstrate correctness.

### Demand Elegance (Balanced)

- For non-trivial changes: pause and ask "is there a more elegant way?"
- If a fix feels hacky: "Knowing everything I know now, implement the elegant solution."
- Skip this for simple, obvious fixes — don't over-engineer.
- Challenge your own work before presenting it.

### Autonomous Bug Fixing

- When given a bug report: just fix it. Don't ask for hand-holding.
- Point at logs, errors, failing tests — then resolve them.
- Zero context switching required from the user.
- Go fix failing CI tests without being told how.

## Task Management

1. **Plan First**: Write plan to `tasks/todo.md` with checkable items.
2. **Verify Plan**: Check in before starting implementation.
3. **Track Progress**: Mark items complete as you go.
4. **Explain Changes**: High-level summary at each step.
5. **Document Results**: Add review section to `tasks/todo.md`.
6. **Capture Lessons**: Update `tasks/lessons.md` after corrections.

## Language

All comments, code, commit messages, and documentation must be written in English. Do not use any other language.
Expand Down Expand Up @@ -111,7 +170,6 @@ Screenize is a macOS screen recording application that captures screen/window co
- `PackageManager` - Singleton managing `.screenize` package CRUD (create, save, load, path resolution)
- `ProjectManager` - Orchestrates project lifecycle, recent projects, delegates to PackageManager
- `ProjectCreator` - Factory creating projects from recordings or imported videos (accepts `PackageInfo`)
- `LegacyProjectMigrator` - Auto-migrates old `.fsproj` projects to `.screenize` format (remove in next minor version)
- `RenderSettings` - Export codec, quality, resolution settings

**`.screenize` package structure:**
Expand Down
Loading