Skip to content

feat(macos): Ulk.app v0.2 — XcodeGen + typed JSON parsing + first functional toggle#147

Merged
izo merged 4 commits intomainfrom
claude/macos-ulk-v0.2-xcode-and-json
May 6, 2026
Merged

feat(macos): Ulk.app v0.2 — XcodeGen + typed JSON parsing + first functional toggle#147
izo merged 4 commits intomainfrom
claude/macos-ulk-v0.2-xcode-and-json

Conversation

@izo
Copy link
Copy Markdown
Owner

@izo izo commented May 6, 2026

Summary

Suite logique de PR #143 (v0.1 mergée). Quatre commits atomiques :

  1. test(cli)framework/cli/cmd/json_contract_test.go : 3 tests Go qui verrouillent le shape de ulk status/doctor/check --json
  2. feat(macos) — Modèles Swift StatusReport/DoctorReport/CheckReport (Ulk/Models/UlkReports.swift) miroir du contrat Go ; UlkBridge.status()/doctorReport()/check() typés ; SystemSnapshot.statusReport peuplé depuis le vrai state.json
  3. build(macos) — XcodeGen remplace le projet Xcode hypothétique : project.yml (~80 lignes YAML, source de vérité) ; .xcodeproj gitignored
  4. feat(macos) — 1er toggle fonctionnel end-to-end (suppression skill community/opt-in via FileManager + alert SwiftUI) ; CI macOS-app passée à 2 jobs parallèles (SwiftPM + XcodeGen/xcodebuild) ; spec card v0.2

Contrat JSON Go ↔ Swift

Pierre angulaire de cette PR. Les deux côtés sont liés par un test :

                  ┌──────────────────────────────────────┐
   ulk status     │  framework/cli/cmd/                  │
   ulk doctor ──→ │  json_contract_test.go               │ ──┐
   ulk check      │  asserts JSON shape stable           │   │ break
                  └──────────────────────────────────────┘   │ on
                                                              │ either
                  ┌──────────────────────────────────────┐   │ side
   SwiftUI app ←─ │  apps/macos/Ulk/Ulk/Models/          │ ──┘
                  │  UlkReports.swift                    │
                  │  (StatusReport/DoctorReport/...)     │
                  └──────────────────────────────────────┘

Test plan

  • cd framework/cli && go test ./cmd/ -run "TestStatusJSONContract|TestDoctorJSONContract|TestCheckJSONContract" → ok
  • cd apps/macos/Ulk && swift test (CI macos-14 — SPM job)
  • cd apps/macos/Ulk && xcodegen generate && xcodebuild -project Ulk.xcodeproj -scheme Ulk build (CI macos-14 — xcodegen job)
  • Smoke test manuel sur macOS 14+ : ouvrir Ulk.app, vérifier qu'un skill community apparaît avec une corbeille → confirmer suppression → recharge auto

Limites assumées (v0.2.1+)

  • Toggles MCPs et CLIs : pas wired (ce PR couvre uniquement Skills comme proof end-to-end)
  • Recherche globale highlight : pas implémentée
  • Notifications natives macOS : pas implémentées
  • Sparkle réel : v0.3 (besoin Apple Developer credentials)

Spec complète : docs/backlog/2026-05-06-FEATURE-MACOS-COMPANION-APP/CARD.md

Note sur l'autre check rouge attendu

