Why local automation needs two layers: the connector/muscle split for macOS
We shipped Mac automation that “worked.” Provenance lived in a SQLite file on the user’s laptop. At 2 AM an agent sent mail via AppleScript. Security asked: who authorized it? The only answer was a path under Application Support that HumanOS could not see.
That is not a trust layer. That is a log file wearing a product badge.
The first wrong answer
First pass: a Tauri Rust command (applescript_run_jxa), a local SQLite provenance table, a React settings panel for capability grants. It worked on macOS. It felt complete.
It was wrong—not because of a bug, but because we built a parallel governance fabric. HUMΛN’s value is a single fabric for provenance, delegation, and policy. A local provenance table is a second fabric nobody else can verify.
The second wrong answer
So we moved logic server-side. A Linux-hosted agent would call an API that somehow reached the Mac, ran osascript, and logged to the canonical trail.
The problem: osascript does not run on Linux. BRIDGE_PLATFORM_UNSUPPORTED is a permanent architectural constraint. JXA must execute on a Mac—either a self-hosted agent (Path A) or the user’s Companion app (Path B).
The correct answer: two layers, both first-class
HUMΛN already had the vocabulary. We had to use it correctly.
Connectors are transport
A connector is a bidirectional gateway to an external system. @human/connector-applescript runs JXA via child_process.execFile('/usr/bin/osascript'), validates against a command catalog, and returns structured errors. It has no opinion on approval. It has no org identity. It is transport.
BaseConnector.invoke does not receive ExecutionContext. It cannot log provenance. It cannot request approval.
Muscles are orchestration
A muscle is an intelligent runtime capability. MacAutomationMuscle receives MuscleInvocationContext—ctx.provenance.log, ctx.approval.request, ctx.feedback.emit. It knows the command tier. It logs every significant step to the HumanOS provenance trail.
Agent → muscle (HumanOS: policy, provenance, HITL) → connector (transport: JXA)
The tier model enforces this
Tier 0–1 (reads, pings) go through. Tier 2–3 (mutations, sends) hit ctx.approval.request() first—server HITL lands in the Workforce / Command Plane inbox for human review. Path B Mac execution additionally uses Companion’s MacAutomationProposal for local JXA. The approval decision is cryptographically attributed either way. That is what “single fabric” means.
Where local state belongs
The device-local PermissionStore (mac_capability_grants in apps/human-app) still exists—but only answers: “Has this device’s user granted or denied this capability?”
That is device-local consent, not provenance. It supplements the server HITL gate so “always allow” does not re-prompt. Authoritative record of what ran: HumanOS trail. Never the other way around.
The two paths
Path A — self-hosted macOS agent. Agent process runs on a Mac. ctx.call.invoke('applescript', …) succeeds. Muscle logs to provenance, returns MuscleResult.
Path B — Companion desktop. Agent server on Linux. Bridge throws BRIDGE_PLATFORM_UNSUPPORTED. Muscle returns a MacAutomationIntent. Companion renders MacAutomationProposal, user approves, Tauri runs JXA, outcome via POST /v1/events/emit. Details: companion_integration Path B.
Scroll-stopper: If provenance cannot leave the laptop, it is not provenance—it is a diary.
Why companion_integration: true
The SDK ConnectorManifest field signals honesty: full capability needs Companion desktop; marketplace listings say so; validators require self-hosted in deployment.supportedModes.
So that…
…builders clone a governed pattern instead of inventing a second trust fabric; operators audit Mac actions in the same trail as cloud agents; and nobody mistakes a local SQLite file for HumanOS.
Go deeper
- Product: Companion, HumanOS
- Docs: Quickstart, Provenance
- Community: Path B / companion_integration, Writing a JXA catalog entry, When Companion routes to humans
Series: Part 1 of 3 — Mac Automation Reference
Mac Automation Reference — Part 1 of 3