forkcell 0.1.0a0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
10
+
11
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
12
+
13
+ "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
14
+
15
+ "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
16
+
17
+ "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
18
+
19
+ "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
20
+
21
+ "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work.
22
+
23
+ "Derivative Works" shall mean any work, whether in Source or Object form, that is based on or derived from the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link or bind by name to the interfaces of, the Work and Derivative Works thereof.
24
+
25
+ "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner.
26
+
27
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
28
+
29
+ 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
30
+
31
+ 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work.
32
+
33
+ 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, provided that You meet the following conditions:
34
+
35
+ (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
36
+
37
+ (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
38
+
39
+ (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
40
+
41
+ (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file.
42
+
43
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work shall be under the terms and conditions of this License.
44
+
45
+ 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work.
46
+
47
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48
+
49
+ 8. Limitation of Liability. In no event and under no legal theory shall any Contributor be liable to You for damages arising as a result of this License or out of the use or inability to use the Work.
50
+
51
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer support, warranty, indemnity, or other liability obligations on Your own behalf only.
@@ -0,0 +1,12 @@
1
+ ForkCell
2
+ Copyright 2026 BeforeWire.
3
+
4
+ ForkCell is distributed under the Apache License, Version 2.0.
5
+
6
+ ForkCell depends on OpenShell as its governed runtime. The preview branch pins a runtime fork at:
7
+
8
+ https://github.com/beforewire/openshell
9
+
10
+ That runtime fork is derived from NVIDIA OpenShell and retains the upstream OpenShell copyright, license, and notices in the submodule repository.
11
+
12
+ The OpenShell workspace-substrate patch used by ForkCell is applied in the pinned runtime fork. A patch artifact is retained under `patches/` for review and upstreaming provenance.
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: forkcell
3
+ Version: 0.1.0a0
4
+ Summary: Governed execution cells for AI agents, with rollback and receipts
5
+ Author: BeforeWire
6
+ License: Apache-2.0
7
+ Keywords: ai-agents,sandbox,checkpoint,openshell,policy,receipts
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Requires-Python: >=3.11
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ License-File: NOTICE
16
+ Dynamic: license-file
17
+
18
+ # ForkCell
19
+
20
+ [中文](README.zh-CN.md) | English
21
+
22
+ ForkCell is a governed execution-cell layer for AI agents: it adds fast workspace rollback, policy-bound runs, and reviewable receipts to local agent execution.
23
+
24
+ > Checkpoint -> governed run -> receipt -> accept, restore, or fork.
25
+
26
+ ForkCell is currently the `v0.1.0-preview` source preview (`0.1.0a0` Python package version). The public-preview branch is intentionally small: it contains the ForkCell control plane, a pinned governed-runtime submodule, a review patch artifact, and the minimum scripts/docs needed to understand and run the preview.
27
+
28
+ ## Why ForkCell Exists
29
+
30
+ AI agents increasingly edit repositories, install packages, call APIs, and touch credentials. A plain sandbox can isolate a process, and a plain snapshot can roll files back, but teams also need to answer:
31
+
32
+ - What checkpoint did the agent start from?
33
+ - What runtime policy governed the run?
34
+ - Which egress or L7 policy events occurred?
35
+ - Was the failed run restored, accepted, or forked?
36
+ - Can a reviewer inspect a durable receipt instead of raw logs?
37
+
38
+ ForkCell turns a risky agent command into an auditable transaction.
39
+
40
+ ## What ForkCell Does
41
+
42
+ ForkCell owns the transaction/control plane:
43
+
44
+ - creates filesystem checkpoints for a cell workspace;
45
+ - runs commands through a governed runtime integration;
46
+ - binds policy revision, checkpoint identity, workspace config, and command result into receipts;
47
+ - records accept/restore decisions as first-class artifacts;
48
+ - restores quickly through metadata generation switching on the native overlay backend;
49
+ - keeps fallback/degraded backend decisions explicit.
50
+
51
+ Runtime enforcement is handled by the configured governed runtime; see
52
+ `Runtime Integration` for the current preview substrate.
53
+
54
+ ForkCell does **not** implement business-semantic policy such as refund limits or claim eligibility in core. Business policy should live in an external application/PDP/tool gateway. ForkCell focuses on runtime capability policy and transaction receipts.
55
+
56
+ ## Repository Layout
57
+
58
+ ```text
59
+ forkcell/
60
+ forkcell/ # Python CLI/API and checkpoint providers
61
+ scripts/ # preview build, gateway, and smoke scripts
62
+ patches/ # runtime patch review/provenance artifacts
63
+ docs/ # architecture and preview docs
64
+ upstream/openshell # submodule: current pinned runtime fork
65
+ ```
66
+
67
+ The OpenShell patch is already applied in the pinned `beforewire/openshell` submodule. The patch file under `patches/` is kept as a review/upstreaming artifact, not as a normal build-time step.
68
+
69
+ ## Runtime Integration
70
+
71
+ ForkCell's preview runtime integration uses a pinned OpenShell fork:
72
+
73
+ ```text
74
+ repo: https://github.com/beforewire/openshell
75
+ branch: forkcell-workspace-substrate
76
+ tag: forkcell-runtime-v0.1.3-preview
77
+ commit: 393c25a86d9128ff5e38ecf537809efe58470266
78
+ ```
79
+
80
+ The runtime fork carries a narrow workspace-substrate change:
81
+
82
+ - Docker driver accepts a typed `docker.workspace` / `forkcell_overlay` contract;
83
+ - the workspace backing volume is mounted at a private path;
84
+ - the supervisor prepares/chowns overlay runtime directories before privilege drop and hardening;
85
+ - runtime policy, egress, credential, and OCSF paths stay unchanged.
86
+
87
+ In this preview, OpenShell provides the runtime enforcement layer:
88
+
89
+ - sandbox lifecycle;
90
+ - process and filesystem policy;
91
+ - egress/L7 policy;
92
+ - credential/provider path;
93
+ - OCSF/log events.
94
+
95
+ See `patches/openshell.lock` and `docs/openshell-native-fast-substrate.md`.
96
+
97
+ ## Quickstart
98
+
99
+ Prerequisites:
100
+
101
+ - macOS or Linux host with Docker available;
102
+ - Python 3.11+;
103
+ - Rust/Cargo for building OpenShell CLI/gateway;
104
+ - access to the `beforewire/openshell` submodule.
105
+
106
+ Clone with submodules:
107
+
108
+ ```bash
109
+ git clone --recurse-submodules https://github.com/beforewire/forkcell.git
110
+ cd forkcell
111
+ ```
112
+
113
+ Or initialize submodules after cloning:
114
+
115
+ ```bash
116
+ git submodule update --init --recursive
117
+ ```
118
+
119
+ Install ForkCell locally:
120
+
121
+ ```bash
122
+ python3 -m venv .venv
123
+ source .venv/bin/activate
124
+ pip install -e .
125
+ ```
126
+
127
+ Run the lightweight preview smoke:
128
+
129
+ ```bash
130
+ ./scripts/validate_public_smoke.sh
131
+ ```
132
+
133
+ Build the pinned governed runtime:
134
+
135
+ ```bash
136
+ ./scripts/build_patched_openshell_runtime.sh
137
+ python3 -m forkcell.cli runtime install --from upstream/openshell
138
+ ```
139
+
140
+ Start the local patched runtime gateway:
141
+
142
+ ```bash
143
+ ./scripts/start_patched_openshell_gateway.sh
144
+ export FORKCELL_OPENSHELL_BIN="$PWD/.forkcell/runtime/native-overlay/bin/openshell"
145
+ export OPENSHELL_GATEWAY_ENDPOINT="http://127.0.0.1:17671"
146
+ ```
147
+
148
+ Create a native cell and run a restore-on-fail command:
149
+
150
+ ```bash
151
+ mkdir -p /tmp/forkcell-demo
152
+ printf 'hello\n' >/tmp/forkcell-demo/hello.txt
153
+
154
+ python3 -m forkcell.cli native init demo --from /tmp/forkcell-demo
155
+ python3 -m forkcell.cli native run --checkpoint-before --restore-on-fail demo -- \
156
+ sh -lc 'echo changed > hello.txt; exit 7'
157
+ python3 -m forkcell.cli receipt show --cell demo --latest --format md
158
+ cat /tmp/forkcell-demo/hello.txt
159
+ ```
160
+
161
+ The command intentionally exits with status `7` inside the sandbox. Success means
162
+ ForkCell records `Decision: restored` in the receipt and the final `cat` prints
163
+ `hello`.
164
+
165
+ Stop the gateway when done:
166
+
167
+ ```bash
168
+ ./scripts/stop_patched_openshell_gateway.sh
169
+ ```
170
+
171
+ ## Current Preview Metrics
172
+
173
+ Latest validation for this preview line:
174
+
175
+ - native overlay `restore_sync_ms`: `0ms` on small, medium, and pruned workspaces, meaning the synchronous generation switch is sub-ms/rounded to zero;
176
+ - native overlay correctness matrix: `7/7` cases passed;
177
+ - native policy smoke: deny host, allow GET, and L7 deny passed;
178
+ - runtime packaging and CI-style gate passed;
179
+ - runtime sandbox lifecycle is still roughly hundreds of milliseconds, so only the synchronous restore substrate should be described as sub-ms/`0ms`.
180
+
181
+ Fresh README-path validation on macOS + Docker also produced a tiny-workspace receipt with `checkpoint duration: 0ms`, `restore duration: 0ms`, `restore_sync_ms: 0ms`, and `total_restore_path_ms: 726ms`. The latter includes runtime sandbox delete/lifecycle and log collection, not just ForkCell's restore substrate.
182
+
183
+ A sanitized evidence summary is in `docs/evidence-summary.md`.
184
+
185
+ ## Backends
186
+
187
+ - `native-overlay`: production fast path when the patched governed runtime is configured.
188
+ - `layer-clone`: compatible fallback; restore is metadata-only but run-layer preparation copies the checkpoint tree.
189
+ - `volume-delta`: governed Docker volume workspace with CAS/delta restore.
190
+ - `local-overlay`: local degraded-policy filesystem fallback for development.
191
+
192
+ In this preview, `native-overlay`, `layer-clone`, and `volume-delta` are backed by OpenShell. The backend names describe ForkCell restore strategies; the runtime integration describes the sandbox/policy engine underneath.
193
+
194
+ ## Non-goals For This Preview
195
+
196
+ - no memory/process checkpoint;
197
+ - no VM/MicroVM/KVM isolation layer;
198
+ - no business-semantic policy evaluator in ForkCell core;
199
+ - no replacement for OpenShell policy/egress enforcement;
200
+ - no claim of pure macOS/Windows native isolation;
201
+ - no claim that full sandbox lifecycle is `0ms`.
202
+
203
+ ## Documentation
204
+
205
+ - `docs/architecture.md` - product boundary and control-plane architecture.
206
+ - `docs/openshell-native-fast-substrate.md` - OpenShell workspace substrate design.
207
+ - `docs/testing-plan.md` - preview smoke and integration validation plan.
208
+ - `docs/evidence-summary.md` - sanitized validation summary.
209
+
210
+ ## About BeforeWire
211
+
212
+ ForkCell is part of BeforeWire's agent-trust infrastructure work: make agent execution reviewable, reversible, and policy-bound without pretending that local development needs a full cloud MicroVM product on day one.
213
+
214
+ ## Status
215
+
216
+ `v0.1.0-preview` / `0.1.0a0` is experimental. The preview is intended to show the product boundary and the working checkpoint/restore/receipt path before the project is promoted to a broader public release.
@@ -0,0 +1,199 @@
1
+ # ForkCell
2
+
3
+ [中文](README.zh-CN.md) | English
4
+
5
+ ForkCell is a governed execution-cell layer for AI agents: it adds fast workspace rollback, policy-bound runs, and reviewable receipts to local agent execution.
6
+
7
+ > Checkpoint -> governed run -> receipt -> accept, restore, or fork.
8
+
9
+ ForkCell is currently the `v0.1.0-preview` source preview (`0.1.0a0` Python package version). The public-preview branch is intentionally small: it contains the ForkCell control plane, a pinned governed-runtime submodule, a review patch artifact, and the minimum scripts/docs needed to understand and run the preview.
10
+
11
+ ## Why ForkCell Exists
12
+
13
+ AI agents increasingly edit repositories, install packages, call APIs, and touch credentials. A plain sandbox can isolate a process, and a plain snapshot can roll files back, but teams also need to answer:
14
+
15
+ - What checkpoint did the agent start from?
16
+ - What runtime policy governed the run?
17
+ - Which egress or L7 policy events occurred?
18
+ - Was the failed run restored, accepted, or forked?
19
+ - Can a reviewer inspect a durable receipt instead of raw logs?
20
+
21
+ ForkCell turns a risky agent command into an auditable transaction.
22
+
23
+ ## What ForkCell Does
24
+
25
+ ForkCell owns the transaction/control plane:
26
+
27
+ - creates filesystem checkpoints for a cell workspace;
28
+ - runs commands through a governed runtime integration;
29
+ - binds policy revision, checkpoint identity, workspace config, and command result into receipts;
30
+ - records accept/restore decisions as first-class artifacts;
31
+ - restores quickly through metadata generation switching on the native overlay backend;
32
+ - keeps fallback/degraded backend decisions explicit.
33
+
34
+ Runtime enforcement is handled by the configured governed runtime; see
35
+ `Runtime Integration` for the current preview substrate.
36
+
37
+ ForkCell does **not** implement business-semantic policy such as refund limits or claim eligibility in core. Business policy should live in an external application/PDP/tool gateway. ForkCell focuses on runtime capability policy and transaction receipts.
38
+
39
+ ## Repository Layout
40
+
41
+ ```text
42
+ forkcell/
43
+ forkcell/ # Python CLI/API and checkpoint providers
44
+ scripts/ # preview build, gateway, and smoke scripts
45
+ patches/ # runtime patch review/provenance artifacts
46
+ docs/ # architecture and preview docs
47
+ upstream/openshell # submodule: current pinned runtime fork
48
+ ```
49
+
50
+ The OpenShell patch is already applied in the pinned `beforewire/openshell` submodule. The patch file under `patches/` is kept as a review/upstreaming artifact, not as a normal build-time step.
51
+
52
+ ## Runtime Integration
53
+
54
+ ForkCell's preview runtime integration uses a pinned OpenShell fork:
55
+
56
+ ```text
57
+ repo: https://github.com/beforewire/openshell
58
+ branch: forkcell-workspace-substrate
59
+ tag: forkcell-runtime-v0.1.3-preview
60
+ commit: 393c25a86d9128ff5e38ecf537809efe58470266
61
+ ```
62
+
63
+ The runtime fork carries a narrow workspace-substrate change:
64
+
65
+ - Docker driver accepts a typed `docker.workspace` / `forkcell_overlay` contract;
66
+ - the workspace backing volume is mounted at a private path;
67
+ - the supervisor prepares/chowns overlay runtime directories before privilege drop and hardening;
68
+ - runtime policy, egress, credential, and OCSF paths stay unchanged.
69
+
70
+ In this preview, OpenShell provides the runtime enforcement layer:
71
+
72
+ - sandbox lifecycle;
73
+ - process and filesystem policy;
74
+ - egress/L7 policy;
75
+ - credential/provider path;
76
+ - OCSF/log events.
77
+
78
+ See `patches/openshell.lock` and `docs/openshell-native-fast-substrate.md`.
79
+
80
+ ## Quickstart
81
+
82
+ Prerequisites:
83
+
84
+ - macOS or Linux host with Docker available;
85
+ - Python 3.11+;
86
+ - Rust/Cargo for building OpenShell CLI/gateway;
87
+ - access to the `beforewire/openshell` submodule.
88
+
89
+ Clone with submodules:
90
+
91
+ ```bash
92
+ git clone --recurse-submodules https://github.com/beforewire/forkcell.git
93
+ cd forkcell
94
+ ```
95
+
96
+ Or initialize submodules after cloning:
97
+
98
+ ```bash
99
+ git submodule update --init --recursive
100
+ ```
101
+
102
+ Install ForkCell locally:
103
+
104
+ ```bash
105
+ python3 -m venv .venv
106
+ source .venv/bin/activate
107
+ pip install -e .
108
+ ```
109
+
110
+ Run the lightweight preview smoke:
111
+
112
+ ```bash
113
+ ./scripts/validate_public_smoke.sh
114
+ ```
115
+
116
+ Build the pinned governed runtime:
117
+
118
+ ```bash
119
+ ./scripts/build_patched_openshell_runtime.sh
120
+ python3 -m forkcell.cli runtime install --from upstream/openshell
121
+ ```
122
+
123
+ Start the local patched runtime gateway:
124
+
125
+ ```bash
126
+ ./scripts/start_patched_openshell_gateway.sh
127
+ export FORKCELL_OPENSHELL_BIN="$PWD/.forkcell/runtime/native-overlay/bin/openshell"
128
+ export OPENSHELL_GATEWAY_ENDPOINT="http://127.0.0.1:17671"
129
+ ```
130
+
131
+ Create a native cell and run a restore-on-fail command:
132
+
133
+ ```bash
134
+ mkdir -p /tmp/forkcell-demo
135
+ printf 'hello\n' >/tmp/forkcell-demo/hello.txt
136
+
137
+ python3 -m forkcell.cli native init demo --from /tmp/forkcell-demo
138
+ python3 -m forkcell.cli native run --checkpoint-before --restore-on-fail demo -- \
139
+ sh -lc 'echo changed > hello.txt; exit 7'
140
+ python3 -m forkcell.cli receipt show --cell demo --latest --format md
141
+ cat /tmp/forkcell-demo/hello.txt
142
+ ```
143
+
144
+ The command intentionally exits with status `7` inside the sandbox. Success means
145
+ ForkCell records `Decision: restored` in the receipt and the final `cat` prints
146
+ `hello`.
147
+
148
+ Stop the gateway when done:
149
+
150
+ ```bash
151
+ ./scripts/stop_patched_openshell_gateway.sh
152
+ ```
153
+
154
+ ## Current Preview Metrics
155
+
156
+ Latest validation for this preview line:
157
+
158
+ - native overlay `restore_sync_ms`: `0ms` on small, medium, and pruned workspaces, meaning the synchronous generation switch is sub-ms/rounded to zero;
159
+ - native overlay correctness matrix: `7/7` cases passed;
160
+ - native policy smoke: deny host, allow GET, and L7 deny passed;
161
+ - runtime packaging and CI-style gate passed;
162
+ - runtime sandbox lifecycle is still roughly hundreds of milliseconds, so only the synchronous restore substrate should be described as sub-ms/`0ms`.
163
+
164
+ Fresh README-path validation on macOS + Docker also produced a tiny-workspace receipt with `checkpoint duration: 0ms`, `restore duration: 0ms`, `restore_sync_ms: 0ms`, and `total_restore_path_ms: 726ms`. The latter includes runtime sandbox delete/lifecycle and log collection, not just ForkCell's restore substrate.
165
+
166
+ A sanitized evidence summary is in `docs/evidence-summary.md`.
167
+
168
+ ## Backends
169
+
170
+ - `native-overlay`: production fast path when the patched governed runtime is configured.
171
+ - `layer-clone`: compatible fallback; restore is metadata-only but run-layer preparation copies the checkpoint tree.
172
+ - `volume-delta`: governed Docker volume workspace with CAS/delta restore.
173
+ - `local-overlay`: local degraded-policy filesystem fallback for development.
174
+
175
+ In this preview, `native-overlay`, `layer-clone`, and `volume-delta` are backed by OpenShell. The backend names describe ForkCell restore strategies; the runtime integration describes the sandbox/policy engine underneath.
176
+
177
+ ## Non-goals For This Preview
178
+
179
+ - no memory/process checkpoint;
180
+ - no VM/MicroVM/KVM isolation layer;
181
+ - no business-semantic policy evaluator in ForkCell core;
182
+ - no replacement for OpenShell policy/egress enforcement;
183
+ - no claim of pure macOS/Windows native isolation;
184
+ - no claim that full sandbox lifecycle is `0ms`.
185
+
186
+ ## Documentation
187
+
188
+ - `docs/architecture.md` - product boundary and control-plane architecture.
189
+ - `docs/openshell-native-fast-substrate.md` - OpenShell workspace substrate design.
190
+ - `docs/testing-plan.md` - preview smoke and integration validation plan.
191
+ - `docs/evidence-summary.md` - sanitized validation summary.
192
+
193
+ ## About BeforeWire
194
+
195
+ ForkCell is part of BeforeWire's agent-trust infrastructure work: make agent execution reviewable, reversible, and policy-bound without pretending that local development needs a full cloud MicroVM product on day one.
196
+
197
+ ## Status
198
+
199
+ `v0.1.0-preview` / `0.1.0a0` is experimental. The preview is intended to show the product boundary and the working checkpoint/restore/receipt path before the project is promoted to a broader public release.
@@ -0,0 +1,7 @@
1
+ """ForkCell MVP package."""
2
+
3
+ __version__ = "0.1.0a0"
4
+
5
+ from forkcell.api import ForkCellClient, ForkCellCommandError, ForkCellSandbox
6
+
7
+ __all__ = ["ForkCellClient", "ForkCellCommandError", "ForkCellSandbox", "__version__"]
@@ -0,0 +1,191 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import subprocess
6
+ import sys
7
+ import uuid
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+ from typing import Any, Iterable, Mapping
11
+
12
+
13
+ class ForkCellCommandError(RuntimeError):
14
+ def __init__(self, args: list[str], returncode: int, stdout: str, stderr: str) -> None:
15
+ self.args_list = args
16
+ self.returncode = returncode
17
+ self.stdout = stdout
18
+ self.stderr = stderr
19
+ super().__init__(
20
+ f"forkcell command failed ({returncode}): {' '.join(args)}\nstdout:\n{stdout}\nstderr:\n{stderr}"
21
+ )
22
+
23
+
24
+ @dataclass(frozen=True)
25
+ class CommandResult:
26
+ args: list[str]
27
+ returncode: int
28
+ stdout: str
29
+ stderr: str
30
+ json: dict[str, Any]
31
+
32
+
33
+ def _extract_json_object(text: str) -> dict[str, Any]:
34
+ decoder = json.JSONDecoder()
35
+ for index, char in enumerate(text):
36
+ if char != "{":
37
+ continue
38
+ try:
39
+ value, end = decoder.raw_decode(text[index:])
40
+ except json.JSONDecodeError:
41
+ continue
42
+ if isinstance(value, dict) and not text[index + end :].strip():
43
+ return value
44
+ raise ValueError("missing JSON object in command output")
45
+
46
+
47
+ def _normalize_command(command: str | Iterable[str]) -> list[str]:
48
+ if isinstance(command, str):
49
+ return ["sh", "-lc", command]
50
+ return [str(part) for part in command]
51
+
52
+
53
+ LEGACY_BACKEND_ALIASES = {
54
+ "openshell-native-overlay": "native-overlay",
55
+ "openshell-layer-clone": "layer-clone",
56
+ "openshell-volume": "volume-delta",
57
+ }
58
+
59
+
60
+ def _normalize_backend(backend: str) -> str:
61
+ return LEGACY_BACKEND_ALIASES.get(backend, backend)
62
+
63
+
64
+ class ForkCellClient:
65
+ """Small Python facade for agent-style ForkCell workflows.
66
+
67
+ The facade intentionally shells out to `python -m forkcell.cli` so the API
68
+ and CLI share the same state, receipts, and review artifacts during the
69
+ current governed-runtime integration.
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ *,
75
+ root: str | Path | None = None,
76
+ python: str | None = None,
77
+ env: Mapping[str, str] | None = None,
78
+ ) -> None:
79
+ self.root = Path(root or Path.cwd()).resolve()
80
+ self.python = python or sys.executable
81
+ self.env = dict(os.environ)
82
+ if env:
83
+ self.env.update(env)
84
+
85
+ def cli(self, args: list[str], *, check: bool = True) -> CommandResult:
86
+ full_args = [self.python, "-m", "forkcell.cli", *args]
87
+ proc = subprocess.run(full_args, cwd=self.root, env=self.env, text=True, capture_output=True)
88
+ parsed: dict[str, Any] = {}
89
+ output = proc.stdout.strip()
90
+ if output:
91
+ try:
92
+ parsed = _extract_json_object(output)
93
+ except ValueError:
94
+ parsed = {}
95
+ if check and proc.returncode != 0:
96
+ raise ForkCellCommandError(full_args, proc.returncode, proc.stdout, proc.stderr)
97
+ return CommandResult(
98
+ args=full_args,
99
+ returncode=proc.returncode,
100
+ stdout=proc.stdout,
101
+ stderr=proc.stderr,
102
+ json=parsed,
103
+ )
104
+
105
+ def create_native_cell(
106
+ self,
107
+ *,
108
+ source: str | Path,
109
+ name: str | None = None,
110
+ backend: str = "native-overlay",
111
+ ) -> "ForkCellSandbox":
112
+ cell = name or f"fc-api-{uuid.uuid4().hex[:8]}"
113
+ self.cli(["native", "init", cell, "--from", str(Path(source).resolve())])
114
+ return ForkCellSandbox(client=self, name=cell, backend=_normalize_backend(backend))
115
+
116
+ def native_cell(self, name: str, *, backend: str = "native-overlay") -> "ForkCellSandbox":
117
+ return ForkCellSandbox(client=self, name=name, backend=_normalize_backend(backend))
118
+
119
+ def review_status(self) -> dict[str, Any]:
120
+ return self.cli(["review", "status", "--format", "json"]).json
121
+
122
+
123
+ @dataclass
124
+ class ForkCellSandbox:
125
+ client: ForkCellClient
126
+ name: str
127
+ backend: str = "native-overlay"
128
+ auto_delete: bool = True
129
+
130
+ def __post_init__(self) -> None:
131
+ self.backend = _normalize_backend(self.backend)
132
+
133
+ def __enter__(self) -> "ForkCellSandbox":
134
+ return self
135
+
136
+ def __exit__(self, exc_type: object, exc: object, tb: object) -> None:
137
+ if self.auto_delete:
138
+ self.delete(check=False)
139
+
140
+ def status(self) -> dict[str, Any]:
141
+ return self.client.cli(["native", "status", self.name]).json
142
+
143
+ def checkpoint(self, *, name: str | None = None) -> dict[str, Any]:
144
+ args = ["native", "checkpoint", self.name]
145
+ if name:
146
+ args.extend(["--name", name])
147
+ return self.client.cli(args).json
148
+
149
+ def restore(self, checkpoint: str | None = None) -> dict[str, Any]:
150
+ args = ["native", "restore", self.name]
151
+ if checkpoint:
152
+ args.append(checkpoint)
153
+ return self.client.cli(args).json
154
+
155
+ def run(
156
+ self,
157
+ command: str | Iterable[str],
158
+ *,
159
+ checkpoint_before: bool = False,
160
+ checkpoint_name: str | None = None,
161
+ restore_on_fail: bool = False,
162
+ policy: str | Path | None = None,
163
+ logs_since: str = "5m",
164
+ ) -> dict[str, Any]:
165
+ if self.backend == "native-overlay":
166
+ args = ["native", "run"]
167
+ elif self.backend == "layer-clone":
168
+ args = ["native", "run-layer"]
169
+ else:
170
+ args = ["run", self.name, "--backend", self.backend]
171
+ if checkpoint_before:
172
+ args.append("--checkpoint-before")
173
+ if checkpoint_name:
174
+ args.extend(["--checkpoint-name", checkpoint_name])
175
+ if restore_on_fail:
176
+ args.append("--restore-on-fail")
177
+ if policy:
178
+ args.extend(["--policy", str(policy)])
179
+ if logs_since:
180
+ args.extend(["--logs-since", logs_since])
181
+ if self.backend in {"native-overlay", "layer-clone"}:
182
+ args.append(self.name)
183
+ args.extend(["--", *_normalize_command(command)])
184
+ run = self.client.cli(args).json
185
+ receipt = Path(run.get("receipt", ""))
186
+ if receipt.exists():
187
+ return json.loads(receipt.read_text())
188
+ return run
189
+
190
+ def delete(self, *, check: bool = True) -> dict[str, Any]:
191
+ return self.client.cli(["native", "delete", self.name], check=check).json