Skip to content
Merged
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: 7 additions & 1 deletion .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Keep these four files consistent when architecture or agent guidance changes.

## Project layout
- Main app: `Source/Marker Data/Marker Data/`
- Workflow Extension: `Source/Marker Data/Workflow Extension/` (`WorkflowExtensionView.swift` — Extract + Roles tabs)
- Workflow Extension: `Source/Marker Data/Workflow Extension/` (`WorkflowExtensionView.swift` — Extract + Roles tabs; two Compile Sources rows including unused main-app membership — do not delete). `WorkflowExtensionViewController.swift` is appex-only.
- 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`
Expand Down Expand Up @@ -46,6 +46,8 @@ Keep these four files consistent when architecture or agent guidance changes.
- **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 (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).
- **FCPXML UTTypes:** public `UTType.fcpxml` / `.fcpxmld` (`UTTypeExtension`; private `finalCutProType` = `UTType(identifier) ?? UTType(importedAs:identifier, conformingTo:)`). First Extract layout evaluates these types — never `!`. Keep `UTImportedTypeDeclarations` in `Marker-Data-Info.plist`. Do not split the Share Destination **Asset Description File** document type.
- **File menu:** `FileCommands` replaces `.newItem` (Open Pagemaker ⌘P, Install Share Destination, Show/Clean Cache ⌘K). Do not empty `.newItem` in `Marker_DataApp` and do not add a second Close. Extract **Choose File** stays on `ExtractView` (`FilePicker`, ⌘O).

## Pitfalls to avoid
- Do not remove or rename persisted settings keys without a migration.
Expand All @@ -61,10 +63,14 @@ Keep these four files consistent when architecture or agent guidance changes.
- 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.
- Do not force-unwrap `UTType("com.apple.finalcutpro.xml")` / `.xmld` — resolve with `UTType(identifier) ?? UTType(importedAs:identifier, conformingTo:)` and keep `UTImportedTypeDeclarations` in `Marker-Data-Info.plist`. First Extract layout evaluates these types; FCP may be absent (App Preview). Do not split the Share Destination **Asset Description File** document type.
- File menu custom items replace `.newItem` so system Close stays last — do not empty `.newItem` and do not add a second Close.

## Definition of done for code changes
- 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`).
- FCPXML `UTType`s still use `importedAs` fallback (no `!`); Info.plist still has `UTImportedTypeDeclarations`; Share Destination **Asset Description File** type is unchanged.
- File menu still replaces `.newItem` with app actions; system Close stays last (no second Close; do not empty `.newItem`).
- 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 **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.
Expand Down
25 changes: 20 additions & 5 deletions AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [New export fields / overlays](#new-export-fields--overlays)
- [New database platform](#new-database-platform)
- [FCP integrations](#fcp-integrations)
- [File menu](#file-menu)
- [Drop overlay / shared Workflow Extension UI](#drop-overlay--shared-workflow-extension-ui)
- [App icon / dialogs](#app-icon--dialogs)
- [Uninstaller cleanup paths](#uninstaller-cleanup-paths)
Expand Down Expand Up @@ -58,16 +59,19 @@ For deeper module/data-flow detail, see **`ARCHITECTURE.md`**. For hard always/n

| Concern | File |
|---------|------|
| `@main` app | `Source/Marker Data/Marker Data/Marker_DataApp.swift` — constructs `SettingsContainer`, `DatabaseManager`, `ExtractionModel`, `QueueModel`; menu commands; Failed Tasks + Pagemaker windows |
| `@main` app | `Source/Marker Data/Marker Data/Marker_DataApp.swift` — constructs `SettingsContainer`, `DatabaseManager`, `ExtractionModel`, `QueueModel`; menu commands (`FileCommands` replaces `.newItem`); Failed Tasks + Pagemaker windows |
| AppKit / Sparkle delegate | `Source/Marker Data/Marker Data/ApplicationDelegate.swift` |
| Sidebar navigation | `Source/Marker Data/Marker Data/Views/Main/ContentView.swift` (`MainViews` enum) |
| Extract UI | `Source/Marker Data/Marker Data/Views/Main/ExtractView.swift` |
| Extraction orchestration | `Source/Marker Data/Marker Data/Models/Extract/Extraction Model/ExtractionModel.swift` |
| External handoffs (open / Workflow Extension) | `.../ExtractionModel_EventHandlers.swift` |
| FCPXML intake (files / pasteboard / textClipping) | `Utilities/Other/FCPXMLIntake.swift`, `TextClippingReader.swift` |
| Extract drop modifier | `Views/Components/FCPXMLDropModifier.swift` (`.fcpxmlDropDestination`) |
| FCPXML UTTypes | `Utilities/Extensions/UTTypeExtension.swift` — public `UTType.fcpxml` / `.fcpxmld` via private `finalCutProType` (`UTType(identifier) ?? UTType(importedAs:identifier, conformingTo:)` — never `!`); `Source/Marker Data/Marker-Data-Info.plist` `UTImportedTypeDeclarations` + Asset Description File `LSItemContentTypes` |
| File menu | `Views/Menu Bar Commands/FileCommands.swift` — replaces `.newItem` (Open Pagemaker ⌘P, Install Share Destination, Show/Clean Cache ⌘K); system Close stays last |
| Info.plist | `Source/Marker Data/Marker-Data-Info.plist` — Sparkle, Share Destination document types (**Asset Description File** name is a contract), imported FCPXML UTIs |
| Drop overlay (Extract / Roles / Queue + WE) | `Views/Components/DropTargetOverlay.swift` (also Workflow Extension Compile Sources) |
| Workflow Extension UI | `Source/Marker Data/Workflow Extension/WorkflowExtensionView.swift` |
| Workflow Extension UI | `Source/Marker Data/Workflow Extension/WorkflowExtensionView.swift` — Extract + Roles tabs; **two** Compile Sources rows (main app + appex — do not delete the main-app membership). `WorkflowExtensionViewController.swift` is appex-only. |
| Color helpers (`markerAccent`, `heroGradient`) | `Utilities/Extensions/ColorExtension.swift` |
| Queue UI | `Views/Detail Views/QueueView.swift` |
| Queue scan/upload | `Models/Queue/QueueModel.swift` |
Expand Down Expand Up @@ -225,14 +229,21 @@ Also: getter for `colorSwatchSettings` **forces `enableSwatch = false` when extr
- Note: existing property spelling is `plaform` on `DatabaseProfileModel` — keep consistent when extending.

### FCP integrations
- Share Destination: `Resources/OSAScriptingDefinition.sdef` + Obj‑C under `FCP Share Destination/Objective-C Code/` + Swift `OpenEventHandler`.
- Workflow Extension: DistributedNotificationCenter names + fixed Movies-cache FCPXML path; roles via `preferences.json`.
- Share Destination: `Resources/OSAScriptingDefinition.sdef` + Obj‑C under `FCP Share Destination/Objective-C Code/` + Swift `OpenEventHandler`. Keep the **Asset Description File** document type name (`DocumentController` matches it).
- Workflow Extension: DistributedNotificationCenter names + fixed Movies-cache FCPXML path; roles via `preferences.json`. Appex `Info.plist` `ProExtensionAttributes` are 700×550 (FCP host min); SwiftUI frame is 600×400. `WorkflowExtensionView.swift` has two Compile Sources rows.
- Extract panel intake: `FCPXMLIntake` / `FCPXMLDropModifier` — keep Dock Open With (`OpenEventHandler`) and Share Destination paths distinct.
- FCPXML UTTypes: public `UTType.fcpxml` / `.fcpxmld` (private `finalCutProType`, never `!`) + `Marker-Data-Info.plist` `UTImportedTypeDeclarations` / Asset Description File `LSItemContentTypes`.

### File menu
- Custom File items live in `FileCommands` as `CommandGroup(replacing: .newItem)`.
- Do **not** also empty `.newItem` in `Marker_DataApp` (that puts system Close first). Emptying `.toolbar` in `Marker_DataApp` is unrelated (removes the default View-menu toolbar group).
- Do **not** add a Close item — system Close / Close All remain last.
- Current items (in order): **Open Pagemaker** (⌘P) → **Install FCP Share Destination…** → **Show Cache** / **Clean Cache** (⌘K). Extract **Choose File** still uses ⌘O on the Extract panel (`FilePicker`), not the File menu. Extract completion also shows **Open Pagemaker** when the profile is extract-only Notion or Airtable.

### Drop overlay / shared Workflow Extension UI
- Update copy in **`GUARDRAILS.md`** (Drop overlay copy table) when changing messages.
- Workflow Extension **Extract** (`WorkflowExtensionView`) and **Roles** (shared `RolesSettingsView`) both show overlays.
- Shared types must stay in **both** targets’ Compile Sources (two `PBXBuildFile` rows, one `PBXFileReference`). Minimum shared UI: `DropTargetOverlay`, `ColorExtension`, `DialogIcon.swift`, `HelpButton`, `OverlayHelpButton`. Roles/settings files listed in **ARCHITECTURE.md**. Shared chrome uses `Color.markerAccent`.
- Shared types must stay in **both** targets’ Compile Sources (two `PBXBuildFile` rows, one `PBXFileReference`). Minimum shared UI: `DropTargetOverlay`, `ColorExtension`, `DialogIcon.swift`, `HelpButton`, `OverlayHelpButton`. `WorkflowExtensionView.swift` is also dual-membership (appex UI; do not delete the main-app Compile Sources row). `WorkflowExtensionViewController.swift` is appex-only. Roles/settings files listed in **ARCHITECTURE.md**. Shared chrome uses `Color.markerAccent`.

### App icon / dialogs
- Icon Composer **`Marker-Data.icon`** (`ASSETCATALOG_COMPILER_APPICON_NAME` = Marker-Data) lives beside the catalog — **not** inside `Assets.xcassets`. Main-app `AppIcon.appiconset` is an empty placeholder. Never flatten the layer PNG into `AppIconSingle` (imageset removed).
Expand Down Expand Up @@ -304,11 +315,15 @@ Exact overlay strings and always/never rules: **`GUARDRAILS.md`**.
- **Shared `pbxproj` rows:** do not remove a second `DialogIcon.swift in Sources` (or other shared files) — the file is compiled into two targets.
- **Persisted typos:** do not rename JSON key `plaform` without a migration.
- **WE cache folder:** the extension does not `mkdir` Movies cache; a first-time drop can fail if the main app has never created `~/Movies/Marker Data Cache/`.
- **FCPXML `UTType` force-unwrap:** `UTType("com.apple.finalcutpro.xml")!` traps on first Extract layout when Final Cut Pro is not installed (App Preview / machines without FCP). Resolve with `UTType(identifier) ?? UTType(importedAs:identifier, conformingTo:)` and keep `UTImportedTypeDeclarations` in `Marker-Data-Info.plist`. Do not split the Share Destination **Asset Description File** document type.
- **File menu Close last:** custom File items replace `.newItem` (`FileCommands`). Do not empty `.newItem` (that puts system Close first) and do not add a second Close.

## Definition of done for most changes
- App builds **unsigned** Debug **and** Release for **arm64** (`CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO`; Workflow Extension still embeds).
- Settings still load and migrate cleanly (`preferences.json` + `Configurations/*.json`).
- Extraction works for `.fcpxml` and `.fcpxmld`, including FCP pasteboard / textClipping intake via `FCPXMLIntake`.
- FCPXML `UTType`s still use `importedAs` fallback (no `!`); Info.plist still has `UTImportedTypeDeclarations`; Share Destination **Asset Description File** type is unchanged.
- File menu still replaces `.newItem` with app actions; system Close stays last (no second Close; do not empty `.newItem`).
- Drop overlays still work on main-app Extract / Roles / Queue **and** Workflow Extension Extract + Roles.
- Queue scan/upload still works for folders containing `extract_info.json`, including **moved/copied** folders (`manifestURL`).
- Skipped / no-media swatch finishes as **“Extract done”** (not **“Analysing swatch done”**).
Expand Down
Loading