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: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ scripts/repo-maintenance/validate-all.sh

For documentation-only work, also inspect the changed Markdown structure and links. Do not run visible apps, simulators, GUI automation, or disruptive service checks without approval.

Automated validation and runtime evidence prove different things:

- Swift tests should cover deterministic parsing, target metadata, formatting, and reusable helper behavior.
- Builds prove that the checked-in source compiles against the selected toolchain.
- Runtime captures prove the observed private-framework, daemon, notification, Accessibility, permission, or entitlement behavior only for the recorded environment.

Do not convert an environment-specific observation into a unit-test claim, and do not describe a passing build or test as proof that a private runtime surface is present, permitted, or stable across OS versions.

## Pull Request Expectations

Summarize the target, evidence gathered, conclusions promoted, commands run, environment used, and any remaining inference or blocked runtime proof. Keep reviewable raw captures separate from generated or ignored bulk output.
Expand Down
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,28 @@ Individual probes may require a particular macOS build, private frameworks, TCC

## Usage

The safest starting points are the read-only commands:
Start with the target inventory, then read the target overview linked from [`docs/README.md`](./docs/README.md):

```sh
swift run spelunk targets
```

### Command Safety

These commands are read-only in intent: they do not send playback commands, change routes, dismiss notifications, or alter account or message state. Loading private frameworks and querying system services can still fail because of OS, entitlement, TCC, sandbox, or SIP boundaries.

| Command | Purpose | Runtime Boundary | Output |
| --- | --- | --- | --- |
| `swift run spelunk targets` | List every seeded research target and its documentation paths. | None beyond building the package. | Human-readable target index. |
| `swift run spelunk notifications --max-depth 6` | Inspect the Notification Center Accessibility tree. | Requires Accessibility trust to expose the tree; captured strings may contain personal notification content. | JSON capability and tree snapshot. |
| `swift run spelunk objc-runtime ...` | Load selected framework images and inventory matching Objective-C metadata. | The requested image is loaded into the probe process; private images may reject loading or execute framework initialization. | Text or JSON metadata. |
| `swift run spelunk string-constants ...` | Resolve selected exported string constants from a framework image. | Loads the requested image; symbols may be absent or use an unsupported representation. | Text or JSON resolution results. |
| `swift run spelunk notification-observe ...` | Observe named Darwin or distributed notifications for a bounded duration. | Waits for live events; payload contents are not recorded. | Text or JSON registration and event results. |
| `swift run mr-now-playing-probe [options]` | Query MediaRemote now-playing, client, player, origin, or queue state. | Contacts private media services; some options register notifications or issue read requests. | Human-readable runtime observations. |
| `swift run mr-interface-probe` | Inspect selected MediaRemote Objective-C runtime interfaces. | Loads the private framework into the probe process. | Human-readable class and method inventory. |
| `swift run mr-route-probe [options]` | Query endpoints, routes, contexts, and output-device metadata. | Contacts private routing services; default invocation does not change the active route. | Human-readable route observations. |

Common read-only examples:

```sh
swift run spelunk notifications --max-depth 6
Expand All @@ -50,7 +71,7 @@ swift run mr-interface-probe
swift run mr-route-probe
```

The package also contains `mr-internal-probe`, `now-playing-fixture`, and the `MRXPCTraceInterpose` dynamic library for narrower experiments. Repeatable MediaRemote capture helpers live under [`tools/`](./tools/README.md).
The package also contains `mr-internal-probe`, `now-playing-fixture`, and the `MRXPCTraceInterpose` dynamic library for narrower experiments. These are not general starting points: read the [MediaRemote experiment documentation](./docs/frameworks/MediaRemote/experiments.md) before using them. Repeatable MediaRemote capture helpers and their individual purposes live under [`tools/`](./tools/README.md).

For each target, use:

Expand All @@ -64,6 +85,8 @@ Every writeup should identify the active OS and SDK or Xcode version, distinguis

For research intake, local setup, validation, documentation boundaries, and review expectations, see [`CONTRIBUTING.md`](./CONTRIBUTING.md). Durable agent-facing rules live in [`AGENTS.md`](./AGENTS.md), and planned work lives in [`ROADMAP.md`](./ROADMAP.md).

Automated tests cover deterministic, reusable helper behavior. Environment-specific private-framework calls, daemon responses, permissions, and OS behavior require a documented runtime observation; a passing unit test or build does not prove that those live surfaces are available or authorized on another machine.

