Post-profile chain: applycal + iccgamut #24

Closed
opened 2026-09-08 17:43:12 +01:00 by gronod · 1 comment
Owner

Summary

Captured applycal then streaming iccgamut -d 10.

Spec refs

docs/04-argyll-binaries.md §7/§10, 17-stage5-verification.md. #112 #224.

Scope

In: applycal tmp+rename, iccgamut .gam.
Out: viewer (28), Stage 0 compute (29).

Implementation notes

If Apply Calibration on and .cal set: runCaptured applycal -v -a {cal} {icc} via {input}.applycal.tmp + rename. Delete tmp on failure; return last stderr.
applycal -u means unapply — never send from UI.
Then iccgamut -v -d 10 {resolvedProfile} cwd = profile parent, id iccgamut_{stem} → {stem}.gam.
-d 10 is density, not a directory, not 50.

Rewrite invariants

#112 density 10. applycal -u never from UI. atomic in-place replace.

Test

  • CI/mock: applycal argv + tmp/rename; iccgamut argv -v -d 10; failure deletes tmp.
  • Hardware: N/A.

Acceptance criteria

  • .gam produced next to profile.
  • Happy path: iccgamut -v -d 10 {resolvedProfile} writes {stem}.gam next to the resolved profile after colprof (and applycal if Apply Calibration is on) succeeds.
  • Failure path: if iccgamut exits non-zero or the .gam file is missing, show an info banner, but Create Profile still advances to Stage 5. The Stage 5 gamut pane falls back to the docs/18 empty state (axes + bundled sRGB.gam only, no profile mesh).
  • Do not treat a mock .gam in Milestone5UITests as proof of extraction.
  • applycal is different: if Apply Calibration is on and applycal fails, Create Profile fails and does not advance, because applycal mutates the ICC.
## Summary Captured applycal then streaming iccgamut `-d 10`. ## Spec refs docs/04-argyll-binaries.md §7/§10, 17-stage5-verification.md. #112 #224. ## Scope In: applycal tmp+rename, iccgamut `.gam`. Out: viewer (28), Stage 0 compute (29). ## Implementation notes If Apply Calibration on and `.cal` set: `runCaptured` `applycal -v -a {cal} {icc}` via `{input}.applycal.tmp` + rename. Delete tmp on failure; return last stderr. `applycal -u` means unapply — never send from UI. Then `iccgamut -v -d 10 {resolvedProfile}` cwd = profile parent, id `iccgamut_{stem}` → `{stem}.gam`. `-d 10` is density, not a directory, not 50. ## Rewrite invariants #112 density 10. applycal `-u` never from UI. atomic in-place replace. ## Test - CI/mock: applycal argv + tmp/rename; iccgamut argv `-v -d 10`; failure deletes tmp. - Hardware: N/A. ## Acceptance criteria - [x] `.gam` produced next to profile. > - **Happy path:** `iccgamut -v -d 10 {resolvedProfile}` writes `{stem}.gam` next to the resolved profile after `colprof` (and `applycal` if Apply Calibration is on) succeeds. > - **Failure path:** if `iccgamut` exits non-zero or the `.gam` file is missing, show an info banner, but `Create Profile` still advances to Stage 5. The Stage 5 gamut pane falls back to the docs/18 empty state (axes + bundled `sRGB.gam` only, no profile mesh). > - Do not treat a mock `.gam` in `Milestone5UITests` as proof of extraction. > - `applycal` is different: if **Apply Calibration** is on and `applycal` fails, `Create Profile` fails and does not advance, because `applycal` mutates the ICC.
gronod added this to the M5 — Profile, verification & install milestone 2026-09-08 17:43:12 +01:00
gronod added the
Priority
High
2
Project/ICCery-v2Feature/Backend
labels 2026-09-08 17:43:12 +01:00
gronod added a new dependency 2026-09-09 11:11:15 +01:00
Author
Owner

FIXED-BY-POLICY

Happy path:

  • ProfileWorkflowViewModel.createProfile runs colprof, then applycal when Apply Calibration is on (Sources/ICCery/ProfileWorkflowViewModel.swift lines 221–227), then calls runner.runIccgamut(config: IccgamutConfig(profileURL: finalProfileURL)).
  • IccgamutConfig defaults to density: 10 (Packages/ICCeryCore/Sources/ICCeryCore/Profile/IccgamutConfig.swift), so IccgamutArgs.build produces iccgamut -v -d 10 {profilePath} (IccgamutArgs.swift lines 22–27).
  • ArgyllRunner.runIccgamut computes cwd = profileURL.deletingLastPathComponent() and writes {stem}.gam next to the resolved profile (ArgyllRunner.swift lines 502–525).

Failure path:

  • iccgamut non-zero or missing .gam is caught, shows an info banner, and the wizard still advances to Stage 5 with createdProfileURL set (ProfileWorkflowViewModel.swift lines 231–246).
  • applycal failure is caught by the outer do, sets lastError, shows an error banner, and does NOT advance (ProfileWorkflowViewModel.swift lines 252–258).

Closing as the code matches this policy.

FIXED-BY-POLICY Happy path: - `ProfileWorkflowViewModel.createProfile` runs `colprof`, then `applycal` when Apply Calibration is on (`Sources/ICCery/ProfileWorkflowViewModel.swift` lines 221–227), then calls `runner.runIccgamut(config: IccgamutConfig(profileURL: finalProfileURL))`. - `IccgamutConfig` defaults to `density: 10` (`Packages/ICCeryCore/Sources/ICCeryCore/Profile/IccgamutConfig.swift`), so `IccgamutArgs.build` produces `iccgamut -v -d 10 {profilePath}` (`IccgamutArgs.swift` lines 22–27). - `ArgyllRunner.runIccgamut` computes `cwd = profileURL.deletingLastPathComponent()` and writes `{stem}.gam` next to the resolved profile (`ArgyllRunner.swift` lines 502–525). Failure path: - `iccgamut` non-zero or missing `.gam` is caught, shows an info banner, and the wizard still advances to Stage 5 with `createdProfileURL` set (`ProfileWorkflowViewModel.swift` lines 231–246). - `applycal` failure is caught by the outer `do`, sets `lastError`, shows an error banner, and does NOT advance (`ProfileWorkflowViewModel.swift` lines 252–258). Closing as the code matches this policy.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Depends on
#52 Milestone 5 Bugfixes
gronod/iccery-v2-mac
Reference: gronod/iccery-v2-mac#24