Skip to content
Merged

Dev #152

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
20 changes: 11 additions & 9 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Keep these four files consistent when architecture or agent guidance changes.
- Uninstaller: `Source/Marker Data/Marker Data Uninstaller/` (target **Uninstall Marker Data**; product `Uninstall Marker Data.app`; bundle ID `co.theacharya.MarkerData.Uninstaller`)
- FCP Share Destination (Swift + Obj‑C): `Source/Marker Data/Marker Data/FCP Share Destination/`
- Bundled binaries (do not modify internals): `Source/Marker Data/Marker Data/Resources/airlift`, `csv2notion_neo`
- Build: open `Source/Marker Data/Marker Data.xcodeproj`, scheme **Marker Data**, **Apple Silicon** (`arm64`) only
- CI: `macos-26` runners with **Xcode 26.6.0**; Workflow Extensions SDK from `SDK/Workflow_Extensions_1.0.3.dmg`
- Build: open `Source/Marker Data/Marker Data.xcodeproj`, scheme **Marker Data**, **Apple Silicon** (`arm64`) only. After code or agent-doc changes, unsigned Debug **and** Release: `CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO`, `EXCLUDED_ARCHS=x86_64`.
- CI: `macos-26` runners with **Xcode 26.6.0**; Workflow Extensions SDK from `SDK/Workflow_Extensions_1.0.3.dmg` (ignore unused `1.0.2` DMG in that folder)

## Swift / SwiftUI conventions
- Format Swift with SwiftFormat (see `CONTRIBUTING.md`).
Expand All @@ -30,7 +30,8 @@ Keep these four files consistent when architecture or agent guidance changes.
- On launch, `SettingsVersioningManager.updateAll()` migrates JSON **before** decode — dict-based `upgradeVersion(...)`, one step per version increment.
- UI binds via `@EnvironmentObject SettingsContainer` and `$settings.store.<property>`.
- Export pipeline reads settings through `SettingsStore.markersExtractorSettings(fcpxmlFileUrl:)` → `MarkersExtractor.Settings` — wire new export-related fields there. Roles are reloaded from disk inside that method.
- `RolesManager` reads/writes `preferences.json` directly (Workflow Extension sync via DistributedNotification `.rolesChanged`) — keep `roles` compatible.
- `RolesManager` reads/writes `preferences.json` directly (Workflow Extension sync via DistributedNotification `.rolesChanged`) — keep `roles` compatible. The appex compiles `SettingsStore.swift` and does **not** run `SettingsVersioningManager`.
- Do not rename persisted key `plaform` without a migration.
- **Any new/changed/renamed persisted `SettingsStore` property:**
1. Bump `SettingsStore.version`
2. Add migration `case` for the previous version
Expand All @@ -40,30 +41,31 @@ Keep these four files consistent when architecture or agent guidance changes.

## Key runtime flows (see ARCHITECTURE.md for detail)
- **Extract intake:** `FCPXMLIntake` resolves `.fcpxml` / `.fcpxmld`, Finder `.textClipping`, and Final Cut Pro pasteboard → temp file under `~/Movies/Marker Data Cache/` → `ExtractionModel.receiveFiles` / `receiveItemProviders`
- **Extract:** `ExtractionModel` → MarkersExtractor → optional `ColorPaletteRenderer.render(...) -> Bool` (`await applyTaskAppearance` only after image checks inside renderer; `false` → `markProcessAsFinished` / “Extract done”; `true` → `markAllProcessesFinished`; never `reset()` before swatch) → optional `DatabaseUploader`
- **Extract:** `ExtractionModel` → MarkersExtractor → optional `ColorPaletteRenderer.render(...) -> Bool` (`await applyTaskAppearance` only after image checks inside renderer; `false` → `markProcessAsFinished` / “Extract done”; `true` → `markAllProcessesFinished` because `ImageRenderService` replaces extract URLs with image URLs; never `reset()` before swatch) → optional `DatabaseUploader`
- **Drop overlays:** shared `DropTargetOverlay` on main-app Extract / Roles / Queue **and** Workflow Extension Extract + Roles — exact copy in **GUARDRAILS.md**; border uses `Color.markerAccent` (not host `accentColor`)
- **Queue:** scans for `extract_info.json` (Notion/Airtable + JSON manifest only) → upload via `QueueInstance.manifestURL` (local JSON beside folder preferred) → parallel re-upload; folder drop clears queue and disables auto-scan
- **Workflow Extension:** Extract tab drops `.fcpxml` → Movies-cache handoff → open `/Applications/Marker Data.app` → DistributedNotification `.workflowExtensionFileReceived`; both Extract and Roles show `DropTargetOverlay` (`WorkflowExtensionView` + shared `RolesSettingsView`). Extension Compile Sources must include `DropTargetOverlay` + `ColorExtension` (+ shared Roles sources)
- **Share Destination:** `OSAScriptingDefinition.sdef` + Obj‑C `MakeCommand` → Movies cache → local `FCPShareStart` → Apple Event open → `.openFile`
- **Workflow Extension:** Extract tab drops `.fcpxml` → Movies-cache handoff (does **not** mkdir the cache folder) → open `/Applications/Marker Data.app` → DistributedNotification `.workflowExtensionFileReceived`; both Extract and Roles show `DropTargetOverlay`. Shared sources have **two** `pbxproj` Compile Sources rows (one file, two targets) — never “dedupe”. Membership list: **ARCHITECTURE.md → Workflow Extension target**. Header uses `MarkerDataAppIcon.image()` at 100×100 from the **containing** `Marker Data.app` — not the appex `AppIcon.appiconset`. TabView keeps `.padding(.bottom, 40)` so the drop zone stays above the overlaid help “?”.
- **Share Destination:** `OSAScriptingDefinition.sdef` + Obj‑C `MakeCommand` (cache `<name>/` then location `…/<name>/<name>`) → local `FCPShareStart` → Apple Event open → `.openFile`. `OpenEventHandler.setupHandler()` on init, `.FCPShareStart`, and `Marker_DataApp` `.task` (main queue).

