dshm-compat 0.1.3 → 0.1.5
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/AGENTS.md +17 -0
- package/CHANGELOG.md +75 -9
- package/INSTALL.md +6 -6
- package/README.md +39 -15
- package/assets/qemu-x86_64/NOTICE.md +17 -0
- package/assets/qemu-x86_64/qemu-x86_64 +0 -0
- package/assets/qemu-x86_64/rootfs/lib/x86_64-linux-gnu/libc.so.6 +0 -0
- package/assets/qemu-x86_64/rootfs/lib/x86_64-linux-gnu/libgcc_s.so.1 +0 -0
- package/assets/qemu-x86_64/rootfs/lib64/ld-linux-x86-64.so.2 +0 -0
- package/docs/ARCHITECTURE.md +18 -8
- package/docs/RECIPES.md +79 -91
- package/index.js +104 -1
- package/lib/analyze.js +9 -1
- package/lib/convert.js +58 -4
- package/lib/elf.js +41 -0
- package/lib/guest.js +6 -3
- package/lib/plan.js +10 -0
- package/lib/release.js +185 -0
- package/lib/rules.js +7 -22
- package/lib/s2-native.js +316 -0
- package/lib/sidecar.js +185 -0
- package/lib/source-build.js +165 -0
- package/lib/uninstall.js +94 -0
- package/lib/zip.js +59 -0
- package/package.json +3 -1
- package/lib/recipes/dsh-ops.js +0 -209
package/AGENTS.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# dshm-compat development rules
|
|
2
|
+
|
|
3
|
+
## No per-plugin adaptation
|
|
4
|
+
|
|
5
|
+
- **Never** add a production branch, recipe, rule, or hand-built artifact for one
|
|
6
|
+
package name. `dshm-compat` must adapt plugins through its generic engines.
|
|
7
|
+
- S2/native plugins go through `lib/s2-native.js`: detect the worker and the
|
|
8
|
+
standard runtime/spawn patterns, stage the worker, normalize the manifest, and
|
|
9
|
+
validate the result. Package names may appear only in tests and documentation
|
|
10
|
+
examples, never in `if (name === ...)` logic.
|
|
11
|
+
- If a plugin has a genuinely unique protocol, expose a **generic extension
|
|
12
|
+
point** in the plugin engine (patterns, hooks, or sidecar descriptor), not a
|
|
13
|
+
one-off patch.
|
|
14
|
+
- `dsh-ops` is a regression fixture. It proves the generic S2 adapter; it is not
|
|
15
|
+
a special case.
|
|
16
|
+
- Deliverables are the plugin and its generic tooling, not a converted tarball
|
|
17
|
+
for a single plugin.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,16 +1,82 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
- Spawn rewriting now uses `['bash', file]` plus a staged shell wrapper instead
|
|
6
|
+
of `bash -c 'exec "$0" "$@"'`. `dshm-vm-bash` drops positional parameters for
|
|
7
|
+
`-c`, so the old form produced `Permission denied` and lost worker arguments.
|
|
8
|
+
- `runGuestFile` and sidecars use the same non-`-c` path (`bash <wrapper> <args>`).
|
|
9
|
+
- Release acquisition tries the package-version tag first, then the latest
|
|
10
|
+
release, falls back to the API asset endpoint, verifies `sha256` when
|
|
11
|
+
available, and returns attempts instead of a silent failure.
|
|
12
|
+
- Source-only packages return `needs-build` with an external build contract;
|
|
13
|
+
when the same package has a published npm build, `convert` automatically
|
|
14
|
+
retries that build instead. Verified with `dsh-ops` 0.4.0 GitHub source:
|
|
15
|
+
it falls back to `dsh-ops@0.3.0` and produces a validated package.
|
|
16
|
+
- Added `compat_build`: a source build planner for `Cargo.toml`/Node
|
|
17
|
+
`build`/`prepack` packages, plus an opt-in `backend:"guest"` attempt that
|
|
18
|
+
provisions Rust or Node in the Alpine guest and runs the build there. The
|
|
19
|
+
guest path depends on guest network/disk and is explicitly experimental.
|
|
20
|
+
- Added `compat_uninstall` and `engines.dsh` normalization.
|
|
21
|
+
- Offline regression suite: 30/30.
|
|
22
|
+
|
|
23
|
+
## 0.1.4
|
|
24
|
+
|
|
25
|
+
- The generic S2 adapter now accepts **x86_64** workers: it bundles
|
|
26
|
+
`qemu-x86_64` and a minimal x86_64 glibc rootfs, stages a shell wrapper, and
|
|
27
|
+
runs the worker under QEMU in the guest. No AArch64 rebuild is required for
|
|
28
|
+
plugins that publish a `linux-x64` runtime.
|
|
29
|
+
- If the package contains no worker, the adapter looks at the GitHub repository
|
|
30
|
+
release assets, prefers `linux-arm64` then `linux-x64`, extracts the archive
|
|
31
|
+
(ZIP or tar.gz), and uses the first AArch64/x86_64 ELF. No package name is
|
|
32
|
+
special-cased.
|
|
33
|
+
- Source-only native packages (for example a Rust `native/` tree with no
|
|
34
|
+
prebuilt runtime) now classify as S2 instead of S0, so the native adapter gets
|
|
35
|
+
a chance to build or acquire a worker.
|
|
36
|
+
- Verified end-to-end: `compat_convert("https://github.com/T-Auto/dsh-ops")`
|
|
37
|
+
with **no workerPath** acquires the upstream `linux-x64` release asset, wraps
|
|
38
|
+
it in QEMU, patches the runtime/spawn/peer/os-cpu gates, and validates.
|
|
39
|
+
- Spawn rewrite now uses `['bash', file]` and stages a shell wrapper around the
|
|
40
|
+
real worker instead of `bash -c 'exec "$0" "$@"'`. `dshm-vm-bash` drops
|
|
41
|
+
`$0`/`$@` for `-c` commands, which caused `Permission denied` and lost
|
|
42
|
+
arguments; the non-`-c` path preserves them.
|
|
43
|
+
- Release selection first tries the tag matching the package version (`vX.Y.Z`),
|
|
44
|
+
then the latest release with assets; missing tags fall through instead of
|
|
45
|
+
returning an empty asset list.
|
|
46
|
+
- Release download falls back from `browser_download_url` to the GitHub API
|
|
47
|
+
asset endpoint (`Accept: application/octet-stream`), records every attempt,
|
|
48
|
+
and verifies the asset `sha256` digest when GitHub provides one. Failures are
|
|
49
|
+
returned in `acquisition.attempts`, not swallowed.
|
|
50
|
+
- The adapter also rewrites resolved-shell spawns (`[file, '-c', command]` and
|
|
51
|
+
`[file, scriptPath]`) to `['bash', '-c', command]` / `['bash', scriptPath]`,
|
|
52
|
+
so the shell component does not exec an ELF from the app sandbox.
|
|
53
|
+
- `runGuestFile` now invokes `bash <script> <args>` instead of
|
|
54
|
+
`bash -c 'exec "$0" "$@"'`; sidecars stage a wrapper script so positional
|
|
55
|
+
arguments survive `dshm-vm-bash`.
|
|
56
|
+
- Source packages with no built `main` and a `build`/`prepack` script return
|
|
57
|
+
`needs-build` with an external `npm ci && npm run build && npm pack` contract
|
|
58
|
+
instead of `recipe-mismatch`.
|
|
59
|
+
- Added `compat_uninstall` for profile-local removal (node_modules + dependency
|
|
60
|
+
+ bundle entry), and `engines.dsh` is stripped alongside `os`/`cpu`.
|
|
61
|
+
- Offline regression suite: 28/28.
|
|
62
|
+
|
|
3
63
|
## 0.1.3
|
|
4
64
|
|
|
5
|
-
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
65
|
+
- Added a **generic S2 native adapter** (`lib/s2-native.js`). It discovers the
|
|
66
|
+
worker and the runtime matrix in the package, appends the DSHM target,
|
|
67
|
+
rewrites `${platform}-${arch}` templates, wraps standard `const/let argv =
|
|
68
|
+
[file]` spawn calls in `bash -c`, removes foreign `os`/`cpu` gates and
|
|
69
|
+
non-Linux optional payloads, and relaxes the DSH `peerDependencies` range.
|
|
70
|
+
There are no package-name branches and no built-in per-package rules.
|
|
71
|
+
- Added a generic guest sidecar bridge (`compat_sidecar` / `lib/sidecar.js`):
|
|
72
|
+
stage a Linux/AArch64 worker from a converted tarball into
|
|
73
|
+
`$DSH_HOME/dshm-compat/sidecars/<id>`, list/probe it, and call it with one
|
|
74
|
+
JSON request/response through the Alpine guest.
|
|
75
|
+
- `compat_plan` now infers `rust`, `c/c++`, or `node-gyp` from source files in
|
|
76
|
+
the report instead of relying on a package-specific rule.
|
|
77
|
+
- S2 conversion dispatches on the strategy and the generic patterns, not on a
|
|
78
|
+
package name; GitHub specs work through the same path.
|
|
79
|
+
- Offline regression suite: 25/25.
|
|
14
80
|
|
|
15
81
|
## 0.1.2
|
|
16
82
|
|
package/INSTALL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Installing dshm-compat
|
|
2
2
|
|
|
3
|
-
The artifact is a normal DSH bundle package: `dshm-compat-0.1.
|
|
4
|
-
It is host-only, has no runtime dependencies, and adds
|
|
3
|
+
The artifact is a normal DSH bundle package: `dshm-compat-0.1.5.tgz`.
|
|
4
|
+
It is host-only, has no runtime dependencies, and adds twelve agent tools.
|
|
5
5
|
|
|
6
6
|
## A. DSHM (the tablet)
|
|
7
7
|
|
|
@@ -15,7 +15,7 @@ input calls `pnpm view` before installing and fails with
|
|
|
15
15
|
`Command failed with EACCES: pnpm view ... spawn pnpm EACCES`. Use one of these
|
|
16
16
|
instead:
|
|
17
17
|
|
|
18
|
-
- ask the DSHM Agent to run `pnpm add dshm-compat@0.1.
|
|
18
|
+
- ask the DSHM Agent to run `pnpm add dshm-compat@0.1.5` in its bash tool (the
|
|
19
19
|
bundled pnpm shim routes that command to the host install queue); or
|
|
20
20
|
- install from a GitHub repository URL; or
|
|
21
21
|
- after any working install, use the plugin's own `compat_install` tool for
|
|
@@ -28,7 +28,7 @@ not accept local paths, `file:` or `http://` specs.
|
|
|
28
28
|
|
|
29
29
|
### A2. HTTPS tarball
|
|
30
30
|
|
|
31
|
-
Put `dshm-compat-0.1.
|
|
31
|
+
Put `dshm-compat-0.1.5.tgz` on any HTTPS host (GitHub Release, Gitee Release,
|
|
32
32
|
object storage) and paste the `.tgz` URL into the same Add plugin input. DSHM's
|
|
33
33
|
installer accepts tarball specs; if the current market UI refuses a plain URL,
|
|
34
34
|
use A1.
|
|
@@ -38,7 +38,7 @@ use A1.
|
|
|
38
38
|
If `hdc` is available and the app can read the path:
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
|
-
hdc file send dshm-compat-0.1.
|
|
41
|
+
hdc file send dshm-compat-0.1.5.tgz /data/storage/el2/base/haps/entry/files/dshm-compat-0.1.5.tgz
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Then enter the absolute path (or `file:/...`) in the Add plugin input. This
|
|
@@ -47,7 +47,7 @@ depends on the DSHM build's local-file support; A1 is safer.
|
|
|
47
47
|
## B. Desktop DSH (for testing only)
|
|
48
48
|
|
|
49
49
|
```powershell
|
|
50
|
-
& 'D:\安装\dsh-desktop\resources\runtime\cli\bin\dsh.cmd' plugin --profile desktop add 'D:\dsh\dsh-26-09-30\dshm-compat\dshm-compat-0.1.
|
|
50
|
+
& 'D:\安装\dsh-desktop\resources\runtime\cli\bin\dsh.cmd' plugin --profile desktop add 'D:\dsh\dsh-26-09-30\dshm-compat\dshm-compat-0.1.5.tgz'
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
If the profile reports `ERR_PNPM_UNEXPECTED_VIRTUAL_STORE`, its `node_modules`
|
package/README.md
CHANGED
|
@@ -5,11 +5,12 @@ them through the least invasive strategy that can work.
|
|
|
5
5
|
|
|
6
6
|
## Current phase
|
|
7
7
|
|
|
8
|
-
0.1.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
and a profile-local fallback for artifacts the host
|
|
8
|
+
0.1.5 adds runtime-bridge fixes (non-`-c` spawn wrappers), release asset
|
|
9
|
+
fallbacks, and `compat_uninstall`; 0.1.4 added the generic S2 adapter with
|
|
10
|
+
x86_64 QEMU and GitHub Release acquisition. Phase 1 ships the analyzer, the
|
|
11
|
+
S0/S1 converter, the generic S2 engine, guest probing/provisioning, the DSHM
|
|
12
|
+
install-queue transport, and a profile-local fallback for artifacts the host
|
|
13
|
+
queue rejects:
|
|
13
14
|
|
|
14
15
|
- `compat_analyze` downloads an npm/GitHub/local package and classifies it.
|
|
15
16
|
- `compat_plan` returns the concrete conversion plan without changing anything.
|
|
@@ -18,12 +19,21 @@ and a profile-local fallback for artifacts the host queue rejects:
|
|
|
18
19
|
install lifecycle scripts, client platform), vendors missing pure-JS runtime
|
|
19
20
|
dependencies into a flat `node_modules`, validates the resulting tarball, and
|
|
20
21
|
repacks it as a DSHM tarball; for S1 it removes a native dependency that the
|
|
21
|
-
DSHM core already provides. For
|
|
22
|
-
|
|
23
|
-
`
|
|
22
|
+
DSHM core already provides. For S2 it uses the generic native adapter: it
|
|
23
|
+
detects the worker, `PLATFORMS` matrix, `${platform}-${arch}` templates,
|
|
24
|
+
standard spawn calls, and foreign `os`/`cpu`/peer gates. A worker can come from
|
|
25
|
+
`workerPath`, the package's `runtime/linux-*`, or the GitHub Release assets
|
|
26
|
+
(linux-arm64 first, then linux-x64). An x86_64 worker is executed through the
|
|
27
|
+
bundled `qemu-x86_64` and glibc rootfs, so no AArch64 rebuild is required.
|
|
28
|
+
A source-only checkout is retried against the package's published npm build
|
|
29
|
+
(with a `fallback` field in the result); only when neither a worker nor a
|
|
30
|
+
published build exists does it return `needs-build`/`needs-native-build` with
|
|
31
|
+
the external build command. Package names are not special-cased.
|
|
24
32
|
- `compat_guest_probe` reports the Alpine guest kernel/packages/tools.
|
|
25
33
|
- `compat_guest_provision` installs a reviewed allowlist of Alpine packages in
|
|
26
34
|
the guest (`confirm:true` required).
|
|
35
|
+
- `compat_sidecar` stages a native Linux/AArch64 worker from a converted
|
|
36
|
+
tarball and lists/probes/calls it in the guest with JSON stdin/stdout.
|
|
27
37
|
- `compat_status` lists stored reports and install attempts.
|
|
28
38
|
- `compat_doctor` checks DSHM mode, core, profile/bundle, queue, state, and the
|
|
29
39
|
guest in one read-only call.
|
|
@@ -31,26 +41,40 @@ and a profile-local fallback for artifacts the host queue rejects:
|
|
|
31
41
|
`.tgz` paths (and `file:`/`link:`) are unpacked directly into the owning DSH
|
|
32
42
|
profile and its bundle list, then need a DSHM restart; this is required
|
|
33
43
|
because the DSHM host queue rejects local specs.
|
|
44
|
+
- `compat_build` plans a source build (PC/CI commands) or, with
|
|
45
|
+
`backend:"guest"` and `confirm:true`, provisions Node/Rust in the Alpine
|
|
46
|
+
guest and attempts the build there. The guest path is experimental and
|
|
47
|
+
depends on guest network/disk.
|
|
48
|
+
- `compat_uninstall` removes a profile-local package, its dependency entry, and
|
|
49
|
+
its bundle entry; it also needs a restart.
|
|
34
50
|
- `compat_convert` with `install:true` uses the same local fallback for its
|
|
35
51
|
converted tarball.
|
|
36
52
|
|
|
37
|
-
The converter
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
The converter stops at the manifest/repack/vendor boundary for S0/S1. S2 also
|
|
54
|
+
returns `needs-build` for a source-only package or `needs-native-build` when no
|
|
55
|
+
Linux worker can be obtained. It does not silently claim that an unsupported
|
|
56
|
+
native build succeeded.
|
|
41
57
|
|
|
42
58
|
See [architecture](docs/ARCHITECTURE.md) and [conversion recipes](docs/RECIPES.md).
|
|
43
59
|
|
|
60
|
+
## Development policy
|
|
61
|
+
|
|
62
|
+
There are **no per-plugin production branches**. S2 native plugins go through
|
|
63
|
+
the generic `lib/s2-native.js` engine; package names appear only in tests and
|
|
64
|
+
documentation examples. If a plugin has a unique protocol, add a generic
|
|
65
|
+
extension point (pattern, hook, or sidecar descriptor) instead of a one-off
|
|
66
|
+
patch. See [AGENTS.md](AGENTS.md).
|
|
67
|
+
|
|
44
68
|
## CLI
|
|
45
69
|
|
|
46
70
|
The same converter runs on a PC without installing the DSH plugin:
|
|
47
71
|
|
|
48
72
|
```sh
|
|
49
73
|
node bin/dshm-compat.mjs analyze dsh-m
|
|
50
|
-
node bin/dshm-compat.mjs plan
|
|
74
|
+
node bin/dshm-compat.mjs plan some-native-plugin
|
|
51
75
|
node bin/dshm-compat.mjs convert dsh-cache-billing --no-vendor
|
|
52
|
-
node bin/dshm-compat.mjs convert
|
|
53
|
-
node bin/dshm-compat.mjs scan dsh-m
|
|
76
|
+
node bin/dshm-compat.mjs convert some-native-plugin --worker ./some-native-worker
|
|
77
|
+
node bin/dshm-compat.mjs scan dsh-m some-native-plugin some-plugin
|
|
54
78
|
```
|
|
55
79
|
|
|
56
80
|
`convert` writes the tarball under `$DSH_HOME/dshm-compat/builds` (override with
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Bundled QEMU x86_64 user-mode runtime
|
|
2
|
+
|
|
3
|
+
This directory is a generic fallback for S2 plugins that ship a `linux-x64`
|
|
4
|
+
native worker but no AArch64 build. `qemu-x86_64` executes the x86_64 worker in
|
|
5
|
+
the DSHM Alpine guest; the `rootfs/` directory supplies the glibc loader and
|
|
6
|
+
libraries the worker links against.
|
|
7
|
+
|
|
8
|
+
- `qemu-x86_64`: Alpine 3.22 `qemu-x86_64` 10.0.0-r1 (aarch64 build), GPL-2.0.
|
|
9
|
+
Source: https://pkgs.alpinelinux.org/package/v3.22/community/aarch64/qemu-x86_64
|
|
10
|
+
- `rootfs/lib64/ld-linux-x86-64.so.2`,
|
|
11
|
+
`rootfs/lib/x86_64-linux-gnu/libc.so.6`,
|
|
12
|
+
`rootfs/lib/x86_64-linux-gnu/libgcc_s.so.1`: Ubuntu 24.04 x86_64 base rootfs,
|
|
13
|
+
LGPL-2.1/GPL-2.0 with GCC runtime exception.
|
|
14
|
+
Source: https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/
|
|
15
|
+
|
|
16
|
+
The fallback is optional: when a plugin has a native AArch64 worker, the generic
|
|
17
|
+
S2 adapter stages that directly and these files are not used.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -37,7 +37,7 @@ spec ──► resolve (npm / GitHub / local .tgz)
|
|
|
37
37
|
──► extract (ustar/pax, no dependency)
|
|
38
38
|
──► analyze (manifest, native files, scripts, platform/Electron scan, core inventory)
|
|
39
39
|
──► plan (S0..S4 + concrete steps)
|
|
40
|
-
──► convert (S0/S1
|
|
40
|
+
──► convert (S0/S1 manifest, S2 generic native adapter)
|
|
41
41
|
──► pack (ustar writer)
|
|
42
42
|
──► install queue (DSHM only)
|
|
43
43
|
```
|
|
@@ -50,14 +50,20 @@ spec ──► resolve (npm / GitHub / local .tgz)
|
|
|
50
50
|
| `lib/tar.js` | ustar/pax extraction with traversal and size guards |
|
|
51
51
|
| `lib/analyze.js` | classification evidence, strategy, confidence, next action |
|
|
52
52
|
| `lib/core.js` | locate `$DSH_HOME/cores/<version>/node_modules` and compare runtime dependencies |
|
|
53
|
-
| `lib/rules.js` |
|
|
54
|
-
| `lib/convert.js` | S0 manifest rewrite/repack and vendoring; S1 native-dependency removal |
|
|
53
|
+
| `lib/rules.js` | operator-supplied custom rules only; no built-in per-package rules |
|
|
54
|
+
| `lib/convert.js` | S0 manifest rewrite/repack and vendoring; S1 native-dependency removal; dispatch to the S2 adapter |
|
|
55
|
+
| `lib/s2-native.js` | generic S2 worker/runtime/spawn/peer adapter |
|
|
56
|
+
| `lib/release.js` | GitHub Release Linux worker discovery and extraction |
|
|
57
|
+
| `lib/zip.js` | dependency-free ZIP reader for release assets |
|
|
55
58
|
| `lib/vendor.js` | flat `node_modules` vendoring for missing pure-JS dependencies |
|
|
56
59
|
| `lib/validate.js` | post-conversion manifest/entry/dependency validation |
|
|
57
60
|
| `lib/plan.js` | user-visible conversion plan for every strategy |
|
|
58
61
|
| `lib/guest.js` | read-only Alpine guest probe through `subprocess` |
|
|
59
62
|
| `lib/install.js` | DSHM install-queue producer with polling and cancellation |
|
|
60
63
|
| `lib/local-install.js` | profile-local tarball install with staging, backup, and rollback |
|
|
64
|
+
| `lib/uninstall.js` | profile-local removal of files, dependency, and bundle entry |
|
|
65
|
+
| `lib/source-build.js` | source-build planner and experimental guest build |
|
|
66
|
+
| `lib/sidecar.js` | generic guest worker staging and JSON-stdio calls |
|
|
61
67
|
| `lib/doctor.js` | one-shot DSHM/core/profile/queue/guest diagnosis |
|
|
62
68
|
| `lib/state.js` | bounded report/install index and atomic writes |
|
|
63
69
|
| `lib/pack.js` | dependency-free ustar/gzip writer |
|
|
@@ -72,18 +78,22 @@ spec ──► resolve (npm / GitHub / local .tgz)
|
|
|
72
78
|
| `compat_convert` | writes a converted tarball; optionally submits it to the install queue |
|
|
73
79
|
| `compat_guest_probe` | read-only guest command |
|
|
74
80
|
| `compat_guest_provision` | installs allowlisted Alpine packages in the guest |
|
|
81
|
+
| `compat_sidecar` | stages/lists/probes/calls a JSON-stdio native worker in the guest |
|
|
75
82
|
| `compat_doctor` | read-only DSHM/core/profile/queue/guest diagnosis |
|
|
76
83
|
| `compat_install` | writes one install-queue request; runs third-party code |
|
|
84
|
+
| `compat_build` | plans a source build, or provisions a guest toolchain and runs it with confirm:true |
|
|
85
|
+
| `compat_uninstall` | removes a profile-local package, dependency, and bundle entry |
|
|
77
86
|
| `compat_status` | read-only |
|
|
78
87
|
|
|
79
88
|
## Phase status
|
|
80
89
|
|
|
81
90
|
- **Phase 1 (done):** analyzer, batch triage, S0 manifest converter + flat
|
|
82
|
-
dependency vendoring + output validation, S1 manifest substitution,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
dependency vendoring + output validation, S1 manifest substitution, generic S2
|
|
92
|
+
native adapter (AArch64 worker, x86_64 worker through bundled QEMU, GitHub
|
|
93
|
+
Release acquisition), dependency preflight, guest probe/provisioning, worker
|
|
94
|
+
execution primitive, install queue, offline tests.
|
|
95
|
+
- **Phase 2 (next):** on-device guest verification, automatic worker build
|
|
96
|
+
(desktop/CI), nested version-conflict vendoring, sidecar RPC.
|
|
87
97
|
- **Phase 3:** WASM/remote fallback, market UI entry, compatibility registry
|
|
88
98
|
updates.
|
|
89
99
|
|
package/docs/RECIPES.md
CHANGED
|
@@ -1,104 +1,92 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
These are the
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
- `dsh-plugin.json`
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
1
|
+
# Generic conversion patterns
|
|
2
|
+
|
|
3
|
+
These are the patterns behind `S1`/`S2` plans. They are **generic**: no
|
|
4
|
+
production branch is keyed on a package name. A package name may appear only in
|
|
5
|
+
tests or as a documentation example.
|
|
6
|
+
|
|
7
|
+
## S2: native worker
|
|
8
|
+
|
|
9
|
+
The generic adapter in `lib/s2-native.js` recognizes the common shape of a
|
|
10
|
+
native DSH plugin:
|
|
11
|
+
|
|
12
|
+
1. A worker binary under `runtime/<platform>-<arch>/<name>`, a worker passed
|
|
13
|
+
explicitly with `workerPath`, or a Linux asset on the repository's GitHub
|
|
14
|
+
Release (arm64 preferred, then x64).
|
|
15
|
+
2. A JS module exporting a `PLATFORMS` array and interpolating
|
|
16
|
+
`${platform}-${arch}` into runtime paths.
|
|
17
|
+
3. Spawn calls of the form `const argv = [file]` or `let argv = [file]`.
|
|
18
|
+
4. Optional `package.json` `os`/`cpu` gates and a DSH `peerDependencies` range.
|
|
19
|
+
|
|
20
|
+
For each match it:
|
|
21
|
+
|
|
22
|
+
- appends `linux-arm64` (AArch64 worker) or `linux-x64` (x86_64 worker) to
|
|
23
|
+
`PLATFORMS` and injects a `resolveTarget()` helper so `openharmony`/arm64
|
|
24
|
+
resolves to that target in both `resolveWorker` and `tryResolveWorker`;
|
|
25
|
+
- replaces `${platform}-${arch}` **inside template literals** with
|
|
26
|
+
`${resolveTarget(platform, arch)}`;
|
|
27
|
+
- rewrites every standard spawn call to `['bash', file]` and stages a shell
|
|
28
|
+
wrapper at `file` that `exec`s the real worker with `"$@"`. The
|
|
29
|
+
non-`-c` path is required because `dshm-vm-bash` drops positional parameters
|
|
30
|
+
for `bash -c`; the wrapper preserves the worker's argv;
|
|
31
|
+
- removes `os`/`cpu`/`engines.dsh`, drops win32/darwin optional payloads, and
|
|
32
|
+
relaxes `@deepseek-ai/dsh` to `workspace:*`;
|
|
33
|
+
- adds `openharmony`/target/arch to `dsh-plugin.json` component targets;
|
|
34
|
+
- stages the wrapper at `runtime/<target>/<worker>` and the real binary at
|
|
35
|
+
`<worker>-bin` (AArch64) or `<worker>-x64` (x86_64), with a matching
|
|
36
|
+
`provenance.json` (`version`, `target`, `executable`, `sha256`).
|
|
37
|
+
|
|
38
|
+
A source package whose `main` is absent but which has a `build`/`prepack` script
|
|
39
|
+
returns `needs-build` with `npm ci && npm run build && npm pack`; the produced
|
|
40
|
+
tarball is then passed back to `compat_convert`. Before returning that, the
|
|
41
|
+
converter retries the package's latest published npm build and records a
|
|
42
|
+
`fallback` field when it succeeds. This keeps a source checkout from being
|
|
43
|
+
misreported as a broken recipe while still preferring a runnable published build.
|
|
44
|
+
|
|
45
|
+
### Guest source build
|
|
46
|
+
|
|
47
|
+
`compat_build { spec, backend: "plan" }` returns the exact PC/CI commands. With
|
|
48
|
+
`backend: "guest"` and `confirm: true`, the plugin provisions Node or Rust in
|
|
49
|
+
the Alpine guest and runs the detected command (`cargo build --release`, or
|
|
50
|
+
`npm ci && npm run build && npm pack`). This is experimental: it needs guest
|
|
51
|
+
network, enough guest disk for the toolchain, and a guest-visible source
|
|
52
|
+
directory. A failure returns the exact `apk`/build stderr; fall back to an
|
|
53
|
+
external build and pass the produced artifact to `compat_convert`.
|
|
54
|
+
|
|
55
|
+
An x86_64 worker is staged as a shell wrapper plus `qemu-x86_64`, a minimal
|
|
56
|
+
x86_64 glibc rootfs, and the original `<worker>-x64`; the wrapper runs QEMU in
|
|
57
|
+
the guest. This makes a `linux-x64` runtime usable without an AArch64 rebuild.
|
|
58
|
+
|
|
59
|
+
If no worker is supplied, none is found in the package, and the GitHub Release
|
|
60
|
+
has no Linux asset, the result is `needs-native-build` with the cross-build
|
|
61
|
+
command. The adapter never builds the worker itself.
|
|
62
|
+
|
|
63
|
+
### Building the worker
|
|
64
|
+
|
|
65
|
+
For a Rust crate under `native/`:
|
|
39
66
|
|
|
40
67
|
```sh
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
cross build --release --locked --manifest-path native/Cargo.toml --target aarch64-unknown-linux-musl
|
|
44
|
-
# or
|
|
68
|
+
cargo build --release --locked --manifest-path native/Cargo.toml --target aarch64-unknown-linux-musl
|
|
69
|
+
# or, with a Zig-based cross linker:
|
|
45
70
|
cargo zigbuild --release --locked --manifest-path native/Cargo.toml --target aarch64-unknown-linux-musl
|
|
46
71
|
```
|
|
47
72
|
|
|
48
|
-
The
|
|
49
|
-
|
|
50
|
-
`serde`, `serde_json`, `uuid`, `regex`.
|
|
73
|
+
The result must be a static AArch64 musl ELF: `e_machine == 183`, no
|
|
74
|
+
`PT_INTERP`. Dynamic glibc binaries will not start in the Alpine guest.
|
|
51
75
|
|
|
52
|
-
|
|
53
|
-
`provenance.json` (`version`, `target`, `executable`, `sha256`).
|
|
76
|
+
### Generic sidecar
|
|
54
77
|
|
|
55
|
-
|
|
78
|
+
A native worker that follows one-JSON-request / one-JSON-response can also be
|
|
79
|
+
staged and called without patching the plugin's own tool layer:
|
|
56
80
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
`dshm-vm-bash` only redirects `bash -c`, so patch both call sites to:
|
|
64
|
-
|
|
65
|
-
```js
|
|
66
|
-
argv: ['bash', '-c', 'exec "$0"', file]
|
|
81
|
+
```json
|
|
82
|
+
compat_sidecar { "action": "stage", "tarball": "<converted.tgz>", "workerPath": "runtime/linux-arm64/worker", "id": "my-worker" }
|
|
83
|
+
compat_sidecar { "action": "probe", "id": "my-worker" }
|
|
84
|
+
compat_sidecar { "action": "call", "id": "my-worker", "input": { "ping": true }, "confirm": true }
|
|
67
85
|
```
|
|
68
86
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
### 4. Shell component
|
|
74
|
-
|
|
75
|
-
`lib/shells/resolve.js` treats every non-win32 host as POSIX and probes the
|
|
76
|
-
**host** for `/bin/bash`. DSHM's host has no bash. Patch the DSHM branch to
|
|
77
|
-
report the guest's `/bin/bash` as available; `ops_bash` then spawns
|
|
78
|
-
`bash -c`, which `dshm-vm-bash` routes into the guest.
|
|
79
|
-
|
|
80
|
-
Disable the PowerShell rung: the pwsh payload is win32-only.
|
|
81
|
-
|
|
82
|
-
### 5. PTC vs file
|
|
83
|
-
|
|
84
|
-
`lib/ptc/worker.js` calls `sandbox.confine()` for non-`danger-full-access`
|
|
85
|
-
policies. If DSHM's sandbox provider cannot confine the worker, PTC tools fail
|
|
86
|
-
closed. The `file` component uses policy checks but no `sandbox.confine`, so
|
|
87
|
-
port `ops_*` file tools first and treat PTC as a later optimization.
|
|
88
|
-
|
|
89
|
-
### 6. Verification
|
|
90
|
-
|
|
91
|
-
Run on the device:
|
|
92
|
-
|
|
93
|
-
- `ops_stat` on a workspace file;
|
|
94
|
-
- `ops_grep` over a small tree;
|
|
95
|
-
- `ops_write_file` then `ops_stat` (check the new revision);
|
|
96
|
-
- `ops_copy` / `ops_move` (9p rename/atomicity);
|
|
97
|
-
- a failure case with a read-only policy.
|
|
98
|
-
|
|
99
|
-
Watch for `cap-std`/`rustix` failures on 9p (`openat2`, `statx`, `renameat2`,
|
|
100
|
-
`flock`). If those fail, the fallback is a JS reimplementation of the worker
|
|
101
|
-
protocol rather than a guest port.
|
|
87
|
+
Staging checks the worker is an AArch64 ELF and puts it under
|
|
88
|
+
`$DSH_HOME/dshm-compat/sidecars/<id>/`. Calls run through
|
|
89
|
+
`bash -c 'exec "$0" "$@"'`, which `dshm-vm-bash` routes into Alpine.
|
|
102
90
|
|
|
103
91
|
## Common native dependencies
|
|
104
92
|
|