This table gathers every pyproc capability behind the product entrance a user starts from. It is not a market-readiness or adoption table: it groups the public surface by intrinsic value, contract state, prerequisites, runnable surface, verification, and boundaries.
Canonical sources are split:
- Install, version pinning, import boundaries: contract.md
- The speed-measurement contract: benchmarking.md (measurements live only in ledgers and artifacts. Speed is something you measure yourself with the Speed Lab, not a number posted here for you to trust)
.pymachinetrust and the permission UI: trustPermissions.md- Portable bundle (
PYBUNDLE1) envelope layout: bundleFormat.md - Reopening product resources after a revival: resumeCatalog.md
- Platform requirements and preflight (browser, JSPI, COOP/COEP, engine, resources): platformRequirements.md
- PyProc Eyes perception and evidence wire: APX 1.0
Contract states match the README's Capability contract. They describe only what pyproc itself can prove.
| State | Conditions |
|---|---|
| Complete | The declared success, failure, and recovery invariants run in a real browser; the installed package exposes the same path; a deliberate failure proves the guard; types and docs state the boundary. |
| Bounded | The listed behavior is implemented and gated, while a precise intrinsic boundary remains in the row. No fallback or elapsed-time condition changes this state. |
| Probe | A runnable experiment proves a narrow mechanism, but it is not part of the default product entrance. |
| Engine proof | A second engine proves separation of primitives; it is not the default Python Machine. |
A state drops immediately if its own invariant, installed path, negative proof, or declared boundary disappears. Adoption, user count, another repository, release age, and market response are never inputs.
Every Complete row appears here. The structure gate compares the two sets and rejects missing browser, installed-package, negative, or boundary evidence.
| Surface | Invariant | Browser gate | Installed-package gate | Negative proof | Declared boundary |
|---|---|---|---|---|---|
| Python runtime | Real CPython executes, loads packages, and owns file IO in the tab | npm run test:browser |
npm run test:installed |
invalid options and corrupted engine bytes are deliberate RED fixtures | Pinned Pyodide package corpus and browser platform requirements |
| Deployment asset integrity | Engine, worker, and Service Worker bytes are verified before execution | npm run test:browser |
npm run test:installed |
bad script, core, worker, and manifest hashes are deliberate RED fixtures | Same-origin static asset layout |
| Default durable Machine | open() settles a command only after heap, /home/web, and outcome share one durable generation |
npm run test:browser |
npm run test:installed |
commit failure and failover outcome-unknown paths are deliberate RED fixtures | Last completed generation; an unprovable in-flight effect is never replayed |
A runnable surface is an example a person opens, a browser gate, a probe, or a tracked benchmark artifact. Every product claim must be reproducible through one of the runnable surfaces in the table below.
| Capability | Product value | Public surface | Contract state | Prerequisites | Runnable surface | Verification | Boundaries |
|---|---|---|---|---|---|---|---|
| Python runtime | Runs CPython, package loading, stdout/stderr, and file IO in a browser tab | boot -> machine handle (machine.run/machine.fs), checkEnvironment, escape hatch machine.runtime (Runtime, FileSystem, MemoryCapability); PAGE_SIZE is in pyproc/history |
Complete | A supported browser (platformRequirements.md), Pyodide v314.0.2 (CPython 3.14), optional SRI, and use of the public API rather than the internal raw.FS |
basic example, browser gate | npm test, npm run test:browser, npm run test:installed |
Not a guarantee for every Python package. Native C extensions need a Pyodide build or a static build |
| Deployment asset integrity | Copies worker, SharedWorker, and Service Worker assets to your own origin and verifies the bytes | getPyProcAssetManifest, verifyPyProcAssetIntegrity, registerPyProcServiceWorker, PYPROC_ASSET_MANIFEST_VERSION in pyproc/assets |
Complete | Your deployment preserves the manifest's relative path structure, provides the pyproc-assets SRI manifest, and configures Service Worker scope and headers |
asset manifest CLI, installed-package browser gate | npm test, npm run test:package, npm run test:installed |
Opening a worker graph from CDN URLs alone is blocked by the browser's same-origin policy |
| Restore reactivity | Saves state at execution boundaries and offers live-diff restore, time travel, and branching | machine.history (checkpoint/restore/tree/prune); the internal contract is ReactiveController (machine.runtime.enableReactive()) |
Bounded | Declared checkpoint boundaries, the recorded engine/manifest contract, and a restorable heap delta | browser gate, the [hash soundness] and [reactive tree] property and fuzz sections of the structure gate | npm test (the [hash soundness] false-negative fuzz plus the [reactive tree] arbitrary-tree reference-integrity property, both with negative tests confirmed), npm run test:browser (full-heap byte-for-byte round trip and more) |
Does not automatically capture an in-flight Promise, a network request, or an external handle at an arbitrary moment |
| Process OS | Spawns Python workers as processes and offers snapshot-fork, live fork fan-out (forkMany), map, mapArray, sharded matmul, signals, and IPC |
machine.proc() -> PyProc, SIGNAL |
Bounded | crossOriginIsolated, SharedArrayBuffer, JSPI, same-origin worker assets, and handling of the checkEnvironment() result |
process OS example, speed lab, browser gate, installed-package browser gate | npm run test:browser, npm run test:installed, npm run test:examples |
Not full POSIX fork and not native shared-memory threads. It is a browser-worker OS model. The boundary identity that fork and forkMany rest on holds only worker-to-worker: a replay in the main kernel and one in a worker kernel produce different bytes even at the same heap length (loader and context differences), and for the same reason heap addresses differ across browsers and machines (same contents, different layout; measured 2026-07-17 at 178-184 of 480 pages). That is why fork stays between workers and PyProc is the coordinator |
| Browser server URL | Runs a Python ASGI app inside the kernel and fetches it from a real browser URL | machine.runtime.enableAsgiServer() (AsgiServer), VirtualOrigin (SW registration through registerPyProcServiceWorker in pyproc/assets) |
Bounded | pyprocSw.js Service Worker registration, same-origin scope, and a route-prefix design |
server dev example, installed-package browser gate | npm run test:installed, npm run test:examples |
Not a real TCP listener, and three boundaries are now measured and gated rather than assumed: a synthesized response cannot set a browser cookie, a WebSocket upgrade never reaches the kernel (fetch interception only), and a streaming response arrives as one buffered body, so more_body is accepted but SSE does not stream |
| Terminal and borrowed syscalls | Attaches a serverless Python terminal, blocking input, a subprocess worker, and a sync bridge | machine.term() (Terminal), machine.runtime.enableSyscallBridge() (SyscallBridge) |
Bounded | A JSPI-capable browser, terminal UI event wiring, and the child worker asset | terminal example, terminal probe, syscall probe | npm run test:browser, terminal and syscall probes |
A borrowed-syscall layer, not a complete POSIX syscall table |
| Environment lane | Reproduces a repeatable environment from a declaration (packages, lock, wheel cache) | The boot manifest (packages/env/setup/wheelDir, absorbing the former bootEnv/runScript), machine.runtime.enableWheelCache() (WheelCache) |
Bounded | Wheels installable under Pyodide, a consistent lock and manifest, and an OPFS cache | env manager campaign, PEP 723 probe, wheel cache probe | env manager probes, installed-package gate | Native wheels cannot be carried over as they are. Reproducibility breaks if engine, lock, and cache fall out of step |
| Portable machine image | Exports the heap delta and /home/web as a .pymachine and reopens it under a signature and a trusted public key |
boot({ deterministic: true }) (formerly bootSession) plus machine.history.export/save (formerly Session), open (formerly openMachine); the signature chain lives in pyproc/history (formerly createMachineKeyPair/exportMachinePublicKey/fingerprintMachinePublicKey), Init (machine.runtime.enableInit()) |
Bounded | The same engine and manifest, use of /home/web, a trust key or explicit trust, and a resume.py hook design |
machine example, installed-package browser gate, golden workflow | npm test (the [envelope and image boundary] section: bundle index-forgery rejected at the prefix, machineImage adversarial-input boundaries, negative tests confirmed), npm run test:installed, npm run test:golden |
A signature is provenance trust, not permission. File descriptors, sockets, and DB connections must be reopened by resume.py |
| Machine journal | Uses idle commits and a WAL to revive a crashed tab from the heap and /home/web of the last commit |
machine.history.commit/recover/watch/pack (MachineJournal) |
Bounded | OPFS, an idle-commit policy, pack/prune operations, and the same engine and manifest | journal probe, large heap journal probe, installed-package browser gate | journal probes, npm run test:installed |
A long-lived blob store grows without pack and prune. It is subject to browser storage quota. Changes after a commit are lost |
| Permission jail | Restricts Python code's net, clipboard, home, and worker permissions through a permission manifest and CSP | enableJail(permissions) on machine.runtime, returning { jail, permissions, connectSrc } |
Probe | A permission manifest, the jail context's CSP, a host allowlist, and a permission UI | jail probe, installed-package browser gate, trust and permissions | npm run test:installed, npm run test:browser (the enableJail evidence checks), jail probes |
Not a sandbox that removes every side channel available to code in the same parent window. Strong isolation requires an opaque-origin design |
| Browser automation product | Lets MCP and native clients run persistent Python, semantic browser actions, deterministic device viewports, first-navigation tracing, native screenshots, and bounded artifact retrieval on an allowed Chromium target | Installed pyproc-mcp and pyproc-control bins share one version 1 manifest and ControlHost. The stable pyproc/control Node.js facade starts that same host. The 23-action pipeline provides eight-state semantic readiness, explicit lazy hydration, PNG/JPEG/WebP artifact delivery, opaque chunk read/delete, popup and frame handling, and a separately raw-allowlisted command |
Bounded | Node 22, a pinned engine root or immutable index URL, Chromium-family major 137 or newer with CDP protocol major 1, a broker-owned temporary profile, exact HTTP(S) origins and actions, fixed risk, filesystem roots for upload, and operator acknowledgement plus purpose for external effects | browser automation product guide, JavaScript Control SDK, Control Protocol guide, installed MCP and native product gates | npm run test:contracts, npm run test:package, npm run test:mcp, npm run test:mcp-product, npm run test:control-product, npm run test:browser-control, and npm run test:browser-control-stress on Chrome Ubuntu and Edge Windows |
The default surface remains four Python operations and opens no CDP authority. Opt-in control does not attach to the user's default profile, expose internal action methods as raw permissions, put the CDP endpoint in Python, or add a proxy listener. Startup traces redact query and secret-shaped values. Native images are bounded by the inline quota and retain the artifact chunk fallback. Lazy hydration is an explicit external effect. Artifact quota, TTL, deletion, and process shutdown bound disk retention. Open shadow roots and authorized frame chains are supported; closed roots are unsupported. Cookie values are absent from metadata reads and traces. Python restore never rolls back browser effects. An interrupted sent effect is outcomeUnknown and is not retried. The operator owns legal authority and consequential-action approval |
| PyProc Eyes perception | Lets clients reason over one bounded semantic, spatial, and temporal graph, request pixels only for unresolved regions, and verify an effect against DOM and network evidence | automation.observe with representation: "apx.graph", automation.act with verify, MCP native image attachments, Python client.perception(sessionRef), and JavaScript client.perception(sessionRef). APX schemas ship inside the npm tarball and examples live with the public contract without adding a Control operation |
Bounded | Browser automation authority with snapshot; screenshot for Native CDP visual probes; explicit action permission and risk acknowledgement for effects |
APX 1.0, JavaScript Control SDK, browser automation guide, Python SDK guide | npm run test:contracts, npm run test:apx, npm run test:mcp-product, npm run test:control-product, npm run test:frame-space, npm run test:replay-space, and npm run test:python-sdk on Chrome Ubuntu and Edge Windows |
Native CDP reports live level L4 plus verified crops; FrameSpace reports level L3 and visual mode off; ReplaySpace returns recorded terminals without live sensing. There is no shipped OCR or inference provider. entityRef is identity, not authority; locators expire; visual evidence never widens permission |
| Cooperative frame and replay providers | Runs an opted-in page in a credentialless sandbox without CDP, or replays a recorded automation suffix without sending browser effects | FrameSpace uses an authenticated machine bridge plus private target MessageChannel and returns level L3 APX. RecordingSpace writes a canonical SHA-256 chain plus content-addressed screenshot sidecars under an exclusive writer lock. ReplaySpace matches exact operation inputs and resumes only with identity, final, cursor, and prefix pins |
Bounded | Frame targets must load the shipped bridge and accept opaque-origin storage isolation. Recording files are absolute private paths and can contain full inputs. Recording JSON and artifact sizes are bounded; replay requires a complete chain and all sidecars | FrameSpace guide, ReplaySpace guide | Installed FrameSpace Control, MCP, and Python SDK gates; installed APX plus inline and non-inline record/replay gate with target request count zero; contract mutation, missing artifact, write failure, concurrency, shutdown drain, divergence, and cursor fixtures | Frame actions are cooperative and untrusted, screenshots are DOM renders, APX visual mode is off, and signed-in storage is unavailable. Recording digests are corruption detection, not authorship authentication. Python restore does not undo the original effect |
| Python control SDK | Lets a Python application start the same product host, run persistent Python, checkpoint, cancel, query APX perception, automate a browser, and receive verified screenshot bytes without JavaScript application code | Separate zero-runtime-dependency pyproc-control wheel and source distribution with PyProcClient, PerceptionClient, ControlRequest, ControlResult, Attachment, strict codec, and stable errors |
Bounded | Python 3.10 or newer, the same-version npm package on PATH, a valid product manifest, engine assets, and browser authority for automation operations |
Python SDK guide, clean install product gate | npm run test:python-sdk builds and installs both distribution forms in separate clean environments, runs transport and facade fixtures, and completes Native CDP plus FrameSpace Python, APX, checkpoint, cancel, permission, screenshot, digest, artifact, and single-use ID checks on Chrome Ubuntu and Edge Windows |
The SDK is a local client, not a hosted service. It does not bundle Node, Chromium, or the Python engine. A post-send cancellation is outcomeUnknown, and Python restore cannot undo external effects |
| JavaScript Control SDK | Lets a Node.js application start the exact installed product, run persistent Python, checkpoint, cancel, query APX through Native CDP or FrameSpace, and receive verified screenshot bytes | Stable pyproc/control with PyProcControlClient, PerceptionClient, ControlRequest, ControlRemoteError, strict protocol validation, and bounded owned-process shutdown |
Bounded | Node 22, the same exact npm package, a valid product manifest, engine assets, and explicit browser authority for automation operations | JavaScript Control SDK, installed Control product gate | npm run test:contracts, npm run test:types, npm run test:package, and npm run test:control-product import the public subpath and run Native CDP plus FrameSpace on Chrome Ubuntu and Edge Windows |
Node.js only. Browser application code uses the root Machine. The SDK owns no independent effect meaning and never retries applied or outcomeUnknown work |
| Outbound sockets | Lets Python socket, urllib, and http.client reach an external host:port |
SocketBridge (pyproc/socket) |
Probe | A WS-to-TCP relay, JSPI blocking recv, and product operation of that relay | hermetic socket lane, Python socket probe | socket bridge probes | Inbound sockets are a browser security wall. For HTTPS the relay handles TLS |
| Device filesystem | Exposes browser features as Python file paths | machine.runtime.enableDeviceFs() (DeviceFs) |
Bounded | Explicit device injection, browser permissions, and a clear file-path policy | installed-package browser gate, device FS probe, machine campaign | npm run test:installed, device FS probes |
Only explicitly configured devices allowed by browser policy exist |
| GPU compute | Uploads f32 arrays to WebGPU and runs a GPU-resident linear algebra pipeline | GpuCompute, GpuArray, GpuBridge (pyproc/gpu) |
Probe | WebGPU, a windowed browser, a real GPU, and an f32 data path | GPU campaign, GPU tiled probe, GPU Python probe | GPU probes on real hardware | WGSL has no f64. Headless CI numbers are not evidence of product performance |
| Default durable Machine | Opens one named Python Machine across tabs and cold-reopens it after every tab closes | open() / open({ name }) -> KernelElection; run auto-commits heap, /home/web, and forwarded outcome before settling |
Complete | Web Locks, BroadcastChannel, OPFS, the verified same-origin engine distribution, and the same origin. SAB-based OS capabilities also need crossOriginIsolated and JSPI |
immortal demo, kernel election probe, installed-package browser gate, golden workflow | npm test (serialized run/commit, commit-failure outcome-unknown, election fencing and outcome records), npm run test:installed (argument-free open plus cold reopen without manual commit), npm run test:golden |
Not a multi-user server. Recovery is to the last completed command generation. A normal follower cut off mid-command still cannot prove leader-heap portability, so the durable RPC state table closes it as non-retryable outcome-unknown |
| Machine container and jobs | Starts a separate machine kernel inside a browser worker and offers job control | machine.containers() -> MachineContainer, machine.jobs() -> JobControl (a process-OS lane: it assumes the same replay pool as machine.proc) |
Bounded | crossOriginIsolated, the worker graph, and an explicit process-lifecycle policy |
browser gate (the machine.jobs and machine.containers evidence checks), installed-package browser gate, machine container probe, job control probe, pipe and shm probe | npm run test:browser, the MachineContainer and JobControl rows of npm run test:installed, process OS probes |
Not a Linux container and not an OS scheduler. It is pyproc's browser-kernel isolation model |
| Guests on one wire | Two guests on one computer exchange real Ethernet frames instead of merely coexisting | The built-in network device of createWebComputer (a MemoryEthernetSwitch), the pyprocNet module inside the Python guest, and the frame law exported from pyproc/machine |
Bounded | createWebComputer with network left on, and a guest that speaks frames |
guest network probe, packet network probe | npm run test:web-machine (the guest network probe runs in CI; the Linux crossing is in the local --v86 lane) |
Only ARP and ICMP echo are answered automatically; TCP, UDP, and DNS are the guest's own business. There is no uplink, so guests reach each other and nothing else. Both guests currently share one JS thread, so a frame arrives between run() calls rather than during one |
| Non-Pyodide engine seam | Proves the session and time-travel primitives work on non-Pyodide CPython 3.14 WASI | bootWasi, WasiSession (pyproc/wasi) |
Engine proof | A caller-provided wasmURL, the WASI worker asset, and the JSON value bridge |
WASI browser gate, engine port campaign, WASI REPL probe | WASI gate, dual engine probe in npm run test:web-machine:wasi |
Not the production default engine. The value bridge is JSON-centric and C extensions need a static build |
- The README's Product entrances table is the API map. This document groups those paths into capability contracts backed by runnable evidence.
- Run
checkEnvironment()and the deployment preflight before entering a capability whose prerequisites require them. - Keep Probe rows outside the default product path until their own acceptance conditions become automated.
- Where the browser physically blocks something - inbound sockets and arbitrary native binaries above all - pyproc alone promises nothing. Those need a relay, an agent, a static build, or a change in the platform.