Files
dckcandClaude Opus 5.5 fe9ad200c4 refactor(no-ambient-authority): rename from ocap-discipline
Name the skill for what triggers it. Cite Wikipedia on capability-based
security and ambient authority, and point newcomers to awesome-ocap.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 18:35:03 -05:00

2.8 KiB

name, description
name description
io-between-turns I/O between turns — use when writing or reviewing code that reads or writes files, sockets, databases, or other shared external state; when choosing between sync and async APIs (readFileSync vs fs/promises, DatabaseSync, blocking calls); when someone says "sync I/O is a pointy instrument" or "I/O should be done between turns". Sync access is fine only for state that is local, prompt, and private to the one actor (e.g. a Durable Object's SQLite).

I/O between turns

Event-loop concurrency (E, JavaScript, Workers) runs one turn at a time: deliver one event, run the resulting calls to completion, then take the next. A turn that never waits on the outside world is isolated: nothing else can change what it can see while it runs. I/O on shared or slow resources belongs between turns: issue it, end the turn, and continue when the result arrives as a later event.

"Execution proceeds by taking a pending-delivery from the queue, delivering its message to its object, and processing all the resulting immediate-calls in conventional call-return order. This is called a turn. … Because each event's turn runs to completion before the next is serviced, they are temporally isolated." — Concurrency Among Strangers: Programming in E as Plan Coordination, Miller, Tribble & Shapiro, TGC 2005, §5.2

"The actual E system does provide synchronous file I/O operations. When these files are local, prompt, and private to the vat accessing them, this does not violate turn isolation, but since files may be remote, non-prompt, or shared, the availability of these synchronous I/O operations does violate the E model." — same paper, §6, footnote 5

(Mark Miller's thesis, Robust Composition, 2006, builds on this paper.)

the rule

  • Shared, remote, or slow state → async, between turns. The filesystem, the network, other processes' databases: use promise APIs (node:fs/promises, fetch) and await them. No readFileSync/writeFileSync, no blocking calls inside a turn.
  • Local, prompt, and private to the actor → sync is fine. A Durable Object's SQLite (ctx.storage.sql) is reachable only by its own DO, so it is "more or less more RAM": synchronous access keeps turn isolation.
  • Only a sync API exists, for shared state? (e.g. node:sqlite's DatabaseSync on a file other processes may touch.) Keep it at the program's edge and say why in a comment, so it doesn't read as a precedent.

see also