Le job pré-existant Go CLI > Coverage gate (issue #144) va probablement échouer ici aussi car cette PR touche .github/workflows/**. Ce n'est pas une régression de cette PR — la couverture du package cmd est à 18% sur main. Voir #144 pour le fix.

https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu


Generated by Claude Code

claude added 4 commits May 6, 2026 21:48
Adds 3 contract tests under framework/cli/cmd/json_contract_test.go that
unmarshal real --json output into typed structs mirroring the contract
consumed by the macOS companion app (apps/macos/Ulk/Models/UlkReports.swift).

Any future breaking change to the JSON shape (renamed/removed field,
type change) will fail these tests, forcing a coordinated update on the
Swift side. The Go types are intentionally lenient (pointers + omitempty)
to accept both the not-installed status payload and the full one.

Tested: go test ./cmd/ -run "TestStatusJSONContract|TestDoctorJSONContract|TestCheckJSONContract" → ok

https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
Replaces ad-hoc text parsing with strongly-typed Codable models that
mirror the JSON contract enforced by framework/cli/cmd/json_contract_test.go.

- UlkReports.swift : StatusReport / DoctorReport / DoctorIssue /
  CheckReport / CheckTool — all Codable + Equatable, with derived
  helpers (enabledModules, unfixed, isHealthy, missingTools)
- UlkBridge.swift : new typed methods status() / doctorReport() / check()
  that decode JSON via decodeJSON<T>(); runCapturing gains an
  allowNonZeroExit param so doctor (which exits non-zero when issues
  exist but emits valid JSON) is not flagged as a hard error
- UlkBridge.detectInstall() now prefers status() over filesystem heuristics
  when the binary is available — populates SystemSnapshot.statusReport
  and configFlags from the real state.json modules map
- SystemSnapshot gains statusReport: StatusReport? field
- SystemState exposes removeSkill(_:) wrapper that delegates to UlkBridge
  and reloads the snapshot
- UlkBridge.removeSkill(named:) does input sanitisation (no slashes) and
  uses FileManager.removeItem on ~/.claude/skills/<name>
- UlkReportsTests : 5 tests covering not-installed/full payload, doctor
  healthy/with-issues, check found+missing

https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
XcodeGen generates Ulk.xcodeproj from project.yml (~80 lines of YAML)
on demand. The .xcodeproj is gitignored — source of truth lives in
project.yml. Avoids 1000+ line UUID-laced project.pbxproj diffs and
keeps the file tree in sync automatically.

- project.yml : Ulk app target (macOS 14+, hardened runtime,
  entitlements wired, AppIcon + AccentColor) + UlkTests target
  (bundle.unit-test, gathers coverage)
- .gitignore : Ulk.xcodeproj/ ignored (regenerable artefact)
- README : new "Projet Xcode" section explaining XcodeGen workflow,
  v0.2 status, JSON contract section, updated build commands

Local dev :
  brew install xcodegen
  cd apps/macos/Ulk && xcodegen generate && open Ulk.xcodeproj

https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
- SkillsTab : trash button on community/opt-in skills triggers a
  destructive-style SwiftUI alert, then SystemState.removeSkill →
  UlkBridge.removeSkill (FileManager) → snapshot reload. Bundled
  skills (figma-, swift-, flutter-, kepano-, …) keep their reveal-
  in-Finder action only — they are managed by `ulk install`, not by
  direct deletion. Switched the folder action to
  NSWorkspace.activateFileViewerSelecting so it actually reveals
  rather than opens the directory.
- CI macos-app.yml : split into two parallel jobs
    1. spm — swift build/test (UlkCore library) — fast feedback
    2. xcodegen — brew install xcodegen → generate → xcodebuild
       on the real .xcodeproj with CODE_SIGNING_ALLOWED=NO. Catches
       project.yml drift immediately.
- Spec card : Roadmap v0.1 marked done (PR #143), v0.2 detailed,
  v0.2.1 added (remaining toggles + search + notifications),
  Changelog updated, related field gains json_contract_test.go.

https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Warning

Rate limit exceeded

@izo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 33 minutes and 20 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e01aa5a8-afb3-495d-b8a1-920c4d4ae2d7

📥 Commits

Reviewing files that changed from the base of the PR and between 69c94e9 and 9d97468.

📒 Files selected for processing (11)
  • .github/workflows/macos-app.yml
  • apps/macos/Ulk/.gitignore
  • apps/macos/Ulk/README.md
  • apps/macos/Ulk/Tests/UlkTests/UlkReportsTests.swift
  • apps/macos/Ulk/Ulk/Models/SystemState.swift
  • apps/macos/Ulk/Ulk/Models/UlkReports.swift
  • apps/macos/Ulk/Ulk/Scenes/Dashboard/SkillsTab.swift
  • apps/macos/Ulk/Ulk/Services/UlkBridge.swift
  • apps/macos/Ulk/project.yml
  • docs/backlog/2026-05-06-FEATURE-MACOS-COMPANION-APP/CARD.md
  • framework/cli/cmd/json_contract_test.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/macos-ulk-v0.2-xcode-and-json

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@izo izo marked this pull request as ready for review May 6, 2026 22:02
@izo izo merged commit 5305c12 into main May 6, 2026
5 of 7 checks passed
@izo izo deleted the claude/macos-ulk-v0.2-xcode-and-json branch May 6, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants