AGENTIC INFRASTRUCTURE / GOVERNANCE
The Scope You Forgot to Name
Mapping the com.apple.macl incident to the governance layer that wasn't there.
The Folder That Refused to Open
On April 20th, my ~/Downloads folder went unreadable.
I was deep in another task — building agent-review-gate infrastructure across the hive — when an agent tried to read a file in Downloads and got a permission error. I tried it myself from the terminal. Permission denied. I tried with sudo. Permission denied. I sat with that for a second. Downloads. The folder every macOS user reflexively trusts to be accessible. Locked out of it. With root.
I cleared an extended attribute I didn’t fully understand — sudo xattr -d com.apple.macl ~/Downloads — and the folder came back. I noted it in the continuity doc as a bullet point. Weird thing, fixed. Moved on.
April 26th, same machine. Same folder. Same problem. This time I went deeper. I watched the attribute reappear after I cleared it. I worked through whether the re-stamp was the block reasserting itself or something else. It turned out to be normal post-fix behavior — macOS re-recording the access grant after the next sandboxed read — but I couldn’t have told you that the first time it happened. I fixed it again. Noted it again. Pattern forming.
April 28th, my work MacBook. Different physical machine. Same failure. I had to chmod -N ~/Downloads to read the directory. The pattern was no longer ambiguous. From the session log:
“somehow we’re changing the attributes of directories — I don’t know how, but I know it’s us, because it happened today to my work laptop too.”
That was the moment the framing shifted. Weird thing, fixed doesn’t survive three incidents across two machines. There was a class of failure under the hood and I’d been treating its instances as exceptions.
What This Is Not
Before going further: this is not a macOS bug story. The operating system was doing exactly what it was designed to do. The instances were correct; the model that classified them as failures was incomplete.
It’s also not a configuration hygiene story. Every individual config file on my system was internally consistent. No layer contradicted another. The CLAUDE.md hierarchy was coherent on its own terms.
It’s not an AI tool story either. The same incident would have arisen with any sandboxed application that touched ~/Downloads. The agentic harness was the trigger, not the cause.
And — perhaps most importantly for the kind of reader who has spent a career inside UNIX — this is not a permissions story. POSIX permissions worked exactly as documented. They simply weren’t the load-bearing authority layer. The engineer mental model that still treats chmod and chown as the top of the access stack is the actual problem the incident exposes.
The failure was structural. And the structure it exposed was a scope I’d never named.
What’s Actually Happening at the Substrate
Here is the mechanism, because the mechanism is the evidence.
When a sandboxed application — Claude Desktop, in my case, but it could equally be any productivity app with file-picker access — touches ~/Downloads, macOS creates a security-scoped bookmark and writes an extended attribute called com.apple.macl to the directory. The attribute encodes a cryptographic record of the access grant, including the requesting app’s UUID. This is intended, documented sandbox behavior.
Once that attribute exists, every subsequent access to the directory routes through the sandbox policy evaluator — TCC, Transparency Consent and Control — before hitting the filesystem. Non-sandboxed processes hit the TCC evaluation path and get denied, because they don’t carry the sandbox entitlements TCC is looking for. Filesystem permissions are not consulted. They are not even reached.
The structural detail worth pausing on: TCC isn’t checking the user making the call. It’s checking the execution lineage — which app, instantiated from which signed bundle, running under which sandbox profile, made this request. A CLI tool invoked from Terminal has no such lineage to present. It wasn’t launched from a sandboxed bundle. It carries no entitlement to surface. Root doesn’t help because root is a property of the user identity, and TCC isn’t asking about user identity. It’s asking about the call’s origin in the application graph, and answering “this call has no recognized origin, deny.”
This is why sudo cannot help. The argument isn’t that root has no power. The argument is that on this evaluation path, filesystem privilege is irrelevant — TCC is asking a different question than POSIX answers. POSIX asks who is making this call? TCC asks what is making this call, and through which sandbox provenance? Root can answer the first question. It cannot answer the second.
This is not a unique macOS quirk. It is a recognizable family pattern. Kubernetes admission controllers override pod-level assumptions; IAM organization policies supersede local cloud permissions; enterprise MDM compliance layers invalidate local admin authority. In each case the structural lesson is identical: the documented permissions model is not the actual enforcement layer. The OS, the cluster, the cloud, the enterprise — each one runs an evaluation stack above the layer most engineers think of as authoritative.
The engineer who hasn’t internalized this lives one substrate-level incident away from being surprised by it. As I was.
The Scope You Forgot to Name
My CLAUDE.md hierarchy at the time of the incident had three named scopes:
- Global (
~/.claude/CLAUDE.md) — personal defaults - Project (
.claude/CLAUDE.mdper repo) — context-specific overrides - Skill — local instructions inside individual skills
Three scopes, each owned, each with rules about precedence. None of them named the operating system.
This sounds obvious in retrospect — of course the OS isn’t a CLAUDE.md file — but the obviousness is exactly the failure shape. The OS was a layer my governance model depended on without governing. Worse: it was a layer that could mutate my system’s state — write an extended attribute, lock a folder, route future calls through an evaluator — without triggering any signal inside my configuration hierarchy. None of my files knew the OS had acted. None of my files had standing to anticipate that it would.
That is the pathology, stated as compactly as I can state it:
Something outside your model is inside your system.
Not “you wrote the wrong rules.” Not “your scopes conflict.” Something stronger: an external dependency can mutate your governed state, and your governance model has no scope from which to see or anticipate the mutation. The unnamed scope is not a missing file. It is a missing acknowledgment.
The fix is not to write a CLAUDE.md for the OS. The OS does not read your files. The fix is to acknowledge — in the model, in the hierarchy of precedence, in the protocols you write for yourself — that the OS exists as a scope with authority you do not hold, behaviors you must anticipate, and constraints that override your stated rules. Name it, even if you cannot govern it.
That naming changes everything downstream. The structural shift is concrete: an unnamed scope produces unexpected failures — surprises, weird bugs, recurrences you didn’t see coming. A named scope produces anticipated failures — exceptions you can route around, conditions you can check for, behaviors you can design against. The failure doesn’t disappear when you name the scope. It moves from your surprise budget to your exception-handling budget, which are two completely different things.
Once the OS layer is in the model, the SessionStart hook that originally triggered the recurrence becomes redesignable: not “a hook that runs on every session,” but “a hook that runs on every session, aware of which operating system it’s running on, and which sandbox behaviors that OS will impose.” The instruction’s altitude changes because the model has more layers.
The Fix Hierarchy, Mapped
Field Notes № 014 introduced a four-layer model for agentic substrate failure: L1 Identity, L2 Authority, L3 Gating, L4 Recovery. The PocketOS incident decomposed cleanly against those layers. So does this one. The four fixes I applied in sequence map directly onto the framework:
L4 — Reactive xattr clear. xattr -d com.apple.macl ~/Downloads. Restores access. Does not prevent recurrence. Necessary, insufficient.
L3 — SessionStart hook backstop. A hook that clears com.apple.macl from ~/Downloads, ~/Desktop, and ~/Documents at every session open. Prevents recurrence across all nodes. Relies on the hook’s correct deployment but does not require knowing which app set the attribute.
L1/L2 — Full Disk Access grant. On my M4 Pro, where I identified Claude Desktop as the responsible sandboxed app, granting it Full Disk Access pre-authorizes its access entirely, which cuts the per-directory stamping cycle at its source. This is the structural fix — it re-establishes identity and authority for the requesting app inside the OS’s own model. Whether that grant is the right trust calibration for your environment is its own question, and outside the scope of this piece.
The work laptop fallback. On the work machine, I never identified the specific app responsible for the attribute. The L1/L2 fix wasn’t available to me there. The L3 hook is the active mitigation — and it works.
That last layer is the one worth pausing on. The work laptop’s resolution is L3 carrying weight that L1/L2 would normally take. In a textbook account, this looks like compromise. In practice, it is the standard pattern: in complex systems with partial visibility into the responsible component, mitigation regularly precedes complete structural understanding. You stand up the gate first, then you keep looking — and sometimes you never find the answer, and the gate is what protects you.
But it’s worth being honest about what L3-alone actually means. The unidentified app is still unidentified. I don’t know what’s setting the attribute. I still have a hook that clears it on every session open — which means I have an invisible state-mutator running inside my system, on a schedule I can predict, with mitigation that holds if and only if the hook continues to deploy correctly to every node. That isn’t governance. It’s a controlled standoff. The fact that it has held so far is evidence of the mitigation’s competence, not of the system’s structural completeness.
The unresolved attribution still nags at the engineer in me. The discipline is recognizing that the nag is information, not direction.
The Same Shape at Every Scale
Take that sentence — the discipline is recognizing that the nag is information, not direction — and re-read it as if it described an organizational failure rather than an OS one. Because it does.
Pick any large matrixed organization. When a problem surfaces in one corner, you’ll find smart people, high performers working to solve it. Without a governance layer that can see the work in progress across teams, two or three other groups encounter the same problem independently and begin to build their own fix. The fixes overlap in some places, conflict in others, leave the original problem unaddressed in yet others. None of them attach to one another. There is no scope with explicit authority over the cross-team problem domain, and no visibility infrastructure that would let parallel efforts find each other early enough for coordination to emerge.
Four parts to that pattern: independent discovery, knowledge-management failure, governance vacuum, fix proliferation with drift. They map directly onto the xattr case. The unnamed scope at OS level is the unowned problem domain at organizational level. TCC silently enforcing its rules is the enterprise substrate silently enforcing operational reality — CI/CD gates blocking deployments, regulatory checks rerouting releases, compliance systems quietly vetoing roadmaps — without asking what the org chart says. Three machines deterministically reproducing the same failure under identical software conditions isn’t the same as three teams chaotically reproducing the same coordination failure under political and budgetary pressure — the mechanisms differ — but the structural shape of the failure is identical: parallel work that the system has no infrastructure to surface to itself. And the prescription is identical in shape: name what you depend on, build the infrastructure that lets you detect parallel work, treat visibility as the substrate of governance rather than its decoration.
A fair reader will push back here: organizational duplication has other causes too. Politics. Budget partitioning. Territorial behavior. Incentive misalignment. All true. The unnamed-scope claim is not a complete theory of organizational dysfunction. It is one structural cause, and a recurring one, and it is the cause most often missed because it presents as a coordination failure rather than a governance failure.
The substrate doesn’t care which interpretation the operators prefer. At personal-infrastructure scale, three machines and one unowned scope teach the lesson cheap. At organizational scale, you don’t get to find out on a different machine. You find out in front of a customer, or a regulator, or a board.
Close
Three machines. Two fixes. One scope nobody owned.
The OS doesn’t care which file in your hierarchy failed to acknowledge it. The substrate enforces what it enforces. The governance layer either names what it depends on, or finds out the hard way — repeatedly, on different machines, until the lesson is forced.
Name what you depend on. Especially the scopes you don’t have files for.