Skip to content
Merged
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

Control windows, files, displays, power, and sound from one native macOS menu bar app. Add the utilities you need, use them independently, or combine settings with Scenes and Presentation. Away provides an authenticated privacy curtain.

The current download, v1.0.0, contains Sound. The other modules are integrated in this repository and are in development toward the next release. The [product status guide](guide/product-status.md) records each module's state.
The current download, v1.0.0, contains Sound. Source builds include additional utilities in development toward the next release. The [product status guide](guide/product-status.md) distinguishes integrated features from work still under review.

[semper.systems](https://www.semper.systems/)

Expand Down Expand Up @@ -59,6 +59,7 @@ not download a Semper DMG from an unofficial source.
## Architecture Highlights

- **Independent Utilities**: Home provides module summaries, attention items, up to four pinned actions, search, and recent action outcomes for the current session. Add, pause, or remove modules individually; adding a module starts no service and requests no permission. Detailed controls open in a native window.
- **Manual Window Layout**: Five optional actions arrange eligible windows into halves, maximize, center, or restore the preceding placement. Full-height windows and targets are refused, which can limit halves and maximize when both the Dock and menu bar auto-hide. Source integration and native acceptance are tracked in the [product status guide](guide/product-status.md#window-layout).
- **Local Awake Sessions**: Public IOKit power assertions prevent idle system sleep, optionally keep the display on, and keep timed user sessions separate from Scene requests.
- **Authenticated Away Curtain**: One opaque panel covers each display, ordinary input is filtered, and local widgets can show time, battery, Away duration, and awake-request state.
- **Swift 6 & Core Audio TCC Taps**: Built using modern Swift 6 strict concurrency (`@MainActor`, `Sendable`) and low-latency CoreAudio process taps.
Expand All @@ -80,6 +81,7 @@ not download a Semper DMG from an unofficial source.
- Sound requires Screen & System Audio Recording permission for CoreAudio process taps.
- Microphone permission is used only for input-device monitoring.
- Accessibility permission is optional for system media-key control.
- Workspace Restore and Window Layout actions require Accessibility access to read and move app windows.

Away is a Semper privacy curtain, not the macOS Lock Screen or an operating-system security boundary. Force Quit, Semper failure, restart, administrator or Accessibility control, remote access, authorized capture software, and display-change timing can expose the desktop. Its awake request does not prevent lid-close sleep, manual Sleep, or forced low-power sleep.

Expand Down Expand Up @@ -124,6 +126,9 @@ in your keychain so macOS can recognize later source updates as the same app.
- [Product Status](guide/product-status.md)
- [Module Shell](guide/module-shell.md)
- [Direct Utilities: Workspace Restore, File Shelf, Safe Eject](guide/direct-utilities.md)
- [Choose Files in File Shelf](guide/shelf-file-selection.md)
- [Presentation Controls](guide/presentation-controls.md)
- [Window Layout](guide/window-layout.md)
- [Awake Sessions](guide/awake-sessions.md)
- [URL Schemes](guide/url-schemes.md)
- [App Shortcuts](guide/app-shortcuts.md)
Expand Down
55 changes: 34 additions & 21 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Semper roadmap

Semper is one menu bar app with nine utility modules: Sound, Awake, Displays,
Workspace Restore, File Shelf, Safe Eject, Scenes, Away, and Presentation. All
nine are integrated on `main`. The downloadable release is v1.0.0, which
contains Sound only. This roadmap orders the work to deliver the whole suite as
Semper's source in this change set contains ten utility modules: Sound, Awake,
Displays, Workspace Restore, Window Layout, File Shelf, Safe Eject, Scenes,
Away, and Presentation. The baseline has nine integrated modules. Window Layout
becomes the tenth integrated module when this change set merges into `main`.
The downloadable release is v1.0.0, which contains Sound only. This roadmap
orders the work to deliver the whole suite as
dependable signed releases without hiding experimental behavior. Per-module
state lives in the [product status guide](guide/product-status.md).

Expand All @@ -27,21 +29,28 @@ state lives in the [product status guide](guide/product-status.md).
- Denied or revoked permissions, limited runtimes, and failed cleanup stay
visible with a recovery path. Quit drains composed sessions before the
services they use. See the [module shell guide](guide/module-shell.md).
- Finish the current interaction gaps first: keyboard-accessible file selection
in File Shelf and cancellation while Presentation prepares or starts.

### 3. Window Layout

The next planned increment. It is not implemented today.

- Manual placement commands: left half, right half, maximize to the usable
screen area, center, and restore the last placement.
- Built in its own branch on the existing Workspace Restore window helpers.
- Manual actions only: no automatic tiling and no window watching.
- Preserve the intended window when the menu bar takes focus. Verify each
placement and keep later manual adjustments intact when restoring.
- Test half and maximized windows through later center and restore actions
without weakening Workspace Restore's fullscreen protections.
- Complete native acceptance of the integrated File Shelf picker and
Presentation preparation/start cancellation, including keyboard routing,
focus, dismissal, and recovery.

### 3. Window Layout acceptance and compatibility

The cleared implementation from [PR #106](https://github.com/niharnm/Semper/pull/106)
is included in this change set. Integration requires its merge to `main`;
native acceptance remains open. See the [Window Layout guide](guide/window-layout.md).

- Verify all five manual commands, optional shortcuts, Home/search/pinned
actions, intended-window selection, and later manual changes on real apps.
- Keep the conservative full-height exclusion explicit. Ordinary full-height
windows and targets are refused; halves and maximize can be unavailable when
both Dock and menu bar auto-hide. Smaller-window center and restore still
require eligible geometry.
- After an attempted write, an excluded or unreadable result requires manual
review. Verify that its recovery message survives cancellation and pause
until acknowledged.
- Resolve full-height compatibility through verified behavior before broad
support claims. Preserve Workspace Restore's protections. No automatic tiling
or persisted window history is included.

### 4. Cross-module workflows

Expand All @@ -58,11 +67,14 @@ The next planned increment. It is not implemented today.
restarts.
- File Shelf and Safe Eject: behavior improvements from reproducible reports,
keeping original files and volumes safe.
- After File Shelf's file picker, add **Resize Image Copy** for one selected
- Finish review of File Shelf's **Resize a Copy** for one selected
local JPEG or PNG. Offer 1024 or 2048 pixels on the longest edge without
enlargement, show output dimensions, and save a separate copy. Preserve
orientation, color and transparency, explain metadata handling, and support
cancellation. No batch processing, uploads, or original-file replacement.
- Preserve pending cleanup through lifecycle changes, bound expiry retries,
verify file ownership before removal, and report the actual saved path.
Image-copy integration waits for the corrected implementation and tests.
- Awake and Away: keep power assertions and the curtain testable and honest
about what they do not block.
- A new utility needs a clear local user job, no account requirement, the
Expand Down Expand Up @@ -119,7 +131,8 @@ discussion and include a hardware test plan.
Homebrew are current.
- Integrated on `main` and in no download yet: Awake, Displays, Workspace
Restore, File Shelf, Safe Eject, Scenes, Away, and Presentation.
- Planned additions: Window Layout and File Shelf's Resize Image Copy action.
- Implemented in this change set, awaiting integration: Window Layout.
- Under review, not integrated: File Shelf's Resize a Copy.
- Hardware-dependent: process taps, device routing, DDC, Bluetooth call mode,
media keys, Accessibility window operations, volume ejection, and permission
behavior.
Expand Down
15 changes: 15 additions & 0 deletions Semper/Modules/ModuleRegistry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ enum UtilityModuleID: String, CaseIterable, Codable, Hashable, Identifiable, Sen
case awake
case displays
case workspace
case windowLayout = "window-layout"
case shelf
case storage
case scenes
Expand Down Expand Up @@ -65,6 +66,20 @@ struct UtilityModuleDescriptor: Identifiable, Equatable, Sendable {
.init(
id: .workspace, title: "Workspace Restore", summary: "Save and restore app window positions.",
symbolName: "macwindow.on.rectangle"),
.init(
id: .windowLayout, title: "Window Layout", summary: "Arrange the frontmost app window.",
symbolName: "rectangle.split.2x1",
disclosure: .init(
permissionReasons: [
.init(name: "Accessibility", reason: "Reads and arranges a window only when you invoke an action.")
],
runningBackgroundPolicy:
"Remembers the last active app while running. Window reads and changes happen only on request; pausing stops observation and drains pending work.",
localDataPolicy:
"Window identity and the previous placement stay in memory. Pausing preserves them; removing the module or quitting clears them. No window titles are collected.",
conflicts: ["Finish active Workspace Restore work and end Away before arranging windows."],
hardwareRequirements: ["Requires standard windows with readable geometry and move/resize support. Full-height windows and targets are conservatively refused."]
)),
.init(
id: .shelf, title: "File Shelf", summary: "Keep references to files close at hand.", symbolName: "tray.fill"
),
Expand Down
1 change: 1 addition & 0 deletions Semper/Modules/ShellUITestFixture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
soundFactory: { _, _ in try probe.refuse(.sound) },
awakeFactory: { try probe.refuse(.awake) },
workspaceFactory: { try probe.refuse(.workspace) },
windowLayoutFactory: { _ in try probe.refuse(.windowLayout) },
shelfFactory: { try probe.refuse(.shelf) },
storageFactory: { try probe.refuse(.storage) },
sceneLibraryStore: FileSceneLibraryStore(directory: sceneDirectory),
Expand Down
2 changes: 1 addition & 1 deletion Semper/Modules/UtilityLifecycle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ final class UtilityLifecycle {
for task in stops { _ = await task.result }
// Composed sessions restore before their underlying services stop.
let order: [UtilityModuleID] = [
.away, .presentation, .scenes, .workspace, .shelf, .storage, .displays, .sound, .awake,
.away, .presentation, .scenes, .windowLayout, .workspace, .shelf, .storage, .displays, .sound, .awake,
]
var retainedServices: [UtilityModuleID: String] = [:]
for id in order {
Expand Down
Loading
Loading