Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
118b765
Scaffold OpenDisplay monorepo and platform-independent safety core
claude Jun 22, 2026
e295883
Fix invalid CI workflow YAML (unquoted colon in echo)
claude Jun 22, 2026
8bc3b00
Fix ScenePlanner compile error and select Xcode 16 on macOS CI
claude Jun 22, 2026
983d1ab
Make macOS and SwiftLint CI jobs blocking
claude Jun 22, 2026
b6ca341
Harden disconnect transaction (Codex P1s) + local-first tooling
claude Jun 22, 2026
3cd75ef
Remove remote CI; scaffold Xcode project (XcodeGen) for the macOS tar…
claude Jun 22, 2026
3b9f74a
Add macOS Quickstart handoff doc
claude Jun 22, 2026
b29bade
Add Docs/HANDOVER.md session handover
claude Jun 22, 2026
4f74bfe
Fix macOS framework codesign: synthesize Info.plist for framework tar…
claude Jun 22, 2026
2794314
M0: real CoreGraphicsProvider enumeration + observation event source
claude Jun 22, 2026
4ad0bf4
M0: SkyLight lifecycle provider (real disconnect) + public mirroring …
claude Jun 22, 2026
57e54f9
M0: disk-backed rescue-readable CheckpointStore + rescue reads it end…
claude Jun 22, 2026
fb000cc
M0: live disconnect verified on hardware; fix cross-framework provide…
claude Jun 22, 2026
54d29c6
M0: fix duplicate type metadata via dynamic core frameworks
claude Jun 22, 2026
aab3394
M0: implement real private logical disconnect (SkyLight CGS config tr…
claude Jun 22, 2026
e49b8bc
M0: rescue can re-enable a privately-disconnected display (closes the…
claude Jun 22, 2026
617a19b
M0: friendly display names in the menu bar (NSScreen.localizedName)
claude Jun 22, 2026
bc0df92
M0: global Reconnect-All hotkey (Ctrl-Opt-Cmd-R) via Carbon
claude Jun 22, 2026
3313390
M0: confirm global hotkey live; file-based fire marker for LaunchServ…
claude Jun 22, 2026
eab4931
M1: real opendisplay CLI — enumeration, diagnose, dry-run disconnect,…
claude Jun 22, 2026
2e48e3a
M1: CommandGateway — single audited command path returning ResultEnve…
claude Jun 22, 2026
f1671c1
M1: App Intents — "Reconnect All" via Shortcuts/Siri, routed through …
claude Jun 22, 2026
d7a943c
M1: Settings UI — Displays + Diagnostics & Recovery tabs
claude Jun 22, 2026
60a4056
M1: test CommandGateway partial-reconnect branch
claude Jun 22, 2026
ecba282
M1: menu-bar designed states — scanning / ready / empty / reconnectin…
claude Jun 22, 2026
ee724d0
M1: persisted SettingsStore + wire into app
claude Jun 22, 2026
573a2ab
M1: transaction audit log (AUT-010), wired into CommandGateway
claude Jun 22, 2026
dc40884
M1: route opendisplay CLI through CommandGateway
claude Jun 22, 2026
8724b8d
M1: recent activity view in Settings (surfaces the audit log)
claude Jun 22, 2026
2801f6c
M1: DisplayRegistry — persisted identity resolution (cross-platform c…
claude Jun 22, 2026
835472d
M1: wire DisplayRegistry into the CLI — real fingerprints, alias/tag …
claude Jun 22, 2026
7795ddf
M1: wire DisplayRegistry into the app — aliases in the menu bar + ren…
claude Jun 22, 2026
d12decb
Fix: open Settings on the active display; use openSettings action (ma…
claude Jun 22, 2026
7f3ac91
M1 (Epic 4): scene capture, persistence, and planning
claude Jun 22, 2026
dc5cf67
M1 (Epic 4): CLI scene commands — save / list / show / plan / delete …
claude Jun 22, 2026
256557f
M1 (Epic 4): scene apply — restore a saved arrangement (verified live)
claude Jun 22, 2026
65ebd92
M1: BetterDisplay-style menu + "always one active" invariant + displa…
claude Jun 22, 2026
d73f29f
M1 (Epic 5): built-in display brightness in the menu
claude Jun 22, 2026
3c9d02b
M1 (Epic 5): external display brightness over DDC/CI
claude Jun 22, 2026
b3fc209
M1 (Epic 5): hardware control — DDC contrast + volume in the menu
claude Jun 22, 2026
32a6587
M1: Mirror-to-main toggle + read-only Display info panel
claude Jun 22, 2026
62f27e5
M1: software dimming (Image adjustments) — gamma brightness for any d…
claude Jun 22, 2026
aa21ab6
M1: Display-mode picker — refresh rate + Retina (HiDPI) toggle
claude Jun 22, 2026
367ba88
M1: CLI brightness + ddc control commands
claude Jun 22, 2026
a134833
M1: "Set Display Brightness" App Intent (Shortcuts / Siri)
claude Jun 23, 2026
ac3d239
docs: README status reflects the functional macOS app
claude Jun 23, 2026
ac49afc
M1 (Epic 5): input source — read current + DDC switch picker
claude Jun 23, 2026
67e25cc
M1 (Epic 5): colour mode — DDC colour-preset picker
claude Jun 23, 2026
a9f577d
M1: screen rotation v1 — read-only + backend abstraction (writes defe…
claude Jun 23, 2026
b140e05
M1 (Epic 5): per-display ICC colour profiles via public ColorSync
claude Jun 23, 2026
91b85c9
M1 (Epic 5): gated experimental rotation backend (SkyLight, opt-in, h…
claude Jun 23, 2026
8dd9aa3
M1: menu row trailing values (rotation angle, active colour mode/prof…
claude Jun 23, 2026
84c59fd
Fix: persist managed-offline displays so a turned-off display survive…
claude Jun 23, 2026
0639c25
Harden rotation recovery + ICC/control cache across topology changes
claude Jun 23, 2026
75dfb49
Experimental rotation: Settings toggle + bundle the helper into the .app
claude Jun 23, 2026
3faba8d
UI redesign: sidebar Settings + leaner menu, plus design-system compo…
claude Jun 23, 2026
05b1788
Optimize for Apple Silicon + peak performance; remove dead code
claude Jun 23, 2026
8f8794c
docs: README features + binary install instructions; CHANGELOG 0.1.0
claude Jun 23, 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
80 changes: 80 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Bug report
description: Report a problem with OpenDisplay
title: "[bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for the report. Please redact identifying data (display serials, usernames).
If a display became unreachable, note which recovery action you used.
- type: input
id: app-version
attributes:
label: OpenDisplay version
placeholder: "e.g. 0.3.0 (build 123)"
validations:
required: true
- type: dropdown
id: build-flavor
attributes:
label: Build flavor
options: ["Full", "Public-API-only"]
validations:
required: true
- type: input
id: macos
attributes:
label: macOS version / build
placeholder: "e.g. 15.5 (24F74)"
validations:
required: true
- type: input
id: mac-model
attributes:
label: Mac model & chip
placeholder: "e.g. MacBook Pro 14\" M3 Pro (Apple Silicon)"
validations:
required: true
- type: input
id: displays
attributes:
label: Display model(s)
placeholder: "e.g. LG UltraFine 4K + built-in Retina"
validations:
required: true
- type: dropdown
id: route
attributes:
label: Connection route
multiple: true
options: ["Direct USB-C/DP", "HDMI", "Thunderbolt dock", "USB-C hub", "KVM", "Adapter", "Wireless (Sidecar/AirPlay)"]
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. ...
2. ...
validations:
required: true
- type: textarea
id: expected-actual
attributes:
label: Expected vs actual behavior
validations:
required: true
- type: dropdown
id: recovery
attributes:
label: Was a recovery action needed?
options: ["No", "Reconnect All", "Automatic rollback", "Rescue utility", "Safe mode", "Manual intervention"]
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs / diagnostics bundle
description: Attach a redacted diagnostics bundle if available.
63 changes: 63 additions & 0 deletions .github/ISSUE_TEMPLATE/compatibility_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Compatibility report
description: Report hardware/OS compatibility results for a capability
title: "[compat]: "
labels: ["compatibility"]
body:
- type: markdown
attributes:
value: |
Helps build the certified compatibility matrix. **Redact serials and other
identifying data.**
- type: input
id: mac-model
attributes:
label: Mac model & chip
placeholder: "e.g. Mac mini M2 (Apple Silicon)"
validations:
required: true
- type: input
id: macos
attributes:
label: macOS build
placeholder: "e.g. 15.5 (24F74)"
validations:
required: true
- type: input
id: display
attributes:
label: Display model & firmware
placeholder: "e.g. Dell U2720Q (firmware M3B103)"
validations:
required: true
- type: dropdown
id: route
attributes:
label: Route
options: ["Direct", "Thunderbolt dock", "USB-C hub", "KVM", "Adapter", "Wireless"]
validations:
required: true
- type: dropdown
id: capability
attributes:
label: Capability tested
options:
- Logical disconnect / reconnect
- DDC brightness
- DDC volume / contrast / input
- Resolution / refresh / rotation modes
- HDR / XDR
- Mirroring / main display
- Virtual display
validations:
required: true
- type: dropdown
id: result
attributes:
label: Result
options: ["Works (verified)", "Works (unverified read-back)", "Degraded", "Fails"]
validations:
required: true
- type: textarea
id: notes
attributes:
label: Notes
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security report (private)
url: https://github.com/aquitaine/opendisplay/security/policy
about: Please report vulnerabilities privately — do not open a public issue.
45 changes: 45 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Feature request
description: Suggest an improvement or new capability
title: "[feature]: "
labels: ["enhancement"]
body:
- type: textarea
id: problem
attributes:
label: Problem / use-case
description: What are you trying to do? What's painful today?
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed solution
validations:
required: true
- type: dropdown
id: domain
attributes:
label: Related capability domain
options:
- Display lifecycle & topology
- Modes, scaling & geometry
- Brightness, audio, color & input
- Virtual displays, capture & presentation
- Automation & integrations
- Diagnostics, configuration & recovery
- User experience & accessibility
- Other
validations:
required: true
- type: dropdown
id: tier
attributes:
label: Core or Labs?
description: Labs = experimental / system-sensitive / undocumented behavior.
options: ["Core", "Labs", "Not sure"]
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
32 changes: 32 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!-- Thanks for contributing to OpenDisplay! Please complete this checklist. -->

## Summary

<!-- What does this change and why? Link the issue it closes. -->

Closes #

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor / internal
- [ ] Docs
- [ ] Lifecycle / recovery / safety (requires threat & recovery review)

## Checklist

- [ ] **Clean-room:** this contribution is my original work, or its source and license are
identified. No proprietary code, copied UI, copy, or assets.
- [ ] Tests added/updated (unit/state-machine for logic; hardware evidence for provider changes).
- [ ] `make test` passes locally (`swift test` green) and SwiftLint is clean. (No remote CI — local verification is the gate.)
- [ ] The **public-API-only** build still compiles with experimental providers absent (NFR-010).
- [ ] Docs updated where behavior changed.
- [ ] Commits are signed off (`git commit -s`, DCO).

## Safety & recovery

- [ ] This PR does **not** touch lifecycle, the transaction coordinator, checkpoints, the
rescue path, startup, IPC, capture, update, or network.
- [ ] If it does: I have described new failure modes and how recovery stays guaranteed, and
requested a threat & recovery review (RFC linked if applicable).
39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Swift / SwiftPM
.build/
.swiftpm/
Package.resolved.user
*.xcodeproj/xcuserdata/
*.xcworkspace/xcuserdata/
DerivedData/

# Xcode — the project is generated by XcodeGen (`make xcode`); do not commit it.
/OpenDisplay.xcodeproj/
xcuserdata/
*.xcuserstate
*.moved-aside
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

# macOS
.DS_Store

# Release / signing artifacts (never commit secrets or signed binaries)
*.app
*.pkg
*.dmg
*.zip
ExportOptions.plist
*.p12
*.cer
*.provisionprofile
notarization-*.json

# Editor
.idea/
*.swp

# Local build output (XcodeGen `make build` writes here) and local agent/session config
build/
.claude/
18 changes: 18 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": 1,
"lineLength": 110,
"indentation": { "spaces": 4 },
"maximumBlankLines": 1,
"respectsExistingLineBreaks": true,
"lineBreakBeforeEachArgument": false,
"indentConditionalCompilationBlocks": false,
"rules": {
"AllPublicDeclarationsHaveDocumentation": false,
"AlwaysUseLowerCamelCase": true,
"NeverForceUnwrap": false,
"OrderedImports": true,
"UseLetInEveryBoundCaseVariable": true,
"UseShorthandTypeNames": true,
"ReturnVoidInsteadOfEmptyTuple": true
}
}
46 changes: 46 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# SwiftLint configuration for OpenDisplay.
# Keep rules pragmatic; the domain packages are the strictest because they encode safety logic.
included:
- Packages
- Providers
- Apps
- Tools
excluded:
- .build
- "**/.build"
- Tests/Fixtures

opt_in_rules:
- empty_count
- explicit_init
- first_where
- sorted_imports
- unused_import
- redundant_nil_coalescing
- closure_spacing
- operator_usage_whitespace

line_length:
warning: 120
error: 160
ignores_comments: true

type_body_length:
warning: 400
error: 600

file_length:
warning: 600
error: 1000

function_body_length:
warning: 80
error: 140

identifier_name:
min_length: 2
excluded: [id, x, y, dx, dy, to, on]

cyclomatic_complexity:
warning: 12
error: 20
16 changes: 16 additions & 0 deletions Apps/OpenDisplay/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# OpenDisplay (app)

**macOS app target** (SwiftUI + AppKit). The menu-bar popover (primary surface) and the
settings window, built from `Packages/OpenDisplayDesignSystem`. Hosts the dependency
composition root: `DisplayRegistry`, `TopologyCoordinator`, providers, stores, and the
`RecoveryService` (Reconnect All + global hotkey).

Surfaces (PRD §8.1): menu-bar root, topology workspace, display detail, scenes, automation,
health & recovery, Labs. The UI consumes immutable snapshots and submits commands through the
command gateway — it never mutates domain state directly.

Milestone: **M1 (menu-bar + connect/disconnect) → M3 (Core 1.0)**.

> Scaffolded: run `make xcode` to generate the project, then build/run the `OpenDisplay`
> scheme. The app currently runs against `SimulatedDisplaySystem`; real providers land in M0.
> Sources: `Apps/OpenDisplay/Sources` (`OpenDisplayApp`, `AppModel`, `MenuBarView`, `SettingsView`).
23 changes: 23 additions & 0 deletions Apps/OpenDisplay/Resources/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>OpenDisplay</string>
<key>CFBundleDisplayName</key>
<string>OpenDisplay</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<!-- Menu-bar agent: no Dock icon (PRD UX-001). -->
<key>LSUIElement</key>
<true/>
</dict>
</plist>
14 changes: 14 additions & 0 deletions Apps/OpenDisplay/Resources/OpenDisplay.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
Display-lifecycle management needs access incompatible with the App Sandbox, so it is
disabled here. The exact entitlement set (and whether any Labs feature needs more) is an
open question pending technical/legal review — PRD Q-002. Distribution is Developer ID +
hardened runtime (set via build settings), not the App Store (D-007).
-->
<key>com.apple.security.app-sandbox</key>
<false/>
</dict>
</plist>
Loading