sandboxedjs 0.2.10 → 0.2.12
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.
- package/README.md +96 -63
- package/assets/logo.png +0 -0
- package/bin/sandboxedjs-egress.mjs +25 -10
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/service-worker.js +3 -2
- package/docs/agent/COMMANDS.md +85 -0
- package/docs/agent/DECISION-TREE.md +84 -0
- package/docs/agent/INVARIANTS.md +40 -0
- package/docs/agent/LAUNCH-PROMPT.md +37 -0
- package/docs/agent/LOOP.md +84 -0
- package/docs/agent/README.md +77 -0
- package/docs/agent/ROADMAP.md +37 -0
- package/docs/agent/STATE.md +93 -0
- package/docs/agent/tasks/00-verify-inherited-work.md +36 -0
- package/docs/agent/tasks/01-authoritative-metadata.md +34 -0
- package/docs/agent/tasks/02-native-dependencies.md +35 -0
- package/docs/agent/tasks/03-reproducible-inputs.md +27 -0
- package/docs/agent/tasks/04-build-frontends.md +27 -0
- package/docs/agent/tasks/05-registry-integration.md +27 -0
- package/docs/agent/tasks/06-package-cohorts.md +42 -0
- package/docs/agent/tasks/07-build-on-miss-boundary.md +31 -0
- package/docs/browser-runtime-architecture.md +142 -0
- package/docs/compatibility-implementation-plan.md +98 -0
- package/docs/developer-tool-packs.md +134 -0
- package/docs/frontend-automation.md +49 -0
- package/docs/fullstack-deployment.md +163 -0
- package/docs/handoff.md +275 -0
- package/docs/original-x64.md +39 -0
- package/docs/platform-hardening.md +49 -0
- package/docs/python/abi.md +97 -0
- package/docs/python/architecture.md +94 -0
- package/docs/python/baseline-inventory.md +54 -0
- package/docs/python/build-on-miss.md +198 -0
- package/docs/python/compatibility.md +206 -0
- package/docs/python/cross-build.md +354 -0
- package/docs/python/extensions.md +282 -0
- package/docs/python/release-gates.md +46 -0
- package/docs/python/virtual-sockets-plan.md +331 -0
- package/docs/runtime-lifecycle-fixes.md +39 -0
- package/docs/server-previews.md +268 -0
- package/docs/virtual-browser.md +120 -0
- package/package.json +5 -3
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Prompt to launch or resume Claude Opus
|
|
2
|
+
|
|
3
|
+
Copy the text below into the coding task. Do not paste the rest of this folder
|
|
4
|
+
into the prompt; the agent should read files on demand.
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
You are the sole implementation agent for the SandboxedJS native Python
|
|
8
|
+
package platform. The project controller is:
|
|
9
|
+
|
|
10
|
+
agent-projects/python-package-platform/README.md
|
|
11
|
+
|
|
12
|
+
Begin by reading only README.md, STATE.md, and the current task named in
|
|
13
|
+
STATE.md. Follow LOOP.md. Execute commands and make decisions from their actual
|
|
14
|
+
outputs. Continue through tasks while gates pass and context remains healthy.
|
|
15
|
+
Keep STATE.md current so another task can resume without chat history.
|
|
16
|
+
|
|
17
|
+
Preserve all pre-existing and staged work. Do not commit, publish, deploy,
|
|
18
|
+
discard changes, weaken ABI validation, or change the ABI contract unless I
|
|
19
|
+
explicitly authorize it. Use focused tests before broad suites. Keep long build
|
|
20
|
+
logs in /tmp and bring only decisive excerpts into context.
|
|
21
|
+
|
|
22
|
+
If a stop condition in LOOP.md occurs, stop with a compact escalation packet.
|
|
23
|
+
The goal is a general package platform; NumPy is a later acceptance case, not a
|
|
24
|
+
package-specific architecture target.
|
|
25
|
+
|
|
26
|
+
Do not merely review or propose a plan. Work autonomously: inspect, edit,
|
|
27
|
+
execute focused commands, diagnose their outputs, verify exit gates, update
|
|
28
|
+
STATE.md, and advance to the next task. Do not ask for confirmation between
|
|
29
|
+
ordinary in-scope steps. Continue until a documented stop condition requires my
|
|
30
|
+
decision or all roadmap gates are complete.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Execution policy
|
|
34
|
+
|
|
35
|
+
This workflow assumes one Claude Opus agent. Do not delegate work to other
|
|
36
|
+
models or create subagents. Use the stop conditions and ask the user for one
|
|
37
|
+
concrete decision only when necessary.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Agent execution loop
|
|
2
|
+
|
|
3
|
+
Use this loop exactly. It is designed for a smaller model that can act well
|
|
4
|
+
when each decision is grounded in the previous command's output.
|
|
5
|
+
|
|
6
|
+
## 1. Orient
|
|
7
|
+
|
|
8
|
+
Read `README.md`, `STATE.md`, and the current task only. Inspect `git status
|
|
9
|
+
--short` before editing. Treat all pre-existing changes as user-owned.
|
|
10
|
+
|
|
11
|
+
State the current hypothesis in one sentence. A hypothesis must predict an
|
|
12
|
+
observable result, for example: "the linker cannot find `libxml2` because the
|
|
13
|
+
dynamic sysroot is absent from target link flags."
|
|
14
|
+
|
|
15
|
+
## 2. Choose the cheapest discriminating command
|
|
16
|
+
|
|
17
|
+
Run the smallest command that can disprove the hypothesis. Prefer, in order:
|
|
18
|
+
|
|
19
|
+
1. static inspection of one relevant file;
|
|
20
|
+
2. one unit test or one fixture build;
|
|
21
|
+
3. one runtime import test;
|
|
22
|
+
4. the focused suite;
|
|
23
|
+
5. the full suite only at a milestone gate.
|
|
24
|
+
|
|
25
|
+
Never rerun a long build unchanged. If a command failed, inspect its decisive
|
|
26
|
+
error first and change either the hypothesis or the implementation.
|
|
27
|
+
|
|
28
|
+
## 3. Classify the result
|
|
29
|
+
|
|
30
|
+
Use `DECISION-TREE.md`. Every failure must be classified before code changes.
|
|
31
|
+
If there is not enough evidence, gather more evidence rather than guessing.
|
|
32
|
+
|
|
33
|
+
## 4. Make one coherent change
|
|
34
|
+
|
|
35
|
+
Change the smallest architectural seam that removes the demonstrated failure
|
|
36
|
+
class. Do not add a package-name conditional to the generic builder. A package
|
|
37
|
+
patch belongs in an explicit recipe patch directory, with a comment explaining
|
|
38
|
+
the upstream assumption it replaces.
|
|
39
|
+
|
|
40
|
+
Use `apply_patch` for hand edits. Do not overwrite files with shell redirects.
|
|
41
|
+
Do not alter generated ABI files directly.
|
|
42
|
+
|
|
43
|
+
## 5. Verify in layers
|
|
44
|
+
|
|
45
|
+
Run the focused check that failed. If it passes, run the task's exit gate.
|
|
46
|
+
Compilation is never the final gate for an extension: install and import it in
|
|
47
|
+
the owned CPython runtime and exercise at least one native behavior.
|
|
48
|
+
|
|
49
|
+
## 6. Record and advance
|
|
50
|
+
|
|
51
|
+
Update `STATE.md` with compact evidence. If the task exit gate passes, set its
|
|
52
|
+
checkboxes, point `Current task` to the next task in `ROADMAP.md`, and continue
|
|
53
|
+
if budget remains.
|
|
54
|
+
|
|
55
|
+
## Stop conditions
|
|
56
|
+
|
|
57
|
+
Stop and request a user decision when:
|
|
58
|
+
|
|
59
|
+
- the next action requires credentials, deployment, paid infrastructure, or
|
|
60
|
+
publishing outside the repository;
|
|
61
|
+
- fulfilling the task requires changing the ABI contract rather than fixing a
|
|
62
|
+
consumer of it;
|
|
63
|
+
- an upstream license is unclear or incompatible;
|
|
64
|
+
- a destructive action, history rewrite, or discard of existing work appears
|
|
65
|
+
necessary;
|
|
66
|
+
- the same failure class survives three evidence-driven attempts;
|
|
67
|
+
- a design choice changes public API or materially increases shipped runtime
|
|
68
|
+
size without an already-stated budget.
|
|
69
|
+
|
|
70
|
+
When stopping, preserve logs and state the smallest exact decision needed.
|
|
71
|
+
|
|
72
|
+
## Escalation packet for the user
|
|
73
|
+
|
|
74
|
+
When a stop condition is reached, prepare a compact packet containing:
|
|
75
|
+
|
|
76
|
+
- intended invariant;
|
|
77
|
+
- exact command;
|
|
78
|
+
- final 80-150 relevant log lines;
|
|
79
|
+
- files and functions involved;
|
|
80
|
+
- three attempted hypotheses and what disproved each;
|
|
81
|
+
- the decision required.
|
|
82
|
+
|
|
83
|
+
Do not send entire build logs or the full repository history. Wait for the
|
|
84
|
+
user's decision, record it in `STATE.md`, and then resume this same loop.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# SandboxedJS native Python package platform
|
|
2
|
+
|
|
3
|
+
This folder is an executable work specification for a coding agent. Its goal is
|
|
4
|
+
not to port NumPy. Its goal is to make native Python packages a platform
|
|
5
|
+
capability of SandboxedJS, with NumPy eventually serving as one demanding
|
|
6
|
+
acceptance case.
|
|
7
|
+
|
|
8
|
+
## Start here
|
|
9
|
+
|
|
10
|
+
At the beginning of every turn, read only these files:
|
|
11
|
+
|
|
12
|
+
1. `README.md` (this file).
|
|
13
|
+
2. `STATE.md`.
|
|
14
|
+
3. The one task file named by `STATE.md`.
|
|
15
|
+
|
|
16
|
+
Do not reread every document on every turn. Open `INVARIANTS.md`,
|
|
17
|
+
`DECISION-TREE.md`, or `COMMANDS.md` only when the current task points to them
|
|
18
|
+
or an observed failure requires them. This is intentional: the folder is also
|
|
19
|
+
a context and token budget.
|
|
20
|
+
|
|
21
|
+
Then execute the loop in `LOOP.md`. Continue until the current task's exit gate
|
|
22
|
+
passes or a stop condition requires the user or a stronger model.
|
|
23
|
+
|
|
24
|
+
## Product objective
|
|
25
|
+
|
|
26
|
+
The eventual user experience is:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pip install some-package
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The implementation may obtain a pure wheel, install an already-built
|
|
33
|
+
SandboxedJS wheel, or ask an external build system to create and cache a wheel.
|
|
34
|
+
It must never install a host-native artifact by relabeling it, silently omit a
|
|
35
|
+
dependency, or claim support because compilation alone succeeded.
|
|
36
|
+
|
|
37
|
+
## Current baseline
|
|
38
|
+
|
|
39
|
+
The working tree already contains staged, uncommitted work produced in an
|
|
40
|
+
earlier session:
|
|
41
|
+
|
|
42
|
+
- a generic setuptools cross environment;
|
|
43
|
+
- package-owned `setup.py` and `pyproject.toml` builds;
|
|
44
|
+
- C and Cython fixtures;
|
|
45
|
+
- the existing PyO3 path;
|
|
46
|
+
- side-module validation and runtime import tests;
|
|
47
|
+
- `docs/python/cross-build.md`, which records ten known assumptions.
|
|
48
|
+
|
|
49
|
+
Preserve those staged changes. Do not unstage, discard, rewrite wholesale, or
|
|
50
|
+
commit them unless the user explicitly requests it. First verify them and
|
|
51
|
+
record the result in `STATE.md`.
|
|
52
|
+
|
|
53
|
+
## Scope boundary
|
|
54
|
+
|
|
55
|
+
This project owns:
|
|
56
|
+
|
|
57
|
+
- reproducible cross-build inputs;
|
|
58
|
+
- build/host/target dependency separation;
|
|
59
|
+
- package build-backend execution;
|
|
60
|
+
- ABI-valid wheel construction and metadata;
|
|
61
|
+
- wheel indexing, resolution, installation, and runtime verification;
|
|
62
|
+
- explicit recipes and patches for irreducibly package-specific behavior;
|
|
63
|
+
- compatibility evidence.
|
|
64
|
+
|
|
65
|
+
This project does not own, unless the user separately authorizes it:
|
|
66
|
+
|
|
67
|
+
- a hosted public build service;
|
|
68
|
+
- cloud accounts, deployment, billing, or package signing infrastructure;
|
|
69
|
+
- pretending raw sockets, subprocesses, GPU APIs, or unavailable operating
|
|
70
|
+
system capabilities exist;
|
|
71
|
+
- broad unrelated cleanup of SandboxedJS.
|
|
72
|
+
|
|
73
|
+
## Definition of success
|
|
74
|
+
|
|
75
|
+
Success is a general pipeline demonstrated by several independent package
|
|
76
|
+
shapes, not one famous package. The final gate is described in `ROADMAP.md`.
|
|
77
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Capability roadmap
|
|
2
|
+
|
|
3
|
+
Advance only when the current task's exit gate passes. Each task must leave a
|
|
4
|
+
focused regression test.
|
|
5
|
+
|
|
6
|
+
| Order | Task | Capability produced |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| 00 | `tasks/00-verify-inherited-work.md` | trusted baseline for the staged generic builder |
|
|
9
|
+
| 01 | `tasks/01-authoritative-metadata.md` | wheel metadata derived from the package |
|
|
10
|
+
| 02 | `tasks/02-native-dependencies.md` | declared target libraries and profile sysroot |
|
|
11
|
+
| 03 | `tasks/03-reproducible-inputs.md` | hashed sources, build tools, patches, provenance |
|
|
12
|
+
| 04 | `tasks/04-build-frontends.md` | explicit backend interface beyond setuptools/PyO3 |
|
|
13
|
+
| 05 | `tasks/05-registry-integration.md` | reproducible build output consumable by `pip` |
|
|
14
|
+
| 06 | `tasks/06-package-cohorts.md` | evidence across independent package shapes |
|
|
15
|
+
| 07 | `tasks/07-build-on-miss-boundary.md` | local protocol/spec for an eventual build service |
|
|
16
|
+
|
|
17
|
+
## Platform completion gate
|
|
18
|
+
|
|
19
|
+
The platform milestone is complete when all of the following are true:
|
|
20
|
+
|
|
21
|
+
- Pure wheels continue to install directly and transactionally.
|
|
22
|
+
- Three native language/build shapes work without package-name branches.
|
|
23
|
+
- At least one extension links a separately built native target library.
|
|
24
|
+
- At least one package needs and cleanly carries a visible target patch.
|
|
25
|
+
- Wheel metadata and dependency resolution come from authoritative package
|
|
26
|
+
metadata plus explicit target constraints.
|
|
27
|
+
- Every indexed artifact is source-pinned, hash-verifiable, ABI-identified,
|
|
28
|
+
installable, importable, and behavior-tested in the owned runtime.
|
|
29
|
+
- A compatibility report distinguishes supported, recipe-required,
|
|
30
|
+
platform-blocked, and not-yet-attempted packages.
|
|
31
|
+
- The external build-on-miss interface is specified without embedding a
|
|
32
|
+
compiler toolchain in the browser runtime.
|
|
33
|
+
|
|
34
|
+
NumPy may be attempted after tasks 00-05. It is evidence for native dependency,
|
|
35
|
+
build-probe, memory, and scientific-stack behavior; it is not itself the
|
|
36
|
+
definition of platform completion.
|
|
37
|
+
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Execution state
|
|
2
|
+
|
|
3
|
+
Keep under roughly 120 lines. Replace stale detail instead of appending.
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
- Phase: `complete`
|
|
8
|
+
- Blocker: none
|
|
9
|
+
- User decision required: none outstanding
|
|
10
|
+
|
|
11
|
+
## Repository layout (restructured)
|
|
12
|
+
|
|
13
|
+
src/
|
|
14
|
+
kernel/ fs/ net/ shell/ the linux-mimicking core
|
|
15
|
+
node/ module shims, commonjs engine, esm transform
|
|
16
|
+
python/ cpython, syscalls, pip, resolver, worker, abi, local-builder
|
|
17
|
+
worker/ pods, sync channel, worker host
|
|
18
|
+
tools/ esbuild, rolldown, ffmpeg hosts
|
|
19
|
+
container/ pkg/ agent/ preview/ hosting/
|
|
20
|
+
docs/ every markdown file: agent/, python/, handoff.md
|
|
21
|
+
python-runtime/ the Python build pipeline (Makefile, scripts, recipes)
|
|
22
|
+
|
|
23
|
+
`src/runtime/` is gone. Moves were done with `git mv` and every relative import
|
|
24
|
+
recomputed programmatically. Four references were strings rather than import
|
|
25
|
+
specifiers -- two `dist/` paths whose depth changed, a `/src/runtime/python/`
|
|
26
|
+
check in config.ts, and a test allowlist -- and those caused 79 failures until
|
|
27
|
+
found. There was no dead code to remove: 2 of 130 source files are unreferenced
|
|
28
|
+
and both are ambient `.d.ts` files tsconfig loads implicitly.
|
|
29
|
+
|
|
30
|
+
## Packages: nothing to pre-build any more
|
|
31
|
+
|
|
32
|
+
`pip install <anything>` now builds a wheel when the index has none.
|
|
33
|
+
|
|
34
|
+
- `scripts/auto_recipe.py` writes a recipe from what PyPI and the source
|
|
35
|
+
already state: identity, verified sdist, and the declared PEP 517 backend.
|
|
36
|
+
Backends with no adapter are refused by name. Build requirements the lock has
|
|
37
|
+
never seen are pinned at that moment rather than dropped.
|
|
38
|
+
- `src/python/local-builder.ts` runs the pipeline; `bin/sandboxedjs-build-wheels.mjs`
|
|
39
|
+
serves the index and builds on request, for browsers that have no compiler.
|
|
40
|
+
- Opt-in, defaulting on only in Node from a checkout. Submit-and-poll, because
|
|
41
|
+
a connection held open for a minutes-long build reads as an unreachable
|
|
42
|
+
service.
|
|
43
|
+
- Verified: `pip install ujson` with no recipe -> generated, built, indexed,
|
|
44
|
+
installed, imported, both locally and through the service.
|
|
45
|
+
|
|
46
|
+
## Two real defects found and fixed
|
|
47
|
+
|
|
48
|
+
- The browser's default wheel index was filtered to the wheels whose bytes are
|
|
49
|
+
inlined in the bundle, so every other built wheel was invisible -- `pip
|
|
50
|
+
install numpy` reported no usable distribution while numpy sat unreferenced
|
|
51
|
+
beside the interpreter. The index now lists all built wheels, served from
|
|
52
|
+
next to the interpreter, with the inlined bytes as an overlay keyed by
|
|
53
|
+
filename.
|
|
54
|
+
- The post-build index read went through pip's memoizing cache and returned the
|
|
55
|
+
pre-build copy, so a package was built twice.
|
|
56
|
+
|
|
57
|
+
## Pre-existing failures, verified not caused by this work
|
|
58
|
+
|
|
59
|
+
11 tests, reproduced identically in a clean worktree at HEAD: `python-syscalls`
|
|
60
|
+
(5), `cpython` (2), `python-abi/baseline` (3), `python-runtime/asyncio` (1).
|
|
61
|
+
Also: pytest's default output capture fails in the container
|
|
62
|
+
(`OSError: [Errno 8] Bad file descriptor`), so upstream suites need
|
|
63
|
+
`--capture=no`.
|
|
64
|
+
|
|
65
|
+
## Unverified
|
|
66
|
+
|
|
67
|
+
`import numpy` in a browser. The embedded browser used for testing blocks
|
|
68
|
+
nested module workers loaded over HTTP, which the runtime needs to start Python
|
|
69
|
+
at all -- `python3 --version` times out there too, and so does a trivial nested
|
|
70
|
+
worker. `pip install numpy` was verified in that browser and returns 0.
|
|
71
|
+
|
|
72
|
+
## Last evidence
|
|
73
|
+
|
|
74
|
+
`npx vitest run`: 610 passed, 24 skipped, 12 failed (the 11 above plus one
|
|
75
|
+
PyPI-network flake that passes in isolation). `npm run typecheck`: pass.
|
|
76
|
+
`npm run build`: pass. All 16 wheels byte-identical across rebuilds.
|
|
77
|
+
|
|
78
|
+
## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template## Compact checkpoint template
|
|
79
|
+
|
|
80
|
+
Replace the sections above after each meaningful loop:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
Phase: <name>
|
|
84
|
+
Current task: <path>
|
|
85
|
+
Last completed task: <path or none>
|
|
86
|
+
Blocker: <one sentence or none>
|
|
87
|
+
User decision required: <yes/no and exact decision>
|
|
88
|
+
Last evidence:
|
|
89
|
+
- <command>: <pass/fail and decisive result>
|
|
90
|
+
Next action: <one concrete action>
|
|
91
|
+
Files changed this loop: <paths>
|
|
92
|
+
```
|
|
93
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Task 00: verify inherited generic cross-build work
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Establish that the staged setuptools/Cython work is real and reproducible
|
|
6
|
+
before building new layers on it. Do not expand scope in this task.
|
|
7
|
+
|
|
8
|
+
## Procedure
|
|
9
|
+
|
|
10
|
+
1. Inspect `git status --short`, `git diff --cached --check`, and the staged
|
|
11
|
+
diff limited to the files listed in `STATE.md`.
|
|
12
|
+
2. Confirm recipes cannot provide ABI compiler or linker flags.
|
|
13
|
+
3. Confirm generated artifacts are checked for WebAssembly, `dylink`, and the
|
|
14
|
+
derived `PyInit_*` symbol.
|
|
15
|
+
4. Run the setuptools and Cython fixture builds. Rebuild the wheel index after
|
|
16
|
+
any wheel output changes.
|
|
17
|
+
5. Run `npm run build` only if runtime bundles required by the acceptance test
|
|
18
|
+
are absent or older than relevant inputs.
|
|
19
|
+
6. Run `npx vitest run test/python-runtime/extensions.test.ts`.
|
|
20
|
+
7. Run `npm run typecheck`.
|
|
21
|
+
|
|
22
|
+
## Exit gate
|
|
23
|
+
|
|
24
|
+
- Staged diff check passes.
|
|
25
|
+
- Setuptools C, Cython, and PyO3 wheels install and execute native behavior in
|
|
26
|
+
the owned runtime.
|
|
27
|
+
- Pydantic acceptance remains green.
|
|
28
|
+
- No test passed by weakening or skipping an ABI assertion.
|
|
29
|
+
- `STATE.md` contains exact passing commands and points to task 01.
|
|
30
|
+
|
|
31
|
+
## If it fails
|
|
32
|
+
|
|
33
|
+
Use `DECISION-TREE.md`. Fix only regressions within the inherited work. After
|
|
34
|
+
three failed evidence-driven attempts on the same class, prepare an escalation
|
|
35
|
+
packet instead of redesigning the ABI.
|
|
36
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Task 01: authoritative wheel metadata
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
The current builder synthesizes `METADATA` from recipe fields. That duplicates
|
|
6
|
+
the package's dependency declarations and can create a wheel that installs but
|
|
7
|
+
resolves the wrong environment.
|
|
8
|
+
|
|
9
|
+
## Deliverable
|
|
10
|
+
|
|
11
|
+
Generate distribution metadata using the package's build metadata path under
|
|
12
|
+
the controlled build environment. Preserve upstream `Name`, `Version`,
|
|
13
|
+
`Requires-Dist`, extras, Python requirements, entry points, licenses, and other
|
|
14
|
+
install-relevant files. SandboxedJS should add only its wheel tag, generator,
|
|
15
|
+
and `Build-ABI` assertion.
|
|
16
|
+
|
|
17
|
+
Recipe constraints may explicitly override a target-inapplicable dependency,
|
|
18
|
+
but every override must be visible, justified, and tested.
|
|
19
|
+
|
|
20
|
+
## Required tests
|
|
21
|
+
|
|
22
|
+
- A fixture declares a conditional and an extra dependency upstream; neither
|
|
23
|
+
is copied into the recipe.
|
|
24
|
+
- The resulting wheel and generated `index.json` contain the authoritative
|
|
25
|
+
requirements.
|
|
26
|
+
- The resolver respects at least one marker/extras case.
|
|
27
|
+
- A disagreement between recipe identity and upstream identity fails loudly.
|
|
28
|
+
- Existing extension runtime tests remain green.
|
|
29
|
+
|
|
30
|
+
## Exit gate
|
|
31
|
+
|
|
32
|
+
No generic setuptools fixture needs handwritten `requires` metadata, and the
|
|
33
|
+
index is provably derived from the wheel produced from upstream metadata.
|
|
34
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Task 02: native target dependencies and sysroot
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
Extensions that name libraries or include their headers cannot currently
|
|
6
|
+
declare, build, locate, or link those target dependencies generically.
|
|
7
|
+
|
|
8
|
+
## Design requirement
|
|
9
|
+
|
|
10
|
+
Represent native target dependencies separately from Python runtime
|
|
11
|
+
dependencies and host build requirements. Each dependency must identify a
|
|
12
|
+
pinned source, hash, build recipe, output markers, license/provenance, and ABI
|
|
13
|
+
profile. The dynamic profile uses `out/sysroot-dynamic`; incompatible profiles
|
|
14
|
+
must never share object archives.
|
|
15
|
+
|
|
16
|
+
Add sysroot include and library search paths through generated cross-build
|
|
17
|
+
configuration, not ad hoc recipe flags.
|
|
18
|
+
|
|
19
|
+
## Reduced acceptance fixture
|
|
20
|
+
|
|
21
|
+
Before attempting a large external library, create a tiny static target library
|
|
22
|
+
with a header and one function. Build/install it through the dependency system,
|
|
23
|
+
then build a setuptools extension that declares the library normally and calls
|
|
24
|
+
it. The wheel must install and execute the function in the owned runtime.
|
|
25
|
+
|
|
26
|
+
After the reduced fixture passes, add one small real native library already
|
|
27
|
+
compatible with the project architecture. Do not begin with BLAS or NumPy.
|
|
28
|
+
|
|
29
|
+
## Exit gate
|
|
30
|
+
|
|
31
|
+
- Dependency closure is deterministic and cycle/error aware.
|
|
32
|
+
- Rebuilds are skipped only when validated output markers match inputs/profile.
|
|
33
|
+
- Missing dependency and wrong-profile reuse have focused negative tests.
|
|
34
|
+
- Reduced and real-library extensions import and run in owned CPython.
|
|
35
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Task 03: reproducible inputs, patches, and provenance
|
|
2
|
+
|
|
3
|
+
## Deliverable
|
|
4
|
+
|
|
5
|
+
Unify source archives, build-tool wheels, native dependencies, and package
|
|
6
|
+
patches under verified acquisition. No release artifact may depend on an
|
|
7
|
+
unpinned `pip install setuptools wheel ...` result.
|
|
8
|
+
|
|
9
|
+
Define a visible patch layout. A patch records package/version, upstream source
|
|
10
|
+
hash, reason, target fact being substituted, and a test. Patch application must
|
|
11
|
+
fail on drift rather than fuzzily succeeding against another source version.
|
|
12
|
+
|
|
13
|
+
Record enough provenance in build output or adjacent index metadata to answer:
|
|
14
|
+
|
|
15
|
+
- which source hash produced this wheel;
|
|
16
|
+
- which build tools and target libraries were used;
|
|
17
|
+
- which ABI ID and recipe revision were used;
|
|
18
|
+
- which patches were applied.
|
|
19
|
+
|
|
20
|
+
## Exit gate
|
|
21
|
+
|
|
22
|
+
- Offline rebuild succeeds from a populated verified cache.
|
|
23
|
+
- A changed hash, unpinned build tool, or drifting patch fails before compile.
|
|
24
|
+
- Two identical clean builds produce equivalent wheel contents, allowing only
|
|
25
|
+
explicitly documented archive timestamp normalization until deterministic
|
|
26
|
+
ZIP output is implemented.
|
|
27
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Task 04: build frontend interface
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Turn the current kinds into a stable backend interface rather than accumulating
|
|
6
|
+
branches in `build_extension.py`.
|
|
7
|
+
|
|
8
|
+
## Required interface
|
|
9
|
+
|
|
10
|
+
Each backend receives verified source, host tools, target configuration,
|
|
11
|
+
declared native dependencies, staging directory, and ABI contract. It returns a
|
|
12
|
+
wheel tree or wheel plus build evidence. It cannot mutate the ABI.
|
|
13
|
+
|
|
14
|
+
Retain proven setuptools/Cython and PyO3 behavior. Add another frontend only
|
|
15
|
+
when a selected cohort package requires it; likely candidates include PEP 517
|
|
16
|
+
wheel hooks, Meson, or scikit-build/CMake. Do not implement all frontends
|
|
17
|
+
speculatively.
|
|
18
|
+
|
|
19
|
+
Keep package quirks in patches/recipes and backend mechanics in adapters.
|
|
20
|
+
|
|
21
|
+
## Exit gate
|
|
22
|
+
|
|
23
|
+
- Backend selection is explicit and schema-validated.
|
|
24
|
+
- The generic orchestrator has no package-name checks.
|
|
25
|
+
- Existing fixtures pass through the interface.
|
|
26
|
+
- One pyproject-only package runs through a real isolated PEP 517 path.
|
|
27
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Task 05: registry and installer integration
|
|
2
|
+
|
|
3
|
+
## Deliverable
|
|
4
|
+
|
|
5
|
+
Produce an immutable wheel repository that the existing SandboxedJS `pip`
|
|
6
|
+
resolver can consume. Define schema versioning, atomic publication layout,
|
|
7
|
+
digest verification, ABI partitioning, and dependency metadata.
|
|
8
|
+
|
|
9
|
+
The browser runtime remains an installer, not a compiler. A missing native
|
|
10
|
+
wheel should return a structured, actionable classification that a host may use
|
|
11
|
+
later to request a build. It must not perform an implicit remote mutation.
|
|
12
|
+
|
|
13
|
+
## Required tests
|
|
14
|
+
|
|
15
|
+
- Correct ABI wheel wins over incompatible and host-native candidates.
|
|
16
|
+
- Wrong ABI and wrong digest are refused before installation.
|
|
17
|
+
- A failed graph leaves no partial site-packages state.
|
|
18
|
+
- A newly built test wheel can be indexed, served, installed, imported, and
|
|
19
|
+
exercised through the ordinary container command.
|
|
20
|
+
- Index publication cannot expose a wheel before its metadata and content are
|
|
21
|
+
complete.
|
|
22
|
+
|
|
23
|
+
## Exit gate
|
|
24
|
+
|
|
25
|
+
A clean consumer needs only a runtime plus index URL/object; no local source
|
|
26
|
+
tree or compiler is required for supported packages.
|
|
27
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Task 06: representative package cohorts
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Measure generality without allowing one package to define the architecture.
|
|
6
|
+
|
|
7
|
+
## Selection method
|
|
8
|
+
|
|
9
|
+
Choose small packages first, pin exact versions and hashes, and record why each
|
|
10
|
+
adds a new capability. Select at least one from each applicable cohort:
|
|
11
|
+
|
|
12
|
+
1. pure wheel control case;
|
|
13
|
+
2. setuptools C extension without external target libraries;
|
|
14
|
+
3. generated C/Cython extension;
|
|
15
|
+
4. Rust/PyO3 extension;
|
|
16
|
+
5. extension using a separately built native target library;
|
|
17
|
+
6. package requiring a visible cross-compilation patch;
|
|
18
|
+
7. pyproject/PEP 517 backend not already covered;
|
|
19
|
+
8. scientific-stack stress case, eventually including NumPy.
|
|
20
|
+
|
|
21
|
+
Do not count existing probes as real-package cohort evidence, but retain them as
|
|
22
|
+
reduced regression tests.
|
|
23
|
+
|
|
24
|
+
## Compatibility report
|
|
25
|
+
|
|
26
|
+
For every attempted package, record exactly one status:
|
|
27
|
+
|
|
28
|
+
- `supported-generic`;
|
|
29
|
+
- `supported-recipe`;
|
|
30
|
+
- `blocked-platform-capability`;
|
|
31
|
+
- `blocked-toolchain`;
|
|
32
|
+
- `not-yet-attempted`.
|
|
33
|
+
|
|
34
|
+
Record build command, source hash, wheel hash, ABI ID, test behavior, peak size
|
|
35
|
+
or memory when material, and the earliest unsupported assumption on failure.
|
|
36
|
+
|
|
37
|
+
## Exit gate
|
|
38
|
+
|
|
39
|
+
At least five independent real packages across four native/build shapes pass
|
|
40
|
+
runtime behavior tests, and failures produce reusable classifications instead
|
|
41
|
+
of package-specific branches.
|
|
42
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Task 07: external build-on-miss boundary
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Specify the seam that can later connect the installer to a trusted build
|
|
6
|
+
service without deploying that service or placing a toolchain in the browser.
|
|
7
|
+
|
|
8
|
+
## Deliverable
|
|
9
|
+
|
|
10
|
+
Define versioned request/status/result schemas. A request includes normalized
|
|
11
|
+
requirement, source/index evidence, target ABI ID, policy/recipe revision, and
|
|
12
|
+
an idempotency key. A result includes immutable wheel/index locations, hashes,
|
|
13
|
+
provenance, logs summary, compatibility classification, and terminal state.
|
|
14
|
+
|
|
15
|
+
States should cover queued, resolving, building host tools, building target
|
|
16
|
+
dependencies, building wheel, testing, published, unsupported, failed, and
|
|
17
|
+
cancelled. Repeated identical requests must converge on one cached artifact.
|
|
18
|
+
|
|
19
|
+
Security requirements include source allowlists/policy, resource limits,
|
|
20
|
+
network isolation, no untrusted artifact publication before runtime tests,
|
|
21
|
+
digest verification, and auditability.
|
|
22
|
+
|
|
23
|
+
## Exit gate
|
|
24
|
+
|
|
25
|
+
- Schemas and a local fake implementation are tested.
|
|
26
|
+
- Installer/host integration can report a buildable miss without automatically
|
|
27
|
+
triggering external work.
|
|
28
|
+
- Cached success, unsupported result, transient failure, cancellation, and ABI
|
|
29
|
+
rollover are covered.
|
|
30
|
+
- No cloud service is deployed without explicit user authorization.
|
|
31
|
+
|