Archive — history, not state. Kept for its reasoning and its evidence; its plan is closed.

Clerk — ARCHIVED 2026-08-03 (C1–C6 landed)

The C line landed in full. C1–C3 established file-granular acquisition, lazy closure preload, and explicit preload/mirror APIs (80d6b259e, merged by 93c69a579). C4 put Git and linked directories behind one advertise/serve upstream protocol and one content-addressed cache (de9633472, merged by 2dfe16eac). C5 made peer shops upstreams over the same protocol (1b28b74ea). C6 named the source-acquisition actor clerk, deleted the old actor/capability vocabulary, and placed the clerk beneath the compiler, fetch, and service fleets (d6fdc3122; C5+C6 merged by 2a6cb2d44).

The C4 close-out lesson is the failed bounded-delivery landing 029361dd1: a fixed width of eight added boot-path backpressure and deadlocked the cold listener. The final C4 drain is instead an unbounded breadth-first turn wave: every callback ready at a turn boundary runs, and callbacks it creates wait for the next turn. That is exactly F3’s ruling — width is an option, the default is unbounded, and backpressure is never a design assumption (plans/derivations.md:158-161). The turn boundary supplies the trampoline/fairness seam; it is not a disguised width.

This file is now a historical record for reasoning, not an active work line. The active index is plans/board.md.

Original plan — lazy, file-based acquisition, and the naming of the shop’s halves

Written 2026-08-02 from John’s ruling. Third of the sibling plans: plans/one-binary.md owns the floor, plans/derivations.md owns turning files into artifacts, this plan owns GETTING the files — and it names the actor that does it. All three share one principle: walk closures, work per-file, in parallel, through requestors; list nothing by hand; nothing greedy, nothing eager.

The verdict on the current machinery

fetch_closure (pit-shop/shop_fetch.cm) walks a program’s import graph “fetching missing PACKAGES along the way” — package-granular and greedy: resolving one entry point clones whole repositories. Links are a separate special lane (pitfs.mount_fs of a live directory), so linked and remote packages take different read paths. Both violate the model below.

The model (John, 2026-08-02)

  • The system is totally file-based. Packages exist to provide a common package.json — shared linker configuration and self-description (its natives, its endowments). A package is a namespace with a manifest, not a unit of transfer.
  • Starting an actor fetches exactly what the actor needs. The sequence for gitea.pockle.world/john/accio::accio:
    1. Get that package’s package.json (link replacements, natives).
    2. Get accio.ce — one file.
    3. Resolve its use imports and endowments to FULL locators.
    4. Fetch the missing ones — in parallel, via requestors — and iterate: their imports, their packages’ package.jsons, transitively. This includes specific files from other remote packages (prosperon, a game engine) — never those packages in full. Present files are never re-fetched; the cache is content-addressed and the check is per-file.
  • Preloading is explicit, not a side effect. Two APIs:
    • preload([locators]) — pull the full closure of a list of actors.
    • mirror([packages]) — pull complete packages, for the cases that genuinely want everything. Actor start NEVER implies mirror. The game sequence shows the split: accio starts lazily, pulls what it needs, runs with prosperon; when prosperon mounts mod packages, IT asks the shop to pull those in — mounting a mod is the explicit act that justifies the full pull.
  • Links become uniform with remote packages. A linked package’s source is copied into the cache like fetched source; the local directory is just a very fast upstream. The freshness question (“did the linked source change?”) is the SAME per-file hash check the derivations plan already asks on every start — one primitive answers both, and the special mount lane dies. (John flagged “unless that’s a pain”: it is not — it is the derivations freshness primitive applied to one more upstream. The one requirement: the per-start check on linked upstreams stays cheap, so edits appear instantly. If measurement ever says otherwise, the fallback is a dirty-notification from the editor side, not a return to the special lane.)
  • The shop can mount anything that has a cache. That is the whole interface: an upstream advertises what it has and serves files by content. A remote git repo: get the manifest, get the specific file. A linked directory: same, locally. Another SHOP: same — it answers with what its cache holds and sends objects over, exactly like git transfer. One protocol, every source. (This is also one-binary’s bundle story from the other side: a mounted bundle is an upstream whose cache happens to arrive as one file.)

Relationship to the derivations plan — no conflict, one lattice

Fetch is the FIRST LEG of the derivation atom. unit_mcode(locator) begins “resolve, check the store” — this plan supplies the step before compile: locate → fetch if absent → compile → lower. The closure walk is SHARED: one import-scan drives both what to fetch and what to build, and the endowment/policy gate happens once, at closure time, before either. The fetch requestor is used by the derivation requestors and composes the same way (parallel(fetch …) over the miss set). Neither plan waits on the other; they meet at the requestor signatures.

The clerk — naming the halves, and the answer to “do we need another arc”