## Pitfalls to avoid
- Do not remove or rename persisted settings keys without a migration.
- Do not assume behavior of `airlift` / `csv2notion_neo` beyond CLI usage in `DatabaseUploader` (and Dropbox setup in `DropboxSetupModel`).
- Do not break Share Destination scripting (`Resources/OSAScriptingDefinition.sdef` + Obj‑C) or Workflow Extension disk/DNC contracts.
- The app warns if not run from `/Applications`; do not remove that check (extension opens that path).
- SwiftUI `.alert` icons: Dock uses Icon Composer (`Marker-Data.icon`), which often yields a blank document glyph. After every `.alert`, chain `.appDialogIcon()` (`Views/Extensions/DialogIcon.swift` → PNG `AppIconSingle`).
- SwiftUI `.alert` / `.confirmationDialog` icons: chain `.appDialogIcon()` after every dialog. `MarkerDataAppIcon` is `@MainActor` (`DialogIcon.swift`). Main-app Dock / About / alerts use Icon Composer `Marker-Data.icon` (`ASSETCATALOG_COMPILER_APPICON_NAME` = Marker-Data). Workflow Extension **header** loads the icon from the containing `Marker Data.app` (walk `appex` → `PlugIns` → `Contents` → `.app`); the appex’s `applicationIconImage` is its own `AppIcon.appiconset` (or Final Cut Pro). Do not flatten the layer PNG into `AppIconSingle`. Do not replace the Workflow Extension bundle/plugin `AppIcon.appiconset`. Uninstaller uses `applicationIconImage`.
- Database models use property name `plaform` — keep consistent unless intentionally migrating.
- If adding new on-disk paths the app uses, update `MarkerDataUninstaller` cleanup paths too.
- Do not upload Queue jobs using only absolute `ExtractInfo.jsonURL` when a same-named JSON exists in the dropped/scanned folder — use `manifestURL`.
- Do not call `ProgressViewModel.reset()` when transitioning extract → swatch. Retitle only via `await applyTaskAppearance` inside `ColorPaletteRenderer` after images exist; skipped swatch must stay “Extract done”.
- `applyTaskAppearance` is `@MainActor` — always `await` it from `ColorPaletteRenderer`.
- FCP timeline drops onto the Dock icon are often pasteboard-only; Extract panel drop is the supported timeline path.
- Do not use `Color.accentColor` / `.accent` for shared chrome hosted in Final Cut Pro — use `Color.markerAccent`.
- Do not delete a second `DialogIcon.swift in Sources` (or other shared files) from `project.pbxproj` — that is two-target membership, not a duplicate file.

## Definition of done for code changes
- App builds (Debug and Release) for arm64 (Workflow Extension still embeds).
- App builds **unsigned** Debug and Release for arm64 (`CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO`; Workflow Extension still embeds).
- Settings load and migrate; extraction works for `.fcpxml`/`.fcpxmld` (incl. FCP pasteboard / textClipping via `FCPXMLIntake`).
- Drop overlays still work on main-app Extract / Roles / Queue **and** Workflow Extension Extract + Roles; queue still finds/uploads `extract_info.json` folders via `manifestURL`.
- Skipped / no-media swatch finishes as “Extract done” (not “Analysing swatch done”).
- New alerts use `.appDialogIcon()`; settings changes include version + migration + wiring as required above.
- New alerts **and** confirmation dialogs use `.appDialogIcon()`; Workflow Extension header still shows the main-app Icon Composer icon (not the appex `AppIcon.appiconset`); settings changes include version + migration + wiring as required above.
- Update `AGENT.md` / `ARCHITECTURE.md` / `GUARDRAILS.md` / `.cursorrules` when behavior changes.
Loading