## Repo Structure

```text
Expand Down
13 changes: 9 additions & 4 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ Build a trustworthy public knowledge base and set of local tools for understandi

## Milestone Progress

- Milestone 0: Repository Foundation - Completed
- Milestone 1: MediaRemote Baseline - In Progress
- Milestone 2: Media Control Experiments - Planned
- Milestone 3: Reusable Research Tooling - In Progress
| Workstream | Status | Current Boundary |
| --- | --- | --- |
| Repository foundation | Completed | SwiftPM, documentation, evidence, validation, and maintenance structure established. |
| MediaRemote | In Progress | Read-only baseline and runtime probes established; interface recovery and non-empty now-playing reproduction remain open. |
| Messages | Baseline Established | Supported/private boundary, storage, runtime, notification, and XPC ownership maps captured; deeper interface and event proof remains open. |
| Phone | Baseline Established | Supported/private boundary, storage, runtime, notification, and XPC ownership maps captured; deeper interface and event proof remains open. |
| UserNotifications | Baseline Established | Read-only Notification Center Accessibility and runtime inventory established; broader state and OS comparisons remain open. |
| Media control experiments | Planned | Mutating command and route experiments remain gated on explicit, bounded research slices. |
| Reusable research tooling | In Progress | Target index, notification, Objective-C runtime, string-constant, and MediaRemote capture helpers exist; generalized capture and reporting remain open. |

## Milestone 0: Repository Foundation

Expand Down
7 changes: 7 additions & 0 deletions Sources/SpelunkingKit/SPKResearchTarget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,11 @@ public extension SPKResearchTarget {
documentationPath: "docs/frameworks/MediaRemote",
researchPath: "research/MediaRemote"
)

static let userNotifications = SPKResearchTarget(
name: "UserNotifications and Notification Center",
summary: "Read-only Notification Center accessibility, process, framework, and notification-delivery research.",
documentationPath: "docs/frameworks/UserNotifications",
researchPath: "research/UserNotifications"
)
}
2 changes: 1 addition & 1 deletion Sources/spelunk/SPKMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct SPKMain {
}

private static func printTargets() {
for target in [SPKResearchTarget.messages, .phone, .mediaRemote] {
for target in [SPKResearchTarget.messages, .phone, .mediaRemote, .userNotifications] {
print(target.name)
print(target.summary)
print("Docs: \(target.documentationPath)")
Expand Down
9 changes: 9 additions & 0 deletions Tests/SpelunkingKitTests/SPKResearchTargetTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ struct SPKResearchTargetTests {
#expect(target.researchPath == "research/MediaRemote")
}

@Test("UserNotifications target points at the persisted documentation and research directories")
func userNotificationsPaths() {
let target = SPKResearchTarget.userNotifications

#expect(target.name == "UserNotifications and Notification Center")
#expect(target.documentationPath == "docs/frameworks/UserNotifications")
#expect(target.researchPath == "research/UserNotifications")
}

@Test("Notification Center probe explains an absent Accessibility grant")
func notificationProbeUntrustedResult() throws {
let encoded = try JSONEncoder().encode(.accessibilityNotTrusted as SPKNotificationCenterAccessibilityProbeResult)
Expand Down
11 changes: 11 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ Cross-target status:

- [Messages and Phone research status](frameworks/messages-phone-status.md)

## Target Directory

| Target | Status | Start Here | Safest First Command |
| --- | --- | --- | --- |
| MediaRemote | Baseline in progress | [MediaRemote overview](frameworks/MediaRemote/README.md) | `swift run mr-now-playing-probe` |
| Messages | Read-only baseline established | [Messages overview](frameworks/Messages/README.md) | `swift run spelunk targets` |
| Phone | Read-only baseline established | [Phone overview](frameworks/Phone/README.md) | `swift run spelunk targets` |
| UserNotifications | Read-only baseline established | [UserNotifications overview](frameworks/UserNotifications/README.md) | `swift run spelunk notifications --max-depth 6` |

The commands above do not intentionally mutate media, message, call, notification, account, or system-service state. Some probes still load private frameworks, contact system daemons, or inspect Accessibility surfaces. Read the target overview for OS, permission, privacy, and runtime boundaries before collecting evidence.

Each target writeup should include:

- scope
Expand Down
Loading
Loading