No third arc. The clerk IS this plan’s organizing frame. The ruling as discussed: clerk = the thing that finds source bits given a locator — resolution, the cache, upstreams (git, links, other shops, bundles), the fetch fleet. The SHOP was always really the consortium: boot starts the clerk; the clerk (with policy beside it) is what the compiler fleet (derivations D2), the fetchers, and the services stand on. The rename lands as the natural outcome of this plan’s increments — when acquisition is one actor’s clean job, that actor gets the name — rather than as a rename-first refactor. The fleet after both plans:

  • boot (irreducible, from the boot section)
  • clerk — locator→bytes: resolve, cache, upstreams, fetch requestors
  • policy — the deny gate, consulted at closure time
  • compiler/lowering requestor fleets (derivations D2; the one builder_worker dies there)
  • services (logger, courier, listener, terminal) — unchanged

What this deletes

  • Package-granular greedy fetch: fetch_closure’s clone-on-miss walk and every “fetch the whole package to get one file” path.
  • The special link lane: resolve_link_target + live pitfs.mount_fs mounts as a distinct read path — links become an upstream of the one cache.
  • The separate answers to “what do you have?” per source kind — one advertise/serve protocol for git, links, shops, bundles.

Increments

  • C1 — the locator requestor. file(locator) → bytes: resolve through package.json, check the cache, fetch from the upstream on miss. The atom this plan contributes to the shared algebra. Wire the existing entry paths to it without changing granularity yet.
  • C2 — lazy actor start. The start path walks the closure and parallel(file …)s the misses — full-package clone dies for starts. The accio scenario is the acceptance test: starting a remote actor transfers only its closure.
  • C3 — preload/mirror. The two explicit APIs; prosperon’s mod-mount asks for mirror. pit shop install becomes mirror by another name.
  • C4 — uniform upstreams. The advertise/serve interface; links copied into the cache with the per-file freshness check; git and linked directories behind one protocol.
  • C5 — shop-mounts-shop. A shop as an upstream serving its cache, git-transfer-style. (Also the seam where a future shared team cache lives.)
  • C6 — the clerk split. Acquisition consolidated into the clerk actor; the name lands; boot starts clerk, clerk stands under the fleets.

Ordering: C1/C2 can start immediately and are independent of one-binary and of derivations D1/D2 (they meet only at requestor signatures). C4’s link uniformity should land with or after derivations D1, since it reuses the per-file freshness primitive. C6 last, when the job is clean enough to name.

Implementation checkpoint — 2026-08-02

  • C1: file(locator) is a coalesced requestor backed by a content-addressed object/catalog mapping and a partial bare Git upstream. Resolver misses fetch manifests and candidate files, never package checkouts.
  • C2: canonical remote starts preload their source closure; module and executable claims resolve in parallel and use the same file requestor. Exact-closure coverage uses a canonical remote-shaped package backed by a small local Git upstream.
  • C3: preload and mirror are public requestors and CLI commands; fetch aliases preload, install aliases mirror, and update refreshes mirrors per file. Mirror refresh removes locator mappings for files deleted upstream while retaining immutable objects by content hash.
  • C4: implemented on codex/clerk-c4-wip after D1 landed: Git and linked directories share advertise/serve, linked bytes enter the same content-addressed cache, and starts reuse E2’s pit.mcode.unit.metadata@1 closure record instead of walking it twice. File-flight completion is coalesced in unbounded breadth-first turn waves: every callback ready at the turn boundary runs, while callbacks created by that wave wait for the next actor turn. There is no implicit width or boot backpressure. Refresh joins cannot publish a stale Git result, and linked manifests arrive before target-specific module candidates are selected. The exact cold drill (remove boot/boot.cart and boot/cart.stamp, plain make, then ./pit ps) and the focused requestor/link gates pass on dev 82d1b05db. The baseline completes 2,302/2,303 after that drill; its sole failure is cart_payload_form, whose documented precondition is the deliberately removed boot/boot.cart.
  • C5: pit shop mount accepts another shop directory as well as a frozen bundle. A peer shop advertises the source locators represented by its cache and serves the catalog-selected object through C4’s protocol; the receiving shop verifies the content hash before copying the bytes into its own cache. Peer mounts precede Git origins, persist independently of bundle mounts, and share the public mount/list/unmount API.
  • C6: the source-side shop actor is now pit-shop/clerk. The fixed root starts it as a boot service and delegates source resolution, cache, upstream, hydration, realization, and service/build coordination through the clerk capability. The old development_shop program and its handoff protocol names are deleted rather than retained as aliases; compiler, fetch, and service fleets continue to stand on the clerk boundary.

The live gitea.pockle.world/john/accio acceptance reaches the partial Git upstream, but its current HEAD has pit.toml and no required package.json. The clerk does not revive the retired TOML manifest path; migrate that package before using it as the live C2 acceptance repository.

Source: plans/archive/clerk.md