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

Federation, Playdate, and Apple-platform checkpoint

Status: implemented and locally verified on 2026-07-14.

Post-checkpoint update (2026-07-14): the portable-library audit below is a record of the state at this checkpoint, not the current package graph. The follow-up split moved the universal blob, fit, json, math/*, and time modules to pitlib; consolidated all file target modules inside the one std package; and extracted pit-net, pit-tls, pit-http, pit-archive, pit-watch, pit-telnet, pit-smtp, and pit-ssh. The empty Web net and unavailable TLS packages were deleted. fetch now selects $nsurl_session, $playdate_http, or $browser_fetch on those targets. See native-module-and-endowment-audit.md for the current ledger.

This checkpoint merges compiler_optimizing into shop_overhaul, turns the shop, compiler, linker, standard library, and target providers into explicit workspace packages, produces sealed Mach application bundles for Playdate and the Apple simulators, and records the remaining library and Playdate work.

Package federation

The repository is now one checkout containing multiple real package roots. That is intentionally the first deployment shape: package identity and dependency resolution are no longer inferred from folders in core, while a later change can move any package root to its own repository without changing use() semantics.

The important boundaries are:

  • pit-shop owns realization, source resolution, package state, and target selection;
  • pit-compiler owns the language compiler and optimization passes;
  • pit-linker owns target toolchains, QBE lowering, and final linking;
  • std owns portable library policy;
  • target implementation packages own the selected file, net, TLS, process, and daemon-transport implementations;
  • git, fetch, and cake are private build-tool packages.

The root manifest selects those packages by dependency alias. In particular, the shop imports pit-compiler/compiler; replacing the pit-compiler dependency locator is now the package-level seam for using a different compiler checkout or repository. Some boot wiring still assumes that alias name and executable protocol, but it no longer assumes the compiler files live inside core.

The default shop fallback is now only std. core is not an ambient fallback. Remaining core/... imports are explicit private dependencies or runtime implementation imports, so they are visible in a package’s graph rather than accidentally exposed as standard-library names.

The merge exposed a stale Git boundary: the optimization branch deleted internal/git_worker.ce, but the later package-split git module still started it. The worker now belongs to the git package and explicitly imports the private process adapter from core; clone, checkout, update, head, origin, and version remain asynchronous requestors.

Portable library audit

The main I/O stack composes correctly:

std/file provider ----\
                       +--> std/io byte-channel operations
std/net provider -----/
          |
          +--> std/tls
          +--> std/http (HTTP/1.1 client and server)
                    |
                    +--> fetch (whole-body convenience requestor)

std/net + std/io also feed websocket, SMTP, Telnet, SSH, DNS, and courier/SEIF.

file and network connections expose the common channel operations used by std/io. http connects through generic net, upgrades through generic tls, and returns its body as a channel. fetch is the higher-level whole-body operation and drains that channel. WebSocket, SMTP, Telnet, and SSH also consume generic network channels rather than raw descriptors.

The following items were behind the architecture at this checkpoint. The fetch item was completed on 2026-07-15:

  1. fetch now selects native NSURLSession, browser Fetch, WinHTTP, dynamically realized libcurl, or Playdate HTTP. It no longer drains the portable HTTP-over-net experiment.
  2. std/http is HTTP/1.1 only. std/h2 and HPACK are useful codecs with tests, but they are not negotiated or composed into the public HTTP client. TLS currently advertises only http/1.1.
  3. std/random and std/time still wrap core/internal/os and core/internal/time. They should follow file: a portable module above target-selected raw clock, entropy, and calendar providers.
  4. std/dns implements DNS and mDNS over UDP and reads POSIX-style resolver files. That is useful protocol code, but it is not an honest universal system resolver for web and constrained targets. Ordinary hostname resolution already belongs to net; DNS packet and service-discovery APIs should be named and packaged separately.
  5. The protocol namespace is still flat (http, smtp, ws, tar, zip, and so on). A Go-like organization such as net/http, net/smtp, and archive/tar would make ownership clearer. That is a public naming choice, so this checkpoint reports it rather than silently selecting the final names.
  6. ssh is substantial protocol and cryptographic code with only manual integration coverage. It uses the correct net/io channel seam, but it should probably become its own package instead of growing the minimal standard-library package.
  7. Target-provider packages currently consume small std helpers through the shop fallback rather than declaring a dependency back to std. This avoids a package dependency cycle (std -> provider -> std), but the long-term provider-support package or internal-namespace rule should make that relationship explicit.
  8. Package privacy is conventional, not enforced. A package can still name an explicit core/internal/... locator. The ambient namespace is gone, but a later privacy rule is needed if internal is to be a hard boundary.

Playdate packaging and readiness

The Playdate application pipeline now emits a sealed Mach seed and packages it with the native Playdate runtime. The bouncing-ball harness runs the same seed and confirms target-selected std/file reaches the Playdate file provider and that the raw Playdate graphics/input endowments drive frames. There is no source compiler in the application bundle and no native/QBE application payload is required.

The simulator package is approximately 12 MiB: about 11 MiB of seed plus a 1.3 MiB simulator executable. This proves the compilation, selection, and packaging pipeline. It does not yet prove that the physical 16 MiB device can run the current memory model.

The optimization branch materially improves Mach execution: typed numeric lanes, exact array loads/stores, fused guards, self-tail-call paths, compact raw continuations, record sizing, and native/Mach suspension work are present and heavily regression-tested. Its Playdate research also reaches a clear result:

  • the active runtime still uses 64-bit PitValue; the accepted 32-bit playdate-nan32 representation is design/prototype work, not the active device representation;
  • the runtime still allocates separate arenas/pools rather than one bounded process-wide Playdate arena;
  • current defaults include a 1 MiB constant arena and an initial 16 MiB buddy pool, already incompatible with a 16 MiB machine before platform and seed memory;
  • compact pointer/key representation and a measured device heap budget remain implementation work; and
  • QBE has no ARM32 backend in this tree, which is why Playdate remains Mach only.

Therefore the simulator app is ready to plug into the Playdate toolchain, but calling it physical-device-ready would be misleading. The next Playdate decision is the representation/arena campaign; actor heap tuning should wait until that architecture is selected, as requested.

iOS, tvOS, and watchOS

All three Apple simulator targets now build sealed Mach-only applications. They share the Darwin asynchronous file, network, and TLS providers, but each application claims its own raw UI endowment:

targetraw UItarget-specific proof
iOS$uikit_window + $spritekittouch/tap repositions and kicks the ball; swipe reverses it
tvOS$uikit_window + $spritekitSiri Remote direction/select/play-pause events alter motion
watchOS$watchkit_interface + $spritekitDigital Crown changes speed; tap moves and swipe reverses

Each app first performs write, append, stat, and read through generic use('file'). Runtime logs confirm the selected provider is darwin-dispatch/dispatch-worker, not a platform-specific file facade. Simulator launches and rendering are verified for all three, and iOS touch is verified end-to-end through the raw event signal into the Pit actor. The tvOS adapter now makes its input view first-responder-capable so UIKit UIPress delivery has an explicit focus path.

The produced .app directories contain the target runtime, seed.qop, Apple metadata/resources, and signatures. They contain no .cm, .ce, compiler, or source tree. Device signing/provisioning is outside this simulator checkpoint.

Remaining decisions and work

  1. Choose the final public namespace for archive and network protocols, then move or split the flat modules without compatibility aliases.
  2. Integrate HTTP/2 with the public HTTP policy where the platform or TLS ALPN supports it; target-selected fetch providers are complete.
  3. Move random/time/calendar onto target-selected raw providers.
  4. Decide and implement the Playdate 32-bit value plus single-arena memory architecture; only then tune actor heap policy and test a physical device.
  5. Enforce package privacy and continue moving private runtime services out of core where repository independence requires it.
  6. When desired, replace local workspace member locators with real repository locators. The resolver and manifests are now shaped for that move.

Source: plans/archive/perf-2026-07/federation-checkpoint-2026-07.md